@contentstack/cli-cm-import-setup 1.0.0-beta.1

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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +115 -0
  3. package/bin/dev.cmd +3 -0
  4. package/bin/dev.js +6 -0
  5. package/bin/run.cmd +3 -0
  6. package/bin/run.js +7 -0
  7. package/lib/commands/cm/stacks/import-setup.d.ts +10 -0
  8. package/lib/commands/cm/stacks/import-setup.js +53 -0
  9. package/lib/config/index.d.ts +3 -0
  10. package/lib/config/index.js +77 -0
  11. package/lib/import/import-setup.d.ts +32 -0
  12. package/lib/import/import-setup.js +112 -0
  13. package/lib/import/index.d.ts +1 -0
  14. package/lib/import/index.js +8 -0
  15. package/lib/import/modules/assets.d.ts +27 -0
  16. package/lib/import/modules/assets.js +102 -0
  17. package/lib/import/modules/base-setup.d.ts +37 -0
  18. package/lib/import/modules/base-setup.js +183 -0
  19. package/lib/import/modules/content-types.d.ts +6 -0
  20. package/lib/import/modules/content-types.js +20 -0
  21. package/lib/import/modules/custom-roles.d.ts +0 -0
  22. package/lib/import/modules/custom-roles.js +0 -0
  23. package/lib/import/modules/entries.d.ts +6 -0
  24. package/lib/import/modules/entries.js +20 -0
  25. package/lib/import/modules/extensions.d.ts +20 -0
  26. package/lib/import/modules/extensions.js +61 -0
  27. package/lib/import/modules/global-fields.d.ts +0 -0
  28. package/lib/import/modules/global-fields.js +0 -0
  29. package/lib/import/modules/index.d.ts +0 -0
  30. package/lib/import/modules/index.js +0 -0
  31. package/lib/import/modules/marketplace-apps.d.ts +26 -0
  32. package/lib/import/modules/marketplace-apps.js +81 -0
  33. package/lib/import/modules/taxonomies.d.ts +53 -0
  34. package/lib/import/modules/taxonomies.js +141 -0
  35. package/lib/types/default-config.d.ts +55 -0
  36. package/lib/types/default-config.js +2 -0
  37. package/lib/types/import-config.d.ts +55 -0
  38. package/lib/types/import-config.js +2 -0
  39. package/lib/types/index.d.ts +115 -0
  40. package/lib/types/index.js +2 -0
  41. package/lib/utils/backup-handler.d.ts +2 -0
  42. package/lib/utils/backup-handler.js +61 -0
  43. package/lib/utils/common-helper.d.ts +0 -0
  44. package/lib/utils/common-helper.js +0 -0
  45. package/lib/utils/file-helper.d.ts +15 -0
  46. package/lib/utils/file-helper.js +144 -0
  47. package/lib/utils/import-config-handler.d.ts +3 -0
  48. package/lib/utils/import-config-handler.js +91 -0
  49. package/lib/utils/index.d.ts +7 -0
  50. package/lib/utils/index.js +16 -0
  51. package/lib/utils/interactive.d.ts +3 -0
  52. package/lib/utils/interactive.js +38 -0
  53. package/lib/utils/log.d.ts +12 -0
  54. package/lib/utils/log.js +31 -0
  55. package/lib/utils/logger.d.ts +8 -0
  56. package/lib/utils/logger.js +157 -0
  57. package/lib/utils/login-handler.d.ts +8 -0
  58. package/lib/utils/login-handler.js +53 -0
  59. package/messages/index.json +1 -0
  60. package/oclif.manifest.json +56 -0
  61. package/package.json +96 -0
