@shopletzy/cli
Advanced tools
Comparing version 1.0.3 to 1.0.4
{ | ||
"name": "@shopletzy/cli", | ||
"version": "1.0.3", | ||
"version": "1.0.4", | ||
"description": "Shopletzy CLI is a command line interface tool for interacting with the Shopletzy eCommerce platform", | ||
@@ -30,2 +30,3 @@ "main": "./src/index.js", | ||
"commander": "^10.0.0", | ||
"form-data": "^4.0.0", | ||
"inquirer": "^9.1.4", | ||
@@ -32,0 +33,0 @@ "jszip": "^3.10.1" |
@@ -9,2 +9,3 @@ import { slzconfig } from "../common/auth.js"; | ||
import path from "path"; | ||
import FormData from "form-data"; | ||
@@ -18,3 +19,3 @@ const log = console.log; | ||
export const createThemeCommand = async () => { | ||
export const initThemeCommand = async () => { | ||
try { | ||
@@ -54,3 +55,3 @@ let answers = await inquirer.prompt([ | ||
process.stdout.write("Creating new theme...\r"); | ||
process.stdout.write("Initializing new theme...\r"); | ||
@@ -81,3 +82,3 @@ const themeDir = answers.themeName; | ||
process.stdout.clearLine(); | ||
log(chalk.green("\nCreated successfully")); | ||
log(chalk.green("Initialized successfully")); | ||
log("\nRun below commands to start developement"); | ||
@@ -88,15 +89,11 @@ log(chalk.blueBright(`\n cd ${answers.themeName}`)); | ||
} catch (error) { | ||
log(chalk.red("Error creating theme")); | ||
log(error); | ||
log(chalk.red("Error initializing theme")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
export const themeDevCommand = async (storeUrl) => { | ||
// Check if config.json file and directories desktop, mobile, shared, img exist | ||
if ( | ||
!fs.existsSync("config.json") || | ||
!fs.existsSync("desktop") || | ||
!fs.existsSync("mobile") || | ||
!fs.existsSync("img") | ||
) { | ||
function ensureValidThemeDir() { | ||
const isValid = | ||
fs.existsSync("config.json") && fs.existsSync("desktop") && fs.existsSync("mobile") && fs.existsSync("img"); | ||
if (!isValid) { | ||
log( | ||
@@ -107,2 +104,9 @@ chalk.red( | ||
); | ||
} | ||
return isValid; | ||
} | ||
export const themeDevCommand = async (storeUrl) => { | ||
// Check if config.json file and directories desktop, mobile, shared, img exist | ||
if (!ensureValidThemeDir()) { | ||
return; | ||
@@ -197,3 +201,3 @@ } | ||
} | ||
console.log(err); | ||
log(err?.response?.data?.message || rr); | ||
log(chalk.red("Error uploading file. Please try again.")); | ||
@@ -235,3 +239,3 @@ process.exit(1); | ||
} catch (error) { | ||
console.error("Error uploading file", error); | ||
log(error?.response?.data?.message || error); | ||
log(chalk.red("Error uploading file. Please try again.")); | ||
@@ -256,3 +260,190 @@ process.exit(1); | ||
export const createThemeCommand = async () => { | ||
try { | ||
let answers = await inquirer.prompt([ | ||
{ | ||
type: "input", | ||
name: "name", | ||
message: "Enter theme name:", | ||
}, | ||
{ | ||
type: "input", | ||
name: "title", | ||
message: "Enter theme title:", | ||
}, | ||
]); | ||
if (!answers.name || !/^[A-z0-9-]{3,200}$/.test(answers.name)) { | ||
log( | ||
chalk.red( | ||
"Please provide a valid theme name. Theme name can only have alphanumeric characters and hyphens." | ||
) | ||
); | ||
return; | ||
} | ||
if (!answers.title || answers.title.length < 3 || answers.title.length > 200) { | ||
log( | ||
chalk.red( | ||
"Please provide a valid theme title. Theme title can only have alphanumeric characters and hyphens." | ||
) | ||
); | ||
return; | ||
} | ||
process.stdout.write("Creating new theme...\r"); | ||
const { data } = await axios.post(apiUrl + "/v1/themes", answers, { | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: "Bearer " + slzconfig.authToken, | ||
}, | ||
}); | ||
log(chalk.green("\nCreated successfully")); | ||
log("Theme ID: " + data._id); | ||
log(); | ||
} catch (error) { | ||
log(chalk.red("Error creating theme")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
export const listThemesCommand = async () => { | ||
try { | ||
const { data } = await axios.get(apiUrl + "/v1/developer/themes", { | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: "Bearer " + slzconfig.authToken, | ||
}, | ||
}); | ||
if (data.length === 0) { | ||
log(chalk.yellow("No themes found")); | ||
return; | ||
} | ||
// Define the table header and format using Chalk | ||
const header = chalk.bold(`${"id".padEnd(30)}\t${"name".padEnd(15)}\tversion\t\trelease\t\tstatus`); | ||
log(header); | ||
data.themes.forEach((theme) => { | ||
let latestReleaseVersion; | ||
if (theme.releases) { | ||
latestReleaseVersion = theme.releases[theme.releases.length - 1].version; | ||
} | ||
const row = `${theme._id.padEnd(30)}\t${theme.name.padEnd(15)}\t${theme.curVer || ""}\t\t${ | ||
latestReleaseVersion || "" | ||
}\t\t${theme.status}`; | ||
log(row); | ||
}); | ||
log(); | ||
} catch (error) { | ||
log(chalk.red("Error listing themes")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
export const uploadThemeCommand = async (themeId, version) => { | ||
try { | ||
if (!ensureValidThemeDir()) { | ||
return; | ||
} | ||
process.stdout.write("Creating theme bundle...\r"); | ||
// Compress all the files in the current theme directory and name the zip file as ${themeId}-${themeVersion}.zip | ||
const zipFileName = `${themeId}-${version}.zip`; | ||
const zip = new JSZip(); | ||
// Get current directory path | ||
function addFilesToZip(dir) { | ||
const files = fs.readdirSync(dir); | ||
for (const file of files) { | ||
const filePath = path.join(dir, file); | ||
const stat = fs.statSync(filePath); | ||
if (stat.isDirectory()) { | ||
addFilesToZip(filePath); | ||
} else { | ||
const content = fs.readFileSync(filePath); | ||
zip.file(file, content); | ||
} | ||
} | ||
} | ||
addFilesToZip(process.cwd()); | ||
process.stdout.clearLine(); | ||
process.stdout.write("Uploading theme...\r"); | ||
const form = new FormData(); | ||
form.append("version", version); | ||
form.append("themeBundle", zip.generateNodeStream({ type: "nodebuffer", streamFiles: true }), zipFileName); | ||
const { data } = await axios.put(apiUrl + "/v1/themes/" + themeId + "/upload", form, { | ||
headers: { | ||
...form.getHeaders(), | ||
Authorization: "Bearer " + slzconfig.authToken, | ||
}, | ||
}); | ||
process.stdout.clearLine(); | ||
log(chalk.green("Uploaded successfully")); | ||
log("\nRun `shopletzy theme publish -i <themeId> -v <version>` command to publish"); | ||
log(); | ||
} catch (error) { | ||
process.stdout.clearLine(); | ||
log(chalk.red("Error listing themes")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
export const publishThemeCommand = async (themeId, version) => { | ||
try { | ||
await axios.put( | ||
apiUrl + "/v1/themes/" + themeId + "/publish", | ||
{ version }, | ||
{ | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: "Bearer " + slzconfig.authToken, | ||
}, | ||
} | ||
); | ||
process.stdout.clearLine(); | ||
log(chalk.green("Published theme successfully")); | ||
log(); | ||
} catch (error) { | ||
process.stdout.clearLine(); | ||
log(chalk.red("Error publishing theme")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
export const unpublishThemeCommand = async (themeId) => { | ||
try { | ||
await axios.put( | ||
apiUrl + "/v1/themes/" + themeId + "/unpublish", | ||
{}, | ||
{ | ||
headers: { | ||
"Content-Type": "application/json", | ||
Authorization: "Bearer " + slzconfig.authToken, | ||
}, | ||
} | ||
); | ||
process.stdout.clearLine(); | ||
log(chalk.green("Unpublished theme successfully")); | ||
log(); | ||
} catch (error) { | ||
process.stdout.clearLine(); | ||
log(chalk.red("Error unpublishing theme")); | ||
log(error?.response?.data?.message || error); | ||
} | ||
}; | ||
// Execute a function when process terminates | ||
process.on("SIGINT", cleanup); |
@@ -5,3 +5,11 @@ #!/usr/bin/env node | ||
import { configureAuth, logoutCommand } from "./commands/login.js"; | ||
import { createThemeCommand, themeDevCommand } from "./commands/theme.js"; | ||
import { | ||
createThemeCommand, | ||
initThemeCommand, | ||
listThemesCommand, | ||
publishThemeCommand, | ||
themeDevCommand, | ||
unpublishThemeCommand, | ||
uploadThemeCommand, | ||
} from "./commands/theme.js"; | ||
import { loadShopletzyConfig } from "./common/auth.js"; | ||
@@ -47,9 +55,49 @@ | ||
theme | ||
.command("new") | ||
.description("Creates new theme") | ||
.command("init") | ||
.description("Initializes new theme directory with starter theme") | ||
.action(() => { | ||
initThemeCommand(); | ||
}); | ||
theme | ||
.command("create") | ||
.description("Creates new theme on store") | ||
.action((options) => { | ||
createThemeCommand(); | ||
}); | ||
theme | ||
.command("list") | ||
.description("Lists all your themes") | ||
.action((options) => { | ||
listThemesCommand(); | ||
}); | ||
theme | ||
.command("upload") | ||
.requiredOption("-i, --id <themeId>", "Id of the theme to upload") | ||
.requiredOption("-v, --version <version>", "Theme version (Eg: 1.0.0)") | ||
.description("Uploads new theme bundle to the store theme") | ||
.action((options) => { | ||
uploadThemeCommand(options.id, options.version); | ||
}); | ||
theme | ||
.command("publish") | ||
.requiredOption("-i, --id <themeId>", "Id of the theme") | ||
.requiredOption("-v, --version <version>", "Theme version (Eg: 1.0.0)") | ||
.description("Publishes uploaded theme release") | ||
.action((options) => { | ||
publishThemeCommand(options.id, options.version); | ||
}); | ||
theme | ||
.command("unpublish") | ||
.requiredOption("-i, --id <themeId>", "Id of the theme") | ||
.description("Unpublishes current theme release") | ||
.action((options) => { | ||
unpublishThemeCommand(options.id); | ||
}); | ||
loadShopletzyConfig(); | ||
program.parse(process.argv); |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
20491
545
8
+ Addedform-data@^4.0.0