@contentstack/cli-cm-import 1.28.1 → 2.0.0-beta
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 +5 -7
- package/lib/commands/cm/stacks/import.d.ts +2 -0
- package/lib/commands/cm/stacks/import.js +46 -11
- package/lib/config/index.js +0 -1
- package/lib/import/module-importer.js +6 -20
- package/lib/import/modules/assets.d.ts +6 -0
- package/lib/import/modules/assets.js +102 -25
- package/lib/import/modules/base-class.d.ts +17 -0
- package/lib/import/modules/base-class.js +45 -0
- package/lib/import/modules/content-types.d.ts +7 -10
- package/lib/import/modules/content-types.js +132 -68
- package/lib/import/modules/custom-roles.d.ts +6 -2
- package/lib/import/modules/custom-roles.js +80 -69
- package/lib/import/modules/entries.d.ts +7 -0
- package/lib/import/modules/entries.js +278 -163
- package/lib/import/modules/environments.d.ts +3 -0
- package/lib/import/modules/environments.js +69 -38
- package/lib/import/modules/extensions.d.ts +3 -0
- package/lib/import/modules/extensions.js +99 -64
- package/lib/import/modules/global-fields.d.ts +8 -1
- package/lib/import/modules/global-fields.js +123 -63
- package/lib/import/modules/index.d.ts +1 -0
- package/lib/import/modules/index.js +1 -0
- package/lib/import/modules/labels.d.ts +3 -0
- package/lib/import/modules/labels.js +104 -54
- package/lib/import/modules/locales.d.ts +15 -4
- package/lib/import/modules/locales.js +194 -94
- package/lib/import/modules/marketplace-apps.d.ts +6 -3
- package/lib/import/modules/marketplace-apps.js +177 -102
- package/lib/import/modules/personalize.d.ts +11 -4
- package/lib/import/modules/personalize.js +138 -47
- package/lib/import/modules/stack.d.ts +6 -0
- package/lib/import/modules/stack.js +71 -27
- package/lib/import/modules/taxonomies.d.ts +4 -2
- package/lib/import/modules/taxonomies.js +60 -46
- package/lib/import/modules/variant-entries.d.ts +7 -4
- package/lib/import/modules/variant-entries.js +76 -35
- package/lib/import/modules/webhooks.d.ts +3 -0
- package/lib/import/modules/webhooks.js +71 -40
- package/lib/import/modules/workflows.d.ts +3 -0
- package/lib/import/modules/workflows.js +98 -48
- package/lib/types/default-config.d.ts +0 -1
- package/lib/types/import-config.d.ts +0 -1
- package/lib/types/index.d.ts +1 -12
- package/lib/utils/backup-handler.js +0 -1
- package/lib/utils/constants.d.ts +243 -0
- package/lib/utils/constants.js +264 -0
- package/lib/utils/import-config-handler.js +2 -0
- package/lib/utils/import-path-resolver.js +3 -13
- package/lib/utils/index.d.ts +1 -1
- package/lib/utils/index.js +6 -2
- package/lib/utils/marketplace-app-helper.js +3 -8
- package/lib/utils/progress-strategy-registry.d.ts +7 -0
- package/lib/utils/progress-strategy-registry.js +72 -0
- package/lib/utils/setup-branch.js +1 -1
- package/oclif.manifest.json +2 -2
- package/package.json +2 -2
- package/lib/import/modules-js/assets.d.ts +0 -33
- package/lib/import/modules-js/assets.js +0 -428
- package/lib/import/modules-js/content-types.d.ts +0 -34
- package/lib/import/modules-js/content-types.js +0 -204
- package/lib/import/modules-js/custom-roles.d.ts +0 -15
- package/lib/import/modules-js/custom-roles.js +0 -143
- package/lib/import/modules-js/entries.d.ts +0 -54
- package/lib/import/modules-js/entries.js +0 -1280
- package/lib/import/modules-js/environments.d.ts +0 -13
- package/lib/import/modules-js/environments.js +0 -85
- package/lib/import/modules-js/extensions.d.ts +0 -18
- package/lib/import/modules-js/extensions.js +0 -86
- package/lib/import/modules-js/global-fields.d.ts +0 -13
- package/lib/import/modules-js/global-fields.js +0 -106
- package/lib/import/modules-js/index.d.ts +0 -1
- package/lib/import/modules-js/index.js +0 -33
- package/lib/import/modules-js/labels.d.ts +0 -20
- package/lib/import/modules-js/labels.js +0 -148
- package/lib/import/modules-js/locales.d.ts +0 -24
- package/lib/import/modules-js/locales.js +0 -196
- package/lib/import/modules-js/marketplace-apps.d.ts +0 -63
- package/lib/import/modules-js/marketplace-apps.js +0 -429
- package/lib/import/modules-js/webhooks.d.ts +0 -17
- package/lib/import/modules-js/webhooks.js +0 -85
- package/lib/import/modules-js/workflows.d.ts +0 -19
- package/lib/import/modules-js/workflows.js +0 -170
- package/lib/utils/log.d.ts +0 -12
- package/lib/utils/log.js +0 -31
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Progress Strategy Registrations for Import Modules
|
|
4
|
+
* This file registers progress calculation strategies for all import modules
|
|
5
|
+
* to ensure correct item counts in the final summary.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
const cli_utilities_1 = require("@contentstack/cli-utilities");
|
|
9
|
+
const constants_1 = require("./constants");
|
|
10
|
+
// Register strategy for Content Types - use Create as primary process
|
|
11
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CONTENT_TYPES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.CONTENT_TYPES_CREATE));
|
|
12
|
+
// Register strategy for Assets - use Asset Upload as primary process
|
|
13
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ASSETS], new cli_utilities_1.CustomProgressStrategy((processes) => {
|
|
14
|
+
const uploadsProcess = processes.get(constants_1.PROCESS_NAMES.ASSET_UPLOAD);
|
|
15
|
+
if (uploadsProcess) {
|
|
16
|
+
return {
|
|
17
|
+
total: uploadsProcess.total,
|
|
18
|
+
success: uploadsProcess.successCount,
|
|
19
|
+
failures: uploadsProcess.failureCount,
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
return null; // Fall back to default aggregation
|
|
23
|
+
}));
|
|
24
|
+
// Register strategy for Entries - use Entry Creation as primary process
|
|
25
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENTRIES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.ENTRIES_CREATE));
|
|
26
|
+
// Register strategy for Global Fields - use Create as primary process
|
|
27
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.GLOBAL_FIELDS], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.GLOBAL_FIELDS_CREATE));
|
|
28
|
+
// Register strategy for Extensions - simple module
|
|
29
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.EXTENSIONS], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.EXTENSIONS_CREATE));
|
|
30
|
+
// Register strategy for Environments - uses default (no nested progress yet)
|
|
31
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.ENVIRONMENTS], new cli_utilities_1.DefaultProgressStrategy());
|
|
32
|
+
// Register strategy for Locales - uses default (no nested progress yet)
|
|
33
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LOCALES], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.LOCALES_CREATE));
|
|
34
|
+
// Register strategy for Labels - uses default (no nested progress yet)
|
|
35
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.LABELS], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.LABELS_CREATE));
|
|
36
|
+
// Register strategy for Webhooks - uses default (no nested progress yet)
|
|
37
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WEBHOOKS], new cli_utilities_1.DefaultProgressStrategy());
|
|
38
|
+
// Register strategy for Workflows - uses default (no nested progress yet)
|
|
39
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.WORKFLOWS], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.WEBHOOKS_IMPORT));
|
|
40
|
+
// Register strategy for Custom Roles - uses default (no nested progress yet)
|
|
41
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.CUSTOM_ROLES], new cli_utilities_1.DefaultProgressStrategy());
|
|
42
|
+
// Register strategy for Taxonomies - uses default (no nested progress yet)
|
|
43
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.TAXONOMIES], new cli_utilities_1.DefaultProgressStrategy());
|
|
44
|
+
// Register strategy for Marketplace Apps - complex module with app installations
|
|
45
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.MARKETPLACE_APPS], new cli_utilities_1.PrimaryProcessStrategy(constants_1.PROCESS_NAMES.CREATE_APPS));
|
|
46
|
+
// Register strategy for Stack Settings - simple module
|
|
47
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.STACK], new cli_utilities_1.DefaultProgressStrategy());
|
|
48
|
+
// Register strategy for Personalize - complex module with projects/experiences
|
|
49
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.PERSONALIZE], new cli_utilities_1.CustomProgressStrategy((processes) => {
|
|
50
|
+
// For personalize import, count project imports as primary metric
|
|
51
|
+
const projectImport = processes.get(constants_1.PROCESS_NAMES.PERSONALIZE_PROJECTS);
|
|
52
|
+
if (projectImport) {
|
|
53
|
+
return {
|
|
54
|
+
total: projectImport.total,
|
|
55
|
+
success: projectImport.successCount,
|
|
56
|
+
failures: projectImport.failureCount,
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
// Fallback to any other main process
|
|
60
|
+
const mainProcess = Array.from(processes.values())[0];
|
|
61
|
+
if (mainProcess) {
|
|
62
|
+
return {
|
|
63
|
+
total: mainProcess.total,
|
|
64
|
+
success: mainProcess.successCount,
|
|
65
|
+
failures: mainProcess.failureCount,
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
return null;
|
|
69
|
+
}));
|
|
70
|
+
// Register strategy for Variant Entries - sub-process of entries
|
|
71
|
+
cli_utilities_1.ProgressStrategyRegistry.register(constants_1.MODULE_NAMES[constants_1.MODULE_CONTEXTS.VARIANT_ENTRIES], new cli_utilities_1.DefaultProgressStrategy());
|
|
72
|
+
exports.default = cli_utilities_1.ProgressStrategyRegistry;
|
|
@@ -19,7 +19,7 @@ const setupBranchConfig = async (config, stackAPIClient) => {
|
|
|
19
19
|
.find()
|
|
20
20
|
.then(({ items }) => items);
|
|
21
21
|
if (branches.length) {
|
|
22
|
-
cli_utilities_1.log.info(`
|
|
22
|
+
cli_utilities_1.log.info(`The stack is branch-enabled, and branches exist. By default, content will be imported into the main branch.`);
|
|
23
23
|
config.branchName = 'main';
|
|
24
24
|
cli_utilities_1.log.debug(`Setting default target branch to 'main'`);
|
|
25
25
|
}
|
package/oclif.manifest.json
CHANGED
|
@@ -111,7 +111,7 @@
|
|
|
111
111
|
"type": "option"
|
|
112
112
|
},
|
|
113
113
|
"branch-alias": {
|
|
114
|
-
"description": "
|
|
114
|
+
"description": "Specify the branch alias where you want to import your content. If not specified, the content is imported into the main branch by default.",
|
|
115
115
|
"exclusive": [
|
|
116
116
|
"branch"
|
|
117
117
|
],
|
|
@@ -212,5 +212,5 @@
|
|
|
212
212
|
]
|
|
213
213
|
}
|
|
214
214
|
},
|
|
215
|
-
"version": "
|
|
215
|
+
"version": "2.0.0-beta"
|
|
216
216
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@contentstack/cli-cm-import",
|
|
3
3
|
"description": "Contentstack CLI plugin to import content into stack",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "2.0.0-beta",
|
|
5
5
|
"author": "Contentstack",
|
|
6
6
|
"bugs": "https://github.com/contentstack/cli/issues",
|
|
7
7
|
"dependencies": {
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
"@contentstack/cli-command": "~1.6.1",
|
|
10
10
|
"@contentstack/cli-utilities": "~1.14.1",
|
|
11
11
|
"@contentstack/management": "~1.22.0",
|
|
12
|
-
"@contentstack/cli-variants": "~
|
|
12
|
+
"@contentstack/cli-variants": "~2.0.0-beta",
|
|
13
13
|
"@oclif/core": "^4.3.0",
|
|
14
14
|
"big-json": "^3.2.0",
|
|
15
15
|
"bluebird": "^3.7.2",
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
export = ImportAssets;
|
|
2
|
-
declare class ImportAssets {
|
|
3
|
-
constructor(importConfig: any, stackAPIClient: any);
|
|
4
|
-
assets: any;
|
|
5
|
-
fails: any[];
|
|
6
|
-
assetConfig: any;
|
|
7
|
-
mapperDirPath: any;
|
|
8
|
-
assetBatchLimit: any;
|
|
9
|
-
uidMapping: {};
|
|
10
|
-
urlMapping: {};
|
|
11
|
-
environmentPath: any;
|
|
12
|
-
assetBucket: any[];
|
|
13
|
-
assetsFolderPath: any;
|
|
14
|
-
folderBucket: any[];
|
|
15
|
-
folderDetails: any[];
|
|
16
|
-
mappedFolderUids: {};
|
|
17
|
-
config: any;
|
|
18
|
-
stackAPIClient: any;
|
|
19
|
-
start(): Promise<any>;
|
|
20
|
-
uidMapperPath: string;
|
|
21
|
-
urlMapperPath: string;
|
|
22
|
-
failsPath: string;
|
|
23
|
-
environment: any;
|
|
24
|
-
uploadVersionedAssets(uid: any, assetFolderPath: any): Promise<any>;
|
|
25
|
-
updateAsset(assetPath: any, metadata: any, filesStreamed: any, _uidContainer: any, urlContainer: any): Promise<any>;
|
|
26
|
-
uploadAsset(assetPath: any, metadata: any, uidContainer: any, urlContainer: any): Promise<any>;
|
|
27
|
-
importFolders(): Promise<any>;
|
|
28
|
-
buildFolderReqObjs(createdFolderUids: any, tree: any, parent_uid: any): void;
|
|
29
|
-
buildTree(coll: any): {};
|
|
30
|
-
findBranches(tree: any, branches: any, coll: any): void;
|
|
31
|
-
publish(assetUid: any, assetObject: any): Promise<any>;
|
|
32
|
-
}
|
|
33
|
-
import Promise = require("bluebird");
|
|
@@ -1,428 +0,0 @@
|
|
|
1
|
-
/*!
|
|
2
|
-
* Contentstack Import
|
|
3
|
-
* Copyright (c) 2024 Contentstack LLC
|
|
4
|
-
* MIT Licensed
|
|
5
|
-
*/
|
|
6
|
-
const fs = require('fs');
|
|
7
|
-
const _ = require('lodash');
|
|
8
|
-
const path = require('path');
|
|
9
|
-
const chalk = require('chalk');
|
|
10
|
-
const mkdirp = require('mkdirp');
|
|
11
|
-
const Promise = require('bluebird');
|
|
12
|
-
let { default: config } = require('../../config');
|
|
13
|
-
const { fileHelper, log, uploadAssetHelper } = require('../../utils');
|
|
14
|
-
const { sanitizePath, validateUids, validateFileName } = require('@contentstack/cli-utilities');
|
|
15
|
-
module.exports = class ImportAssets {
|
|
16
|
-
constructor(importConfig, stackAPIClient) {
|
|
17
|
-
this.fails = [];
|
|
18
|
-
this.uidMapping = {};
|
|
19
|
-
this.urlMapping = {};
|
|
20
|
-
this.assetBucket = [];
|
|
21
|
-
this.folderBucket = [];
|
|
22
|
-
this.folderDetails = [];
|
|
23
|
-
this.mappedFolderUids = {};
|
|
24
|
-
this.config = _.merge(config, importConfig);
|
|
25
|
-
this.stackAPIClient = stackAPIClient;
|
|
26
|
-
this.assetConfig = config.modules['assets-old'];
|
|
27
|
-
this.assetBatchLimit =
|
|
28
|
-
this.assetConfig.hasOwnProperty('assetBatchLimit') && typeof this.assetConfig.assetBatchLimit === 'number'
|
|
29
|
-
? this.assetConfig.assetBatchLimit
|
|
30
|
-
: 2;
|
|
31
|
-
}
|
|
32
|
-
start() {
|
|
33
|
-
let self = this;
|
|
34
|
-
log(self.config, 'Migrating assets', 'success');
|
|
35
|
-
this.assetsFolderPath = path.join(this.config.data, this.assetConfig.dirName);
|
|
36
|
-
this.mapperDirPath = path.resolve(this.config.data, 'mapper', 'assets');
|
|
37
|
-
this.environmentPath = path.resolve(this.config.data, 'environments', 'environments.json');
|
|
38
|
-
this.uidMapperPath = path.join(this.mapperDirPath, 'uid-mapping.json');
|
|
39
|
-
this.urlMapperPath = path.join(this.mapperDirPath, 'url-mapping.json');
|
|
40
|
-
this.failsPath = path.join(this.mapperDirPath, 'fail.json');
|
|
41
|
-
this.assets = fileHelper.readFileSync(path.join(this.assetsFolderPath, this.assetConfig.fileName));
|
|
42
|
-
this.environment = fileHelper.readFileSync(this.environmentPath);
|
|
43
|
-
if (fs.existsSync(this.uidMapperPath)) {
|
|
44
|
-
this.uidMapping = fileHelper.readFileSync(this.uidMapperPath);
|
|
45
|
-
}
|
|
46
|
-
if (fs.existsSync(this.urlMapperPath)) {
|
|
47
|
-
this.urlMapping = fileHelper.readFileSync(this.urlMapperPath);
|
|
48
|
-
}
|
|
49
|
-
mkdirp.sync(this.mapperDirPath);
|
|
50
|
-
return new Promise(function (resolve, reject) {
|
|
51
|
-
if (self.assets === undefined || _.isEmpty(self.assets)) {
|
|
52
|
-
log(self.config, 'No Assets Found', 'success');
|
|
53
|
-
return resolve({ empty: true });
|
|
54
|
-
}
|
|
55
|
-
let batches = [];
|
|
56
|
-
let assetUids = Object.keys(self.assets);
|
|
57
|
-
for (let i = 0; i < assetUids.length; i += self.assetBatchLimit) {
|
|
58
|
-
batches.push(assetUids.slice(i, i + self.assetBatchLimit));
|
|
59
|
-
}
|
|
60
|
-
return self
|
|
61
|
-
.importFolders()
|
|
62
|
-
.then(function () {
|
|
63
|
-
return Promise.map(batches, async function (batch, index) {
|
|
64
|
-
return Promise.map(batch, function (assetUid) {
|
|
65
|
-
if (self.uidMapping.hasOwnProperty(assetUid)) {
|
|
66
|
-
log(self.config, 'Skipping upload of asset: ' + assetUid + '. Its mapped to: ' + self.uidMapping[assetUid], 'success');
|
|
67
|
-
// the asset has been already imported
|
|
68
|
-
return void 0;
|
|
69
|
-
}
|
|
70
|
-
if (!validateUids(assetUid)) {
|
|
71
|
-
reject(`UID Not Valid`);
|
|
72
|
-
}
|
|
73
|
-
let currentAssetFolderPath = path.join(sanitizePath(self.assetsFolderPath), sanitizePath(assetUid));
|
|
74
|
-
if (fs.existsSync(currentAssetFolderPath)) {
|
|
75
|
-
// if this is true, means, the exported asset data is versioned
|
|
76
|
-
// hence, upload each asset with its version
|
|
77
|
-
if (self.config.versioning) {
|
|
78
|
-
return self.uploadVersionedAssets(assetUid, currentAssetFolderPath).catch(function (error) {
|
|
79
|
-
log(self.config, 'Asset upload failed \n' + error, 'error');
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
let uidContainer = {};
|
|
83
|
-
let urlContainer = {};
|
|
84
|
-
if (!validateFileName(self.assets[assetUid].filename)) {
|
|
85
|
-
reject(`File Name Not Valid`);
|
|
86
|
-
}
|
|
87
|
-
let assetPath = path.resolve(sanitizePath(currentAssetFolderPath), sanitizePath(self.assets[assetUid].filename));
|
|
88
|
-
if (self.assets[assetUid].parent_uid && typeof self.assets[assetUid].parent_uid === 'string') {
|
|
89
|
-
if (self.mappedFolderUids.hasOwnProperty(self.assets[assetUid].parent_uid)) {
|
|
90
|
-
self.assets[assetUid].parent_uid = self.mappedFolderUids[self.assets[assetUid].parent_uid];
|
|
91
|
-
}
|
|
92
|
-
else {
|
|
93
|
-
log(self.config, `'${self.assets[assetUid].parent_uid}' parent_uid was not found! Thus, setting it as 'null'`, 'error');
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
return self
|
|
97
|
-
.uploadAsset(assetPath, self.assets[assetUid], uidContainer, urlContainer)
|
|
98
|
-
.then(async function () {
|
|
99
|
-
self.uidMapping[assetUid] = uidContainer[assetUid];
|
|
100
|
-
self.urlMapping[self.assets[assetUid].url] = urlContainer[self.assets[assetUid].url];
|
|
101
|
-
if (self.config.entriesPublish && self.assets[assetUid].publish_details.length > 0) {
|
|
102
|
-
let assetsUid = uidContainer[assetUid];
|
|
103
|
-
try {
|
|
104
|
-
return await self.publish(assetsUid, self.assets[assetUid]);
|
|
105
|
-
}
|
|
106
|
-
catch (error) {
|
|
107
|
-
return error;
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
// assetUid has been successfully uploaded
|
|
111
|
-
// log them onto /mapper/assets/success.json
|
|
112
|
-
})
|
|
113
|
-
.catch(function (error) {
|
|
114
|
-
log(self.config, 'Asset upload failed \n' + error, 'error');
|
|
115
|
-
return error;
|
|
116
|
-
// asset failed to upload
|
|
117
|
-
// log them onto /mapper/assets/fail.json
|
|
118
|
-
});
|
|
119
|
-
}
|
|
120
|
-
log(self.config, `'${currentAssetFolderPath}' does not exist!`, 'error');
|
|
121
|
-
}, { concurrency: self.assetConfig.assetBatchLimit }).then(function () {
|
|
122
|
-
fileHelper.writeFileSync(self.uidMapperPath, self.uidMapping);
|
|
123
|
-
fileHelper.writeFileSync(self.urlMapperPath, self.urlMapping);
|
|
124
|
-
// completed uploading assets
|
|
125
|
-
log(self.config, 'Completed asset import of batch no: ' + (index + 1), 'success');
|
|
126
|
-
return index + 1;
|
|
127
|
-
// TODO: if there are failures, retry
|
|
128
|
-
});
|
|
129
|
-
}, { concurrency: 1 })
|
|
130
|
-
.then(function () {
|
|
131
|
-
let numberOfSuccessfulAssetUploads = Object.keys(self.uidMapping).length;
|
|
132
|
-
if (numberOfSuccessfulAssetUploads > 0) {
|
|
133
|
-
log(self.config, chalk.green(numberOfSuccessfulAssetUploads + ' assets uploaded successfully!'), 'success');
|
|
134
|
-
}
|
|
135
|
-
// TODO: if there are failures, retry
|
|
136
|
-
return resolve();
|
|
137
|
-
})
|
|
138
|
-
.catch(function (error) {
|
|
139
|
-
log(self.config, error, 'error');
|
|
140
|
-
return reject(error);
|
|
141
|
-
});
|
|
142
|
-
})
|
|
143
|
-
.catch(function (error) {
|
|
144
|
-
log(self.config, error, 'error');
|
|
145
|
-
return reject(error);
|
|
146
|
-
});
|
|
147
|
-
});
|
|
148
|
-
}
|
|
149
|
-
uploadVersionedAssets(uid, assetFolderPath) {
|
|
150
|
-
let self = this;
|
|
151
|
-
return new Promise(function (resolve, reject) {
|
|
152
|
-
if (!validateUids(uid)) {
|
|
153
|
-
reject(`UID not valid`);
|
|
154
|
-
}
|
|
155
|
-
let versionedAssetMetadata = fileHelper.readFileSync(path.join(sanitizePath(assetFolderPath), '_contentstack_' + sanitizePath(uid) + '.json'));
|
|
156
|
-
// using last version, find asset's parent
|
|
157
|
-
let lastVersion = versionedAssetMetadata[versionedAssetMetadata.length - 1];
|
|
158
|
-
if (typeof lastVersion.parent_uid === 'string') {
|
|
159
|
-
if (self.mappedFolderUids.hasOwnProperty(lastVersion.parent_uid)) {
|
|
160
|
-
// update each version of that asset with the last version's parent_uid
|
|
161
|
-
versionedAssetMetadata.forEach(function (assetMetadata) {
|
|
162
|
-
assetMetadata.parent_uid = self.mappedFolderUids[lastVersion.parent_uid];
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
log(self.config, (lastVersion.parent_uid + " parent_uid was not found! Thus, setting it as 'null'", 'error'));
|
|
167
|
-
versionedAssetMetadata.forEach(function (assetMetadata) {
|
|
168
|
-
assetMetadata.parent_uid = null;
|
|
169
|
-
});
|
|
170
|
-
}
|
|
171
|
-
}
|
|
172
|
-
let counter = 0;
|
|
173
|
-
let uidContainer = {};
|
|
174
|
-
let urlContainer = {};
|
|
175
|
-
let filesStreamed = [];
|
|
176
|
-
return Promise.map(versionedAssetMetadata, function () {
|
|
177
|
-
let assetMetadata = versionedAssetMetadata[counter];
|
|
178
|
-
if (!validateFileName(assetMetadata.filename)) {
|
|
179
|
-
reject(`File Name not valid`);
|
|
180
|
-
}
|
|
181
|
-
let assetPath = path.join(sanitizePath(assetFolderPath), sanitizePath(assetMetadata.filename));
|
|
182
|
-
if (++counter === 1) {
|
|
183
|
-
return self
|
|
184
|
-
.uploadAsset(assetPath, assetMetadata, uidContainer, urlContainer)
|
|
185
|
-
.then(function () {
|
|
186
|
-
filesStreamed.push(assetMetadata.filename);
|
|
187
|
-
})
|
|
188
|
-
.catch((error) => {
|
|
189
|
-
log(self.config, error, 'error');
|
|
190
|
-
reject(error);
|
|
191
|
-
});
|
|
192
|
-
}
|
|
193
|
-
return self
|
|
194
|
-
.updateAsset(assetPath, assetMetadata, filesStreamed, uidContainer, urlContainer)
|
|
195
|
-
.then(function () {
|
|
196
|
-
filesStreamed.push(assetMetadata.filename);
|
|
197
|
-
})
|
|
198
|
-
.catch((error) => {
|
|
199
|
-
log(self.config, error, 'error');
|
|
200
|
-
});
|
|
201
|
-
}, { concurrency: self.assetConfig.uploadAssetsConcurrency })
|
|
202
|
-
.then(function () {
|
|
203
|
-
self.uidMapping[uid] = uidContainer[uid];
|
|
204
|
-
for (let url in urlContainer) {
|
|
205
|
-
self.urlMapping[url] = urlContainer[url];
|
|
206
|
-
}
|
|
207
|
-
// completed uploading all the versions of the asset
|
|
208
|
-
return resolve();
|
|
209
|
-
})
|
|
210
|
-
.catch(function (error) {
|
|
211
|
-
// failed to upload asset
|
|
212
|
-
// write it on fail logs, but do not stop the process
|
|
213
|
-
log(self.config, 'Failed to upload asset\n' + error, 'error');
|
|
214
|
-
return resolve();
|
|
215
|
-
});
|
|
216
|
-
});
|
|
217
|
-
}
|
|
218
|
-
updateAsset(assetPath, metadata, filesStreamed, _uidContainer, urlContainer) {
|
|
219
|
-
const self = this;
|
|
220
|
-
return new Promise(function (resolve, reject) {
|
|
221
|
-
let requestOption = {};
|
|
222
|
-
if (filesStreamed && filesStreamed.indexOf(metadata.filename) !== -1) {
|
|
223
|
-
log(self.config, 'Skipping re-upload/streaming of ' + metadata.uid + '/' + metadata.filename, 'success');
|
|
224
|
-
requestOption.formData = {};
|
|
225
|
-
return resolve();
|
|
226
|
-
}
|
|
227
|
-
log(self.config, 'Streaming: ' + metadata.uid + '/' + metadata.filename, 'success');
|
|
228
|
-
requestOption.formData = {};
|
|
229
|
-
if (metadata.hasOwnProperty('parent_uid') && typeof metadata.parent_uid === 'string') {
|
|
230
|
-
requestOption.formData['asset[parent_uid]'] = metadata.parent_uid;
|
|
231
|
-
}
|
|
232
|
-
if (metadata.hasOwnProperty('description') && typeof metadata.description === 'string') {
|
|
233
|
-
requestOption.formData['asset[description]'] = metadata.description;
|
|
234
|
-
}
|
|
235
|
-
if (metadata.hasOwnProperty('tags') && Array.isArray(metadata.tags)) {
|
|
236
|
-
requestOption.formData['asset[tags]'] = metadata.tags;
|
|
237
|
-
}
|
|
238
|
-
if (metadata.hasOwnProperty('title') && typeof metadata.title === 'string') {
|
|
239
|
-
requestOption.formData['asset[title]'] = metadata.title;
|
|
240
|
-
}
|
|
241
|
-
return uploadAssetHelper(self.config, requestOption, assetPath)
|
|
242
|
-
.then(function (response) {
|
|
243
|
-
urlContainer[metadata.url] = response.url;
|
|
244
|
-
return resolve();
|
|
245
|
-
})
|
|
246
|
-
.catch(function (error) {
|
|
247
|
-
log(self.config, error, 'error');
|
|
248
|
-
return reject(error);
|
|
249
|
-
});
|
|
250
|
-
});
|
|
251
|
-
}
|
|
252
|
-
uploadAsset(assetPath, metadata, uidContainer, urlContainer) {
|
|
253
|
-
const self = this;
|
|
254
|
-
return new Promise(function (resolve, reject) {
|
|
255
|
-
let requestOption = {};
|
|
256
|
-
if (metadata.hasOwnProperty('parent_uid') && typeof metadata.parent_uid === 'string') {
|
|
257
|
-
requestOption.parent_uid = metadata.parent_uid;
|
|
258
|
-
}
|
|
259
|
-
if (metadata.hasOwnProperty('description') && typeof metadata.description === 'string') {
|
|
260
|
-
requestOption.description = metadata.description;
|
|
261
|
-
}
|
|
262
|
-
// eslint-disable-next-line no-prototype-builtins
|
|
263
|
-
if (metadata.hasOwnProperty('tags') && Array.isArray(metadata.tags)) {
|
|
264
|
-
requestOption.tags = metadata.tags;
|
|
265
|
-
}
|
|
266
|
-
if (metadata.hasOwnProperty('title') && typeof metadata.title === 'string') {
|
|
267
|
-
requestOption.title = metadata.title;
|
|
268
|
-
}
|
|
269
|
-
return uploadAssetHelper(self.config, requestOption, assetPath)
|
|
270
|
-
.then(function (response) {
|
|
271
|
-
uidContainer[metadata.uid] = response.uid;
|
|
272
|
-
urlContainer[metadata.url] = response.url;
|
|
273
|
-
return resolve();
|
|
274
|
-
})
|
|
275
|
-
.catch(function (error) {
|
|
276
|
-
log(self.config, error, 'error');
|
|
277
|
-
return reject(error);
|
|
278
|
-
});
|
|
279
|
-
});
|
|
280
|
-
}
|
|
281
|
-
importFolders() {
|
|
282
|
-
let self = this;
|
|
283
|
-
return new Promise(function (resolve, reject) {
|
|
284
|
-
let mappedFolderPath = path.resolve(self.config.data, 'mapper', 'assets', 'folder-mapping.json');
|
|
285
|
-
self.folderDetails = fileHelper.readFileSync(path.resolve(self.assetsFolderPath, 'folders.json'));
|
|
286
|
-
if (_.isEmpty(self.folderDetails)) {
|
|
287
|
-
log(self.config, 'No folders were found at: ' + path.join(self.assetsFolderPath, 'folders.json'), 'success');
|
|
288
|
-
return resolve();
|
|
289
|
-
}
|
|
290
|
-
let tree = self.buildTree(_.cloneDeep(self.folderDetails));
|
|
291
|
-
let createdFolders = {};
|
|
292
|
-
let createdFolderUids = [];
|
|
293
|
-
// if a few folders have already been created, skip re-creating them
|
|
294
|
-
if (fs.existsSync(mappedFolderPath)) {
|
|
295
|
-
createdFolders = fileHelper.readFileSync(mappedFolderPath);
|
|
296
|
-
// check if the read file has mapped objects
|
|
297
|
-
if (_.isPlainObject(createdFolders)) {
|
|
298
|
-
createdFolderUids = Object.keys(createdFolders);
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
self.buildFolderReqObjs(createdFolderUids, tree, null);
|
|
302
|
-
let idx = 0;
|
|
303
|
-
return Promise.map(self.folderBucket, function () {
|
|
304
|
-
let folder = self.folderBucket[idx];
|
|
305
|
-
if (createdFolders.hasOwnProperty(folder.json.asset.parent_uid)) {
|
|
306
|
-
// replace old uid with new
|
|
307
|
-
folder.json.asset.parent_uid = createdFolders[folder.json.asset.parent_uid];
|
|
308
|
-
}
|
|
309
|
-
return self.stackAPIClient
|
|
310
|
-
.asset()
|
|
311
|
-
.folder()
|
|
312
|
-
.create(folder.json)
|
|
313
|
-
.then((response) => {
|
|
314
|
-
log(self.config, "Created folder: '" + folder.json.asset.name + "'", 'success');
|
|
315
|
-
// assigning newUid to oldUid
|
|
316
|
-
createdFolders[folder.oldUid] = response.uid;
|
|
317
|
-
fileHelper.writeFileSync(mappedFolderPath, createdFolders);
|
|
318
|
-
idx++;
|
|
319
|
-
})
|
|
320
|
-
.catch(function (err) {
|
|
321
|
-
let error = JSON.parse(err.message);
|
|
322
|
-
if (error.errors.authorization || error.errors.api_key) {
|
|
323
|
-
log(self.config, 'Api_key or management_token is not valid', 'error');
|
|
324
|
-
return reject(error);
|
|
325
|
-
}
|
|
326
|
-
log(self.config, err, 'error');
|
|
327
|
-
return error;
|
|
328
|
-
});
|
|
329
|
-
}, { concurrency: self.assetConfig.importFoldersConcurrency })
|
|
330
|
-
.then(function () {
|
|
331
|
-
self.mappedFolderUids = fileHelper.readFileSync(mappedFolderPath);
|
|
332
|
-
// completed creating folders
|
|
333
|
-
return resolve();
|
|
334
|
-
})
|
|
335
|
-
.catch(function (error) {
|
|
336
|
-
log(self.config, error, 'error');
|
|
337
|
-
return reject(error);
|
|
338
|
-
});
|
|
339
|
-
});
|
|
340
|
-
}
|
|
341
|
-
buildFolderReqObjs(createdFolderUids, tree, parent_uid) {
|
|
342
|
-
let self = this;
|
|
343
|
-
for (let leaf in tree) {
|
|
344
|
-
// if the folder is already created, skip
|
|
345
|
-
if (createdFolderUids.indexOf(leaf) !== -1) {
|
|
346
|
-
continue;
|
|
347
|
-
}
|
|
348
|
-
let folderObj = _.find(self.folderDetails, { uid: leaf });
|
|
349
|
-
let requestOption = {
|
|
350
|
-
json: {
|
|
351
|
-
asset: {
|
|
352
|
-
name: folderObj.name,
|
|
353
|
-
parent_uid: parent_uid || null,
|
|
354
|
-
},
|
|
355
|
-
},
|
|
356
|
-
oldUid: leaf,
|
|
357
|
-
};
|
|
358
|
-
self.folderBucket.push(requestOption);
|
|
359
|
-
if (Object.keys(tree[leaf]).length > 0) {
|
|
360
|
-
self.buildFolderReqObjs(createdFolderUids, tree[leaf], leaf);
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
}
|
|
364
|
-
buildTree(coll) {
|
|
365
|
-
let tree = {};
|
|
366
|
-
for (let i = 0; i < coll.length; i++) {
|
|
367
|
-
if (coll[i].parent_uid === null || !coll[i].hasOwnProperty('parent_uid')) {
|
|
368
|
-
tree[coll[i].uid] = {};
|
|
369
|
-
coll.splice(i, 1);
|
|
370
|
-
i--;
|
|
371
|
-
}
|
|
372
|
-
}
|
|
373
|
-
this.findBranches(tree, _.keys(tree), coll);
|
|
374
|
-
return tree;
|
|
375
|
-
}
|
|
376
|
-
findBranches(tree, branches, coll) {
|
|
377
|
-
let self = this;
|
|
378
|
-
_.forEach(branches, (branch) => {
|
|
379
|
-
for (const element of coll) {
|
|
380
|
-
if (branch === element.parent_uid) {
|
|
381
|
-
let childUid = element.uid;
|
|
382
|
-
tree[branch][childUid] = {};
|
|
383
|
-
self.findBranches(tree[branch], [childUid], coll);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
});
|
|
387
|
-
}
|
|
388
|
-
publish(assetUid, assetObject) {
|
|
389
|
-
let envId = [];
|
|
390
|
-
let self = this;
|
|
391
|
-
let locales = [];
|
|
392
|
-
let requestObject = { json: { asset: {} } };
|
|
393
|
-
return new Promise(function (resolve, reject) {
|
|
394
|
-
_.forEach(assetObject.publish_details, function (pubObject) {
|
|
395
|
-
if (self.environment.hasOwnProperty(pubObject.environment)) {
|
|
396
|
-
envId.push(self.environment[pubObject.environment].name);
|
|
397
|
-
let idx = _.indexOf(locales, pubObject.locale);
|
|
398
|
-
if (idx === -1) {
|
|
399
|
-
locales.push(pubObject.locale);
|
|
400
|
-
}
|
|
401
|
-
}
|
|
402
|
-
});
|
|
403
|
-
requestObject.json.asset.environments = envId;
|
|
404
|
-
requestObject.json.asset.locales = locales;
|
|
405
|
-
return self.stackAPIClient
|
|
406
|
-
.asset(assetUid)
|
|
407
|
-
.publish({ publishDetails: requestObject.json.asset })
|
|
408
|
-
.then(function () {
|
|
409
|
-
log(self.config, 'Asset ' + assetUid + ' published successfully', 'success');
|
|
410
|
-
return resolve();
|
|
411
|
-
})
|
|
412
|
-
.catch(function (err) {
|
|
413
|
-
if (err && err.message) {
|
|
414
|
-
let error;
|
|
415
|
-
try {
|
|
416
|
-
error = JSON.parse(err.message);
|
|
417
|
-
}
|
|
418
|
-
catch (cError) {
|
|
419
|
-
error = { errorMessage: err.message };
|
|
420
|
-
}
|
|
421
|
-
log(self.config, 'Asset ' + assetUid + ' not published, ' + error.errorMessage, 'error');
|
|
422
|
-
return reject(err);
|
|
423
|
-
}
|
|
424
|
-
return reject(err);
|
|
425
|
-
});
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
};
|
|
@@ -1,34 +0,0 @@
|
|
|
1
|
-
export = ContentTypesImport;
|
|
2
|
-
declare class ContentTypesImport {
|
|
3
|
-
constructor(importConfig: any, stackAPIClient: any);
|
|
4
|
-
stackAPIClient: any;
|
|
5
|
-
importConfig: any;
|
|
6
|
-
contentTypeConfig: any;
|
|
7
|
-
globalFieldConfig: any;
|
|
8
|
-
importConcurrency: any;
|
|
9
|
-
writeConcurrency: any;
|
|
10
|
-
contentTypesFolderPath: string;
|
|
11
|
-
mapperFolderPath: string;
|
|
12
|
-
existingContentTypesPath: string;
|
|
13
|
-
globalFieldsFolderPath: string;
|
|
14
|
-
globalFieldMapperFolderPath: string;
|
|
15
|
-
globalFieldPendingPath: string;
|
|
16
|
-
ignoredFilesInContentTypesFolder: Map<string, string>;
|
|
17
|
-
contentTypes: any[];
|
|
18
|
-
existingContentTypesUIds: any[];
|
|
19
|
-
titleToUIdMap: Map<any, any>;
|
|
20
|
-
requestOptions: {
|
|
21
|
-
json: {};
|
|
22
|
-
};
|
|
23
|
-
fieldRules: any[];
|
|
24
|
-
installedExtensions: any[];
|
|
25
|
-
globalFields: any[];
|
|
26
|
-
existingGlobalFields: any[];
|
|
27
|
-
pendingGlobalFields: any[];
|
|
28
|
-
start(): Promise<void>;
|
|
29
|
-
seedContentType(contentType: any): Promise<boolean>;
|
|
30
|
-
updateContentType(contentType: any): Promise<void>;
|
|
31
|
-
updateGlobalFields(uid: any): Promise<boolean>;
|
|
32
|
-
mapUidToTitle(): Promise<void>;
|
|
33
|
-
updateFieldRules(contentType: any): any[];
|
|
34
|
-
}
|