diff --git a/package-lock.json b/package-lock.json index e508ad7..c137b94 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@contentstack/apps-cli", - "version": "1.2.1", + "version": "1.3.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "@contentstack/apps-cli", - "version": "1.2.1", + "version": "1.3.0", "license": "MIT", "dependencies": { "@contentstack/cli-command": "^1.2.18", diff --git a/package.json b/package.json index 72b113b..d4c5240 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@contentstack/apps-cli", - "version": "1.2.1", + "version": "1.3.0", "description": "App ClI", "author": "Contentstack CLI", "homepage": "https://github.com/contentstack/contentstack-apps-cli", diff --git a/src/commands/app/create.ts b/src/commands/app/create.ts index c1b8102..3c9cb88 100644 --- a/src/commands/app/create.ts +++ b/src/commands/app/create.ts @@ -21,18 +21,19 @@ import { flags, HttpClient, configHandler, - FlagInput + FlagInput, } from "@contentstack/cli-utilities"; import { BaseCommand } from "../../base-command"; -import { AppManifest, AppType } from "../../types"; +import { AppManifest, AppType, BoilerplateAppType } from "../../types"; import { appCreate, commonMsg } from "../../messages"; import { getOrg, getAppName, getDirName, getOrgAppUiLocation, - sanitizePath + sanitizePath, + selectedBoilerplate, } from "../../util"; export default class Create extends BaseCommand { @@ -96,7 +97,18 @@ export default class Create extends BaseCommand { message: this.messages.CONFIRM_CLONE_BOILERPLATE, })) ) { - await this.boilerplateFlow(); + const boilerplate: BoilerplateAppType = await selectedBoilerplate(); + + if (boilerplate) { + this.sharedConfig.boilerplateName = boilerplate.name + .toLowerCase() + .replace(/ /g, "-"); + this.sharedConfig.appBoilerplateGithubUrl = boilerplate.link; + this.sharedConfig.appName = await getAppName( + this.sharedConfig.boilerplateName + ); + await this.boilerplateFlow(); + } } else { this.manageManifestToggeling(); await this.registerTheAppOnDeveloperHub(false); @@ -198,7 +210,11 @@ export default class Create extends BaseCommand { const zip = new AdmZip(filepath); const dataDir = this.flags["data-dir"] ?? process.cwd(); let targetPath = resolve(dataDir, this.sharedConfig.appName); - const sourcePath = resolve(dataDir, this.sharedConfig.boilerplateName); + + // Get the directory inside the zip file + const zipEntries = zip.getEntries(); + const firstEntry = zipEntries[0]; + const sourcePath = resolve(dataDir, firstEntry.entryName.split("/")[0]); if (this.flags["data-dir"] && !existsSync(this.flags["data-dir"])) { mkdirSync(this.flags["data-dir"], { recursive: true }); @@ -235,10 +251,7 @@ export default class Create extends BaseCommand { */ manageManifestToggeling() { // NOTE Use boilerplate manifest if exist - const manifestPath = resolve( - this.sharedConfig.folderPath || "", - "manifest.json" - ); + const manifestPath = resolve(this.sharedConfig.folderPath, "manifest.json"); if (existsSync(manifestPath)) { this.sharedConfig.manifestPath = manifestPath; @@ -301,7 +314,10 @@ export default class Create extends BaseCommand { this.appData = merge(this.appData, pick(response, validKeys)); if (saveManifest) { writeFileSync( - resolve(this.sharedConfig.folderPath, "manifest.json"), + resolve( + this.sharedConfig.folderPath, + "manifest.json" + ), JSON.stringify(this.appData), { encoding: "utf8", diff --git a/src/config/index.ts b/src/config/index.ts index b0ba642..a85b1da 100644 --- a/src/config/index.ts +++ b/src/config/index.ts @@ -8,6 +8,7 @@ const config = { appBoilerplateGithubUrl: "https://codeload.github.com/contentstack/marketplace-app-boilerplate/zip/refs/heads/main", defaultAppFileName: "manifest", + boilerplatesUrl: 'https://marketplace-artifacts.contentstack.com/cli/starter-template.json' }; export default config; diff --git a/src/types/app.ts b/src/types/app.ts index 0aa3f8f..d84c827 100644 --- a/src/types/app.ts +++ b/src/types/app.ts @@ -140,3 +140,12 @@ export interface LaunchProjectRes { environmentUid: any; developerHubAppUid: any; } + +export interface BoilerplateAppType { + name: string; + description?: string; + link: string; + tags?: string[]; + created_at?: string; + updated_at?: string; +} diff --git a/src/util/common-utils.ts b/src/util/common-utils.ts index 4a19316..551a757 100644 --- a/src/util/common-utils.ts +++ b/src/util/common-utils.ts @@ -7,6 +7,7 @@ import { cliux, Stack, FsUtility, + HttpClient, } from "@contentstack/cli-utilities"; import { projectsQuery } from "../graphql/queries"; import { apiRequestHandler } from "./api-request-handler"; @@ -19,6 +20,7 @@ import { } from "../types"; import { askProjectName } from "./inquirer"; import { deployAppMsg } from "../messages"; +import config from "../config"; export type CommonOptions = { log: LogFn; @@ -396,6 +398,14 @@ const handleProjectNameConflict = async ( } return projectName; }; +async function fetchBoilerplateDetails(): Promise[]> { + try { + const content = await new HttpClient().get(config.boilerplatesUrl); + return content?.data?.templates ?? []; + } catch (error) { + throw error; + } +} export { getOrganizations, @@ -418,4 +428,5 @@ export { disconnectApp, formatUrl, handleProjectNameConflict, + fetchBoilerplateDetails }; diff --git a/src/util/inquirer.ts b/src/util/inquirer.ts index 455b33c..c174821 100644 --- a/src/util/inquirer.ts +++ b/src/util/inquirer.ts @@ -27,6 +27,7 @@ import { fetchApps, sanitizePath, MarketPlaceOptions, + fetchBoilerplateDetails, } from "./common-utils"; import { LaunchProjectRes } from "../types"; @@ -385,6 +386,21 @@ function inquireRequireValidation(input: any): string | boolean { return true; } +const selectedBoilerplate = async (): Promise => { + const boilerplates = await fetchBoilerplateDetails(); + + return await cliux + .inquire({ + type: "search-list", + name: "App", + choices: boilerplates.map((bp) => bp.name), + message: "Select a boilerplate from search list", + }) + .then((name) => { + return find(boilerplates, (boilerplate) => boilerplate.name === name); + }); +}; + export { getOrg, getAppName, @@ -399,5 +415,6 @@ export { askProjectType, askConfirmation, selectProject, - askProjectName + askProjectName, + selectedBoilerplate, };