Skip to content
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
62 changes: 35 additions & 27 deletions src/util/common-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,16 +97,16 @@ function fetchAppInstallations(
const { managementSdk } = options;
const app: any = flags["app-uid"];
return managementSdk
.organization(orgUid)
.app(app as string)
.installation()
.findAll()
.catch(error => {
const {log} = options;
cliux.loader("failed");
log("Some error occurred while fetching app installations.", "warn");
throw error // throwing error here instead of removing the catch block, as the loader needs to stopped in case there is an error.
})
.organization(orgUid)
.app(app as string)
.installation()
.findAll()
.catch((error) => {
const { log } = options;
cliux.loader("failed");
log("Some error occurred while fetching app installations.", "warn");
throw error; // throwing error here instead of removing the catch block, as the loader needs to stopped in case there is an error.
});
}

function deleteApp(flags: FlagInput, orgUid: string, options: CommonOptions) {
Expand Down Expand Up @@ -144,10 +144,10 @@ function fetchStack(flags: FlagInput, options: CommonOptions) {
async function getStacks(
options: CommonOptions,
orgUid: string,
skip: number= 0,
stacks: Stack[] = [],
skip: number = 0,
stacks: Stack[] = []
): Promise<Stack[]> {
const {log, managementSdk} = options;
const { log, managementSdk } = options;
const response = await managementSdk
.organization(orgUid)
.stacks({ include_count: true, limit: 100, asc: "name", skip: skip })
Expand All @@ -168,17 +168,26 @@ async function getStacks(
return stacks;
}

function uninstallApp(flags: FlagInput, orgUid: string, options: CommonOptions, installationUid: string) {
const {managementSdk} = options;
const app: unknown = flags['app-uid'];
function uninstallApp(
flags: FlagInput,
orgUid: string,
options: CommonOptions,
installationUid: string
) {
const { managementSdk } = options;
const app: unknown = flags["app-uid"];
return managementSdk
.organization(orgUid)
.app(app as string)
.installation(installationUid as string)
.uninstall()
.organization(orgUid)
.app(app as string)
.installation(installationUid as string)
.uninstall();
}

async function fetchInstalledApps(flags: FlagInput, orgUid: string, options: CommonOptions) {
async function fetchInstalledApps(
flags: FlagInput,
orgUid: string,
options: CommonOptions
) {
const { managementSdk, log } = options;
const apps = (await fetchApps(flags, orgUid, options)) || [];
let batchRequests = [];
Expand All @@ -196,8 +205,7 @@ async function fetchInstalledApps(flags: FlagInput, orgUid: string, options: Com
.installation()
.findAll();
return installations.items.length ? installations.items : null;
}
catch (error) {
} catch (error) {
log("Unable to fetch installations.", "warn");
log(error, "error");
throw error;
Expand All @@ -217,10 +225,10 @@ async function fetchInstalledApps(flags: FlagInput, orgUid: string, options: Com
return batchRequests.flat();
}

export {
getOrganizations,
getOrgAppUiLocation,
fetchApps,
export {
getOrganizations,
getOrgAppUiLocation,
fetchApps,
fetchApp,
fetchAppInstallations,
deleteApp,
Expand Down
166 changes: 96 additions & 70 deletions src/util/inquirer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,20 +7,20 @@ import {
FlagInput,
configHandler,
Stack,
ContentstackClient
ContentstackClient,
} from "@contentstack/cli-utilities";
import {Installation} from '@contentstack/management/types/app/installation'
import {AppTarget} from '@contentstack/management/types/app/index'
import { Installation } from "@contentstack/management/types/app/installation";
import { AppTarget } from "@contentstack/management/types/app/index";

import config from "../config";
import messages, { $t, commonMsg, errors, uninstallAppMsg } from "../messages";
import {
CommonOptions,
getOrganizations,
import {
CommonOptions,
getOrganizations,
getStacks,
fetchAppInstallations,
fetchInstalledApps,
fetchApps
fetchApps,
} from "./common-utils";

/**
Expand Down Expand Up @@ -87,7 +87,7 @@ async function getOrg(flags: FlagInput, options: CommonOptions) {

if (!(flags.org && find(organizations, { uid: flags.org }))) {
if (flags.org) {
throw new Error(messages.ORG_UID_NOT_FOUND)
throw new Error(messages.ORG_UID_NOT_FOUND);
}

flags.org = await cliux
Expand All @@ -103,46 +103,54 @@ async function getOrg(flags: FlagInput, options: CommonOptions) {
return flags.org;
}

async function getApp(flags: FlagInput, orgUid: string, options: CommonOptions) : Promise<Record<string, any> | undefined> {
async function getApp(
flags: FlagInput,
orgUid: string,
options: CommonOptions
): Promise<Record<string, any> | undefined> {
cliux.loader("Loading Apps");
const apps = (await fetchApps(flags, orgUid, options));
const apps = await fetchApps(flags, orgUid, options);
cliux.loader("done");

if (apps.length === 0) {
throw new Error(messages.APPS_NOT_FOUND)
throw new Error(messages.APPS_NOT_FOUND);
}

flags.app = await cliux
.inquire({
type: "search-list",
name: "App",
choices: apps,
message: messages.CHOOSE_APP
message: messages.CHOOSE_APP,
})
.then((name) => apps.find(app => app.name === name)?.uid)
.then((name) => apps.find((app) => app.name === name)?.uid);

return apps.find(app => app.uid === flags.app);
return apps.find((app) => app.uid === flags.app);
}

async function getInstalledApps(flags: FlagInput, orgUid: string, options: CommonOptions) : Promise<Record<string, any> | undefined> {
async function getInstalledApps(
flags: FlagInput,
orgUid: string,
options: CommonOptions
): Promise<Record<string, any> | undefined> {
cliux.loader("Loading Apps");
const apps = (await fetchInstalledApps(flags, orgUid, options));
const apps = await fetchInstalledApps(flags, orgUid, options);
cliux.loader("done");

if (apps.length === 0) {
throw new Error(messages.APPS_NOT_FOUND)
throw new Error(messages.APPS_NOT_FOUND);
}

flags.app = await cliux
.inquire({
type: "search-list",
name: "App",
choices: apps,
message: messages.CHOOSE_APP
message: messages.CHOOSE_APP,
})
.then((name) => apps.find(app => app.name === name)?.uid)
.then((name) => apps.find((app) => app.name === name)?.uid);

return apps.find(app => app.uid === flags.app);
return apps.find((app) => app.uid === flags.app);
}

/**
Expand Down Expand Up @@ -176,107 +184,125 @@ async function getDeveloperHubUrl(): Promise<string> {
return developerHubBaseUrl;
}

async function getStack(orgUid: string, options: CommonOptions): Promise<Record<string, any> | undefined> {
async function getStack(
orgUid: string,
options: CommonOptions
): Promise<Record<string, any> | undefined> {
cliux.loader("Loading Stacks");
const stacks = (await getStacks(options, orgUid)) || [];
cliux.loader("done");

if (stacks.length === 0) {
// change this to stacks not found
throw new Error(messages.APPS_NOT_FOUND)
throw new Error(messages.APPS_NOT_FOUND);
}

const selectedStack = await cliux
.inquire({
type: "search-list",
name: "Stack",
choices: stacks,
message: messages.CHOOSE_A_STACK
message: messages.CHOOSE_A_STACK,
})
.then((name) => stacks.find(stack => stack.name === name))
.then((name) => stacks.find((stack) => stack.name === name));

return selectedStack;
}

async function getInstallation(
flags: FlagInput,
orgUid: string,
flags: FlagInput,
orgUid: string,
managementSdkForStacks: ContentstackClient,
appType: AppTarget,
options:CommonOptions,
uninstallAll?: boolean,
) : Promise<string> {
const {log} = options;
if (appType === 'stack') {
options: CommonOptions,
uninstallAll?: boolean
): Promise<string> {
const { log } = options;
if (appType === "stack") {
cliux.loader("Loading App Installations");
}
let {items: installations} = (await fetchAppInstallations(flags, orgUid, options)) || [];
let { items: installations } = (await fetchAppInstallations(
flags,
orgUid,
options
)) || { items: [] };

// console.log(installations)
if (!installations?.length) {
if (appType === "stack") cliux.loader("done")
throw new Error(messages.NO_INSTALLATIONS_FOUND)
if (appType === "stack") cliux.loader("done");
throw new Error(messages.NO_INSTALLATIONS_FOUND);
}

let selectedInstallation: string;

if (appType === 'stack') {
if (appType === "stack") {
// fetch stacks from where the app has to be uninstalled
cliux.loader("done");
const stacks: Stack[] = await getStacks({managementSdk: managementSdkForStacks, log: options.log}, orgUid);
installations = populateMissingDataInInstallations(installations as [Installation], stacks)
const stacks: Stack[] = await getStacks(
{ managementSdk: managementSdkForStacks, log: options.log },
orgUid
);
installations = populateMissingDataInInstallations(
installations as [Installation],
stacks
);
// To support uninstall all flag
if (uninstallAll) {
return installations.map(installation => installation.uid).join(',')
return installations.map((installation) => installation.uid).join(",");
}
let _selectedInstallation: string[] = await cliux
.inquire({
type: 'checkbox',
name: 'appInstallation',
let _selectedInstallation: string[] = await cliux.inquire({
type: "checkbox",
name: "appInstallation",
choices: installations,
message: messages.CHOOSE_AN_INSTALLATION,
validate: (input) => {
if (isEmpty(input)) {
return $t(errors.NOT_EMPTY, { value: "stack value"});
return $t(errors.NOT_EMPTY, { value: "stack value" });
}
return true;
}
})
selectedInstallation = _selectedInstallation.join(',')
},
});
selectedInstallation = _selectedInstallation.join(",");
} else {
// as this is an organization app, and it is supposed to only be installed on the source organization
// it will be uninstalled from the selected organization
selectedInstallation = installations.pop()?.uid || ""
selectedInstallation = installations.pop()?.uid || "";
}

log($t(uninstallAppMsg.UNINSTALLING_APP, {
type: appType
}), "info")

return selectedInstallation
log(
$t(uninstallAppMsg.UNINSTALLING_APP, {
type: appType,
}),
"info"
);

return selectedInstallation;
}

function populateMissingDataInInstallations(installations: [Installation], stacks: Stack[]): [Installation] {
let result = installations.map(installation => {
let stack = stacks.filter(stack => stack.api_key === installation.target.uid)?.pop()
function populateMissingDataInInstallations(
installations: [Installation],
stacks: Stack[]
): [Installation] {
let result = installations.map((installation) => {
let stack = stacks
.filter((stack) => stack.api_key === installation.target.uid)
?.pop();
installation.name = stack?.name || installation.target.uid;
installation.value = installation.uid;
return installation;
}) as [Installation];

if (result.length > 0) {
return result
return result;
}

return installations

return installations;
}

export {
getOrg,
getAppName,
getDirName,
getDeveloperHubUrl,
export {
getOrg,
getAppName,
getDirName,
getDeveloperHubUrl,
getApp,
getInstalledApps,
getStack,
Expand Down