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
64 changes: 54 additions & 10 deletions src/commands/app/create.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import * as tmp from "tmp";
import AdmZip from "adm-zip";
import omit from "lodash/omit";
import pick from "lodash/pick";
import * as shell from "shelljs";
import merge from "lodash/merge";
Expand All @@ -14,7 +15,13 @@ import {
writeFileSync,
createWriteStream,
} from "fs";
import { ux, cliux, flags, HttpClient, configHandler } from "@contentstack/cli-utilities";
import {
ux,
cliux,
flags,
HttpClient,
configHandler,
} from "@contentstack/cli-utilities";

import { BaseCommand } from "../../base-command";
import { AppManifest, AppType } from "../../types";
Expand All @@ -28,6 +35,11 @@ import {

export default class Create extends BaseCommand<typeof Create> {
private appData!: AppManifest;
private tempAppData = {
name: "",
target_type: "",
ui_location: { locations: undefined },
} as any;

static description =
"Create a new app in Developer Hub and optionally clone a boilerplate locally.";
Expand Down Expand Up @@ -62,15 +74,14 @@ export default class Create extends BaseCommand<typeof Create> {
async run(): Promise<void> {
this.sharedConfig.org = this.flags.org;
this.sharedConfig.appName = this.flags.name;
this.appData = require(this.sharedConfig.manifestPath);

await this.flagsPromptQueue();

this.appData.name = this.sharedConfig.appName;
this.appData.target_type = this.flags["app-type"] as AppType;
this.tempAppData.name = this.sharedConfig.appName;
this.tempAppData.target_type = this.flags["app-type"] as AppType;

if (this.flags["app-type"] === AppType.ORGANIZATION) {
this.appData.ui_location.locations = getOrgAppUiLocation();
this.tempAppData.ui_location.locations = getOrgAppUiLocation();
}

try {
Expand All @@ -84,6 +95,7 @@ export default class Create extends BaseCommand<typeof Create> {
) {
await this.boilerplateFlow();
} else {
this.manageManifestToggeling();
await this.registerTheAppOnDeveloperHub(false);
}
} catch (error: Error | any) {
Expand All @@ -105,6 +117,8 @@ export default class Create extends BaseCommand<typeof Create> {
await this.unZipBoilerplate(await this.cloneBoilerplate());
tmp.setGracefulCleanup(); // NOTE If graceful cleanup is set, tmp will remove all controlled temporary objects on process exit

this.manageManifestToggeling();

// NOTE Step 2: Registering the app
await this.registerTheAppOnDeveloperHub();

Expand All @@ -114,7 +128,7 @@ export default class Create extends BaseCommand<typeof Create> {
ux.action.stop();
this.log(
this.$t(this.messages.START_APP_COMMAND, {
command: `cd ${this.sharedConfig.folderPath} && npm run start`,
command: `cd "${this.sharedConfig.folderPath}" && npm run start`,
}),
"info"
);
Expand All @@ -133,10 +147,12 @@ export default class Create extends BaseCommand<typeof Create> {
}

//Auto select org in case of oauth
this.sharedConfig.org = configHandler.get('oauthOrgUid') ?? (await getOrg(this.flags, {
log: this.log,
managementSdk: this.managementSdk,
}));
this.sharedConfig.org =
configHandler.get("oauthOrgUid") ??
(await getOrg(this.flags, {
log: this.log,
managementSdk: this.managementSdk,
}));
}

/**
Expand Down Expand Up @@ -208,6 +224,34 @@ export default class Create extends BaseCommand<typeof Create> {
});
}

/**
* @method manageManifestToggeling
*
* The function manages toggling of the manifest file based on the app type, removing the
* "ui_location" property if the app type is an organization.
*/
manageManifestToggeling() {
// NOTE Use boilerplate manifest if exist
const manifestPath = resolve(
this.sharedConfig.folderPath || "",
"manifest.json"
);

if (existsSync(manifestPath)) {
this.sharedConfig.manifestPath = manifestPath;
}

let manifest = require(this.sharedConfig.manifestPath);

if (this.flags["app-type"] === AppType.ORGANIZATION) {
manifest = omit(manifest, ["ui_location"]);
} else {
this.tempAppData = omit(this.tempAppData, ["ui_location"]);
}

this.appData = merge(manifest, this.tempAppData);
}

/**
* @method registerTheAppOnDeveloperHub
*
Expand Down
12 changes: 7 additions & 5 deletions src/commands/app/update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import { existsSync, readFileSync, writeFileSync } from "fs";

import { $t, appUpdate } from "../../messages";
import { fetchApp, getApp, getOrg } from "../../util";
import {AppCLIBaseCommand} from "../../app-cli-base-coomand";
import { AppCLIBaseCommand } from "../../app-cli-base-coomand";

export default class Update extends AppCLIBaseCommand {
private orgUid!: string;
Expand All @@ -28,12 +28,14 @@ export default class Update extends AppCLIBaseCommand {

async run(): Promise<void> {
try {
//if working directory isn't app directory
if(!this.manifestData){
// 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.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 },
{
Expand Down
76 changes: 56 additions & 20 deletions src/config/manifest.json
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
{
"icon": "",
"description": "",
"target_type": "stack",
"icon": "",
"name": "",
"visibility": "private",
"organization_uid": "",
"target_type": "stack",
"visibility": "private",
"uid": "",
"ui_location": {
"signed": false,
"base_url": "http://localhost:3000",
Expand All @@ -13,20 +14,22 @@
"type": "cs.cm.stack.custom_field",
"meta": [
{
"path": "/custom-field",
"signed": true,
"multiple": false,
"path": "/#/custom-field",
"signed": false,
"enabled": true,
"data_type": "number"
"data_type": "json"
}
]
},
{
"type": "cs.cm.stack.config",
"type": "cs.cm.stack.dashboard",
"meta": [
{
"path": "/app-configuration",
"signed": true,
"enabled": true
"path": "/#/stack-dashboard",
"signed": false,
"enabled": true,
"default_width": "half"
}
]
},
Expand All @@ -35,35 +38,68 @@
"meta": [
{
"blur": false,
"path": "/asset-sidebar",
"signed": true,
"path": "/#/asset-sidebar",
"signed": false,
"enabled": true,
"width": 500
}
]
},
{
"type": "cs.cm.stack.dashboard",
"type": "cs.cm.stack.sidebar",
"meta": [
{
"path": "/stack-dashboard",
"signed": true,
"path": "/#/entry-sidebar",
"signed": false,
"enabled": true
}
]
},
{
"type": "cs.cm.stack.full_page",
"meta": [
{
"path": "/#/full-page",
"signed": false,
"enabled": true
}
]
},
{
"type": "cs.cm.stack.field_modifier",
"meta": [
{
"path": "/#/field-modifier",
"signed": false,
"enabled": true,
"default_width": "half"
"allowed_types": ["$all"]
}
]
},
{
"type": "cs.cm.stack.sidebar",
"type": "cs.cm.stack.config",
"meta": [
{
"path": "/#/app-configuration",
"signed": false,
"enabled": true
}
]
},
{
"type": "cs.cm.stack.rte",
"meta": [
{
"path": "/entry-sidebar",
"signed": true,
"path": "/json-rte.js",
"signed": false,
"enabled": true
}
]
}
]
},
"uid": ""
"hosting": {
"provider": "external",
"deployment_url": "http://localhost:3000"
}
}
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
Loading