@@ -0,0 +1,183 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ const utils_1 = require("../../utils");
27
+ const lodash_1 = require("lodash");
28
+ class BaseImportSetup {
29
+ constructor({ config, stackAPIClient, dependencies }) {
30
+ this.config = config;
31
+ this.stackAPIClient = stackAPIClient;
32
+ this.dependencies = dependencies;
33
+ }
34
+ async setupDependencies() {
35
+ var _a;
36
+ for (const moduleName of this.dependencies) {
37
+ try {
38
+ const modulePath = `./${moduleName}`;
39
+ const { default: ModuleClass } = await (_a = modulePath, Promise.resolve().then(() => __importStar(require(_a))));
40
+ const modulePayload = {
41
+ config: this.config,
42
+ stackAPIClient: this.stackAPIClient,
43
+ };
44
+ const moduleInstance = new ModuleClass(modulePayload);
45
+ await moduleInstance.start();
46
+ }
47
+ catch (error) {
48
+ (0, utils_1.log)(this.config, `Error importing '${moduleName}': ${error.message}`, 'error');
49
+ }
50
+ }
51
+ }
52
+ /**
53
+ * @method delay
54
+ * @param {number} ms number
55
+ * @returns {Promise} Promise<void>
56
+ */
57
+ delay(ms) {
58
+ /* eslint-disable no-promise-executor-return */
59
+ return new Promise((resolve) => setTimeout(resolve, ms <= 0 ? 0 : ms));
60
+ }
61
+ /**
62
+ * @method makeConcurrentCall
63
+ * @param {Record<string, any>} env EnvType
64
+ * @param {CustomPromiseHandler} promisifyHandler CustomPromiseHandler
65
+ * @param {boolean} logBatchCompletionMsg boolean
66
+ * @returns {Promise} Promise<void>
67
+ */
68
+ makeConcurrentCall(env, promisifyHandler, logBatchCompletionMsg = true) {
69
+ const { apiParams, apiContent, processName, indexerCount, currentIndexer, concurrencyLimit = this.config.fetchConcurrency, } = env;
70
+ /* eslint-disable no-async-promise-executor */
71
+ return new Promise(async (resolve) => {
72
+ let batchNo = 0;
73
+ let isLastRequest = false;
74
+ const batches = (0, lodash_1.chunk)(apiContent, concurrencyLimit);
75
+ /* eslint-disable no-promise-executor-return */
76
+ if ((0, lodash_1.isEmpty)(batches))
77
+ return resolve();
78
+ for (const [batchIndex, batch] of (0, lodash_1.entries)(batches)) {
79
+ batchNo += 1;
80
+ const allPromise = [];
81
+ const start = Date.now();
82
+ for (const [index, element] of (0, lodash_1.entries)(batch)) {
83
+ let promise = Promise.resolve();
84
+ isLastRequest = (0, lodash_1.isEqual)((0, lodash_1.last)(batch), element) && (0, lodash_1.isEqual)((0, lodash_1.last)(batches), batch);
85
+ if (promisifyHandler instanceof Function) {
86
+ promise = promisifyHandler({
87
+ apiParams,
88
+ isLastRequest,
89
+ element,
90
+ index: Number(index),
91
+ batchIndex: Number(batchIndex),
92
+ });
93
+ }
94
+ else if (apiParams) {
95
+ apiParams.apiData = element;
96
+ promise = this.makeAPICall(apiParams, isLastRequest);
97
+ }
98
+ allPromise.push(promise);
99
+ }
100
+ /* eslint-disable no-await-in-loop */
101
+ await Promise.allSettled(allPromise);
102
+ /* eslint-disable no-await-in-loop */
103
+ await this.logMsgAndWaitIfRequired(processName, start, batches.length, batchNo, logBatchCompletionMsg, indexerCount, currentIndexer);
104
+ if (isLastRequest)
105
+ resolve();
106
+ }
107
+ });
108
+ }
109
+ /**
110
+ * @method logMsgAndWaitIfRequired
111
+ * @param {string} processName string
112
+ * @param {number} start number
113
+ * @param {number} batchNo - number
114
+ * @returns {Promise} Promise<void>
115
+ */
116
+ async logMsgAndWaitIfRequired(processName, start, totelBatches, batchNo, logBatchCompletionMsg = true, indexerCount, currentIndexer) {
117
+ const end = Date.now();
118
+ const exeTime = end - start;
119
+ if (logBatchCompletionMsg) {
120
+ let batchMsg = '';
121
+ // info: Batch No. 20 of import assets is complete
122
+ if (currentIndexer)
123
+ batchMsg += `Current chunk processing is (${currentIndexer}/${indexerCount})`;
124
+ (0, utils_1.log)(this.config, `Batch No. (${batchNo}/${totelBatches}) of ${processName} is complete`, 'success');
125
+ }
126
+ // if (this.config.modules.assets.displayExecutionTime) {
127
+ // console.log(
128
+ // `Time taken to execute: ${exeTime} milliseconds; wait time: ${
129
+ // exeTime < 1000 ? 1000 - exeTime : 0
130
+ // } milliseconds`,
131
+ // );
132
+ // }
133
+ if (exeTime < 1000)
134
+ await this.delay(1000 - exeTime);
135
+ }
136
+ /**
137
+ * @method makeAPICall
138
+ * @param {Record<string, any>} apiOptions - Api related params
139
+ * @param {Record<string, any>} isLastRequest - Boolean
140
+ * @return {Promise} Promise<void>
141
+ */
142
+ makeAPICall(apiOptions, isLastRequest = false) {
143
+ if (apiOptions.serializeData instanceof Function) {
144
+ apiOptions = apiOptions.serializeData(apiOptions);
145
+ }
146
+ const { uid, entity, reject, resolve, apiData, additionalInfo = {}, includeParamOnCompletion } = apiOptions;
147
+ const onSuccess = (response) => resolve({
148
+ response,
149
+ isLastRequest,
150
+ additionalInfo,
151
+ apiData: includeParamOnCompletion ? apiData : undefined,
152
+ });
153
+ const onReject = (error) => reject({
154
+ error,
155
+ isLastRequest,
156
+ additionalInfo,
157
+ apiData: includeParamOnCompletion ? apiData : undefined,
158
+ });
159
+ if (!apiData) {
160
+ return Promise.resolve();
161
+ }
162
+ switch (entity) {
163
+ case 'fetch-assets':
164
+ return this.stackAPIClient
165
+ .asset()
166
+ .query({
167
+ query: {
168
+ $and: [
169
+ { file_size: Number(apiData.file_size) },
170
+ { filename: apiData.filename },
171
+ { title: apiData.title },
172
+ ],
173
+ },
174
+ })
175
+ .find()
176
+ .then(onSuccess)
177
+ .catch(onReject);
178
+ default:
179
+ return Promise.resolve();
180
+ }
181
+ }
182
+ }
183
+ exports.default = BaseImportSetup;
@@ -0,0 +1,6 @@
1
+ import { ModuleClassParams } from '../../types';
2
+ import BaseImportSetup from './base-setup';
3
+ export default class ContentTypesImportSetup extends BaseImportSetup {
4
+ constructor(options: ModuleClassParams);
5
+ start(): Promise<void>;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const utils_1 = require("../../utils");
5
+ const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
6
+ class ContentTypesImportSetup extends base_setup_1.default {
7
+ constructor(options) {
8
+ super(options);
9
+ }
10
+ async start() {
11
+ try {
12
+ await this.setupDependencies();
13
+ (0, utils_1.log)(this.config, `Generate required setup files for content types`, 'success');
14
+ }
15
+ catch (error) {
16
+ (0, utils_1.log)(this.config, `Error generating ${error.message}`, 'error');
17
+ }
18
+ }
19
+ }
20
+ exports.default = ContentTypesImportSetup;
File without changes
File without changes
@@ -0,0 +1,6 @@
1
+ import { ModuleClassParams } from '../../types';
2
+ import BaseImportSetup from './base-setup';
3
+ export default class EntriesImportSetup extends BaseImportSetup {
4
+ constructor(options: ModuleClassParams);
5
+ start(): Promise<void>;
6
+ }
@@ -0,0 +1,20 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const utils_1 = require("../../utils");
5
+ const base_setup_1 = tslib_1.__importDefault(require("./base-setup"));
6
+ class EntriesImportSetup extends base_setup_1.default {
7
+ constructor(options) {
8
+ super(options);
9
+ }
10
+ async start() {
11
+ try {
12
+ await this.setupDependencies();
13
+ (0, utils_1.log)(this.config, `Generate required setup files for entries`, 'success');
14
+ }
15
+ catch (error) {
16
+ (0, utils_1.log)(this.config, `Error generating ${error.message}`, 'error');
17
+ }
18
+ }
19
+ }
20
+ exports.default = EntriesImportSetup;
@@ -0,0 +1,20 @@
1
+ import { ModuleClassParams } from '../../types';
2
+ export default class ExtensionImportSetup {
3
+ private config;
4
+ private extensionsFilePath;
5
+ private extensionMapper;
6
+ private stackAPIClient;
7
+ private dependencies;
8
+ private extensionsConfig;
9
+ private mapperDirPath;
10
+ private extensionsFolderPath;
11
+ private extUidMapperPath;
12
+ constructor({ config, stackAPIClient }: ModuleClassParams);
13
+ /**
14
+ * Start the extension import setup
15
+ * This method reads the extensions from the content folder and generates a mapper file
16
+ * @returns {Promise<void>}
17
+ */
18
+ start(): Promise<void>;
19
+ getExtension(extension: any): Promise<unknown>;
20
+ }
@@ -0,0 +1,61 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../../utils");
4
+ const path_1 = require("path");
5
+ const lodash_1 = require("lodash");
6
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
7
+ class ExtensionImportSetup {
8
+ constructor({ config, stackAPIClient }) {
9
+ this.config = config;
10
+ this.stackAPIClient = stackAPIClient;
11
+ this.extensionsFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'extensions', 'extensions.json');
12
+ this.extensionsConfig = config.modules.extensions;
13
+ this.extUidMapperPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'extensions', 'uid-mapping.json');
14
+ this.extensionMapper = {};
15
+ }
16
+ /**
17
+ * Start the extension import setup
18
+ * This method reads the extensions from the content folder and generates a mapper file
19
+ * @returns {Promise<void>}
20
+ */
21
+ async start() {
22
+ try {
23
+ const extensions = await utils_1.fsUtil.readFile(this.extensionsFilePath);
24
+ if (!(0, lodash_1.isEmpty)(extensions)) {
25
+ // 2. Create mapper directory
26
+ const mapperFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'extensions');
27
+ utils_1.fsUtil.makeDirectory(mapperFilePath); // Use fsUtil
28
+ for (const extension of Object.values(extensions)) {
29
+ const targetExtension = await this.getExtension(extension);
30
+ if (!targetExtension) {
31
+ (0, utils_1.log)(this.config, `Extension with title '${extension.title}' not found in the stack!`, 'info');
32
+ continue;
33
+ }
34
+ this.extensionMapper[extension.uid] = targetExtension.uid;
35
+ }
36
+ await utils_1.fsUtil.writeFile(this.extUidMapperPath, this.extensionMapper);
37
+ (0, utils_1.log)(this.config, `Generated required setup files for extension`, 'success');
38
+ }
39
+ else {
40
+ (0, utils_1.log)(this.config, 'No extensions found in the content folder!', 'error');
41
+ }
42
+ }
43
+ catch (error) {
44
+ (0, utils_1.log)(this.config, `Error generating extension mapper: ${(0, cli_utilities_1.formatError)(error)}`, 'error');
45
+ }
46
+ }
47
+ async getExtension(extension) {
48
+ // Implement this method to get the extension from the stack
49
+ return new Promise(async (resolve, reject) => {
50
+ const { items: [extensionsInStack] = [] } = (await this.stackAPIClient
51
+ .extension()
52
+ .query({ query: { title: extension.title } })
53
+ .findOne()
54
+ .catch((error) => {
55
+ reject(error);
56
+ })) || {};
57
+ resolve(extensionsInStack);
58
+ });
59
+ }
60
+ }
61
+ exports.default = ExtensionImportSetup;
File without changes
File without changes
File without changes
File without changes
@@ -0,0 +1,26 @@
1
+ import { ModuleClassParams } from '../../types';
2
+ import { ContentstackMarketplaceClient, NodeCrypto } from '@contentstack/cli-utilities';
3
+ export default class marketplaceAppImportSetup {
4
+ private config;
5
+ private marketplaceAppsFilePath;
6
+ private marketplaceAppMapper;
7
+ private stackAPIClient;
8
+ private dependencies;
9
+ private marketplaceAppsConfig;
10
+ private mapperDirPath;
11
+ private marketplaceAppsFolderPath;
12
+ private marketplaceAppsUidMapperPath;
13
+ developerHubBaseUrl: string;
14
+ marketplaceAppPath: string;
15
+ nodeCrypto: NodeCrypto;
16
+ appSdk: ContentstackMarketplaceClient;
17
+ constructor({ config, stackAPIClient }: ModuleClassParams);
18
+ /**
19
+ * Start the marketplaceApp import setup
20
+ * This method reads the marketplaceApps from the content folder and generates a mapper file
21
+ * @returns {Promise<void>}
22
+ */
23
+ start(): Promise<void>;
24
+ getMarketplaceApps(): Promise<unknown>;
25
+ createMapper(sourceMarketplaceApps: any, targetMarketplaceApps: any): void;
26
+ }
@@ -0,0 +1,81 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const utils_1 = require("../../utils");
4
+ const path_1 = require("path");
5
+ const lodash_1 = require("lodash");
6
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
7
+ class marketplaceAppImportSetup {
8
+ constructor({ config, stackAPIClient }) {
9
+ this.config = config;
10
+ this.stackAPIClient = stackAPIClient;
11
+ this.marketplaceAppsFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'marketplace_apps', 'marketplace_apps.json');
12
+ this.marketplaceAppsConfig = config.modules['marketplace-apps'];
13
+ this.marketplaceAppsUidMapperPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'marketplace_apps');
14
+ this.marketplaceAppMapper = { app_uid: {}, installation_uid: {}, extension_uid: {} };
15
+ }
16
+ /**
17
+ * Start the marketplaceApp import setup
18
+ * This method reads the marketplaceApps from the content folder and generates a mapper file
19
+ * @returns {Promise<void>}
20
+ */
21
+ async start() {
22
+ try {
23
+ const sourceMarketplaceApps = await utils_1.fsUtil.readFile(this.marketplaceAppsFilePath);
24
+ if (!(0, lodash_1.isEmpty)(sourceMarketplaceApps)) {
25
+ utils_1.fsUtil.makeDirectory(this.marketplaceAppsUidMapperPath); // Use fsUtil
26
+ this.developerHubBaseUrl = this.config.developerHubBaseUrl || (await (0, cli_utilities_1.createDeveloperHubUrl)(this.config.host));
27
+ // NOTE init marketplace app sdk
28
+ const host = this.developerHubBaseUrl.split('://').pop();
29
+ this.appSdk = await (0, cli_utilities_1.marketplaceSDKClient)({ host });
30
+ const targetMarketplaceApps = await this.getMarketplaceApps();
31
+ this.createMapper(sourceMarketplaceApps, targetMarketplaceApps);
32
+ await utils_1.fsUtil.writeFile((0, path_1.join)(this.marketplaceAppsUidMapperPath, 'uid-mapping.json'), this.marketplaceAppMapper);
33
+ (0, utils_1.log)(this.config, `Generated required setup files for marketplaceApp`, 'success');
34
+ }
35
+ else {
36
+ (0, utils_1.log)(this.config, 'No marketplaceApps found in the content folder!', 'info');
37
+ }
38
+ }
39
+ catch (error) {
40
+ (0, utils_1.log)(this.config, `Error generating marketplaceApp mapper: ${(0, cli_utilities_1.formatError)(error)}`, 'error');
41
+ }
42
+ }
43
+ async getMarketplaceApps() {
44
+ // Implement this method to get the marketplaceApp from the stack
45
+ return new Promise(async (resolve, reject) => {
46
+ const { items: marketplaceApps = [] } = (await this.appSdk
47
+ .marketplace(this.config.org_uid)
48
+ .installation()
49
+ .fetchAll({ target_uids: this.config.apiKey })
50
+ .catch((error) => {
51
+ reject(error);
52
+ })) || {};
53
+ resolve(marketplaceApps);
54
+ });
55
+ }
56
+ createMapper(sourceMarketplaceApps, targetMarketplaceApps) {
57
+ sourceMarketplaceApps.forEach((sourceApp) => {
58
+ // Find matching target item based on manifest.name
59
+ const targetApp = targetMarketplaceApps.find((targetApp) => (0, lodash_1.get)(targetApp, 'manifest.name') === (0, lodash_1.get)(sourceApp, 'manifest.name'));
60
+ if (targetApp) {
61
+ // Map app_uid from source and target
62
+ this.marketplaceAppMapper.app_uid[sourceApp.manifest.uid] = targetApp.manifest.uid;
63
+ // Map installation_uid from source and target
64
+ this.marketplaceAppMapper.installation_uid[sourceApp.installation_uid] = targetApp.installation_uid;
65
+ // Map extension_uid by comparing meta.uid in source and target's ui_location.locations
66
+ sourceApp.ui_location.locations.forEach((sourceAppLocation) => {
67
+ const targetAppLocation = targetApp.ui_location.locations.find((targetAppLocation) => targetAppLocation.type === sourceAppLocation.type);
68
+ if (targetAppLocation) {
69
+ sourceAppLocation.meta.forEach((sourceAppMeta) => {
70
+ const targetAppMeta = targetAppLocation.meta.find((targetAppMeta) => targetAppMeta.uid === sourceAppMeta.uid);
71
+ if (targetAppMeta && sourceAppMeta.extension_uid && targetAppMeta.extension_uid) {
72
+ this.marketplaceAppMapper.extension_uid[sourceAppMeta.extension_uid] = targetAppMeta.extension_uid;
73
+ }
74
+ });
75
+ }
76
+ });
77
+ }
78
+ });
79
+ }
80
+ }
81
+ exports.default = marketplaceAppImportSetup;
@@ -0,0 +1,53 @@
1
+ /// <reference types="lodash" />
2
+ import { ModuleClassParams } from '../../types';
3
+ export default class TaxonomiesImportSetup {
4
+ private config;
5
+ private taxonomiesFilePath;
6
+ private stackAPIClient;
7
+ private dependencies;
8
+ private taxonomiesConfig;
9
+ private termsSuccessPath;
10
+ private taxSuccessPath;
11
+ private taxonomiesMapperDirPath;
12
+ private termsMapperDirPath;
13
+ taxonomiesMapper: Record<string, unknown>;
14
+ termsMapper: Record<string, unknown>;
15
+ constructor({ config, stackAPIClient }: ModuleClassParams);
16
+ /**
17
+ * Start the taxonomies import setup
18
+ * This method reads the taxonomies from the content folder and generates a mapper file
19
+ * @returns {Promise<void>}
20
+ */
21
+ start(): Promise<void>;
22
+ /**
23
+ * Retrieves the taxonomies based on the provided taxonomy UID.
24
+ *
25
+ * @param taxonomy - The UID of the taxonomy to retrieve.
26
+ * @returns A promise that resolves to the retrieved taxonomies.
27
+ */
28
+ getTaxonomies(taxonomy: any): Promise<any>;
29
+ /**
30
+ * Sanitizes the attributes of a taxonomy object.
31
+ *
32
+ * @param taxonomy - The taxonomy object to sanitize.
33
+ * @returns The sanitized taxonomy object with invalid keys omitted.
34
+ */
35
+ sanitizeTaxonomyAttribs(taxonomy: Record<string, string>): import("lodash").Omit<Record<string, string>, string>;
36
+ /**
37
+ * Retrieves all terms of a taxonomy.
38
+ *
39
+ * @param taxonomy - The taxonomy object.
40
+ * @param skip - The number of terms to skip (default: 0).
41
+ * @param terms - An array to store the retrieved terms (default: []).
42
+ * @returns A promise that resolves to an array of terms.
43
+ */
44
+ getAllTermsOfTaxonomy(taxonomy: any, skip?: number, terms?: any[]): Promise<any>;
45
+ /**
46
+ * Sanitizes the attributes of the given terms.
47
+ *
48
+ * @param terms - An array of terms to sanitize.
49
+ * @returns The sanitized terms.
50
+ */
51
+ sanitizeTermsAttribs(terms: Record<string, unknown>[]): Record<string, unknown>[];
52
+ handleTaxonomyErrorMsg(err: any): void;
53
+ }
@@ -0,0 +1,141 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const tslib_1 = require("tslib");
4
+ const path_1 = require("path");
5
+ const omit_1 = tslib_1.__importDefault(require("lodash/omit"));
6
+ const isEmpty_1 = tslib_1.__importDefault(require("lodash/isEmpty"));
7
+ const utils_1 = require("../../utils");
8
+ const cli_utilities_1 = require("@contentstack/cli-utilities");
9
+ class TaxonomiesImportSetup {
10
+ constructor({ config, stackAPIClient }) {
11
+ this.taxonomiesMapper = {};
12
+ this.termsMapper = {};
13
+ this.config = config;
14
+ this.stackAPIClient = stackAPIClient;
15
+ this.taxonomiesFilePath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.contentDir), 'taxonomies', 'taxonomies.json');
16
+ this.taxonomiesConfig = config.modules.taxonomies;
17
+ this.taxonomiesMapperDirPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.config.backupDir), 'mapper', 'taxonomies');
18
+ this.taxSuccessPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.taxonomiesMapperDirPath), 'success.json');
19
+ this.termsMapperDirPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.taxonomiesMapperDirPath), 'terms');
20
+ this.termsSuccessPath = (0, path_1.join)((0, cli_utilities_1.sanitizePath)(this.termsMapperDirPath), 'success.json');
21
+ this.taxonomiesMapper = {};
22
+ this.termsMapper = {};
23
+ }
24
+ /**
25
+ * Start the taxonomies import setup
26
+ * This method reads the taxonomies from the content folder and generates a mapper file
27
+ * @returns {Promise<void>}
28
+ */
29
+ async start() {
30
+ try {
31
+ const taxonomies = utils_1.fsUtil.readFile(this.taxonomiesFilePath);
32
+ if (!(0, isEmpty_1.default)(taxonomies)) {
33
+ // 2. Create mapper directory
34
+ utils_1.fsUtil.makeDirectory(this.taxonomiesMapperDirPath);
35
+ utils_1.fsUtil.makeDirectory(this.termsMapperDirPath);
36
+ for (const taxonomy of Object.values(taxonomies)) {
37
+ let targetTaxonomy = await this.getTaxonomies(taxonomy);
38
+ if (!targetTaxonomy) {
39
+ (0, utils_1.log)(this.config, `Taxonomies with uid '${taxonomy.uid}' not found in the stack!`, 'info');
40
+ continue;
41
+ }
42
+ targetTaxonomy = this.sanitizeTaxonomyAttribs(targetTaxonomy);
43
+ this.taxonomiesMapper[taxonomy.uid] = targetTaxonomy;
44
+ const terms = await this.getAllTermsOfTaxonomy(targetTaxonomy);
45
+ const sanitizedTerms = this.sanitizeTermsAttribs(terms);
46
+ this.termsMapper[taxonomy.uid] = sanitizedTerms;
47
+ }
48
+ if (this.taxonomiesMapper !== undefined && !(0, isEmpty_1.default)(this.taxonomiesMapper)) {
49
+ utils_1.fsUtil.writeFile(this.taxSuccessPath, this.taxonomiesMapper);
50
+ }
51
+ if (this.termsMapper !== undefined && !(0, isEmpty_1.default)(this.termsMapper)) {
52
+ utils_1.fsUtil.writeFile(this.termsSuccessPath, this.termsMapper);
53
+ }
54
+ (0, utils_1.log)(this.config, `Generated required setup files for taxonomies`, 'success');
55
+ }
56
+ else {
57
+ (0, utils_1.log)(this.config, 'No taxonomies found in the content folder!', 'info');
58
+ }
59
+ }
60
+ catch (error) {
61
+ (0, utils_1.log)(this.config, `Error generating taxonomies mapper: ${error.message}`, 'error');
62
+ }
63
+ }
64
+ /**
65
+ * Retrieves the taxonomies based on the provided taxonomy UID.
66
+ *
67
+ * @param taxonomy - The UID of the taxonomy to retrieve.
68
+ * @returns A promise that resolves to the retrieved taxonomies.
69
+ */
70
+ async getTaxonomies(taxonomy) {
71
+ return await this.stackAPIClient
72
+ .taxonomy(taxonomy.uid)
73
+ .fetch()
74
+ .then((data) => data)
75
+ .catch((err) => this.handleTaxonomyErrorMsg(err));
76
+ }
77
+ /**
78
+ * Sanitizes the attributes of a taxonomy object.
79
+ *
80
+ * @param taxonomy - The taxonomy object to sanitize.
81
+ * @returns The sanitized taxonomy object with invalid keys omitted.
82
+ */
83
+ sanitizeTaxonomyAttribs(taxonomy) {
84
+ return (0, omit_1.default)(taxonomy, this.taxonomiesConfig.invalidKeys);
85
+ }
86
+ /**
87
+ * Retrieves all terms of a taxonomy.
88
+ *
89
+ * @param taxonomy - The taxonomy object.
90
+ * @param skip - The number of terms to skip (default: 0).
91
+ * @param terms - An array to store the retrieved terms (default: []).
92
+ * @returns A promise that resolves to an array of terms.
93
+ */
94
+ async getAllTermsOfTaxonomy(taxonomy, skip = 0, terms = []) {
95
+ const queryParams = {
96
+ include_count: true,
97
+ limit: 100,
98
+ skip,
99
+ };
100
+ if (skip >= 0)
101
+ queryParams['skip'] = skip || 0;
102
+ queryParams['depth'] = 0;
103
+ await this.stackAPIClient
104
+ .taxonomy(taxonomy.uid)
105
+ .terms()
106
+ .query(queryParams)
107
+ .find()
108
+ .then((data) => {
109
+ terms = terms.concat(data.items);
110
+ if (data.count >= skip + queryParams.limit) {
111
+ return this.getAllTermsOfTaxonomy(taxonomy, skip + 100, terms);
112
+ }
113
+ })
114
+ .catch((err) => this.handleTaxonomyErrorMsg(err));
115
+ return terms;
116
+ }
117
+ /**
118
+ * Sanitizes the attributes of the given terms.
119
+ *
120
+ * @param terms - An array of terms to sanitize.
121
+ * @returns The sanitized terms.
122
+ */
123
+ sanitizeTermsAttribs(terms) {
124
+ for (let index = 0; index < (terms === null || terms === void 0 ? void 0 : terms.length); index++) {
125
+ terms[index] = (0, omit_1.default)(terms[index], this.taxonomiesConfig.invalidKeys);
126
+ }
127
+ return terms;
128
+ }
129
+ handleTaxonomyErrorMsg(err) {
130
+ var _a, _b;
131
+ if ((err === null || err === void 0 ? void 0 : err.errorMessage) || (err === null || err === void 0 ? void 0 : err.message)) {
132
+ const errorMsg = (err === null || err === void 0 ? void 0 : err.errorMessage) || ((_a = err === null || err === void 0 ? void 0 : err.errors) === null || _a === void 0 ? void 0 : _a.taxonomy) || ((_b = err === null || err === void 0 ? void 0 : err.errors) === null || _b === void 0 ? void 0 : _b.term) || (err === null || err === void 0 ? void 0 : err.message);
133
+ (0, utils_1.log)(this.config, errorMsg, 'error');
134
+ }
135
+ else {
136
+ (0, utils_1.log)(this.config, 'Error fetching taxonomy data!', 'error');
137
+ (0, utils_1.log)(this.config, err, 'error');
138
+ }
139
+ }
140
+ }
141
+ exports.default = TaxonomiesImportSetup;