From 37b30d1ddd0bd08cc45eac2ee329a28410e1bc5e Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Wed, 22 May 2024 11:44:36 +0530 Subject: [PATCH 01/11] feat: reinstall command implementation --- package.json | 3 +- src/commands/app/index.ts | 1 + src/commands/app/reinstall.ts | 339 ++++++++++++++++++++++++++++++++++ src/messages/index.ts | 17 +- src/util/common-utils.ts | 45 ++++- 5 files changed, 400 insertions(+), 5 deletions(-) create mode 100644 src/commands/app/reinstall.ts diff --git a/package.json b/package.json index 95ab791..943a668 100644 --- a/package.json +++ b/package.json @@ -96,7 +96,8 @@ "app:update": "APUPT", "app:delete": "APDLT", "app:install": "API", - "app:uninstall": "APUI" + "app:uninstall": "APUI", + "app:reinstall": "APREI" } } } diff --git a/src/commands/app/index.ts b/src/commands/app/index.ts index a70bf4c..6caeef9 100644 --- a/src/commands/app/index.ts +++ b/src/commands/app/index.ts @@ -14,6 +14,7 @@ export default class App extends Command { "$ <%= config.bin %> <%= command.id %>:delete", "$ <%= config.bin %> <%= command.id %>:install", "$ <%= config.bin %> <%= command.id %>:uninstall", + "$ <%= config.bin %> <%= command.id %>:reinstall", ]; async run(): Promise { diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts new file mode 100644 index 0000000..12b1f3a --- /dev/null +++ b/src/commands/app/reinstall.ts @@ -0,0 +1,339 @@ +import { cliux, flags } from "@contentstack/cli-utilities"; +import { AppCLIBaseCommand } from "../../app-cli-base-coomand"; +import { $t, commonMsg, reinstallAppMsg } from "../../messages"; +import { + getOrg, + getApp, + getStack, + reinstallApp as reinstallAppUtil, + fetchApp, + fetchStack, +} from '../../util'; + +export default class Reinstall extends AppCLIBaseCommand { + static description = 'Reinstall an app from the marketplace'; + + static examples = [ + '$ <%= config.bin %> <%= command.id %>', + '$ <%= config.bin %> <%= command.id %> --org --app-uid ', + '$ <%= config.bin %> <%= command.id %> --org --app-uid --stack-api-key ', + ]; + + static flags = { + 'app-uid': flags.string({ + description: reinstallAppMsg.APP_UID, + }), + 'stack-api-key': flags.string({ + description: commonMsg.STACK_API_KEY, + }), + }; + + private authToken: string; + + constructor(argv: any, config: any) { + super(argv, config); + this.authToken = this.getAuthToken(); + } + + private getAuthToken(): string { + return process.env.AUTH_TOKEN || 'AUTHTOKEN'; + } + + async run(): Promise { + try { + let app, stack, appType; + this.flags['app-uid'] = this.manifestData?.uid ?? this.flags['app-uid']; + + if (this.flags['stack-api-key']) { + stack = await fetchStack(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, + })); + + if (!this.flags['app-uid']) { + app = await getApp(this.flags, this.sharedConfig.org, { + managementSdk: this.managementAppSdk, + log: this.log, + }); + } else { + app = await fetchApp(this.flags, this.sharedConfig.org, { + managementSdk: this.managementAppSdk, + log: this.log, + }); + } + appType = app?.['target_type']; + this.flags['app-uid'] = app?.uid; + + if (appType === 'organization' && this.flags['stack-api-key']) { + const confirmation = + this.flags['yes'] || + (await cliux.inquire({ + type: 'confirm', + message: $t(reinstallAppMsg.REINSTALL_ORG_APP_TO_STACK, { + app: app?.name || app?.uid, + }), + name: 'confirmation', + })); + if (!confirmation) { + throw new Error(commonMsg.USER_TERMINATION); + } + } + + if (appType === 'stack' && !this.flags['stack-api-key']) { + this.log( + $t(reinstallAppMsg.MISSING_STACK_API_KEY, { + app: app?.name || app?.uid, + }), + 'warn' + ); + stack = await getStack(this.sharedConfig.org, { + managementSdk: this.managementSdk, + log: this.log, + }); + this.flags['stack-api-key'] = stack?.['api_key']; + } + + this.log( + $t(reinstallAppMsg.REINSTALLING_APP_NOTICE, { + app: app?.name || app?.uid, + type: appType, + target: this.flags['stack-api-key'] || this.sharedConfig.org, + }), + 'info' + ); + + await reinstallAppUtil( + this.flags['app-uid'], + this.authToken, + this.sharedConfig.org, + appType, + this.flags['stack-api-key'] || this.sharedConfig.org + ); + + this.log( + $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { + app: app?.name || (this.flags['app-uid'] as string), + target: stack?.name || this.sharedConfig.org, + }), + 'info' + ); + + this.displayStackUrl(); + } catch (error: any) { + this.log(error?.errorMessage || error?.message || error, 'error'); + this.exit(1); + } + } + + displayStackUrl(): void { + const stackPath = `${this.uiHost}/#!/stack/${this.flags['stack-api-key']}/dashboard`; + this.log(`Please use the following URL to start using the stack: ${stackPath}`, 'info'); + } +} + + + + +// import { +// getOrg, +// getApp, +// getStack, +// reinstallApp, +// fetchApp, +// fetchStack, +// } from "../../util"; + +// export default class Reinstall extends AppCLIBaseCommand { +// static description: string | undefined = "Reinstall an app from the marketplace"; + +// static examples = [ +// "$ <%= config.bin %> <%= command.id %>", +// "$ <%= config.bin %> <%= command.id %> --org --app-uid ", +// "$ <%= config.bin %> <%= command.id %> --org --app-uid --stack-api-key ", +// ]; + +// static flags = { +// "app-uid": flags.string({ +// description: reinstallAppMsg.APP_UID, +// }), +// "stack-api-key": flags.string({ +// description: commonMsg.STACK_API_KEY, +// }), +// }; + +// private authToken: string; + +// constructor(argv: any, config: any) { +// super(argv, config); +// this.authToken = this.getAuthToken(); +// } + +// private getAuthToken(): string { +// return process.env.AUTH_TOKEN || ''; +// } + +// async run(): Promise { +// try { +// let app, stack, appType; +// this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; // manifest file first preference + +// // Validating user-given stack, as reinstallation API doesn't return appropriate errors if stack-api-key is invalid +// // Validate this first, as orgUid is not required for fetching stack +// if (this.flags["stack-api-key"]) { +// stack = await fetchStack(this.flags, { +// managementSdk: this.managementSdk, +// log: this.log, +// }); +// } + +// // Get organization to be used +// 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"]) { +// app = await getApp(this.flags, this.sharedConfig.org, { +// managementSdk: this.managementAppSdk, +// log: this.log, +// }); +// } else { +// app = await fetchApp(this.flags, this.sharedConfig.org, { +// managementSdk: this.managementAppSdk, +// log: this.log, +// }); +// } +// appType = app?.["target_type"]; // Get app-type from the fetched app +// this.flags["app-uid"] = app?.uid; + +// // Construct the reinstall URL +// const manifestUid = this.flags["app-uid"]; +// const reinstallUrl = `/manifests/${manifestUid}/reinstall`; + +// // In case stack-api-key is provided and the selected app is an organization app +// if (appType === "organization" && this.flags["stack-api-key"]) { +// const confirmation = +// this.flags["yes"] || +// (await cliux.inquire({ +// type: "confirm", +// message: $t(reinstallAppMsg.REINSTALL_ORG_APP_TO_STACK, { +// app: app?.name || app?.uid, +// }), +// name: "confirmation", +// })); +// if (!confirmation) { +// throw new Error(commonMsg.USER_TERMINATION); +// } +// } + +// // In case a stack app is selected and no stack-api-key is provided +// if (appType === "stack" && !this.flags["stack-api-key"]) { +// this.log( +// $t(reinstallAppMsg.MISSING_STACK_API_KEY, { +// app: app?.name || app?.uid, +// }), +// "warn" +// ); +// stack = await getStack(this.sharedConfig.org, { +// managementSdk: this.managementSdk, +// log: this.log, +// }); +// this.flags["stack-api-key"] = stack?.["api_key"]; +// } + +// // Prepare options for reinstallApp function +// const options = { +// headers: { +// Authorization: `Bearer ${this.authToken}`, +// }, +// timeout: 30000, // 30 seconds timeout +// }; + +// // Reinstall app +// this.log( +// $t(reinstallAppMsg.REINSTALLING_APP_NOTICE, { +// app: app?.name || app?.uid, +// type: appType, +// target: this.flags["stack-api-key"] || this.sharedConfig.org, +// }), +// "info" +// ); +// await reinstallApp(reinstallUrl, this.flags, this.sharedConfig.org, appType, options); +// this.log( +// $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { +// app: app?.name || (this.flags["app-uid"] as string), +// target: stack?.name || this.sharedConfig.org, +// }), +// "info" +// ); + +// this.displayStackUrl(); +// } catch (error: any) { +// this.log(error?.errorMessage || error?.message || error, "error"); +// this.exit(1); +// } +// } + +// displayStackUrl(): void { +// const stackPath = `${this.uiHost}/#!/stack/${this.flags["stack-api-key"]}/dashboard`; +// this.log(`Please use the following URL to start using the stack: ${stackPath}`, "info"); +// } +// } + + +// import axios from 'axios'; // Assuming you have Axios installed + +// export default class Reinstall extends AppCLIBaseCommand { +// // Other static properties and methods + +// async run(): Promise { +// try { +// // Other code to fetch app details and construct the URL + +// const manifestUid = this.flags["app-uid"]; +// const reinstallUrl = `/manifests/${manifestUid}/reinstall`; + +// // Prepare request payload and headers +// const payload = { +// // If you need to send any data in the request body, add it here +// }; + +// const headers = { +// // If you need to include any headers, such as authorization token, add them here +// Authorization: `Bearer ${this.getAuthToken()}`, +// }; + +// // Make the PUT request to reinstall the app +// const response = await axios.put(reinstallUrl, payload, { headers }); + +// // Handle the response +// if (response.status === 200) { +// this.log( +// $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { +// app: app?.name || (this.flags["app-uid"] as string), +// target: stack?.name || this.sharedConfig.org, +// }), +// "info" +// ); + +// this.displayStackUrl(); +// } else { +// throw new Error("Failed to reinstall the app."); // Handle the error according to your application logic +// } +// } catch (error: any) { +// this.log(error?.response?.data || error?.message || error, "error"); +// this.exit(1); +// } +// } +// } diff --git a/src/messages/index.ts b/src/messages/index.ts index 1b93122..f8ab536 100644 --- a/src/messages/index.ts +++ b/src/messages/index.ts @@ -100,6 +100,15 @@ const uninstallAppMsg = { UNINSTALL_ALL: "Please select stacks from where the app must be uninstalled.", } +const reinstallAppMsg = { + CHOOSE_A_STACK: "Please select a stack", + APP_REINSTALLED_SUCCESSFULLY: "{app} reinstalled successfully in {target}.", + REINSTALL_ORG_APP_TO_STACK: "{app} is an organization app. It cannot be reinstalled to a stack. Do you want to proceed?", + MISSING_STACK_API_KEY: "As {app} is a stack app, it can only be reinstalled in a stack. Please select a stack.", + REINSTALLING_APP_NOTICE: "Installing {app} on {type} {target}.", + APP_UID: "Provide the app UID of an existing app to be reinstalled.", +} + const messages: typeof errors & typeof commonMsg & typeof appCreate & @@ -107,7 +116,8 @@ const messages: typeof errors & typeof getAppMsg & typeof deleteAppMsg & typeof installAppMsg & - typeof uninstallAppMsg = { + typeof uninstallAppMsg & + typeof reinstallAppMsg = { ...errors, ...commonMsg, ...appCreate, @@ -115,7 +125,8 @@ const messages: typeof errors & ...getAppMsg, ...deleteAppMsg, ...installAppMsg, - ...uninstallAppMsg + ...uninstallAppMsg, + ...reinstallAppMsg }; const $t = (msg: string, args: Record): string => { @@ -130,4 +141,4 @@ const $t = (msg: string, args: Record): string => { }; export default messages; -export { $t, errors, commonMsg, appCreate, appUpdate, getAppMsg, deleteAppMsg, installAppMsg, uninstallAppMsg }; +export { $t, errors, commonMsg, appCreate, appUpdate, getAppMsg, deleteAppMsg, installAppMsg, uninstallAppMsg, reinstallAppMsg }; diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 8c8c708..08beac7 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -1,6 +1,7 @@ import { ContentstackClient, FlagInput } from "@contentstack/cli-utilities"; import { AppLocation, Extension, LogFn } from "../types"; -import { cliux, Stack } from "@contentstack/cli-utilities"; +import { cliux, Stack, configHandler } from "@contentstack/cli-utilities"; +import config from "../../src/config"; export type CommonOptions = { log: LogFn; @@ -134,6 +135,47 @@ function installApp( }); } +const region: { cma: string, cda: string, name: string } = configHandler.get("region"); +const developerHubBaseUrl = (config.developerHubUrls as Record)[region.cma]; +async function reinstallApp( + manifestUid: string, + authToken: string, + organizationUid: string, + targetType: string, + targetUid: string +): Promise { + const url = `https://${developerHubBaseUrl}/manifests/${manifestUid}/reinstall`; // Update with the correct URL + + const headers = { + 'Content-Type': 'application/json', + 'authtoken': authToken, + 'organization_uid': organizationUid, + }; + + const body = JSON.stringify({ + target_type: targetType, + target_uid: targetUid, + }); + + try { + const response = await fetch(url, { + method: 'PUT', + headers: headers, + body: body, + }); + + if (!response.ok) { + throw new Error(`HTTP error! Status: ${response.status}`); + } + + const data = await response.json(); + console.log('Success:', data); + } catch (error) { + console.error('Error:', error); + throw error; + } +} + function fetchStack(flags: FlagInput, options: CommonOptions) { const { managementSdk } = options; return managementSdk @@ -237,4 +279,5 @@ export { fetchStack, uninstallApp, fetchInstalledApps, + reinstallApp, }; From cf74452929cab68d34b2421001f623f862ba82a7 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Wed, 22 May 2024 12:23:57 +0530 Subject: [PATCH 02/11] fix: removed unwanted commented code --- src/commands/app/reinstall.ts | 199 ---------------------------------- 1 file changed, 199 deletions(-) diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts index 12b1f3a..17f02d1 100644 --- a/src/commands/app/reinstall.ts +++ b/src/commands/app/reinstall.ts @@ -138,202 +138,3 @@ export default class Reinstall extends AppCLIBaseCommand { this.log(`Please use the following URL to start using the stack: ${stackPath}`, 'info'); } } - - - - -// import { -// getOrg, -// getApp, -// getStack, -// reinstallApp, -// fetchApp, -// fetchStack, -// } from "../../util"; - -// export default class Reinstall extends AppCLIBaseCommand { -// static description: string | undefined = "Reinstall an app from the marketplace"; - -// static examples = [ -// "$ <%= config.bin %> <%= command.id %>", -// "$ <%= config.bin %> <%= command.id %> --org --app-uid ", -// "$ <%= config.bin %> <%= command.id %> --org --app-uid --stack-api-key ", -// ]; - -// static flags = { -// "app-uid": flags.string({ -// description: reinstallAppMsg.APP_UID, -// }), -// "stack-api-key": flags.string({ -// description: commonMsg.STACK_API_KEY, -// }), -// }; - -// private authToken: string; - -// constructor(argv: any, config: any) { -// super(argv, config); -// this.authToken = this.getAuthToken(); -// } - -// private getAuthToken(): string { -// return process.env.AUTH_TOKEN || ''; -// } - -// async run(): Promise { -// try { -// let app, stack, appType; -// this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; // manifest file first preference - -// // Validating user-given stack, as reinstallation API doesn't return appropriate errors if stack-api-key is invalid -// // Validate this first, as orgUid is not required for fetching stack -// if (this.flags["stack-api-key"]) { -// stack = await fetchStack(this.flags, { -// managementSdk: this.managementSdk, -// log: this.log, -// }); -// } - -// // Get organization to be used -// 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"]) { -// app = await getApp(this.flags, this.sharedConfig.org, { -// managementSdk: this.managementAppSdk, -// log: this.log, -// }); -// } else { -// app = await fetchApp(this.flags, this.sharedConfig.org, { -// managementSdk: this.managementAppSdk, -// log: this.log, -// }); -// } -// appType = app?.["target_type"]; // Get app-type from the fetched app -// this.flags["app-uid"] = app?.uid; - -// // Construct the reinstall URL -// const manifestUid = this.flags["app-uid"]; -// const reinstallUrl = `/manifests/${manifestUid}/reinstall`; - -// // In case stack-api-key is provided and the selected app is an organization app -// if (appType === "organization" && this.flags["stack-api-key"]) { -// const confirmation = -// this.flags["yes"] || -// (await cliux.inquire({ -// type: "confirm", -// message: $t(reinstallAppMsg.REINSTALL_ORG_APP_TO_STACK, { -// app: app?.name || app?.uid, -// }), -// name: "confirmation", -// })); -// if (!confirmation) { -// throw new Error(commonMsg.USER_TERMINATION); -// } -// } - -// // In case a stack app is selected and no stack-api-key is provided -// if (appType === "stack" && !this.flags["stack-api-key"]) { -// this.log( -// $t(reinstallAppMsg.MISSING_STACK_API_KEY, { -// app: app?.name || app?.uid, -// }), -// "warn" -// ); -// stack = await getStack(this.sharedConfig.org, { -// managementSdk: this.managementSdk, -// log: this.log, -// }); -// this.flags["stack-api-key"] = stack?.["api_key"]; -// } - -// // Prepare options for reinstallApp function -// const options = { -// headers: { -// Authorization: `Bearer ${this.authToken}`, -// }, -// timeout: 30000, // 30 seconds timeout -// }; - -// // Reinstall app -// this.log( -// $t(reinstallAppMsg.REINSTALLING_APP_NOTICE, { -// app: app?.name || app?.uid, -// type: appType, -// target: this.flags["stack-api-key"] || this.sharedConfig.org, -// }), -// "info" -// ); -// await reinstallApp(reinstallUrl, this.flags, this.sharedConfig.org, appType, options); -// this.log( -// $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { -// app: app?.name || (this.flags["app-uid"] as string), -// target: stack?.name || this.sharedConfig.org, -// }), -// "info" -// ); - -// this.displayStackUrl(); -// } catch (error: any) { -// this.log(error?.errorMessage || error?.message || error, "error"); -// this.exit(1); -// } -// } - -// displayStackUrl(): void { -// const stackPath = `${this.uiHost}/#!/stack/${this.flags["stack-api-key"]}/dashboard`; -// this.log(`Please use the following URL to start using the stack: ${stackPath}`, "info"); -// } -// } - - -// import axios from 'axios'; // Assuming you have Axios installed - -// export default class Reinstall extends AppCLIBaseCommand { -// // Other static properties and methods - -// async run(): Promise { -// try { -// // Other code to fetch app details and construct the URL - -// const manifestUid = this.flags["app-uid"]; -// const reinstallUrl = `/manifests/${manifestUid}/reinstall`; - -// // Prepare request payload and headers -// const payload = { -// // If you need to send any data in the request body, add it here -// }; - -// const headers = { -// // If you need to include any headers, such as authorization token, add them here -// Authorization: `Bearer ${this.getAuthToken()}`, -// }; - -// // Make the PUT request to reinstall the app -// const response = await axios.put(reinstallUrl, payload, { headers }); - -// // Handle the response -// if (response.status === 200) { -// this.log( -// $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { -// app: app?.name || (this.flags["app-uid"] as string), -// target: stack?.name || this.sharedConfig.org, -// }), -// "info" -// ); - -// this.displayStackUrl(); -// } else { -// throw new Error("Failed to reinstall the app."); // Handle the error according to your application logic -// } -// } catch (error: any) { -// this.log(error?.response?.data || error?.message || error, "error"); -// this.exit(1); -// } -// } -// } From dec7bf5dc4b5a6a0f55555016d246ce9c2cc6ae9 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Fri, 24 May 2024 18:18:38 +0530 Subject: [PATCH 03/11] feat: reinstall command implementation --- README.md | 29 +++++++++++ package.json | 2 +- src/commands/app/reinstall.ts | 91 ++++++++++++++++----------------- src/messages/index.ts | 2 +- src/types/app.ts | 12 +++++ src/util/api-request-handler.ts | 38 ++++++++++++++ src/util/common-utils.ts | 62 +++++++++------------- src/util/error-helper.ts | 18 +++++++ 8 files changed, 167 insertions(+), 87 deletions(-) create mode 100644 src/util/api-request-handler.ts create mode 100644 src/util/error-helper.ts diff --git a/README.md b/README.md index 558a96c..09d992e 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,7 @@ USAGE * [`csdx app:delete`](#csdx-appdelete) * [`csdx app:get`](#csdx-appget) * [`csdx app:install`](#csdx-appinstall) +* [`csdx app:reinstall`](#csdx-appreinstall) * [`csdx app:uninstall`](#csdx-appuninstall) * [`csdx app:update`](#csdx-appupdate) @@ -61,6 +62,8 @@ EXAMPLES $ csdx app:install $ csdx app:uninstall + + $ csdx app:reinstall ``` _See code: [src/commands/app/index.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/index.ts)_ @@ -177,6 +180,32 @@ EXAMPLES _See code: [src/commands/app/install.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/install.ts)_ +## `csdx app:reinstall` + +Reinstall an app from the marketplace + +``` +USAGE + $ csdx app:reinstall [--org ] [--app-uid ] [--stack-api-key ] + +FLAGS + --app-uid= Provide the app UID of an existing app to be reinstalled. + --org= Provide the organization UID to fetch the app details for the desired operation. + --stack-api-key= API key of the stack where the app is to be installed. + +DESCRIPTION + Reinstall an app from the marketplace + +EXAMPLES + $ csdx app:reinstall + + $ csdx app:reinstall --org --app-uid + + $ csdx app:reinstall --org --app-uid --stack-api-key +``` + +_See code: [src/commands/app/reinstall.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/reinstall.ts)_ + ## `csdx app:uninstall` Uninstall an app diff --git a/package.json b/package.json index 943a668..f0702bd 100644 --- a/package.json +++ b/package.json @@ -97,7 +97,7 @@ "app:delete": "APDLT", "app:install": "API", "app:uninstall": "APUI", - "app:reinstall": "APREI" + "app:reinstall": "APRI" } } } diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts index 17f02d1..63acf87 100644 --- a/src/commands/app/reinstall.ts +++ b/src/commands/app/reinstall.ts @@ -5,46 +5,36 @@ import { getOrg, getApp, getStack, - reinstallApp as reinstallAppUtil, + reinstallApp, fetchApp, fetchStack, -} from '../../util'; +} from "../../util"; export default class Reinstall extends AppCLIBaseCommand { - static description = 'Reinstall an app from the marketplace'; + static description: string | undefined = + "Reinstall an app from the marketplace"; static examples = [ - '$ <%= config.bin %> <%= command.id %>', - '$ <%= config.bin %> <%= command.id %> --org --app-uid ', - '$ <%= config.bin %> <%= command.id %> --org --app-uid --stack-api-key ', + "$ <%= config.bin %> <%= command.id %>", + "$ <%= config.bin %> <%= command.id %> --org --app-uid ", + "$ <%= config.bin %> <%= command.id %> --org --app-uid --stack-api-key ", ]; static flags = { - 'app-uid': flags.string({ - description: reinstallAppMsg.APP_UID, + "app-uid": flags.string({ + description: commonMsg.APP_UID, }), - 'stack-api-key': flags.string({ + "stack-api-key": flags.string({ description: commonMsg.STACK_API_KEY, }), }; - private authToken: string; - - constructor(argv: any, config: any) { - super(argv, config); - this.authToken = this.getAuthToken(); - } - - private getAuthToken(): string { - return process.env.AUTH_TOKEN || 'AUTHTOKEN'; - } - async run(): Promise { try { let app, stack, appType; - this.flags['app-uid'] = this.manifestData?.uid ?? this.flags['app-uid']; + this.flags["app-uid"] = this.manifestData?.uid ?? this.flags["app-uid"]; - if (this.flags['stack-api-key']) { + if (this.flags["stack-api-key"]) { stack = await fetchStack(this.flags, { managementSdk: this.managementSdk, log: this.log, @@ -58,7 +48,7 @@ export default class Reinstall extends AppCLIBaseCommand { log: this.log, })); - if (!this.flags['app-uid']) { + if (!this.flags["app-uid"]) { app = await getApp(this.flags, this.sharedConfig.org, { managementSdk: this.managementAppSdk, log: this.log, @@ -69,72 +59,77 @@ export default class Reinstall extends AppCLIBaseCommand { log: this.log, }); } - appType = app?.['target_type']; - this.flags['app-uid'] = app?.uid; + appType = app?.["target_type"]; + this.flags["app-uid"] = app?.uid; - if (appType === 'organization' && this.flags['stack-api-key']) { + if (appType === "organization" && this.flags["stack-api-key"]) { + appType = 'organization' const confirmation = - this.flags['yes'] || + this.flags["yes"] || (await cliux.inquire({ - type: 'confirm', + type: "confirm", message: $t(reinstallAppMsg.REINSTALL_ORG_APP_TO_STACK, { app: app?.name || app?.uid, }), - name: 'confirmation', + name: "confirmation", })); if (!confirmation) { throw new Error(commonMsg.USER_TERMINATION); } } - if (appType === 'stack' && !this.flags['stack-api-key']) { + if (appType === "stack" && !this.flags["stack-api-key"]) { + appType = 'stack' + this.log( $t(reinstallAppMsg.MISSING_STACK_API_KEY, { app: app?.name || app?.uid, }), - 'warn' + "warn" ); stack = await getStack(this.sharedConfig.org, { managementSdk: this.managementSdk, log: this.log, }); - this.flags['stack-api-key'] = stack?.['api_key']; + this.flags["stack-api-key"] = stack?.["api_key"]; } this.log( $t(reinstallAppMsg.REINSTALLING_APP_NOTICE, { app: app?.name || app?.uid, type: appType, - target: this.flags['stack-api-key'] || this.sharedConfig.org, + target: this.flags["stack-api-key"] || this.sharedConfig.org, }), - 'info' - ); - - await reinstallAppUtil( - this.flags['app-uid'], - this.authToken, - this.sharedConfig.org, - appType, - this.flags['stack-api-key'] || this.sharedConfig.org + "info" ); - + await reinstallApp({ + flags: this.flags["app-uid"], + type: appType, + orgUid: this.sharedConfig.org, + manifestUid: this.manifestData.uid, + configType: this.sharedConfig, + developerHubBaseUrl: this.developerHubBaseUrl, + }); this.log( $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { - app: app?.name || (this.flags['app-uid'] as string), + app: app?.name || (this.flags["app-uid"] as string), target: stack?.name || this.sharedConfig.org, }), - 'info' + "info" ); this.displayStackUrl(); } catch (error: any) { - this.log(error?.errorMessage || error?.message || error, 'error'); + this.log(error?.errorMessage || error?.message || error, "error"); this.exit(1); } } displayStackUrl(): void { - const stackPath = `${this.uiHost}/#!/stack/${this.flags['stack-api-key']}/dashboard`; - this.log(`Please use the following URL to start using the stack: ${stackPath}`, 'info'); + const stackPath = `${this.uiHost}/#!/stack/${this.flags["stack-api-key"]}/dashboard`; + this.log( + `Please use the following URL to start using the stack: ${stackPath}`, + "info" + ); } } diff --git a/src/messages/index.ts b/src/messages/index.ts index f8ab536..d2d08ff 100644 --- a/src/messages/index.ts +++ b/src/messages/index.ts @@ -105,7 +105,7 @@ const reinstallAppMsg = { APP_REINSTALLED_SUCCESSFULLY: "{app} reinstalled successfully in {target}.", REINSTALL_ORG_APP_TO_STACK: "{app} is an organization app. It cannot be reinstalled to a stack. Do you want to proceed?", MISSING_STACK_API_KEY: "As {app} is a stack app, it can only be reinstalled in a stack. Please select a stack.", - REINSTALLING_APP_NOTICE: "Installing {app} on {type} {target}.", + REINSTALLING_APP_NOTICE: "Reinstalling {app} on {type} {target}.", APP_UID: "Provide the app UID of an existing app to be reinstalled.", } diff --git a/src/types/app.ts b/src/types/app.ts index 81fc9f9..d2f34f1 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -1,3 +1,6 @@ +import { FlagInput } from "@contentstack/cli-utilities"; +import { ConfigType } from "./utils"; + export interface TokenConfiguration { enabled?: boolean; scopes?: string[]; @@ -113,3 +116,12 @@ export interface AppManifest { export interface AppManifestWithUiLocation extends AppManifest { ui_location: LocationConfiguration; } + +export interface ReinstallParams { + flags: FlagInput, + type: string, + orgUid: string, + manifestUid: string, + configType: ConfigType, + developerHubBaseUrl: string +}; \ No newline at end of file diff --git a/src/util/api-request-handler.ts b/src/util/api-request-handler.ts new file mode 100644 index 0000000..a4bcfdb --- /dev/null +++ b/src/util/api-request-handler.ts @@ -0,0 +1,38 @@ +import { HttpClient, configHandler } from "@contentstack/cli-utilities"; +import { formatErrors } from "./error-helper"; + +interface RequestParams { + orgUid: string; + queryParams?: Record; + payload?: any; + url: string; +} + +export async function apiRequestHandler(params: RequestParams): Promise { + const { orgUid, queryParams, payload, url } = params; + const authtoken = configHandler.get('authtoken'); + + const headers = { + organization_uid: orgUid, + authtoken + } + const httpClient = new HttpClient() + httpClient.headers(headers) + if (queryParams) + httpClient.queryParams(queryParams); + + try { + const response = await httpClient.put(url, payload) + const { status, data } = response; + if (status >= 200 && status < 300) { + return data; + } + data?.error + ? formatErrors(data.error) + : data?.error_message || 'Something went wrong'; + throw data; + + } catch (error) { + throw error; + } +} diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 08beac7..9e64d27 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -1,7 +1,7 @@ import { ContentstackClient, FlagInput } from "@contentstack/cli-utilities"; -import { AppLocation, Extension, LogFn } from "../types"; -import { cliux, Stack, configHandler } from "@contentstack/cli-utilities"; -import config from "../../src/config"; +import { AppLocation, ConfigType, Extension, LogFn } from "../types"; +import { cliux, Stack } from "@contentstack/cli-utilities"; +import { apiRequestHandler } from "./api-request-handler"; export type CommonOptions = { log: LogFn; @@ -135,44 +135,32 @@ function installApp( }); } -const region: { cma: string, cda: string, name: string } = configHandler.get("region"); -const developerHubBaseUrl = (config.developerHubUrls as Record)[region.cma]; -async function reinstallApp( - manifestUid: string, - authToken: string, - organizationUid: string, - targetType: string, - targetUid: string -): Promise { - const url = `https://${developerHubBaseUrl}/manifests/${manifestUid}/reinstall`; // Update with the correct URL +async function reinstallApp(params: { + flags: FlagInput; + type: string; + orgUid: string; + manifestUid: string; + configType: ConfigType; + developerHubBaseUrl: string; +}): Promise { + const { type, orgUid, manifestUid, developerHubBaseUrl, flags } = params; - const headers = { - 'Content-Type': 'application/json', - 'authtoken': authToken, - 'organization_uid': organizationUid, + const payload = { + target_type: type, + target_uid: (flags["stack-api-key"] as any) || orgUid, }; - const body = JSON.stringify({ - target_type: targetType, - target_uid: targetUid, - }); - + const url = `https://${developerHubBaseUrl}/manifests/${manifestUid}/reinstall`; try { - const response = await fetch(url, { - method: 'PUT', - headers: headers, - body: body, - }); - - if (!response.ok) { - throw new Error(`HTTP error! Status: ${response.status}`); - } - - const data = await response.json(); - console.log('Success:', data); - } catch (error) { - console.error('Error:', error); - throw error; + const result = await apiRequestHandler({ + orgUid, + queryParams: params, + payload, + url, + }) + return result + } catch (err) { + throw err } } diff --git a/src/util/error-helper.ts b/src/util/error-helper.ts new file mode 100644 index 0000000..8a431a9 --- /dev/null +++ b/src/util/error-helper.ts @@ -0,0 +1,18 @@ +export function formatErrors(errors: any): string { + const errorMessages: string[] = []; + for (const errorKey in errors) { + const errorValue = errors[errorKey]; + if (Array.isArray(errorValue)) { + errorMessages.push(...errorValue.map((error: any) => formatError(error))); + } else { + errorMessages.push(formatError(errorValue)); + } + } + return errorMessages.join(' '); + } + function formatError(error: any): string { + if (typeof error === 'object') { + return Object.values(error).join(' '); + } + return String(error); +} \ No newline at end of file From 298a5c38669cedeacdc39f3a4753be43e3b5b7ce Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Fri, 24 May 2024 19:06:01 +0530 Subject: [PATCH 04/11] fix: setting proper flag value in reinstall class --- src/commands/app/reinstall.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts index 63acf87..ee9da2c 100644 --- a/src/commands/app/reinstall.ts +++ b/src/commands/app/reinstall.ts @@ -103,7 +103,7 @@ export default class Reinstall extends AppCLIBaseCommand { "info" ); await reinstallApp({ - flags: this.flags["app-uid"], + flags: this.flags, type: appType, orgUid: this.sharedConfig.org, manifestUid: this.manifestData.uid, From a96863bbb90ce37872d92a4f1c74bcda6d41057b Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Fri, 24 May 2024 19:10:42 +0530 Subject: [PATCH 05/11] chore: update redme file --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 09d992e..c0ed252 100644 --- a/README.md +++ b/README.md @@ -189,7 +189,7 @@ USAGE $ csdx app:reinstall [--org ] [--app-uid ] [--stack-api-key ] FLAGS - --app-uid= Provide the app UID of an existing app to be reinstalled. + --app-uid= Provide the app UID of an existing app. --org= Provide the organization UID to fetch the app details for the desired operation. --stack-api-key= API key of the stack where the app is to be installed. From a15ec932b930c396e734bbe5f8b6ccc15e2c4002 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Mon, 27 May 2024 10:39:44 +0530 Subject: [PATCH 06/11] chore: version bump to 1.1.7 --- package-lock.json | 4 ++-- package.json | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/package-lock.json b/package-lock.json index e7c77fb..57766d0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/apps-cli", - "version": "1.0.7", + "version": "1.1.7", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/apps-cli", - "version": "1.0.7", + "version": "1.1.7", "license": "MIT", "dependencies": { "@contentstack/cli-command": "~1.2.17", diff --git a/package.json b/package.json index ed1207a..eadfa56 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/apps-cli", - "version": "1.0.7", + "version": "1.1.7", "description": "App ClI", "author": "Contentstack CLI", "homepage": "https://github.com/contentstack/contentstack-apps-cli", From 3f2b6ed8caadc6be1096e83375c5792f8d5e6820 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Mon, 27 May 2024 10:44:03 +0530 Subject: [PATCH 07/11] chore: update version in readme.md --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index c0ed252..a295364 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ $ npm install -g @contentstack/apps-cli $ csdx COMMAND running command... $ csdx (--version|-v) -@contentstack/apps-cli/1.0.7 darwin-arm64 node-v18.16.0 +@contentstack/apps-cli/1.1.7 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -66,7 +66,7 @@ EXAMPLES $ csdx app:reinstall ``` -_See code: [src/commands/app/index.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/index.ts)_ +_See code: [src/commands/app/index.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/index.ts)_ ## `csdx app:create` @@ -97,7 +97,7 @@ EXAMPLES $ csdx app:create --name App-3 --app-type organization --org -d ./boilerplate -c ./external-config.json ``` -_See code: [src/commands/app/create.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/create.ts)_ +_See code: [src/commands/app/create.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/create.ts)_ ## `csdx app:delete` @@ -122,7 +122,7 @@ EXAMPLES $ csdx app:delete --app-uid --org -d ./boilerplate ``` -_See code: [src/commands/app/delete.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/delete.ts)_ +_See code: [src/commands/app/delete.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/delete.ts)_ ## `csdx app:get` @@ -152,7 +152,7 @@ EXAMPLES $ csdx app:get --org --app-uid --app-type organization ``` -_See code: [src/commands/app/get.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/get.ts)_ +_See code: [src/commands/app/get.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/get.ts)_ ## `csdx app:install` @@ -178,7 +178,7 @@ EXAMPLES $ csdx app:install --org --app-uid --stack-api-key ``` -_See code: [src/commands/app/install.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/install.ts)_ +_See code: [src/commands/app/install.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/install.ts)_ ## `csdx app:reinstall` @@ -204,7 +204,7 @@ EXAMPLES $ csdx app:reinstall --org --app-uid --stack-api-key ``` -_See code: [src/commands/app/reinstall.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/reinstall.ts)_ +_See code: [src/commands/app/reinstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/reinstall.ts)_ ## `csdx app:uninstall` @@ -231,7 +231,7 @@ EXAMPLES $ csdx app:uninstall --org --app-uid --installation-uid ``` -_See code: [src/commands/app/uninstall.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/uninstall.ts)_ +_See code: [src/commands/app/uninstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/uninstall.ts)_ ## `csdx app:update` @@ -254,5 +254,5 @@ EXAMPLES $ csdx app:update --app-manifest ./boilerplate/manifest.json ``` -_See code: [src/commands/app/update.ts](https://github.com/contentstack/apps-cli/blob/v1.0.7/src/commands/app/update.ts)_ +_See code: [src/commands/app/update.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/update.ts)_ From 9d26684f6067035702fb06e5e27acd48e844b418 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Mon, 27 May 2024 16:00:46 +0530 Subject: [PATCH 08/11] fix: version bump to 1.1.0 --- README.md | 18 +++++++++--------- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index a295364..b3b410f 100644 --- a/README.md +++ b/README.md @@ -20,7 +20,7 @@ $ npm install -g @contentstack/apps-cli $ csdx COMMAND running command... $ csdx (--version|-v) -@contentstack/apps-cli/1.1.7 darwin-arm64 node-v18.16.0 +@contentstack/apps-cli/1.1.0 darwin-arm64 node-v18.16.0 $ csdx --help [COMMAND] USAGE $ csdx COMMAND @@ -66,7 +66,7 @@ EXAMPLES $ csdx app:reinstall ``` -_See code: [src/commands/app/index.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/index.ts)_ +_See code: [src/commands/app/index.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/index.ts)_ ## `csdx app:create` @@ -97,7 +97,7 @@ EXAMPLES $ csdx app:create --name App-3 --app-type organization --org -d ./boilerplate -c ./external-config.json ``` -_See code: [src/commands/app/create.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/create.ts)_ +_See code: [src/commands/app/create.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/create.ts)_ ## `csdx app:delete` @@ -122,7 +122,7 @@ EXAMPLES $ csdx app:delete --app-uid --org -d ./boilerplate ``` -_See code: [src/commands/app/delete.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/delete.ts)_ +_See code: [src/commands/app/delete.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/delete.ts)_ ## `csdx app:get` @@ -152,7 +152,7 @@ EXAMPLES $ csdx app:get --org --app-uid --app-type organization ``` -_See code: [src/commands/app/get.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/get.ts)_ +_See code: [src/commands/app/get.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/get.ts)_ ## `csdx app:install` @@ -178,7 +178,7 @@ EXAMPLES $ csdx app:install --org --app-uid --stack-api-key ``` -_See code: [src/commands/app/install.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/install.ts)_ +_See code: [src/commands/app/install.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/install.ts)_ ## `csdx app:reinstall` @@ -204,7 +204,7 @@ EXAMPLES $ csdx app:reinstall --org --app-uid --stack-api-key ``` -_See code: [src/commands/app/reinstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/reinstall.ts)_ +_See code: [src/commands/app/reinstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/reinstall.ts)_ ## `csdx app:uninstall` @@ -231,7 +231,7 @@ EXAMPLES $ csdx app:uninstall --org --app-uid --installation-uid ``` -_See code: [src/commands/app/uninstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/uninstall.ts)_ +_See code: [src/commands/app/uninstall.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/uninstall.ts)_ ## `csdx app:update` @@ -254,5 +254,5 @@ EXAMPLES $ csdx app:update --app-manifest ./boilerplate/manifest.json ``` -_See code: [src/commands/app/update.ts](https://github.com/contentstack/apps-cli/blob/v1.1.7/src/commands/app/update.ts)_ +_See code: [src/commands/app/update.ts](https://github.com/contentstack/apps-cli/blob/v1.1.0/src/commands/app/update.ts)_ diff --git a/package-lock.json b/package-lock.json index 57766d0..08f149f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/apps-cli", - "version": "1.1.7", + "version": "1.1.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/apps-cli", - "version": "1.1.7", + "version": "1.1.0", "license": "MIT", "dependencies": { "@contentstack/cli-command": "~1.2.17", diff --git a/package.json b/package.json index eadfa56..8023f8b 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/apps-cli", - "version": "1.1.7", + "version": "1.1.0", "description": "App ClI", "author": "Contentstack CLI", "homepage": "https://github.com/contentstack/contentstack-apps-cli", From d77130d8ef059daa4618971544e8ebe62cb37a71 Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Mon, 27 May 2024 16:27:53 +0530 Subject: [PATCH 09/11] fix: formatting, common api-handler function --- src/util/api-request-handler.ts | 30 +++++++++++++++++++++++------- src/util/common-utils.ts | 3 ++- src/util/error-helper.ts | 30 +++++++++++++++--------------- 3 files changed, 40 insertions(+), 23 deletions(-) diff --git a/src/util/api-request-handler.ts b/src/util/api-request-handler.ts index a4bcfdb..3bb1a2a 100644 --- a/src/util/api-request-handler.ts +++ b/src/util/api-request-handler.ts @@ -3,26 +3,42 @@ import { formatErrors } from "./error-helper"; interface RequestParams { orgUid: string; + method: 'GET' | 'POST' | 'PUT' | 'DELETE'; queryParams?: Record; payload?: any; url: string; } export async function apiRequestHandler(params: RequestParams): Promise { - const { orgUid, queryParams, payload, url } = params; + const { orgUid, method, queryParams, payload, url } = params; const authtoken = configHandler.get('authtoken'); - + const headers = { organization_uid: orgUid, authtoken - } - const httpClient = new HttpClient() - httpClient.headers(headers) - if (queryParams) + }; + + const httpClient = new HttpClient(); + httpClient.headers(headers); + + if (queryParams) { httpClient.queryParams(queryParams); + } try { - const response = await httpClient.put(url, payload) + let response; + if (method === 'GET') { + response = await httpClient.get(url); + } else if (method === 'POST') { + response = await httpClient.post(url, payload); + } else if (method === 'PUT') { + response = await httpClient.put(url, payload); + } else if (method === 'DELETE') { + response = await httpClient.delete(url); + } else { + throw new Error(`Unsupported HTTP method: ${method}`); + } + const { status, data } = response; if (status >= 200 && status < 300) { return data; diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index e1185a2..57ed7f3 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -157,7 +157,8 @@ async function reinstallApp(params: { queryParams: params, payload, url, - }) + method: "PUT" + }) return result } catch (err) { throw err diff --git a/src/util/error-helper.ts b/src/util/error-helper.ts index 8a431a9..1587b02 100644 --- a/src/util/error-helper.ts +++ b/src/util/error-helper.ts @@ -1,18 +1,18 @@ export function formatErrors(errors: any): string { - const errorMessages: string[] = []; - for (const errorKey in errors) { - const errorValue = errors[errorKey]; - if (Array.isArray(errorValue)) { - errorMessages.push(...errorValue.map((error: any) => formatError(error))); - } else { - errorMessages.push(formatError(errorValue)); - } + const errorMessages: string[] = []; + for (const errorKey in errors) { + const errorValue = errors[errorKey]; + if (Array.isArray(errorValue)) { + errorMessages.push(...errorValue.map((error: any) => formatError(error))); + } else { + errorMessages.push(formatError(errorValue)); } - return errorMessages.join(' '); } - function formatError(error: any): string { - if (typeof error === 'object') { - return Object.values(error).join(' '); - } - return String(error); -} \ No newline at end of file + return errorMessages.join(" "); +} +function formatError(error: any): string { + if (typeof error === "object") { + return Object.values(error).join(" "); + } + return String(error); +} From 0946d3ab87a86305617982f9d51991dbbaebf30c Mon Sep 17 00:00:00 2001 From: harshithad0703 Date: Mon, 27 May 2024 17:57:13 +0530 Subject: [PATCH 10/11] fix: error handling, formatting and passing values to params --- src/commands/app/reinstall.ts | 7 +++---- src/util/api-request-handler.ts | 23 +++++++++++------------ src/util/common-utils.ts | 16 +++++++--------- src/util/error-helper.ts | 19 ++++--------------- 4 files changed, 25 insertions(+), 40 deletions(-) diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts index ee9da2c..54a696c 100644 --- a/src/commands/app/reinstall.ts +++ b/src/commands/app/reinstall.ts @@ -105,11 +105,10 @@ export default class Reinstall extends AppCLIBaseCommand { await reinstallApp({ flags: this.flags, type: appType, - orgUid: this.sharedConfig.org, - manifestUid: this.manifestData.uid, - configType: this.sharedConfig, developerHubBaseUrl: this.developerHubBaseUrl, - }); + }, + {orgUid: this.sharedConfig.org, manifestUid: this.manifestData.uid} + ); this.log( $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { app: app?.name || (this.flags["app-uid"] as string), diff --git a/src/util/api-request-handler.ts b/src/util/api-request-handler.ts index 3bb1a2a..2cfcf52 100644 --- a/src/util/api-request-handler.ts +++ b/src/util/api-request-handler.ts @@ -3,7 +3,7 @@ import { formatErrors } from "./error-helper"; interface RequestParams { orgUid: string; - method: 'GET' | 'POST' | 'PUT' | 'DELETE'; + method: "GET" | "POST" | "PUT" | "DELETE"; queryParams?: Record; payload?: any; url: string; @@ -11,11 +11,11 @@ interface RequestParams { export async function apiRequestHandler(params: RequestParams): Promise { const { orgUid, method, queryParams, payload, url } = params; - const authtoken = configHandler.get('authtoken'); + const authtoken = configHandler.get("authtoken"); const headers = { organization_uid: orgUid, - authtoken + authtoken, }; const httpClient = new HttpClient(); @@ -27,13 +27,13 @@ export async function apiRequestHandler(params: RequestParams): Promise { try { let response; - if (method === 'GET') { + if (method === "GET") { response = await httpClient.get(url); - } else if (method === 'POST') { + } else if (method === "POST") { response = await httpClient.post(url, payload); - } else if (method === 'PUT') { + } else if (method === "PUT") { response = await httpClient.put(url, payload); - } else if (method === 'DELETE') { + } else if (method === "DELETE") { response = await httpClient.delete(url); } else { throw new Error(`Unsupported HTTP method: ${method}`); @@ -43,11 +43,10 @@ export async function apiRequestHandler(params: RequestParams): Promise { if (status >= 200 && status < 300) { return data; } - data?.error - ? formatErrors(data.error) - : data?.error_message || 'Something went wrong'; - throw data; - + const error_message = data?.error + ? formatErrors(data) + : data?.error_message || "Something went wrong"; + throw error_message; } catch (error) { throw error; } diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 57ed7f3..83f3636 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -1,5 +1,5 @@ import { ContentstackClient, FlagInput } from "@contentstack/cli-utilities"; -import { AppLocation, ConfigType, Extension, LogFn } from "../types"; +import { AppLocation, Extension, LogFn } from "../types"; import { cliux, Stack } from "@contentstack/cli-utilities"; import { apiRequestHandler } from "./api-request-handler"; @@ -138,13 +138,12 @@ function installApp( async function reinstallApp(params: { flags: FlagInput; type: string; - orgUid: string; - manifestUid: string; - configType: ConfigType; developerHubBaseUrl: string; -}): Promise { - const { type, orgUid, manifestUid, developerHubBaseUrl, flags } = params; - +}, +headers: { orgUid: string, manifestUid: string } +): Promise { + const { type, developerHubBaseUrl, flags } = params; + const {orgUid, manifestUid } = headers; const payload = { target_type: type, target_uid: (flags["stack-api-key"] as any) || orgUid, @@ -153,8 +152,7 @@ async function reinstallApp(params: { const url = `https://${developerHubBaseUrl}/manifests/${manifestUid}/reinstall`; try { const result = await apiRequestHandler({ - orgUid, - queryParams: params, + orgUid, payload, url, method: "PUT" diff --git a/src/util/error-helper.ts b/src/util/error-helper.ts index 1587b02..f5ef089 100644 --- a/src/util/error-helper.ts +++ b/src/util/error-helper.ts @@ -1,18 +1,7 @@ export function formatErrors(errors: any): string { - const errorMessages: string[] = []; - for (const errorKey in errors) { - const errorValue = errors[errorKey]; - if (Array.isArray(errorValue)) { - errorMessages.push(...errorValue.map((error: any) => formatError(error))); - } else { - errorMessages.push(formatError(errorValue)); - } + let errorMessage: string = ""; + if (errors.message) { + errorMessage = errors.message; } - return errorMessages.join(" "); -} -function formatError(error: any): string { - if (typeof error === "object") { - return Object.values(error).join(" "); - } - return String(error); + return errorMessage; } From bc39ecee3d4ff8a8a9fb66b2316a3e469bc6caae Mon Sep 17 00:00:00 2001 From: Aman Kumar Date: Mon, 27 May 2024 18:50:04 +0530 Subject: [PATCH 11/11] refactor: code clean up & added reinstall msg guide --- src/commands/app/install.ts | 15 ++++++++++++++- src/commands/app/reinstall.ts | 10 +++++----- src/messages/index.ts | 1 + src/util/api-request-handler.ts | 29 +++++++++++++++++------------ src/util/common-utils.ts | 26 ++++++++++++-------------- 5 files changed, 49 insertions(+), 32 deletions(-) diff --git a/src/commands/app/install.ts b/src/commands/app/install.ts index d70965c..9223286 100644 --- a/src/commands/app/install.ts +++ b/src/commands/app/install.ts @@ -122,6 +122,12 @@ export default class Install extends AppCLIBaseCommand { this.displayStackUrl(); } catch (error: any) { this.log(error?.errorMessage || error?.message || error, "error"); + if ( + error?.errorMessage === "Installation for app is already done" && + error?.status === 400 + ) { + this.displayReInstallMsg(); + } this.exit(1); } } @@ -136,4 +142,11 @@ export default class Install extends AppCLIBaseCommand { "info" ); } -} \ No newline at end of file + + /** + * @method displayStackUrl - show guid to stack after installing app successfully in the stack + */ + displayReInstallMsg(): void { + this.log(this.messages.APP_ALREADY_INSTALLED, "info"); + } +} diff --git a/src/commands/app/reinstall.ts b/src/commands/app/reinstall.ts index 54a696c..d1d49b1 100644 --- a/src/commands/app/reinstall.ts +++ b/src/commands/app/reinstall.ts @@ -63,7 +63,7 @@ export default class Reinstall extends AppCLIBaseCommand { this.flags["app-uid"] = app?.uid; if (appType === "organization" && this.flags["stack-api-key"]) { - appType = 'organization' + appType = "organization"; const confirmation = this.flags["yes"] || (await cliux.inquire({ @@ -79,7 +79,7 @@ export default class Reinstall extends AppCLIBaseCommand { } if (appType === "stack" && !this.flags["stack-api-key"]) { - appType = 'stack' + appType = "stack"; this.log( $t(reinstallAppMsg.MISSING_STACK_API_KEY, { @@ -106,9 +106,9 @@ export default class Reinstall extends AppCLIBaseCommand { flags: this.flags, type: appType, developerHubBaseUrl: this.developerHubBaseUrl, - }, - {orgUid: this.sharedConfig.org, manifestUid: this.manifestData.uid} - ); + orgUid: this.sharedConfig.org, + manifestUid: this.manifestData.uid, + }); this.log( $t(reinstallAppMsg.APP_REINSTALLED_SUCCESSFULLY, { app: app?.name || (this.flags["app-uid"] as string), diff --git a/src/messages/index.ts b/src/messages/index.ts index d2d08ff..f42960c 100644 --- a/src/messages/index.ts +++ b/src/messages/index.ts @@ -89,6 +89,7 @@ const installAppMsg = { INSTALL_ORG_APP_TO_STACK: "{app} is an organization app. It cannot be installed to a stack. Do you want to proceed?", MISSING_STACK_API_KEY: "As {app} is a stack app, it can only be installed in a stack. Please select a stack.", INSTALLING_APP_NOTICE: "Installing {app} on {type} {target}.", + APP_ALREADY_INSTALLED: "Please use $ csdx app:reinstall to reinstall the app.", } const uninstallAppMsg = { diff --git a/src/util/api-request-handler.ts b/src/util/api-request-handler.ts index 2cfcf52..c064bf1 100644 --- a/src/util/api-request-handler.ts +++ b/src/util/api-request-handler.ts @@ -27,26 +27,31 @@ export async function apiRequestHandler(params: RequestParams): Promise { try { let response; - if (method === "GET") { - response = await httpClient.get(url); - } else if (method === "POST") { - response = await httpClient.post(url, payload); - } else if (method === "PUT") { - response = await httpClient.put(url, payload); - } else if (method === "DELETE") { - response = await httpClient.delete(url); - } else { - throw new Error(`Unsupported HTTP method: ${method}`); + switch (method) { + case "GET": + response = await httpClient.get(url); + break; + case "POST": + response = await httpClient.post(url, payload); + break; + case "PUT": + response = await httpClient.put(url, payload); + break; + case "DELETE": + response = await httpClient.delete(url); + break; + default: + throw new Error(`Unsupported HTTP method: ${method}`); } const { status, data } = response; if (status >= 200 && status < 300) { return data; } - const error_message = data?.error + const errorMessage = data?.error ? formatErrors(data) : data?.error_message || "Something went wrong"; - throw error_message; + throw errorMessage; } catch (error) { throw error; } diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 83f3636..6a843e2 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -139,11 +139,10 @@ async function reinstallApp(params: { flags: FlagInput; type: string; developerHubBaseUrl: string; -}, -headers: { orgUid: string, manifestUid: string } -): Promise { - const { type, developerHubBaseUrl, flags } = params; - const {orgUid, manifestUid } = headers; + orgUid: string; + manifestUid: string; +}): Promise { + const { type, developerHubBaseUrl, flags, orgUid, manifestUid } = params; const payload = { target_type: type, target_uid: (flags["stack-api-key"] as any) || orgUid, @@ -152,14 +151,14 @@ headers: { orgUid: string, manifestUid: string } const url = `https://${developerHubBaseUrl}/manifests/${manifestUid}/reinstall`; try { const result = await apiRequestHandler({ - orgUid, + orgUid, payload, url, - method: "PUT" - }) - return result + method: "PUT", + }); + return result; } catch (err) { - throw err + throw err; } } @@ -254,9 +253,8 @@ async function fetchInstalledApps( return batchRequests.flat(); } - -// To remove the relative path -const sanitizePath = (str: string) => str?.replace(/^(\.\.(\/|\\|$))+/, ''); +// To remove the relative path +const sanitizePath = (str: string) => str?.replace(/^(\.\.(\/|\\|$))+/, ""); export { getOrganizations, @@ -271,5 +269,5 @@ export { uninstallApp, fetchInstalledApps, reinstallApp, - sanitizePath + sanitizePath, };