@contentstack/cli-cm-export-query 1.0.0-beta.9 → 1.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/lib/commands/cm/stacks/export-query.d.ts +1 -0
- package/lib/commands/cm/stacks/export-query.js +4 -0
- package/lib/config/index.js +1 -1
- package/lib/config/index.ts +1 -1
- package/lib/core/module-exporter.js +13 -1
- package/lib/core/query-executor.d.ts +13 -2
- package/lib/core/query-executor.js +102 -137
- package/lib/utils/content-type-helper.js +14 -8
- package/lib/utils/dependency-resolver.d.ts +10 -1
- package/lib/utils/dependency-resolver.js +26 -11
- package/lib/utils/query-parser.js +1 -0
- package/lib/utils/read-content-type-schemas.d.ts +16 -0
- package/lib/utils/read-content-type-schemas.js +158 -0
- package/messages/index.json +75 -1
- package/oclif.manifest.json +1 -1
- package/package.json +22 -15
|
@@ -8,6 +8,7 @@ class ExportQueryCommand extends cli_command_1.Command {
|
|
|
8
8
|
async run() {
|
|
9
9
|
try {
|
|
10
10
|
const { flags } = await this.parse(ExportQueryCommand);
|
|
11
|
+
this.initializeMessageHandler();
|
|
11
12
|
// Setup export configuration
|
|
12
13
|
const exportQueryConfig = await (0, utils_1.setupQueryExportConfig)(flags);
|
|
13
14
|
exportQueryConfig.host = this.cmaHost;
|
|
@@ -41,6 +42,9 @@ class ExportQueryCommand extends cli_command_1.Command {
|
|
|
41
42
|
(0, cli_utilities_1.handleAndLogError)(error);
|
|
42
43
|
}
|
|
43
44
|
}
|
|
45
|
+
initializeMessageHandler() {
|
|
46
|
+
cli_utilities_1.messageHandler.init(this.context);
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
exports.default = ExportQueryCommand;
|
|
46
50
|
ExportQueryCommand.description = 'Export content from a stack using query-based filtering';
|
package/lib/config/index.js
CHANGED
package/lib/config/index.ts
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.ModuleExporter = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
|
+
const path = tslib_1.__importStar(require("path"));
|
|
5
6
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
7
|
const cli_cm_export_1 = tslib_1.__importDefault(require("@contentstack/cli-cm-export"));
|
|
8
|
+
const read_content_type_schemas_1 = require("../utils/read-content-type-schemas");
|
|
7
9
|
class ModuleExporter {
|
|
8
10
|
constructor(exportQueryConfig) {
|
|
9
11
|
this.exportedModules = [];
|
|
@@ -22,6 +24,13 @@ class ModuleExporter {
|
|
|
22
24
|
// Create export command instance
|
|
23
25
|
await cli_cm_export_1.default.run(cmd);
|
|
24
26
|
cli_utilities_1.log.debug(`Export command completed for module: ${moduleName}`, moduleLogContext);
|
|
27
|
+
if (moduleName === 'content-types') {
|
|
28
|
+
const baseDir = options.directory || this.exportQueryConfig.exportDir;
|
|
29
|
+
const branch = options.branch || this.exportQueryConfig.branchName || '';
|
|
30
|
+
const ctDir = path.join((0, cli_utilities_1.sanitizePath)(baseDir), (0, cli_utilities_1.sanitizePath)(branch), 'content_types');
|
|
31
|
+
(0, read_content_type_schemas_1.rebuildContentTypesSchemaJson)(ctDir);
|
|
32
|
+
cli_utilities_1.log.debug('Rebuilt content_types/schema.json from all per-UID JSON files', moduleLogContext);
|
|
33
|
+
}
|
|
25
34
|
// Read the exported data
|
|
26
35
|
// const data = await this.readExportedData(moduleName, options);
|
|
27
36
|
if (!this.exportedModules.includes(moduleName)) {
|
|
@@ -48,10 +57,13 @@ class ModuleExporter {
|
|
|
48
57
|
cmd.push('-d', directory);
|
|
49
58
|
// Module
|
|
50
59
|
cmd.push('--module', moduleName);
|
|
51
|
-
// Alias
|
|
60
|
+
// Alias or management token (mutually exclusive for the export CLI)
|
|
52
61
|
if (options.alias) {
|
|
53
62
|
cmd.push('-a', options.alias);
|
|
54
63
|
}
|
|
64
|
+
else if (this.exportQueryConfig.managementToken) {
|
|
65
|
+
cmd.push('-a', this.exportQueryConfig.managementToken);
|
|
66
|
+
}
|
|
55
67
|
// Branch
|
|
56
68
|
if (options.branch || this.exportQueryConfig.branchName) {
|
|
57
69
|
cmd.push('--branch', options.branch || this.exportQueryConfig.branchName);
|
|
@@ -9,8 +9,19 @@ export declare class QueryExporter {
|
|
|
9
9
|
execute(): Promise<void>;
|
|
10
10
|
private exportGeneralModules;
|
|
11
11
|
private exportQueriedModule;
|
|
12
|
-
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Iteratively expand the set of exported content types, global fields, extensions,
|
|
14
|
+
* taxonomies, and marketplace apps until no new items are discovered (fixpoint).
|
|
15
|
+
*
|
|
16
|
+
* Each iteration scans the combined set of CT and GF documents that currently exist on
|
|
17
|
+
* disk. Any newly discovered referenced content types or global fields are exported and
|
|
18
|
+
* the loop restarts so that their schemas can be scanned in turn. Leaf dependencies
|
|
19
|
+
* (extensions, taxonomies, marketplace apps) are collected and exported in the same pass
|
|
20
|
+
* without triggering an extra iteration, since they do not themselves produce new schemas.
|
|
21
|
+
*
|
|
22
|
+
* Personalize is exported exactly once, after the closure stabilises.
|
|
23
|
+
*/
|
|
24
|
+
private expandSchemaClosure;
|
|
14
25
|
private exportContentModules;
|
|
15
26
|
private exportEntries;
|
|
16
27
|
private exportReferencedAssets;
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.QueryExporter = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
6
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
7
|
const path = tslib_1.__importStar(require("path"));
|
|
7
8
|
const query_parser_1 = require("../utils/query-parser");
|
|
8
9
|
const module_exporter_1 = require("./module-exporter");
|
|
@@ -10,6 +11,7 @@ const utils_1 = require("../utils");
|
|
|
10
11
|
const utils_2 = require("../utils");
|
|
11
12
|
const utils_3 = require("../utils");
|
|
12
13
|
const utils_4 = require("../utils");
|
|
14
|
+
const read_content_type_schemas_1 = require("../utils/read-content-type-schemas");
|
|
13
15
|
class QueryExporter {
|
|
14
16
|
constructor(managementAPIClient, exportQueryConfig) {
|
|
15
17
|
this.exportQueryConfig = exportQueryConfig;
|
|
@@ -31,19 +33,10 @@ class QueryExporter {
|
|
|
31
33
|
await this.exportGeneralModules();
|
|
32
34
|
// Step 4: Export queried modules
|
|
33
35
|
await this.exportQueriedModule(parsedQuery);
|
|
34
|
-
// Step
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
cli_utilities_1.log.info('No content types found, skipping export', this.exportQueryConfig.context);
|
|
39
|
-
process.exit(0);
|
|
40
|
-
}
|
|
41
|
-
// Step 5: export other content types which are referenced in previous step
|
|
42
|
-
cli_utilities_1.log.debug('Starting referenced content types export', this.exportQueryConfig.context);
|
|
43
|
-
await this.exportReferencedContentTypes();
|
|
44
|
-
// Step 6: export dependent modules global fields, extensions, taxonomies
|
|
45
|
-
cli_utilities_1.log.debug('Starting dependent modules export', this.exportQueryConfig.context);
|
|
46
|
-
await this.exportDependentModules();
|
|
36
|
+
// Step 5+6: resolve the full transitive closure of referenced content types,
|
|
37
|
+
// global fields, extensions, taxonomies, and marketplace apps.
|
|
38
|
+
cli_utilities_1.log.debug('Starting schema closure expansion', this.exportQueryConfig.context);
|
|
39
|
+
await this.expandSchemaClosure();
|
|
47
40
|
// Step 7: export content modules entries, assets
|
|
48
41
|
cli_utilities_1.log.debug('Starting content modules export', this.exportQueryConfig.context);
|
|
49
42
|
await this.exportContentModules();
|
|
@@ -71,131 +64,112 @@ class QueryExporter {
|
|
|
71
64
|
}
|
|
72
65
|
cli_utilities_1.log.debug('Queried module export completed', this.exportQueryConfig.context);
|
|
73
66
|
}
|
|
74
|
-
|
|
75
|
-
|
|
67
|
+
/**
|
|
68
|
+
* Iteratively expand the set of exported content types, global fields, extensions,
|
|
69
|
+
* taxonomies, and marketplace apps until no new items are discovered (fixpoint).
|
|
70
|
+
*
|
|
71
|
+
* Each iteration scans the combined set of CT and GF documents that currently exist on
|
|
72
|
+
* disk. Any newly discovered referenced content types or global fields are exported and
|
|
73
|
+
* the loop restarts so that their schemas can be scanned in turn. Leaf dependencies
|
|
74
|
+
* (extensions, taxonomies, marketplace apps) are collected and exported in the same pass
|
|
75
|
+
* without triggering an extra iteration, since they do not themselves produce new schemas.
|
|
76
|
+
*
|
|
77
|
+
* Personalize is exported exactly once, after the closure stabilises.
|
|
78
|
+
*/
|
|
79
|
+
async expandSchemaClosure() {
|
|
80
|
+
cli_utilities_1.log.info('Starting export of referenced content types and dependent modules...', this.exportQueryConfig.context);
|
|
76
81
|
try {
|
|
82
|
+
const ctPath = path.join((0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.exportDir), (0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.branchName || ''), 'content_types');
|
|
83
|
+
const gfPath = path.join((0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.exportDir), (0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.branchName || ''), 'global_fields');
|
|
77
84
|
const referencedHandler = new utils_1.ReferencedContentTypesHandler(this.exportQueryConfig);
|
|
78
|
-
const
|
|
79
|
-
|
|
80
|
-
const
|
|
81
|
-
const
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
return;
|
|
85
|
-
}
|
|
86
|
-
// Step 2: Start with initial batch (all currently exported content types)
|
|
87
|
-
let currentBatch = [...contentTypes];
|
|
88
|
-
cli_utilities_1.log.info(`Starting with ${currentBatch.length} initial content types`, this.exportQueryConfig.context);
|
|
89
|
-
// track reference depth
|
|
85
|
+
const dependenciesHandler = new utils_3.ContentTypeDependenciesHandler(this.stackAPIClient, this.exportQueryConfig);
|
|
86
|
+
const exportedCTUIDs = new Set();
|
|
87
|
+
const exportedGFUIDs = new Set();
|
|
88
|
+
const exportedExtUIDs = new Set();
|
|
89
|
+
const exportedTaxUIDs = new Set();
|
|
90
|
+
const exportedMarketplaceUIDs = new Set();
|
|
90
91
|
let iterationCount = 0;
|
|
91
|
-
|
|
92
|
-
while (currentBatch.length > 0 && iterationCount < this.exportQueryConfig.maxCTReferenceDepth) {
|
|
92
|
+
while (iterationCount < this.exportQueryConfig.maxCTReferenceDepth) {
|
|
93
93
|
iterationCount++;
|
|
94
|
-
cli_utilities_1.log.debug(`
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
94
|
+
cli_utilities_1.log.debug(`Schema closure iteration ${iterationCount}`, this.exportQueryConfig.context);
|
|
95
|
+
const allCTs = (0, read_content_type_schemas_1.readContentTypesFromExportDir)(ctPath);
|
|
96
|
+
const allGFs = (0, read_content_type_schemas_1.readGlobalFieldSchemasFromDir)(gfPath);
|
|
97
|
+
// Record everything currently on disk so we never re-export it.
|
|
98
|
+
allCTs.forEach((ct) => exportedCTUIDs.add(ct.uid));
|
|
99
|
+
allGFs.forEach((gf) => exportedGFUIDs.add(gf.uid));
|
|
100
|
+
const allSchemas = [...allCTs, ...allGFs];
|
|
101
|
+
if (allSchemas.length === 0) {
|
|
102
|
+
cli_utilities_1.log.info('No schemas found on disk, stopping closure', this.exportQueryConfig.context);
|
|
103
|
+
break;
|
|
104
|
+
}
|
|
105
|
+
let foundNewCTs = false;
|
|
106
|
+
let foundNewGFs = false;
|
|
107
|
+
// Step A: find and export referenced content types from the combined schema set.
|
|
108
|
+
if (!this.exportQueryConfig.skipReferences) {
|
|
109
|
+
const referencedUIDs = await referencedHandler.extractReferencedContentTypes(allSchemas);
|
|
110
|
+
const newCTUIDs = referencedUIDs.filter((uid) => !exportedCTUIDs.has(uid));
|
|
111
|
+
if (newCTUIDs.length > 0) {
|
|
112
|
+
cli_utilities_1.log.info(`Found ${newCTUIDs.length} new referenced content type(s) to fetch`, this.exportQueryConfig.context);
|
|
113
|
+
await this.moduleExporter.exportModule('content-types', {
|
|
114
|
+
query: { modules: { 'content-types': { uid: { $in: newCTUIDs } } } },
|
|
115
|
+
});
|
|
116
|
+
// Track immediately so the dedup filter works even if the disk reader
|
|
117
|
+
// hasn't picked up the newly written files yet.
|
|
118
|
+
newCTUIDs.forEach((uid) => exportedCTUIDs.add(uid));
|
|
119
|
+
foundNewCTs = true;
|
|
120
|
+
}
|
|
120
121
|
}
|
|
121
|
-
|
|
122
|
-
|
|
122
|
+
// Step B: find and export dependent modules from the combined schema set.
|
|
123
|
+
if (!this.exportQueryConfig.skipDependencies) {
|
|
124
|
+
const deps = await dependenciesHandler.extractDependencies(allSchemas);
|
|
125
|
+
const newGFUIDs = [...deps.globalFields].filter((uid) => !exportedGFUIDs.has(uid));
|
|
126
|
+
if (newGFUIDs.length > 0) {
|
|
127
|
+
cli_utilities_1.log.info(`Found ${newGFUIDs.length} new global field(s)`, this.exportQueryConfig.context);
|
|
128
|
+
await this.moduleExporter.exportModule('global-fields', {
|
|
129
|
+
query: { modules: { 'global-fields': { uid: { $in: newGFUIDs } } } },
|
|
130
|
+
});
|
|
131
|
+
// Track immediately for the same reason as CTs above.
|
|
132
|
+
newGFUIDs.forEach((uid) => exportedGFUIDs.add(uid));
|
|
133
|
+
foundNewGFs = true;
|
|
134
|
+
}
|
|
135
|
+
// Extensions, taxonomies, and marketplace apps are leaf nodes: they do not
|
|
136
|
+
// produce new schemas, so exporting them never requires an extra iteration.
|
|
137
|
+
const newExtUIDs = [...deps.extensions].filter((uid) => !exportedExtUIDs.has(uid));
|
|
138
|
+
if (newExtUIDs.length > 0) {
|
|
139
|
+
cli_utilities_1.log.info(`Found ${newExtUIDs.length} new extension(s)`, this.exportQueryConfig.context);
|
|
140
|
+
await this.moduleExporter.exportModule('extensions', {
|
|
141
|
+
query: { modules: { extensions: { uid: { $in: newExtUIDs } } } },
|
|
142
|
+
});
|
|
143
|
+
newExtUIDs.forEach((uid) => exportedExtUIDs.add(uid));
|
|
144
|
+
}
|
|
145
|
+
const newMarketplaceUIDs = [...deps.marketplaceApps].filter((uid) => !exportedMarketplaceUIDs.has(uid));
|
|
146
|
+
if (newMarketplaceUIDs.length > 0) {
|
|
147
|
+
cli_utilities_1.log.info(`Found ${newMarketplaceUIDs.length} new marketplace app(s)`, this.exportQueryConfig.context);
|
|
148
|
+
await this.moduleExporter.exportModule('marketplace-apps', {
|
|
149
|
+
query: { modules: { 'marketplace-apps': { installation_uid: { $in: newMarketplaceUIDs } } } },
|
|
150
|
+
});
|
|
151
|
+
newMarketplaceUIDs.forEach((uid) => exportedMarketplaceUIDs.add(uid));
|
|
152
|
+
}
|
|
153
|
+
const newTaxUIDs = [...deps.taxonomies].filter((uid) => !exportedTaxUIDs.has(uid));
|
|
154
|
+
if (newTaxUIDs.length > 0) {
|
|
155
|
+
cli_utilities_1.log.info(`Found ${newTaxUIDs.length} new taxonom(ies)`, this.exportQueryConfig.context);
|
|
156
|
+
await this.moduleExporter.exportModule('taxonomies', {
|
|
157
|
+
query: { modules: { taxonomies: { uid: { $in: newTaxUIDs } } } },
|
|
158
|
+
});
|
|
159
|
+
newTaxUIDs.forEach((uid) => exportedTaxUIDs.add(uid));
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!foundNewCTs && !foundNewGFs) {
|
|
163
|
+
cli_utilities_1.log.info('Schema closure complete, no new content types or global fields found', this.exportQueryConfig.context);
|
|
123
164
|
break;
|
|
124
165
|
}
|
|
125
166
|
}
|
|
126
|
-
|
|
127
|
-
cli_utilities_1.log.success('Referenced content types export completed successfully', this.exportQueryConfig.context);
|
|
128
|
-
}
|
|
129
|
-
catch (error) {
|
|
130
|
-
(0, cli_utilities_1.handleAndLogError)(error, this.exportQueryConfig.context, 'Error exporting referenced content types');
|
|
131
|
-
throw error;
|
|
132
|
-
}
|
|
133
|
-
}
|
|
134
|
-
async exportDependentModules() {
|
|
135
|
-
cli_utilities_1.log.info('Starting export of dependent modules...', this.exportQueryConfig.context);
|
|
136
|
-
try {
|
|
137
|
-
const dependenciesHandler = new utils_3.ContentTypeDependenciesHandler(this.stackAPIClient, this.exportQueryConfig);
|
|
138
|
-
// Extract dependencies from all exported content types
|
|
139
|
-
const dependencies = await dependenciesHandler.extractDependencies();
|
|
140
|
-
cli_utilities_1.log.debug('Dependencies extracted successfully', this.exportQueryConfig.context);
|
|
141
|
-
// Export Global Fields
|
|
142
|
-
if (dependencies.globalFields.size > 0) {
|
|
143
|
-
const globalFieldUIDs = Array.from(dependencies.globalFields);
|
|
144
|
-
cli_utilities_1.log.info(`Exporting ${globalFieldUIDs.length} global fields...`, this.exportQueryConfig.context);
|
|
145
|
-
const query = {
|
|
146
|
-
modules: {
|
|
147
|
-
'global-fields': {
|
|
148
|
-
uid: { $in: globalFieldUIDs },
|
|
149
|
-
},
|
|
150
|
-
},
|
|
151
|
-
};
|
|
152
|
-
await this.moduleExporter.exportModule('global-fields', { query });
|
|
153
|
-
}
|
|
154
|
-
// Export Extensions
|
|
155
|
-
if (dependencies.extensions.size > 0) {
|
|
156
|
-
const extensionUIDs = Array.from(dependencies.extensions);
|
|
157
|
-
cli_utilities_1.log.info(`Exporting ${extensionUIDs.length} extensions...`, this.exportQueryConfig.context);
|
|
158
|
-
const query = {
|
|
159
|
-
modules: {
|
|
160
|
-
extensions: {
|
|
161
|
-
uid: { $in: extensionUIDs },
|
|
162
|
-
},
|
|
163
|
-
},
|
|
164
|
-
};
|
|
165
|
-
await this.moduleExporter.exportModule('extensions', { query });
|
|
166
|
-
}
|
|
167
|
-
// export marketplace apps
|
|
168
|
-
if (dependencies.marketplaceApps.size > 0) {
|
|
169
|
-
const marketplaceAppInstallationUIDs = Array.from(dependencies.marketplaceApps);
|
|
170
|
-
cli_utilities_1.log.info(`Exporting ${marketplaceAppInstallationUIDs.length} marketplace apps...`, this.exportQueryConfig.context);
|
|
171
|
-
const query = {
|
|
172
|
-
modules: {
|
|
173
|
-
'marketplace-apps': {
|
|
174
|
-
installation_uid: { $in: marketplaceAppInstallationUIDs },
|
|
175
|
-
},
|
|
176
|
-
},
|
|
177
|
-
};
|
|
178
|
-
await this.moduleExporter.exportModule('marketplace-apps', { query });
|
|
179
|
-
}
|
|
180
|
-
// Export Taxonomies
|
|
181
|
-
if (dependencies.taxonomies.size > 0) {
|
|
182
|
-
const taxonomyUIDs = Array.from(dependencies.taxonomies);
|
|
183
|
-
cli_utilities_1.log.info(`Exporting ${taxonomyUIDs.length} taxonomies...`, this.exportQueryConfig.context);
|
|
184
|
-
const query = {
|
|
185
|
-
modules: {
|
|
186
|
-
taxonomies: {
|
|
187
|
-
uid: { $in: taxonomyUIDs },
|
|
188
|
-
},
|
|
189
|
-
},
|
|
190
|
-
};
|
|
191
|
-
await this.moduleExporter.exportModule('taxonomies', { query });
|
|
192
|
-
}
|
|
193
|
-
// export personalize
|
|
167
|
+
// Personalize is a single global module exported once after the closure stabilises.
|
|
194
168
|
await this.moduleExporter.exportModule('personalize');
|
|
195
|
-
cli_utilities_1.log.success('
|
|
169
|
+
cli_utilities_1.log.success('Referenced content types and dependent modules exported successfully', this.exportQueryConfig.context);
|
|
196
170
|
}
|
|
197
171
|
catch (error) {
|
|
198
|
-
(0, cli_utilities_1.handleAndLogError)(error, this.exportQueryConfig.context, 'Error
|
|
172
|
+
(0, cli_utilities_1.handleAndLogError)(error, this.exportQueryConfig.context, 'Error during schema closure expansion');
|
|
199
173
|
throw error;
|
|
200
174
|
}
|
|
201
175
|
}
|
|
@@ -244,18 +218,9 @@ class QueryExporter {
|
|
|
244
218
|
const assetUIDs = assetHandler.extractReferencedAssets();
|
|
245
219
|
if (assetUIDs.length > 0) {
|
|
246
220
|
cli_utilities_1.log.info(`Found ${assetUIDs.length} referenced assets to export`, this.exportQueryConfig.context);
|
|
221
|
+
fs.mkdirSync(assetsDir, { recursive: true });
|
|
247
222
|
// Define batch size - can be configurable through exportQueryConfig
|
|
248
223
|
const batchSize = this.exportQueryConfig.assetBatchSize || 100;
|
|
249
|
-
if (assetUIDs.length <= batchSize) {
|
|
250
|
-
const query = {
|
|
251
|
-
modules: {
|
|
252
|
-
assets: {
|
|
253
|
-
uid: { $in: assetUIDs },
|
|
254
|
-
},
|
|
255
|
-
},
|
|
256
|
-
};
|
|
257
|
-
await this.moduleExporter.exportModule('assets', { query });
|
|
258
|
-
}
|
|
259
224
|
// if asset size is bigger than batch size, then we need to export in batches
|
|
260
225
|
// Calculate number of batches
|
|
261
226
|
const totalBatches = Math.ceil(assetUIDs.length / batchSize);
|
|
@@ -36,16 +36,22 @@ class ReferencedContentTypesHandler {
|
|
|
36
36
|
getReferencedContentTypes(schema) {
|
|
37
37
|
const referencedTypes = new Set();
|
|
38
38
|
const traverseSchema = (schemaArray) => {
|
|
39
|
-
var _a, _b, _c, _d;
|
|
39
|
+
var _a, _b, _c, _d, _e;
|
|
40
40
|
for (const field of schemaArray) {
|
|
41
41
|
if (field.data_type === 'group' || field.data_type === 'global_field') {
|
|
42
|
-
// Recursively traverse group and global field schemas
|
|
43
|
-
|
|
42
|
+
// Recursively traverse group and global field schemas.
|
|
43
|
+
// field.schema may be absent when a global_field is represented only by
|
|
44
|
+
// its reference_to UID (stub form in a content type's inline schema).
|
|
45
|
+
if (Array.isArray(field.schema) && field.schema.length > 0) {
|
|
46
|
+
traverseSchema(field.schema);
|
|
47
|
+
}
|
|
44
48
|
}
|
|
45
49
|
else if (field.data_type === 'blocks') {
|
|
46
50
|
// Traverse each block's schema
|
|
47
51
|
for (const blockKey in field.blocks) {
|
|
48
|
-
|
|
52
|
+
if ((_a = field.blocks[blockKey]) === null || _a === void 0 ? void 0 : _a.schema) {
|
|
53
|
+
traverseSchema(field.blocks[blockKey].schema);
|
|
54
|
+
}
|
|
49
55
|
}
|
|
50
56
|
}
|
|
51
57
|
else if (field.data_type === 'reference' && field.reference_to) {
|
|
@@ -60,8 +66,8 @@ class ReferencedContentTypesHandler {
|
|
|
60
66
|
else if (
|
|
61
67
|
// Handle JSON RTE with embedded entries
|
|
62
68
|
field.data_type === 'json' &&
|
|
63
|
-
((
|
|
64
|
-
((
|
|
69
|
+
((_b = field.field_metadata) === null || _b === void 0 ? void 0 : _b.rich_text_type) &&
|
|
70
|
+
((_c = field.field_metadata) === null || _c === void 0 ? void 0 : _c.embed_entry) &&
|
|
65
71
|
field.reference_to) {
|
|
66
72
|
field.reference_to.forEach((ref) => {
|
|
67
73
|
if (ref !== 'sys_assets') {
|
|
@@ -72,8 +78,8 @@ class ReferencedContentTypesHandler {
|
|
|
72
78
|
else if (
|
|
73
79
|
// Handle Text RTE with embedded entries
|
|
74
80
|
field.data_type === 'text' &&
|
|
75
|
-
((
|
|
76
|
-
((
|
|
81
|
+
((_d = field.field_metadata) === null || _d === void 0 ? void 0 : _d.rich_text_type) &&
|
|
82
|
+
((_e = field.field_metadata) === null || _e === void 0 ? void 0 : _e.embed_entry) &&
|
|
77
83
|
field.reference_to) {
|
|
78
84
|
field.reference_to.forEach((ref) => {
|
|
79
85
|
if (ref !== 'sys_assets') {
|
|
@@ -3,7 +3,16 @@ export declare class ContentTypeDependenciesHandler {
|
|
|
3
3
|
private exportQueryConfig;
|
|
4
4
|
private stackAPIClient;
|
|
5
5
|
constructor(stackAPIClient: any, exportQueryConfig: QueryExportConfig);
|
|
6
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Extract all dependencies (global fields, extensions, taxonomies, marketplace apps) from the
|
|
8
|
+
* provided schema documents. When `schemas` is omitted the method falls back to reading content
|
|
9
|
+
* type schemas from disk — kept for backward compatibility with callers that do not supply
|
|
10
|
+
* already-loaded documents.
|
|
11
|
+
*
|
|
12
|
+
* Pass the combined set of content-type AND global-field documents so that transitive
|
|
13
|
+
* dependencies inside global fields are discovered in the same pass.
|
|
14
|
+
*/
|
|
15
|
+
extractDependencies(schemas?: any[]): Promise<{
|
|
7
16
|
globalFields: Set<string>;
|
|
8
17
|
extensions: Set<string>;
|
|
9
18
|
taxonomies: Set<string>;
|
|
@@ -3,18 +3,33 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.ContentTypeDependenciesHandler = void 0;
|
|
4
4
|
const tslib_1 = require("tslib");
|
|
5
5
|
const path = tslib_1.__importStar(require("path"));
|
|
6
|
-
const index_1 = require("./index");
|
|
7
6
|
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
7
|
+
const read_content_type_schemas_1 = require("./read-content-type-schemas");
|
|
8
8
|
class ContentTypeDependenciesHandler {
|
|
9
9
|
constructor(stackAPIClient, exportQueryConfig) {
|
|
10
10
|
this.exportQueryConfig = exportQueryConfig;
|
|
11
11
|
this.stackAPIClient = stackAPIClient;
|
|
12
12
|
}
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Extract all dependencies (global fields, extensions, taxonomies, marketplace apps) from the
|
|
15
|
+
* provided schema documents. When `schemas` is omitted the method falls back to reading content
|
|
16
|
+
* type schemas from disk — kept for backward compatibility with callers that do not supply
|
|
17
|
+
* already-loaded documents.
|
|
18
|
+
*
|
|
19
|
+
* Pass the combined set of content-type AND global-field documents so that transitive
|
|
20
|
+
* dependencies inside global fields are discovered in the same pass.
|
|
21
|
+
*/
|
|
22
|
+
async extractDependencies(schemas) {
|
|
23
|
+
let allSchemas;
|
|
24
|
+
if (schemas !== undefined) {
|
|
25
|
+
allSchemas = schemas;
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
const contentTypesFilePath = path.join((0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.exportDir), (0, cli_utilities_1.sanitizePath)(this.exportQueryConfig.branchName || ''), 'content_types');
|
|
29
|
+
allSchemas = (0, read_content_type_schemas_1.readContentTypesFromExportDir)(contentTypesFilePath);
|
|
30
|
+
}
|
|
31
|
+
if (allSchemas.length === 0) {
|
|
32
|
+
cli_utilities_1.log.info('No schemas found, skipping dependency extraction', this.exportQueryConfig.context);
|
|
18
33
|
return {
|
|
19
34
|
globalFields: new Set(),
|
|
20
35
|
extensions: new Set(),
|
|
@@ -22,16 +37,16 @@ class ContentTypeDependenciesHandler {
|
|
|
22
37
|
marketplaceApps: new Set(),
|
|
23
38
|
};
|
|
24
39
|
}
|
|
25
|
-
cli_utilities_1.log.info(`Extracting dependencies from ${
|
|
40
|
+
cli_utilities_1.log.info(`Extracting dependencies from ${allSchemas.length} schema(s)`, this.exportQueryConfig.context);
|
|
26
41
|
const dependencies = {
|
|
27
42
|
globalFields: new Set(),
|
|
28
43
|
extensions: new Set(),
|
|
29
44
|
taxonomies: new Set(),
|
|
30
45
|
marketplaceApps: new Set(),
|
|
31
46
|
};
|
|
32
|
-
for (const
|
|
33
|
-
if (
|
|
34
|
-
this.traverseSchemaForDependencies(
|
|
47
|
+
for (const doc of allSchemas) {
|
|
48
|
+
if (doc.schema) {
|
|
49
|
+
this.traverseSchemaForDependencies(doc.schema, dependencies);
|
|
35
50
|
}
|
|
36
51
|
}
|
|
37
52
|
// Separate extensions from marketplace apps using the extracted extension UIDs
|
|
@@ -109,7 +124,7 @@ class ContentTypeDependenciesHandler {
|
|
|
109
124
|
});
|
|
110
125
|
}
|
|
111
126
|
// Recursive traversal for nested structures
|
|
112
|
-
if (field.data_type === 'group' && field.schema) {
|
|
127
|
+
if ((field.data_type === 'group' || field.data_type === 'global_field') && field.schema) {
|
|
113
128
|
this.traverseSchemaForDependencies(field.schema, dependencies);
|
|
114
129
|
}
|
|
115
130
|
if (field.data_type === 'blocks' && field.blocks) {
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CLI v1 aggregate content types under `content_types/schema.json`.
|
|
3
|
+
*/
|
|
4
|
+
export declare function readContentTypesFromExportDir(dir: string): any[];
|
|
5
|
+
/**
|
|
6
|
+
* Global fields: prefer `global_fields/globalfields.json` (cm-export v1), then per-file / per-subfolder layouts.
|
|
7
|
+
*/
|
|
8
|
+
export declare function readGlobalFieldSchemasFromDir(dir: string): any[];
|
|
9
|
+
/**
|
|
10
|
+
* Rebuild `content_types/schema.json` from every per–content-type `*.json` in the folder
|
|
11
|
+
* (excluding `schema.json` itself). Each `cm:stacks:export --module content-types` run
|
|
12
|
+
* overwrites `schema.json` with that run’s batch only; query-export runs that module
|
|
13
|
+
* multiple times, so without this merge the aggregate omits earlier types and the
|
|
14
|
+
* entries module (which only reads `schema.json`) skips their entries.
|
|
15
|
+
*/
|
|
16
|
+
export declare function rebuildContentTypesSchemaJson(ctDir: string): void;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.rebuildContentTypesSchemaJson = exports.readGlobalFieldSchemasFromDir = exports.readContentTypesFromExportDir = void 0;
|
|
4
|
+
const tslib_1 = require("tslib");
|
|
5
|
+
const fs = tslib_1.__importStar(require("fs"));
|
|
6
|
+
const path = tslib_1.__importStar(require("path"));
|
|
7
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
8
|
+
const file_helper_1 = require("./file-helper");
|
|
9
|
+
function normalizeToArray(raw) {
|
|
10
|
+
if (raw == null)
|
|
11
|
+
return [];
|
|
12
|
+
if (Array.isArray(raw))
|
|
13
|
+
return raw;
|
|
14
|
+
if (typeof raw === 'object')
|
|
15
|
+
return Object.values(raw);
|
|
16
|
+
return [];
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* CLI v1 aggregate content types under `content_types/schema.json`.
|
|
20
|
+
*/
|
|
21
|
+
function readContentTypesFromExportDir(dir) {
|
|
22
|
+
const schemaPath = path.join((0, cli_utilities_1.sanitizePath)(dir), 'schema.json');
|
|
23
|
+
try {
|
|
24
|
+
const raw = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(schemaPath));
|
|
25
|
+
return normalizeToArray(raw);
|
|
26
|
+
}
|
|
27
|
+
catch (_a) {
|
|
28
|
+
return [];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
exports.readContentTypesFromExportDir = readContentTypesFromExportDir;
|
|
32
|
+
function readGlobalFieldSchemasFromSubdirs(base) {
|
|
33
|
+
if (!fs.existsSync(base))
|
|
34
|
+
return [];
|
|
35
|
+
const out = [];
|
|
36
|
+
for (const name of fs.readdirSync(base)) {
|
|
37
|
+
if (name === 'globalfields.json' || name === 'schema.json')
|
|
38
|
+
continue;
|
|
39
|
+
const full = path.join(base, name);
|
|
40
|
+
let st;
|
|
41
|
+
try {
|
|
42
|
+
st = fs.statSync(full);
|
|
43
|
+
}
|
|
44
|
+
catch (_a) {
|
|
45
|
+
continue;
|
|
46
|
+
}
|
|
47
|
+
if (!st.isDirectory()) {
|
|
48
|
+
if (name.endsWith('.json')) {
|
|
49
|
+
try {
|
|
50
|
+
const doc = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(full));
|
|
51
|
+
if (doc && typeof doc === 'object')
|
|
52
|
+
out.push(doc);
|
|
53
|
+
}
|
|
54
|
+
catch (_b) {
|
|
55
|
+
/* skip invalid */
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
continue;
|
|
59
|
+
}
|
|
60
|
+
const uid = name;
|
|
61
|
+
const candidates = [path.join(full, `${uid}.json`), path.join(full, 'index.json')];
|
|
62
|
+
let loaded = false;
|
|
63
|
+
for (const p of candidates) {
|
|
64
|
+
if (fs.existsSync(p)) {
|
|
65
|
+
try {
|
|
66
|
+
const doc = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(p));
|
|
67
|
+
if (doc && typeof doc === 'object') {
|
|
68
|
+
out.push(doc);
|
|
69
|
+
loaded = true;
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (_c) {
|
|
74
|
+
/* try next */
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
if (loaded)
|
|
79
|
+
continue;
|
|
80
|
+
try {
|
|
81
|
+
for (const f of fs.readdirSync(full)) {
|
|
82
|
+
if (!f.endsWith('.json'))
|
|
83
|
+
continue;
|
|
84
|
+
const doc = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(path.join(full, f)));
|
|
85
|
+
if (doc && typeof doc === 'object') {
|
|
86
|
+
out.push(doc);
|
|
87
|
+
break;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
catch (_d) {
|
|
92
|
+
/* skip */
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
return out;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Global fields: prefer `global_fields/globalfields.json` (cm-export v1), then per-file / per-subfolder layouts.
|
|
99
|
+
*/
|
|
100
|
+
function readGlobalFieldSchemasFromDir(dir) {
|
|
101
|
+
const base = (0, cli_utilities_1.sanitizePath)(dir);
|
|
102
|
+
const aggPath = path.join(base, 'globalfields.json');
|
|
103
|
+
if (fs.existsSync(aggPath)) {
|
|
104
|
+
try {
|
|
105
|
+
const raw = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(aggPath));
|
|
106
|
+
const list = normalizeToArray(raw);
|
|
107
|
+
if (list.length > 0)
|
|
108
|
+
return list;
|
|
109
|
+
}
|
|
110
|
+
catch (_a) {
|
|
111
|
+
/* fall through to subdir scan */
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return readGlobalFieldSchemasFromSubdirs(base);
|
|
115
|
+
}
|
|
116
|
+
exports.readGlobalFieldSchemasFromDir = readGlobalFieldSchemasFromDir;
|
|
117
|
+
/**
|
|
118
|
+
* Rebuild `content_types/schema.json` from every per–content-type `*.json` in the folder
|
|
119
|
+
* (excluding `schema.json` itself). Each `cm:stacks:export --module content-types` run
|
|
120
|
+
* overwrites `schema.json` with that run’s batch only; query-export runs that module
|
|
121
|
+
* multiple times, so without this merge the aggregate omits earlier types and the
|
|
122
|
+
* entries module (which only reads `schema.json`) skips their entries.
|
|
123
|
+
*/
|
|
124
|
+
function rebuildContentTypesSchemaJson(ctDir) {
|
|
125
|
+
const dir = (0, cli_utilities_1.sanitizePath)(ctDir);
|
|
126
|
+
if (!fs.existsSync(dir))
|
|
127
|
+
return;
|
|
128
|
+
const byUid = new Map();
|
|
129
|
+
for (const name of fs.readdirSync(dir)) {
|
|
130
|
+
if (!name.endsWith('.json') || name === 'schema.json')
|
|
131
|
+
continue;
|
|
132
|
+
const fp = path.join(dir, name);
|
|
133
|
+
let st;
|
|
134
|
+
try {
|
|
135
|
+
st = fs.statSync(fp);
|
|
136
|
+
}
|
|
137
|
+
catch (_a) {
|
|
138
|
+
continue;
|
|
139
|
+
}
|
|
140
|
+
if (!st.isFile())
|
|
141
|
+
continue;
|
|
142
|
+
try {
|
|
143
|
+
const doc = file_helper_1.fsUtil.readFile((0, cli_utilities_1.sanitizePath)(fp));
|
|
144
|
+
if (doc && typeof doc === 'object' && !Array.isArray(doc) && typeof doc.uid === 'string') {
|
|
145
|
+
byUid.set(doc.uid, doc);
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
catch (_b) {
|
|
149
|
+
/* skip invalid JSON */
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
const merged = Array.from(byUid.values());
|
|
153
|
+
if (merged.length === 0)
|
|
154
|
+
return;
|
|
155
|
+
const schemaPath = path.join(dir, 'schema.json');
|
|
156
|
+
file_helper_1.fsUtil.writeFile((0, cli_utilities_1.sanitizePath)(schemaPath), merged);
|
|
157
|
+
}
|
|
158
|
+
exports.rebuildContentTypesSchemaJson = rebuildContentTypesSchemaJson;
|
package/messages/index.json
CHANGED
|
@@ -1 +1,75 @@
|
|
|
1
|
-
{
|
|
1
|
+
{
|
|
2
|
+
"ASSET_EXPORT_COMPLETE": "Asset export process completed successfully",
|
|
3
|
+
"ASSET_FOLDERS_EXPORT_COMPLETE": "Asset folder structure exported successfully",
|
|
4
|
+
"ASSET_METADATA_EXPORT_COMPLETE": "Asset metadata exported successfully",
|
|
5
|
+
"ASSET_VERSIONED_METADATA_EXPORT_COMPLETE": "Versioned asset metadata exported successfully",
|
|
6
|
+
"ASSET_DOWNLOAD_COMPLETE": "Asset download completed successfully",
|
|
7
|
+
"ASSET_DOWNLOAD_SUCCESS": "Asset '%s' (UID: %s) downloaded successfully",
|
|
8
|
+
"ASSET_DOWNLOAD_FAILED": "Failed to download asset '%s' (UID: %s)",
|
|
9
|
+
"ASSET_WRITE_FAILED": "Failed to write asset file '%s' (UID: %s)",
|
|
10
|
+
"ASSET_QUERY_FAILED": "Failed to query asset data from the API",
|
|
11
|
+
"ASSET_VERSIONED_QUERY_FAILED": "Failed to query versioned asset data from the API",
|
|
12
|
+
"ASSET_COUNT_QUERY_FAILED": "Failed to retrieve total asset count",
|
|
13
|
+
|
|
14
|
+
"CONTENT_TYPE_EXPORT_COMPLETE": "Content types exported successfully",
|
|
15
|
+
"CONTENT_TYPE_NO_TYPES": "No content types found",
|
|
16
|
+
"CONTENT_TYPE_EXPORT_FAILED": "Failed to export content types",
|
|
17
|
+
"CONTENT_TYPE_NO_TYPES_RETURNED": "API returned no content types for the given query",
|
|
18
|
+
|
|
19
|
+
"ENVIRONMENT_EXPORT_COMPLETE": "Successfully exported %s environment(s)",
|
|
20
|
+
"ENVIRONMENT_EXPORT_SUCCESS": "Environment '%s' exported successfully",
|
|
21
|
+
"ENVIRONMENT_NOT_FOUND": "No environments found in the current stack",
|
|
22
|
+
|
|
23
|
+
"EXTENSION_EXPORT_COMPLETE": "Successfully exported %s extension(s)",
|
|
24
|
+
"EXTENSION_EXPORT_SUCCESS": "Extension '%s' exported successfully",
|
|
25
|
+
"EXTENSION_NOT_FOUND": "No extensions found in the current stack",
|
|
26
|
+
|
|
27
|
+
"GLOBAL_FIELDS_EXPORT_COMPLETE": "Successfully exported %s global field(s)",
|
|
28
|
+
|
|
29
|
+
"LABELS_EXPORT_COMPLETE": "Successfully exported %s label(s)",
|
|
30
|
+
"LABEL_EXPORT_SUCCESS": "Label '%s' exported successfully",
|
|
31
|
+
"LABELS_NOT_FOUND": "No labels found in the current stack",
|
|
32
|
+
|
|
33
|
+
"LOCALES_EXPORT_COMPLETE": "Successfully exported %s locale(s) including %s master locale(s)",
|
|
34
|
+
|
|
35
|
+
"TAXONOMY_EXPORT_COMPLETE": "Successfully exported %s taxonomy entries",
|
|
36
|
+
"TAXONOMY_EXPORT_SUCCESS": "Taxonomy '%s' exported successfully",
|
|
37
|
+
"TAXONOMY_NOT_FOUND": "No taxonomies found in the current stack",
|
|
38
|
+
|
|
39
|
+
"WEBHOOK_EXPORT_COMPLETE": "Successfully exported %s webhook(s)",
|
|
40
|
+
"WEBHOOK_EXPORT_SUCCESS": "Webhook '%s' exported successfully",
|
|
41
|
+
"WEBHOOK_NOT_FOUND": "No webhooks found in the current stack",
|
|
42
|
+
|
|
43
|
+
"WORKFLOW_EXPORT_COMPLETE": "Successfully exported %s workflow(s)",
|
|
44
|
+
"WORKFLOW_EXPORT_SUCCESS": "Workflow '%s' exported successfully",
|
|
45
|
+
"WORKFLOW_NOT_FOUND": "No workflows found in the current stack",
|
|
46
|
+
|
|
47
|
+
"PERSONALIZE_URL_NOT_SET": "Cannot export Personalize project: URL not configured",
|
|
48
|
+
"PERSONALIZE_SKIPPING_WITH_MANAGEMENT_TOKEN": "Skipping Personalize project export: Management token not supported",
|
|
49
|
+
"PERSONALIZE_MODULE_NOT_IMPLEMENTED": "Module '%s' implementation not found",
|
|
50
|
+
"PERSONALIZE_NOT_ENABLED": "Personalize feature is not enabled for this organization",
|
|
51
|
+
|
|
52
|
+
"MARKETPLACE_APPS_EXPORT_COMPLETE": "Successfully exported %s marketplace app(s)",
|
|
53
|
+
"MARKETPLACE_APP_CONFIG_EXPORT": "Exporting configuration for app '%s'",
|
|
54
|
+
"MARKETPLACE_APP_CONFIG_SUCCESS": "Successfully exported configuration for app '%s'",
|
|
55
|
+
"MARKETPLACE_APP_EXPORT_SUCCESS": "Successfully exported app '%s'",
|
|
56
|
+
"MARKETPLACE_APPS_NOT_FOUND": "No marketplace apps found in the current stack",
|
|
57
|
+
"MARKETPLACE_APP_CONFIG_EXPORT_FAILED": "Failed to export configuration for app '%s'",
|
|
58
|
+
"MARKETPLACE_APP_MANIFEST_EXPORT_FAILED": "Failed to export manifest for app '%s'",
|
|
59
|
+
|
|
60
|
+
"COMPOSABLE_STUDIO_EXPORT_START": "Starting Studio project export...",
|
|
61
|
+
"COMPOSABLE_STUDIO_NOT_FOUND": "No Studio project found for this stack",
|
|
62
|
+
"COMPOSABLE_STUDIO_EXPORT_COMPLETE": "Successfully exported Studio project '%s'",
|
|
63
|
+
"COMPOSABLE_STUDIO_EXPORT_FAILED": "Failed to export Studio project: %s",
|
|
64
|
+
"COMPOSABLE_STUDIO_AUTH_REQUIRED": "To export Studio projects, you must be logged in",
|
|
65
|
+
|
|
66
|
+
"ENTRIES_EXPORT_COMPLETE": "Successfully exported entries (Content Type: %s, Locale: %s)",
|
|
67
|
+
"ENTRIES_EXPORT_SUCCESS": "All entries exported successfully",
|
|
68
|
+
"ENTRIES_VERSIONED_EXPORT_SUCCESS": "Successfully exported versioned entry (Content Type: %s, UID: %s, Locale: %s)",
|
|
69
|
+
"ENTRIES_EXPORT_VERSIONS_FAILED": "Failed to export versions for content type '%s' (UID: %s)",
|
|
70
|
+
|
|
71
|
+
"BRANCH_EXPORT_FAILED": "Failed to export contents from branch (UID: %s)",
|
|
72
|
+
|
|
73
|
+
"ROLES_NO_CUSTOM_ROLES": "No custom roles found in the current stack",
|
|
74
|
+
"ROLES_EXPORTING_ROLE": "Exporting role '%s'"
|
|
75
|
+
}
|
package/oclif.manifest.json
CHANGED
package/package.json
CHANGED
|
@@ -1,19 +1,19 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-export-query",
|
|
3
3
|
"description": "Contentstack CLI plugin to export content from stack",
|
|
4
|
-
"version": "1.0.0
|
|
4
|
+
"version": "1.0.0",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
8
|
-
"@contentstack/cli-
|
|
9
|
-
"@contentstack/cli-
|
|
10
|
-
"@contentstack/cli-
|
|
11
|
-
"@
|
|
8
|
+
"@contentstack/cli-variants": "~1.4.3",
|
|
9
|
+
"@contentstack/cli-cm-export": "~1.24.3",
|
|
10
|
+
"@contentstack/cli-command": "~1.8.2",
|
|
11
|
+
"@contentstack/cli-utilities": "~1.18.3",
|
|
12
|
+
"@oclif/core": "^4.10.5",
|
|
12
13
|
"async": "^3.2.6",
|
|
13
14
|
"big-json": "^3.2.0",
|
|
14
15
|
"bluebird": "^3.7.2",
|
|
15
|
-
"
|
|
16
|
-
"lodash": "^4.17.23",
|
|
16
|
+
"lodash": "^4.18.1",
|
|
17
17
|
"merge": "^2.1.1",
|
|
18
18
|
"mkdirp": "^1.0.4",
|
|
19
19
|
"progress-stream": "^2.0.0",
|
|
@@ -21,22 +21,25 @@
|
|
|
21
21
|
"tslib": "^2.8.1",
|
|
22
22
|
"winston": "^3.19.0"
|
|
23
23
|
},
|
|
24
|
+
"overrides": {
|
|
25
|
+
"brace-expansion": "^5.0.5"
|
|
26
|
+
},
|
|
24
27
|
"devDependencies": {
|
|
25
28
|
"@contentstack/cli-dev-dependencies": "~1.3.1",
|
|
26
|
-
"@oclif/plugin-help": "^6.2.
|
|
27
|
-
"@oclif/test": "^4.1.
|
|
29
|
+
"@oclif/plugin-help": "^6.2.44",
|
|
30
|
+
"@oclif/test": "^4.1.18",
|
|
28
31
|
"@types/big-json": "^3.2.5",
|
|
29
32
|
"@types/chai": "^4.3.20",
|
|
30
33
|
"@types/mkdirp": "^1.0.2",
|
|
31
34
|
"@types/mocha": "^10.0.10",
|
|
32
|
-
"@types/node": "^20.19.
|
|
35
|
+
"@types/node": "^20.19.39",
|
|
33
36
|
"@types/progress-stream": "^2.0.5",
|
|
34
37
|
"@types/sinon": "^17.0.4",
|
|
35
38
|
"chai": "^4.5.0",
|
|
36
39
|
"dotenv": "^16.6.1",
|
|
37
40
|
"dotenv-expand": "^9.0.0",
|
|
38
41
|
"eslint": "^8.57.1",
|
|
39
|
-
"eslint-config-oclif": "^6.0.
|
|
42
|
+
"eslint-config-oclif": "^6.0.157",
|
|
40
43
|
"husky": "^9.1.7",
|
|
41
44
|
"mocha": "10.8.2",
|
|
42
45
|
"nyc": "^15.1.0",
|
|
@@ -46,19 +49,23 @@
|
|
|
46
49
|
"typescript": "^4.9.5"
|
|
47
50
|
},
|
|
48
51
|
"scripts": {
|
|
49
|
-
"build": "
|
|
50
|
-
"clean": "rm -rf ./lib ./node_modules tsconfig.
|
|
52
|
+
"build": "pnpm compile && pnpm copy-config && oclif manifest && oclif readme",
|
|
53
|
+
"clean": "rm -rf ./lib ./node_modules tsconfig.tsbuildinfo",
|
|
51
54
|
"compile": "tsc -b tsconfig.json",
|
|
52
55
|
"postpack": "rm -f oclif.manifest.json",
|
|
53
|
-
"
|
|
56
|
+
"copy-config": "cp -r src/config lib/",
|
|
57
|
+
"prepack": "pnpm compile && pnpm copy-config && oclif manifest && oclif readme",
|
|
54
58
|
"version": "oclif readme && git add README.md",
|
|
55
59
|
"test:report": "tsc -p test && nyc --reporter=lcov --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
|
|
56
60
|
"pretest": "tsc -p test",
|
|
57
61
|
"test": "nyc --extension .ts mocha --forbid-only \"test/**/*.test.ts\"",
|
|
62
|
+
"posttest": "npm run lint",
|
|
58
63
|
"lint": "eslint src/**/*.ts",
|
|
59
64
|
"format": "eslint src/**/*.ts --fix",
|
|
65
|
+
"test:integration": "INTEGRATION_TEST=true mocha --config ./test/.mocharc.js --forbid-only \"test/run.test.js\"",
|
|
66
|
+
"test:integration:report": "INTEGRATION_TEST=true nyc --extension .js mocha --forbid-only \"test/run.test.js\"",
|
|
60
67
|
"test:unit": "mocha --forbid-only \"test/unit/**/*.test.ts\"",
|
|
61
|
-
"
|
|
68
|
+
"test:unit:report": "nyc --reporter=text --extension .ts mocha --forbid-only \"test/unit/**/*.test.ts\""
|
|
62
69
|
},
|
|
63
70
|
"engines": {
|
|
64
71
|
"node": ">=14.0.0"
|