Skip to content

Commit

Permalink
Merge pull request #1663 from contentstack/feat/import-setup-asset-ma…
Browse files Browse the repository at this point in the history
…pper

asset mapper, marketplace
  • Loading branch information
shafeeqd959 authored Nov 6, 2024
2 parents 9311979 + 4c35079 commit dc4db88
Show file tree
Hide file tree
Showing 5 changed files with 127 additions and 4 deletions.
5 changes: 3 additions & 2 deletions packages/contentstack-import-setup/src/config/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ const config: DefaultConfig = {
// not passing `locale` will migrate all the locales present
// locales: ['fr-fr'],
host: 'https://api.contentstack.io/v3',
developerHubBaseUrl: '',
modules: {
'custom-roles': {
dirName: 'custom-roles',
Expand All @@ -36,12 +37,12 @@ const config: DefaultConfig = {
'content-types': {
dirName: 'content_types',
fileName: 'content_types.json',
dependencies: ['assets', 'extensions', 'taxonomies'],
dependencies: ['extensions', 'marketplace-apps', 'taxonomies'],
},
entries: {
dirName: 'entries',
fileName: 'entries.json',
dependencies: ['assets', 'environments', 'marketplace-apps', 'taxonomies'],
dependencies: ['assets', 'marketplace-apps', 'taxonomies'],
},
'global-fields': {
dirName: 'global_fields',
Expand Down
6 changes: 6 additions & 0 deletions packages/contentstack-import-setup/src/import/import-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ export default class ImportSetup {
*/
async start() {
try {
if (!this.config.management_token) {
const stackDetails: Record<string, unknown> = await this.stackAPIClient.fetch();
this.config.stackName = stackDetails.name as string;
this.config.org_uid = stackDetails.org_uid as string;
}

const backupDir = await backupHandler(this.config);
if (backupDir) {
this.config.backupDir = backupDir;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,8 @@ export default class ExtensionImportSetup {
.extension()
.query({ query: { title: extension.title } })
.findOne()
.catch((error) => {
reject(true);
.catch((error: Error) => {
reject(error);
})) || {};
resolve(extensionsInStack);
});
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import { log, fsUtil } from '../../utils';
import { join } from 'path';
import { ImportConfig, ModuleClassParams } from '../../types';
import { get, isEmpty } from 'lodash';
import {
formatError,
isAuthenticated,
marketplaceSDKClient,
ContentstackMarketplaceClient,
NodeCrypto,
createDeveloperHubUrl,
} from '@contentstack/cli-utilities';

export default class marketplaceAppImportSetup {
private config: ImportConfig;
private marketplaceAppsFilePath: string;
private marketplaceAppMapper: any;
private stackAPIClient: ModuleClassParams['stackAPIClient'];
private dependencies: ModuleClassParams['dependencies'];
private marketplaceAppsConfig: ImportConfig['modules']['marketplace-apps'];
private mapperDirPath: string;
private marketplaceAppsFolderPath: string;
private marketplaceAppsUidMapperPath: string;
public developerHubBaseUrl: string;
public marketplaceAppPath: string;
public nodeCrypto: NodeCrypto;
public appSdk: ContentstackMarketplaceClient;

constructor({ config, stackAPIClient }: ModuleClassParams) {
this.config = config;
this.stackAPIClient = stackAPIClient;
this.marketplaceAppsFilePath = join(this.config.contentDir, 'marketplace_apps', 'marketplace_apps.json');
this.marketplaceAppsConfig = config.modules['marketplace-apps'];
this.marketplaceAppsUidMapperPath = join(this.config.backupDir, 'mapper', 'marketplace_apps');
this.marketplaceAppMapper = { app_uid: {}, installation_uid: {}, extension_uid: {} };
}

/**
* Start the marketplaceApp import setup
* This method reads the marketplaceApps from the content folder and generates a mapper file
* @returns {Promise<void>}
*/
async start() {
try {
const sourceMarketplaceApps: any = await fsUtil.readFile(this.marketplaceAppsFilePath);
if (!isEmpty(sourceMarketplaceApps)) {
fsUtil.makeDirectory(this.marketplaceAppsUidMapperPath); // Use fsUtil
this.developerHubBaseUrl = this.config.developerHubBaseUrl || (await createDeveloperHubUrl(this.config.host));
// NOTE init marketplace app sdk
const host = this.developerHubBaseUrl.split('://').pop();
this.appSdk = await marketplaceSDKClient({ host });
const targetMarketplaceApps: any = await this.getMarketplaceApps();
this.createMapper(sourceMarketplaceApps, targetMarketplaceApps);
await fsUtil.writeFile(join(this.marketplaceAppsUidMapperPath, 'uid-mapping.json'), this.marketplaceAppMapper);

log(this.config, `Generated required setup files for marketplaceApp`, 'success');
} else {
log(this.config, 'No marketplaceApps found in the content folder!', 'error');
}
} catch (error) {
log(this.config, `Error generating marketplaceApp mapper: ${formatError(error)}`, 'error');
}
}

async getMarketplaceApps() {
// Implement this method to get the marketplaceApp from the stack
return new Promise(async (resolve, reject) => {
const { items: marketplaceApps = [] } =
(await this.appSdk
.marketplace(this.config.org_uid)
.installation()
.fetchAll({ target_uids: this.config.apiKey })
.catch((error: Error) => {
reject(error);
})) || {};
resolve(marketplaceApps);
});
}

createMapper(sourceMarketplaceApps: any, targetMarketplaceApps: any) {
sourceMarketplaceApps.forEach((sourceApp: any) => {
// Find matching target item based on manifest.name
const targetApp = targetMarketplaceApps.find(
(targetApp: any) => get(targetApp, 'manifest.name') === get(sourceApp, 'manifest.name'),
);

if (targetApp) {
// Map app_uid from source and target
this.marketplaceAppMapper.app_uid[sourceApp.manifest.uid] = targetApp.manifest.uid;

// Map installation_uid from source and target
this.marketplaceAppMapper.installation_uid[sourceApp.installation_uid] = targetApp.installation_uid;

// Map extension_uid by comparing meta.uid in source and target's ui_location.locations
sourceApp.ui_location.locations.forEach((sourceAppLocation: any) => {
const targetAppLocation = targetApp.ui_location.locations.find(
(targetAppLocation: any) => targetAppLocation.type === sourceAppLocation.type,
);

if (targetAppLocation) {
sourceAppLocation.meta.forEach((sourceAppMeta: any) => {
const targetAppMeta = targetAppLocation.meta.find(
(targetAppMeta: any) => targetAppMeta.uid === sourceAppMeta.uid,
);

if (targetAppMeta && sourceAppMeta.extension_uid && targetAppMeta.extension_uid) {
this.marketplaceAppMapper.extension_uid[sourceAppMeta.extension_uid] = targetAppMeta.extension_uid;
}
});
}
});
}
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { Modules } from '.';

export default interface DefaultConfig {
host: string;
developerHubBaseUrl: string;
modules: {
'custom-roles': {
dirName: string;
Expand Down

0 comments on commit dc4db88

Please sign in to comment.