From bb5ba5cbf9219fb5b23f5ab631b3b620246a958c Mon Sep 17 00:00:00 2001 From: Aman Kumar Date: Wed, 20 Dec 2023 12:46:57 +0530 Subject: [PATCH] fix: handled login & region error, use manifest fle as default input --- src/app-cli-base-coomand.ts | 36 +++++++++++++++++++++++++++++++++++ src/base-command.ts | 15 +++++++++++++++ src/commands/app/create.ts | 7 ++++--- src/commands/app/delete.ts | 12 ++++++++---- src/commands/app/get.ts | 15 ++++++++++----- src/commands/app/install.ts | 30 +++++++++++++++++++++++------ src/commands/app/uninstall.ts | 12 ++++++++---- src/commands/app/update.ts | 15 +++++++++------ src/messages/index.ts | 3 ++- src/util/common-utils.ts | 1 - 10 files changed, 116 insertions(+), 30 deletions(-) create mode 100644 src/app-cli-base-coomand.ts diff --git a/src/app-cli-base-coomand.ts b/src/app-cli-base-coomand.ts new file mode 100644 index 0000000..538369d --- /dev/null +++ b/src/app-cli-base-coomand.ts @@ -0,0 +1,36 @@ +import { resolve } from "path"; +import { existsSync, readFileSync } from "fs"; + +import config from "./config"; +import { AppManifest } from "./types"; +import { BaseCommand } from "./commands/app/base-command"; + +export abstract class AppCLIBaseCommand extends BaseCommand< + typeof AppCLIBaseCommand +> { + protected manifestPath!: string; + protected manifestData!: AppManifest & Record; + + /** + * The `start` function call getManifestData which reads manifest file is current working directory is app directory + */ + start() { + this.getManifestData(); + } + + //move this into abstract command + getManifestData() { + this.manifestPath = resolve(process.cwd(), `${config.defaultAppFileName}.json`); + if (existsSync(this.manifestPath)) { + try { + this.manifestData = JSON.parse( + readFileSync(this.manifestPath, { + encoding: "utf-8", + }) + ); + } catch (error) { + throw error; + } + } + } +} diff --git a/src/base-command.ts b/src/base-command.ts index 029324b..47bd1f6 100644 --- a/src/base-command.ts +++ b/src/base-command.ts @@ -12,6 +12,7 @@ import { managementSDKInitiator, InquirePayload, cliux, + isAuthenticated, } from "@contentstack/cli-utilities"; import config from "./config"; @@ -67,6 +68,7 @@ export abstract class BaseCommand extends Command { ux.registerSearchPlugin(); this.registerConfig(); + this.validateRegionAndAuth(); this.developerHubBaseUrl = this.sharedConfig.developerHubBaseUrl || (await getDeveloperHubUrl()); @@ -154,4 +156,17 @@ export abstract class BaseCommand extends Command { message: message as string, }); } + + /** + * The `validateRegionAndAuth` function verify whether region is set and user is logged in or not + */ + validateRegionAndAuth() { + //Step1: check region + if (this.region) { + //Step2: user logged in or not + if (!isAuthenticated()) { + throw new Error(this.messages.CLI_APP_CLI_LOGIN_FAILED); + } + } + } } diff --git a/src/commands/app/create.ts b/src/commands/app/create.ts index 0b6ebf2..f824efd 100644 --- a/src/commands/app/create.ts +++ b/src/commands/app/create.ts @@ -14,7 +14,7 @@ import { writeFileSync, createWriteStream, } from "fs"; -import { ux, cliux, flags, HttpClient } from "@contentstack/cli-utilities"; +import { ux, cliux, flags, HttpClient, configHandler } from "@contentstack/cli-utilities"; import { BaseCommand } from "../../base-command"; import { AppManifest, AppType } from "../../types"; @@ -132,10 +132,11 @@ export default class Create extends BaseCommand { ); } - this.sharedConfig.org = await getOrg(this.flags, { + //Auto select org in case of oauth + this.sharedConfig.org = configHandler.get('oauthOrgUid') ?? (await getOrg(this.flags, { log: this.log, managementSdk: this.managementSdk, - }); + })); } /** diff --git a/src/commands/app/delete.ts b/src/commands/app/delete.ts index 695cd31..3f87c6a 100644 --- a/src/commands/app/delete.ts +++ b/src/commands/app/delete.ts @@ -1,9 +1,10 @@ -import { BaseCommand } from "../../base-command"; import { cliux, flags } from "@contentstack/cli-utilities"; + +import {AppCLIBaseCommand} from "../../app-cli-base-coomand"; import { $t, commonMsg, deleteAppMsg } from "../../messages"; import { getOrg, fetchAppInstallations, deleteApp, getApp } from "../../util"; -export default class Delete extends BaseCommand { +export default class Delete extends AppCLIBaseCommand { static description = "Delete app from marketplace"; static examples = [ @@ -21,10 +22,13 @@ export default class Delete extends BaseCommand { async run(): Promise { try { let app; - this.sharedConfig.org = await getOrg(this.flags, { + this.start(); + this.sharedConfig.org = this.manifestData?.organization_uid ?? (await getOrg(this.flags, { managementSdk: this.managementSdk, log: this.log, - }); + })); + this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; + if (!this.flags["app-uid"]) { app = await getApp(this.flags, this.sharedConfig.org, { managementSdk: this.managementAppSdk, diff --git a/src/commands/app/get.ts b/src/commands/app/get.ts index 9ee4002..18325cd 100644 --- a/src/commands/app/get.ts +++ b/src/commands/app/get.ts @@ -1,9 +1,10 @@ -import { BaseCommand } from "../../base-command"; -import { getOrg, getApp, writeFile, fetchApp } from "../../util"; import { flags } from "@contentstack/cli-utilities"; + import { commonMsg } from "../../messages"; +import {AppCLIBaseCommand} from "../../app-cli-base-coomand"; +import { getOrg, getApp, writeFile, fetchApp } from "../../util"; -export default class Get extends BaseCommand { +export default class Get extends AppCLIBaseCommand { static description = "Get details of an app in developer hub"; static examples = [ @@ -31,10 +32,14 @@ export default class Get extends BaseCommand { async run(): Promise { try { let appData; - this.sharedConfig.org = await getOrg(this.flags, { + this.start(); + this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; + + this.sharedConfig.org = this.manifestData?.organization_uid ?? (await getOrg(this.flags, { managementSdk: this.managementSdk, log: this.log, - }); + })); + if (!this.flags["app-uid"]) { appData = await getApp(this.flags, this.sharedConfig.org, { managementSdk: this.managementAppSdk, diff --git a/src/commands/app/install.ts b/src/commands/app/install.ts index 18fb164..da2e219 100644 --- a/src/commands/app/install.ts +++ b/src/commands/app/install.ts @@ -1,5 +1,6 @@ -import { BaseCommand } from "../../base-command"; import { cliux, flags } from "@contentstack/cli-utilities"; + +import { AppCLIBaseCommand } from "../../app-cli-base-coomand"; import { $t, commonMsg, installAppMsg } from "../../messages"; import { getOrg, @@ -10,7 +11,7 @@ import { fetchStack, } from "../../util"; -export default class Install extends BaseCommand { +export default class Install extends AppCLIBaseCommand { static description: string | undefined = "Install an app from the marketplace"; @@ -32,6 +33,8 @@ export default class Install extends BaseCommand { async run(): Promise { try { let app, stack, appType; + this.start(); + this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; //manifest file first preference // validating user given stack, as installation API doesn't return appropriate errors if stack-api-key is invalid // validating this first, as orgUid is not required for fetching stack @@ -43,10 +46,12 @@ export default class Install extends BaseCommand { } // get organization to be used - this.sharedConfig.org = await getOrg(this.flags, { - managementSdk: this.managementSdk, - log: this.log, - }); + this.sharedConfig.org = + this.manifestData?.organization_uid ?? + (await getOrg(this.flags, { + managementSdk: this.managementSdk, + log: this.log, + })); // fetch app details if (!this.flags["app-uid"]) { @@ -114,9 +119,22 @@ export default class Install extends BaseCommand { }), "info" ); + + this.displayStackUrl(); } catch (error: any) { this.log(error?.errorMessage || error?.message || error, "error"); this.exit(1); } } + + /** + * @method displayStackUrl - show guid to stack after installing app successfully in the stack + */ + displayStackUrl(): void { + const stackPath = `${this.uiHost}/#!/stack/${this.flags["stack-api-key"]}/dashboard`; + this.log( + `Start using the stack using the following url: ${stackPath}`, + "info" + ); + } } diff --git a/src/commands/app/uninstall.ts b/src/commands/app/uninstall.ts index 1a40133..b0949cd 100644 --- a/src/commands/app/uninstall.ts +++ b/src/commands/app/uninstall.ts @@ -1,10 +1,11 @@ -import { BaseCommand } from "../../base-command"; import { flags } from "@contentstack/cli-utilities"; -import { getOrg, fetchApp, getInstalledApps } from "../../util"; + import { commonMsg, uninstallAppMsg } from "../../messages"; +import {AppCLIBaseCommand} from "../../app-cli-base-coomand"; +import { getOrg, fetchApp, getInstalledApps } from "../../util"; import { UninstallAppFactory } from "../../factories/uninstall-app-factory"; -export default class Uninstall extends BaseCommand { +export default class Uninstall extends AppCLIBaseCommand { static description = "Uninstall an app"; static examples = [ @@ -28,8 +29,11 @@ export default class Uninstall extends BaseCommand { async run(): Promise { try { let app, appType + this.start(); + this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; + // get organization to be used - this.sharedConfig.org = await getOrg(this.flags, {managementSdk: this.managementSdk, log: this.log}); + this.sharedConfig.org = this.manifestData?.organization_uid ?? (await getOrg(this.flags, {managementSdk: this.managementSdk, log: this.log})); // fetch app details if (!this.flags['app-uid']) { diff --git a/src/commands/app/update.ts b/src/commands/app/update.ts index 14cf3fb..fec1129 100644 --- a/src/commands/app/update.ts +++ b/src/commands/app/update.ts @@ -5,15 +5,13 @@ import { flags } from "@contentstack/cli-utilities"; import { App } from "@contentstack/management/types/app"; import { existsSync, readFileSync, writeFileSync } from "fs"; -import { AppManifest } from "../../types"; -import { BaseCommand } from "../../base-command"; import { $t, appUpdate } from "../../messages"; import { fetchApp, getApp, getOrg } from "../../util"; +import {AppCLIBaseCommand} from "../../app-cli-base-coomand"; -export default class Update extends BaseCommand { +export default class Update extends AppCLIBaseCommand { private orgUid!: string; private manifestPathRetry: number = 0; - private manifestData!: AppManifest & Record; static description = "Update the existing app in developer hub"; @@ -30,8 +28,13 @@ export default class Update extends BaseCommand { async run(): Promise { try { - await this.validateManifest(); - this.orgUid = this.flags.org || this.manifestData.organization_uid; + this.start(); + //if working directory isn't app directory + if(!this.manifestData){ + await this.validateManifest(); + } + this.flags["app-manifest"] = this.manifestPath ?? this.flags["app-manifest"]; + this.orgUid = this.flags.org ?? this.manifestData?.organization_uid; this.sharedConfig.org = await getOrg( { org: this.orgUid as any }, { diff --git a/src/messages/index.ts b/src/messages/index.ts index eb06c1b..6e0f533 100644 --- a/src/messages/index.ts +++ b/src/messages/index.ts @@ -34,7 +34,8 @@ const commonMsg = { APP_TYPE_DESCRIPTION: "Type of App", CONTACT_SUPPORT: "Please contact the support team.", STACK_API_KEY: "API key of the stack where the app is to be installed.", - USER_TERMINATION: "Process terminated by the user." + USER_TERMINATION: "Process terminated by the user.", + CLI_APP_CLI_LOGIN_FAILED: 'You are not logged in. Please login with command $ csdx auth:login' }; const appCreate = { diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 39aef40..c4a661f 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -67,7 +67,6 @@ async function fetchApps( .catch((error) => { cliux.loader("failed"); log("Some error occurred while fetching apps.", "warn"); - log(error.errorMessage, "error"); throw error; });