Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

asset mapper, marketplace #1663

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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) {
shafeeqd959 marked this conversation as resolved.
Show resolved Hide resolved
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
Loading