Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@hypermode/modus-cli

Package Overview
Dependencies
Maintainers
0
Versions
31
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@hypermode/modus-cli - npm Package Compare versions

Comparing version 0.13.0-test5 to 0.13.0

dist/commands/info/index.d.ts

3

dist/commands/build/index.d.ts

@@ -9,3 +9,4 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
};

@@ -12,0 +13,0 @@ static description: string;

@@ -29,4 +29,9 @@ /*

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -46,3 +51,3 @@ }),

const app = await getAppInfo(appPath);
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -53,6 +58,11 @@ }

const results = await withSpinner("Building " + app.name, async () => {
const execOpts = {
cwd: appPath,
env: process.env,
shell: true,
};
switch (app.sdk) {
case SDK.AssemblyScript:
if (!(await fs.exists(path.join(appPath, "node_modules")))) {
const results = await execFileWithExitCode("npm", ["install"], { cwd: appPath, env: process.env });
const results = await execFileWithExitCode("npm", ["install"], execOpts);
if (results.exitCode !== 0) {

@@ -63,3 +73,3 @@ this.logError("Failed to install dependencies");

}
return await execFileWithExitCode("npx", ["modus-as-build"], { cwd: appPath, env: process.env });
return await execFileWithExitCode("npx", ["modus-as-build"], execOpts);
case SDK.Go:

@@ -78,3 +88,3 @@ const version = app.sdkVersion || (await vi.getLatestInstalledSdkVersion(app.sdk, true));

}
return await execFileWithExitCode(buildTool, ["."], { cwd: appPath, env: process.env });
return await execFileWithExitCode(buildTool, ["."], execOpts);
default:

@@ -81,0 +91,0 @@ this.logError("Unsupported SDK");

@@ -9,7 +9,9 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
runtime: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
prerelease: import("@oclif/core/interfaces").BooleanFlag<boolean>;
nowatch: import("@oclif/core/interfaces").BooleanFlag<boolean>;
freq: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
"no-build": import("@oclif/core/interfaces").BooleanFlag<boolean>;
"no-watch": import("@oclif/core/interfaces").BooleanFlag<boolean>;
delay: import("@oclif/core/interfaces").OptionFlag<number, import("@oclif/core/interfaces").CustomOptions>;
};

@@ -19,3 +21,6 @@ static description: string;

run(): Promise<void>;
private watchForEnvFileChanges;
private watchForManifestChanges;
private watchForAppCodeChanges;
private logError;
}

@@ -14,9 +14,15 @@ /*

import chalk from "chalk";
import pm from "picomatch";
import chokidar from "chokidar";
import * as fs from "../../util/fs.js";
import * as vi from "../../util/versioninfo.js";
import * as installer from "../../util/installer.js";
import { SDK } from "../../custom/globals.js";
import { getHeader } from "../../custom/header.js";
import { getAppInfo } from "../../util/appinfo.js";
import { isOnline, withSpinner } from "../../util/index.js";
import { readHypermodeSettings } from "../../util/hypermode.js";
import BuildCommand from "../build/index.js";
const MANIFEST_FILE = "modus.json";
const ENV_FILES = [".env", ".env.local", ".env.development", ".env.dev", ".env.development.local", ".env.dev.local"];
export default class DevCommand extends Command {

@@ -31,4 +37,9 @@ static args = {

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -43,12 +54,15 @@ }),

aliases: ["pre"],
description: "Use a prerelease version of the Modus runtime. Not needed if specifying a runtime version.",
description: "Use a prerelease version of the Modus runtime. Not needed if specifying a runtime version.",
}),
nowatch: Flags.boolean({
aliases: ["no-watch"],
"no-build": Flags.boolean({
aliases: ["nobuild"],
description: "Don't build the app before running (or when watching for changes)",
}),
"no-watch": Flags.boolean({
aliases: ["nowatch"],
description: "Don't watch app code for changes",
}),
freq: Flags.integer({
char: "f",
description: "Frequency to check for changes when using --watch",
default: 3000,
delay: Flags.integer({
description: "Delay (in milliseconds) between file change detection and rebuild",
default: 500,
}),

@@ -61,4 +75,4 @@ };

const appPath = path.resolve(args.path);
if (!(await fs.exists(path.join(appPath, "modus.json")))) {
this.log(chalk.red("A modus.json file was not found at " + appPath));
if (!(await fs.exists(path.join(appPath, MANIFEST_FILE)))) {
this.log(chalk.red(`A ${MANIFEST_FILE} file was not found at ${appPath}`));
this.log(chalk.red("Please either execute the modus command from the app directory, or specify the path to the app you want to run."));

@@ -69,3 +83,3 @@ this.exit(1);

const { sdk, sdkVersion } = app;
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -79,5 +93,5 @@ }

}
catch {
catch (e) {
spinner.fail(chalk.red(`Failed to download ${sdkText}`));
this.exit(1);
throw e;
}

@@ -96,5 +110,5 @@ spinner.succeed(chalk.dim(`Installed ${sdkText}`));

}
catch {
catch (e) {
spinner.fail(chalk.red("Failed to download " + runtimeText));
this.exit(1);
throw e;
}

@@ -118,5 +132,5 @@ spinner.succeed(chalk.dim("Installed " + runtimeText));

}
catch {
catch (e) {
spinner.fail(chalk.red("Failed to download " + runtimeText));
this.exit(1);
throw e;
}

@@ -142,42 +156,209 @@ spinner.succeed(chalk.dim("Installed " + runtimeText));

const runtimePath = path.join(vi.getRuntimePath(runtimeVersion), "modus_runtime" + ext);
await BuildCommand.run([appPath, "--no-logo"]);
spawn(runtimePath, ["-appPath", path.join(appPath, "build")], {
stdio: "inherit",
env: {
...process.env,
MODUS_ENV: "dev",
// Build the app on first run (this includes copying the manifest file)
if (!flags["no-build"]) {
await BuildCommand.run([appPath, "--no-logo"]);
}
const appBuildPath = path.join(appPath, "build");
// Copy env files to the build directory
await copyEnvFiles(appPath, appBuildPath);
// Read Hypermode settings if they exist, so they can be forwarded to the runtime
const hypSettings = await readHypermodeSettings();
const env = {
...process.env,
MODUS_ENV: "dev",
HYP_EMAIL: hypSettings.email,
HYP_JWT: hypSettings.jwt,
HYP_ORG_ID: hypSettings.orgId,
};
// Spawn the runtime child process
const child = spawn(runtimePath, ["-appPath", appBuildPath, "-refresh=1s"], {
stdio: ["inherit", "inherit", "pipe"],
env: env,
});
child.stderr.pipe(process.stderr);
// Handle the runtime process exit
child.on("close", (code) => {
// note: can't use "this.exit" here because it would throw an unhandled exception
// but "process.exit" works fine.
if (code) {
this.log(chalk.magentaBright(`Runtime terminated with code ${code}`) + "\n");
process.exit(code);
}
else {
this.log(chalk.magentaBright("Runtime terminated successfully.") + "\n");
process.exit();
}
});
// Forward SIGINT and SIGTERM to the child process for graceful shutdown from user ctrl+c or kill.
process.on("SIGINT", () => {
if (child && !child.killed) {
child.kill("SIGINT");
}
});
process.on("SIGTERM", () => {
if (child && !child.killed) {
child.kill("SIGTERM");
}
});
// Watch for changes in the app directory and rebuild the app when changes are detected
if (!flags["no-watch"]) {
this.watchForEnvFileChanges(appPath, child.stderr);
this.watchForManifestChanges(appPath, child.stderr);
if (!flags["no-build"]) {
this.watchForAppCodeChanges(appPath, sdk, child.stderr, flags.delay);
}
}
}
watchForEnvFileChanges(appPath, runtimeOutput) {
// Whenever any of the env files change, copy to the build directory.
// The runtime will automatically reload them when it detects a change to the copies in the build folder.
const sourcePaths = ENV_FILES.map((file) => path.join(appPath, file));
const onAddOrChange = async (sourcePath) => {
const filename = path.basename(sourcePath);
const outputPath = path.join(appPath, "build", filename);
try {
runtimeOutput.pause();
this.log();
this.log(chalk.magentaBright(`Detected change in ${filename} file. Applying...`));
await fs.copyFile(sourcePath, outputPath);
}
catch (e) {
this.log(chalk.red(`Failed to copy ${filename} to build directory.`), e);
}
finally {
this.log();
runtimeOutput.resume();
}
};
chokidar
.watch(appPath, {
ignored: (filePath) => {
if (filePath === appPath) {
return false;
}
return !ENV_FILES.includes(path.basename(filePath));
},
ignoreInitial: true,
persistent: true,
})
.on("add", onAddOrChange)
.on("change", onAddOrChange)
.on("unlink", async (sourcePath) => {
const filename = path.basename(sourcePath);
const outputPath = path.join(appPath, "build", filename);
try {
runtimeOutput.pause();
this.log();
this.log(chalk.magentaBright(`Detected ${filename} deleted. Applying...`));
await fs.unlink(outputPath);
}
catch (e) {
this.log(chalk.red(`Failed to delete ${filename} from build directory.`), e);
}
finally {
this.log();
runtimeOutput.resume();
}
});
if (!flags.nowatch) {
const delay = flags.freq;
let lastModified = 0;
let lastBuild = 0;
let paused = true;
setInterval(async () => {
if (paused) {
return;
}
watchForManifestChanges(appPath, runtimeOutput) {
// Whenever the manifest file changes, copy it to the build directory.
// The runtime will automatically reload the manifest when it detects a change to the copy in the build folder.
const sourcePath = path.join(appPath, MANIFEST_FILE);
const outputPath = path.join(appPath, "build", MANIFEST_FILE);
const onAddOrChange = async () => {
try {
runtimeOutput.pause();
this.log();
this.log(chalk.magentaBright("Detected manifest change. Applying..."));
await fs.copyFile(sourcePath, outputPath);
}
catch (e) {
this.log(chalk.red(`Failed to copy ${MANIFEST_FILE} to build directory.`), e);
}
finally {
this.log();
runtimeOutput.resume();
}
};
chokidar
.watch(sourcePath, {
ignoreInitial: true,
persistent: true,
})
.on("add", onAddOrChange)
.on("change", onAddOrChange)
.on("unlink", async () => {
try {
runtimeOutput.pause();
this.log();
this.log(chalk.magentaBright("Detected manifest deleted. Applying..."));
await fs.unlink(outputPath);
}
catch (e) {
this.log(chalk.red(`Failed to delete ${MANIFEST_FILE} from build directory.`), e);
}
finally {
this.log();
runtimeOutput.resume();
}
});
}
watchForAppCodeChanges(appPath, sdk, runtimeOutput, delay) {
let lastModified = 0;
let lastBuild = 0;
let paused = true;
setInterval(async () => {
if (paused) {
return;
}
paused = true;
if (lastBuild > lastModified) {
return;
}
lastBuild = Date.now();
try {
runtimeOutput.pause();
this.log();
this.log(chalk.magentaBright("Detected source code change. Rebuilding..."));
this.log();
await BuildCommand.run([appPath, "--no-logo"]);
}
catch (e) {
this.log(chalk.magenta("Waiting for more changes..."));
this.log(chalk.dim("Press Ctrl+C at any time to stop the server."));
}
finally {
runtimeOutput.resume();
}
}, delay);
const globs = getGlobsToWatch(sdk);
// NOTE: The built-in fs.watch or fsPromises.watch is insufficient for our needs.
// Instead, we use chokidar for consistent behavior in cross-platform file watching.
const pmOpts = { posixSlashes: true };
chokidar
.watch(appPath, {
ignored: (filePath, stats) => {
const relativePath = path.relative(appPath, filePath);
if (!stats || !relativePath)
return false;
let ignore = false;
if (pm(globs.excluded, pmOpts)(relativePath)) {
ignore = true;
}
paused = true;
if (lastBuild > lastModified) {
return;
else if (stats.isFile()) {
ignore = !pm(globs.included, pmOpts)(relativePath);
}
lastBuild = Date.now();
try {
this.log();
this.log(chalk.magentaBright("Detected change. Rebuilding..."));
this.log();
await BuildCommand.run([appPath, "--no-logo"]);
if (process.env.MODUS_DEBUG) {
this.log(chalk.dim(`${ignore ? "ignored: " : "watching:"} ${relativePath}`));
}
catch { }
}, delay);
(async () => {
const watcher = fs.watch(appPath, { recursive: true });
for await (const event of watcher) {
if (event.filename && path.dirname(event.filename) !== "build") {
lastModified = Date.now();
paused = false;
}
}
})();
}
return ignore;
},
ignoreInitial: true,
persistent: true,
})
.on("all", () => {
lastModified = Date.now();
paused = false;
});
}

@@ -188,2 +369,31 @@ logError(message) {

}
function getGlobsToWatch(sdk) {
const included = [];
const excluded = [".git/**", "build/**"];
switch (sdk) {
case SDK.AssemblyScript:
included.push("**/*.ts", "**/asconfig.json", "**/tsconfig.json", "**/package.json");
excluded.push("node_modules/**");
break;
case SDK.Go:
included.push("**/*.go", "**/go.mod");
excluded.push("**/*_generated.go", "**/*.generated.go", "**/*_test.go");
break;
default:
throw new Error(`Unsupported SDK: ${sdk}`);
}
return { included, excluded };
}
async function copyEnvFiles(appPath, buildPath) {
for (const file of ENV_FILES) {
const src = path.join(appPath, file);
const dest = path.join(buildPath, file);
if (await fs.exists(src)) {
await fs.copyFile(src, dest);
}
else if (await fs.exists(dest)) {
await fs.unlink(dest);
}
}
}
//# sourceMappingURL=index.js.map

@@ -6,7 +6,7 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
name: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
dir: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
sdk: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
template: import("@oclif/core/interfaces").OptionFlag<string | undefined, import("@oclif/core/interfaces").CustomOptions>;
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -16,9 +16,5 @@ prerelease: import("@oclif/core/interfaces").BooleanFlag<boolean>;

run(): Promise<void>;
private promptAppName;
private promptInstallPath;
private promptSdkSelection;
private promptTemplate;
private createApp;
private logError;
private confirmAction;
private abort;
}

@@ -19,5 +19,9 @@ /*

import { GitHubOwner, GitHubRepo, MinGoVersion, MinNodeVersion, MinTinyGoVersion, ModusHomeDir, SDK, parseSDK } from "../../custom/globals.js";
import { ask, clearLine, withSpinner } from "../../util/index.js";
import { withSpinner } from "../../util/index.js";
import { extract } from "../../util/tar.js";
import SDKInstallCommand from "../sdk/install/index.js";
import { getHeader } from "../../custom/header.js";
import * as inquirer from "@inquirer/prompts";
import { getGoVersion, getTinyGoVersion } from "../../util/systemVersions.js";
const MODUS_DEFAULT_TEMPLATE_NAME = "default";
export default class NewCommand extends Command {

@@ -27,4 +31,9 @@ static description = "Create a new Modus app";

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -45,6 +54,6 @@ }),

}),
template: Flags.string({
char: "t",
description: "Template to use",
}),
// template: Flags.string({
// char: "t",
// description: "Template to use",
// }),
force: Flags.boolean({

@@ -63,78 +72,57 @@ char: "f",

async run() {
const { flags } = await this.parse(NewCommand);
if (!flags.nologo) {
this.log(getHeader(this.config.version));
try {
const { flags } = await this.parse(NewCommand);
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));
}
this.log(chalk.hex("#A585FF")(NewCommand.description) + "\n");
let sdk;
if (flags.sdk) {
sdk = parseSDK(flags.sdk);
}
else {
const sdkInput = await inquirer.select({
message: "Select a SDK",
default: SDK.Go,
choices: [
{
value: SDK.Go,
},
{
value: SDK.AssemblyScript,
},
],
});
sdk = parseSDK(sdkInput);
}
const defaultAppName = getDefaultAppNameBySdk(sdk);
let name = flags.name ||
(await inquirer.input({
message: "Pick a name for your app:",
default: defaultAppName,
}));
name = toValidAppName(name);
const dir = flags.dir || "." + path.sep + name;
if (!flags.force && (await fs.exists(dir))) {
const confirmed = await inquirer.confirm({ message: `Directory ${dir} already exists. Do you want to overwrite it?`, default: false });
if (!confirmed) {
this.abort();
}
}
if (!flags.force) {
const confirmed = await inquirer.confirm({ message: "Continue?", default: true });
if (!confirmed) {
this.abort();
}
}
this.log();
await this.createApp(name, dir, sdk, MODUS_DEFAULT_TEMPLATE_NAME, flags.force, flags.prerelease);
}
this.log(chalk.hex("#A585FF")(NewCommand.description) + "\n");
const name = flags.name || (await this.promptAppName());
if (!name) {
this.logError("An app name is required.");
this.exit(1);
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
const dir = flags.dir ? path.join(process.cwd(), flags.dir) : await this.promptInstallPath("." + path.sep + name);
if (!dir) {
this.logError("An install directory is required.");
this.exit(1);
}
const sdk = parseSDK(flags.sdk
? Object.values(SDK)[Object.keys(SDK)
.map((v) => v.toLowerCase())
.indexOf(flags.sdk?.trim().toLowerCase())]
: await this.promptSdkSelection());
const template = flags.template || (await this.promptTemplate("default"));
if (!template) {
this.logError("A template is required.");
this.exit(1);
}
if (!flags.force && !(await this.confirmAction("Continue? [y/n]"))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
}
this.log();
await this.createApp(name, dir, sdk, template, flags.force, flags.prerelease);
}
async promptAppName() {
this.log("App Name?");
const name = ((await ask(chalk.dim(" -> "))) || "").trim();
clearLine(2);
this.log("App Name: " + chalk.dim(name.length ? name : "Not Provided"));
return name;
}
async promptInstallPath(defaultValue) {
this.log("Install Directory? " + chalk.dim(`(${defaultValue})`));
const dir = ((await ask(chalk.dim(" -> "))) || defaultValue).trim();
clearLine(2);
this.log("Directory: " + chalk.dim(dir));
return path.resolve(dir);
}
async promptSdkSelection() {
this.log("Select an SDK");
for (const [index, sdk] of Object.values(SDK).entries()) {
this.log(chalk.dim(` ${index + 1}. ${sdk}`));
}
const selectedIndex = Number.parseInt(((await ask(chalk.dim(" -> "))) || "1").trim(), 10) - 1;
const sdk = Object.values(SDK)[selectedIndex];
clearLine(Object.values(SDK).length + 2);
if (!sdk)
this.exit(1);
this.log("SDK: " + chalk.dim(sdk));
return sdk;
}
async promptTemplate(defaultValue) {
this.log("Template? " + chalk.dim(`(${defaultValue})`));
const template = ((await ask(chalk.dim(" -> "))) || defaultValue).trim();
clearLine(2);
this.log("Template: " + chalk.dim(template));
return template;
}
async createApp(name, dir, sdk, template, force, prerelease) {
if (!force && (await fs.exists(dir))) {
if (!(await this.confirmAction("Attempting to overwrite a folder that already exists.\nAre you sure you want to continue? [y/n]"))) {
clearLine();
return;
}
else {
clearLine(2);
}
}
// Validate SDK-specific prerequisites

@@ -153,25 +141,46 @@ const sdkText = `Modus ${sdk} SDK`;

const goVersion = await getGoVersion();
if (!goVersion) {
this.logError(`Go is not installed. Please install Go ${MinGoVersion} or newer and try again.`);
this.logError(`You will also need to install TinyGo ${MinTinyGoVersion} or newer.`);
this.exit(1);
const tinyGoVersion = await getTinyGoVersion();
const foundGo = !!goVersion;
const foundTinyGo = !!tinyGoVersion;
const okGo = foundGo && semver.gte(goVersion, MinGoVersion);
const okTinyGo = foundTinyGo && semver.gte(tinyGoVersion, MinTinyGoVersion);
if (okGo && okTinyGo) {
break;
}
if (semver.lt(goVersion, MinGoVersion)) {
this.logError(`The ${sdkText} requires Go version ${MinGoVersion} or newer.`);
this.logError(`You have Go version ${goVersion}.`);
this.logError(`Please upgrade Go and try again.`);
this.exit(1);
this.log(`The Modus Go SDK requires both of the following:`);
if (okGo) {
this.log(chalk.dim(`• Go v${MinGoVersion} or newer `) + chalk.green(`(found v${goVersion})`));
}
const tinyGoVersion = await getTinyGoVersion();
if (!tinyGoVersion) {
this.logError(`TinyGo is not installed. Please install Go ${MinTinyGoVersion} or newer and try again.`);
this.exit(1);
else if (foundGo) {
this.log(chalk.dim(`• Go v${MinGoVersion} or newer `) + chalk.red(`(found v${goVersion})`));
}
if (semver.lt(tinyGoVersion, MinTinyGoVersion)) {
this.logError(`The Modus Go SDK requires TinyGo version ${MinTinyGoVersion} or newer.`);
this.logError(`You have TinyGo version ${tinyGoVersion}.`);
this.logError(`Please upgrade TinyGo and try again.`);
this.exit(1);
else {
this.log(chalk.dim(`• Go v${MinGoVersion} or newer `) + chalk.red("(not found)"));
}
break;
if (okTinyGo) {
this.log(chalk.dim(`• TinyGo v${MinTinyGoVersion} or newer `) + chalk.green(`(found v${tinyGoVersion})`));
}
else if (foundTinyGo) {
this.log(chalk.dim(`• TinyGo v${MinTinyGoVersion} or newer `) + chalk.red(`(found v${tinyGoVersion})`));
}
else {
this.log(chalk.dim(`• TinyGo v${MinTinyGoVersion} or newer `) + chalk.red("(not found)"));
}
this.log();
if (!okGo) {
this.log(chalk.yellow(`Please install Go ${MinGoVersion} or newer from https://go.dev/dl`));
this.log();
}
if (!okTinyGo) {
this.log(chalk.yellow(`Please install TinyGo ${MinTinyGoVersion} or newer from https://tinygo.org/getting-started/install`));
if (os.platform() === "win32") {
this.log(`Note that you will need to install the binaryen components for wasi support.`);
}
this.log();
}
this.log(`Make sure to add Go and TinyGo to your PATH. You can check for yourself by running:`);
this.log(`${chalk.dim("$")} go version`);
this.log(`${chalk.dim("$")} tinygo version`);
this.log();
this.exit(1);
}

@@ -191,10 +200,19 @@ // Verify and/or install the Modus SDK

if (!installedSdkVersion) {
if (!(await this.confirmAction(`You do not have the ${sdkText} installed. Would you like to install it now? [y/n]`))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
const confirmed = inquirer.confirm({
message: `You do not have the ${sdkText} installed. Would you like to install it now?`,
default: true,
});
if (!confirmed) {
this.abort();
}
updateSDK = true;
else {
updateSDK = true;
}
}
else if (latestVersion !== installedSdkVersion) {
if (await this.confirmAction(`You have ${installedSdkVersion} of the ${sdkText}. The latest is ${latestVersion}. Would you like to update? [y/n]`)) {
const confirmed = await inquirer.confirm({
message: `You have ${installedSdkVersion} of the ${sdkText}. The latest is ${latestVersion}. Would you like to update?`,
default: true,
});
if (confirmed) {
updateSDK = true;

@@ -229,2 +247,3 @@ }

cwd: ModusHomeDir,
shell: true,
env: {

@@ -249,5 +268,5 @@ ...process.env,

}
await execFile("tar", ["-xf", templatesArchive, "-C", dir, "--strip-components=2", `templates/${template}`]);
await extract(templatesArchive, dir, "--strip-components=2", `templates/${template}`);
// Apply SDK-specific modifications
const execOpts = { env: process.env, cwd: dir };
const execOpts = { env: process.env, cwd: dir, shell: true };
switch (sdk) {

@@ -273,34 +292,31 @@ case SDK.AssemblyScript:

}
async confirmAction(message) {
this.log(message);
const cont = ((await ask(chalk.dim(" -> "))) || "n").toLowerCase().trim();
clearLine(2);
return cont === "yes" || cont === "y";
abort() {
this.log(chalk.dim("Aborted"));
this.exit(1);
}
}
async function getGoVersion() {
try {
const result = await execFile("go", ["version"], {
cwd: ModusHomeDir,
env: process.env,
});
const parts = result.stdout.split(" ");
const str = parts.length > 2 ? parts[2] : undefined;
if (str?.startsWith("go")) {
return str.slice(2);
}
}
catch { }
function toValidAppName(input) {
// Remove any characters that aren't alphanumeric, spaces, or a few other valid characters.
// Replace spaces with hyphens.
return input
.trim() // Remove leading/trailing spaces
.toLowerCase() // Convert to lowercase for consistency
.replace(/[^a-z0-9\s-]/g, "") // Remove invalid characters
.replace(/\s+/g, "-") // Replace spaces (or multiple spaces) with a single hyphen
.replace(/-+/g, "-") // Replace multiple consecutive hyphens with a single hyphen
.replace(/^-|-$/g, ""); // Remove leading or trailing hyphens
}
async function getTinyGoVersion() {
try {
const result = await execFile("tinygo", ["version"], {
cwd: ModusHomeDir,
env: process.env,
});
const parts = result.stdout.split(" ");
return parts.length > 2 ? parts[2] : undefined;
const MODUS_NEW_DEFAULT_APP_NAME = "modus-app";
const MODUS_NEW_GO_APP_NAME = "modus-go-app";
const MODUS_NEW_AS_APP_NAME = "modus-as-app";
function getDefaultAppNameBySdk(sdk) {
switch (sdk) {
case SDK.AssemblyScript:
return MODUS_NEW_AS_APP_NAME;
case SDK.Go:
return MODUS_NEW_GO_APP_NAME;
default:
return MODUS_NEW_DEFAULT_APP_NAME;
}
catch { }
}
//# sourceMappingURL=index.js.map

@@ -9,3 +9,4 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -12,0 +13,0 @@ prerelease: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -26,4 +26,9 @@ /*

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -45,3 +50,3 @@ }),

const { args, flags } = await this.parse(RuntimeInstallCommand);
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -97,5 +102,5 @@ }

}
catch {
catch (e) {
spinner.fail(chalk.red(`Failed to download ${runtimeText}`));
this.exit(1);
throw e;
}

@@ -102,0 +107,0 @@ spinner.succeed(chalk.dim(`Installed ${runtimeText}`));

@@ -7,3 +7,4 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
};

@@ -10,0 +11,0 @@ run(): Promise<void>;

@@ -18,4 +18,9 @@ /*

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -26,3 +31,3 @@ }),

const { flags } = await this.parse(RuntimeListCommand);
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -29,0 +34,0 @@ }

@@ -7,2 +7,3 @@ import { Command } from "@oclif/core";

static flags: {
help: import("@oclif/core/interfaces").BooleanFlag<void>;
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -15,3 +16,3 @@ };

private logError;
private confirmAction;
private abort;
}

@@ -13,3 +13,4 @@ /*

import * as vi from "../../../util/versioninfo.js";
import { ask, clearLine, withSpinner } from "../../../util/index.js";
import { withSpinner } from "../../../util/index.js";
import * as inquirer from "@inquirer/prompts";
export default class RuntimeRemoveCommand extends Command {

@@ -23,2 +24,7 @@ static args = {

static flags = {
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
force: Flags.boolean({

@@ -35,3 +41,3 @@ char: "f",

if (!args.version) {
this.logError(`No runtime version specified! Run ${chalk.whiteBright("modus runtime remove <version>")}, or ${chalk.whiteBright("modus runtime remove all")}`);
this.logError(`No runtime version specified. Run ${chalk.whiteBright("modus runtime remove <version>")}, or ${chalk.whiteBright("modus runtime remove all")}`);
return;

@@ -45,5 +51,17 @@ }

}
else if (!flags.force && !(await this.confirmAction("Really, remove all Modus runtimes? [y/n]"))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
else if (!flags.force) {
try {
const confirmed = await inquirer.confirm({
message: "Are you sure you want to remove all Modus runtimes?",
default: false,
});
if (!confirmed) {
this.abort();
}
}
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
}

@@ -65,5 +83,17 @@ for (const version of versions) {

}
else if (!flags.force && !(await this.confirmAction(`Really, remove ${runtimeText} ? [y/n]`))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
else if (!flags.force) {
try {
const confirmed = await inquirer.confirm({
message: `Are you sure you want to remove ${runtimeText}?`,
default: false,
});
if (!confirmed) {
this.abort();
}
}
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
}

@@ -90,9 +120,7 @@ await this.removeRuntime(args.version);

}
async confirmAction(message) {
this.log(message);
const cont = ((await ask(chalk.dim(" -> "))) || "n").toLowerCase().trim();
clearLine(2);
return cont === "yes" || cont === "y";
abort() {
this.log(chalk.dim("Aborted"));
this.exit(1);
}
}
//# sourceMappingURL=index.js.map

@@ -10,3 +10,4 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
force: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -13,0 +14,0 @@ prerelease: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -32,4 +32,9 @@ /*

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -51,3 +56,3 @@ }),

const { args, flags } = await this.parse(SDKInstallCommand);
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -137,5 +142,5 @@ }

}
catch {
catch (e) {
spinner.fail(chalk.red(`Failed to download ${sdkText}`));
this.exit(1);
throw e;
}

@@ -184,5 +189,5 @@ spinner.succeed(chalk.dim(`Installed ${sdkText}`));

}
catch {
catch (e) {
spinner.fail(chalk.red(`Failed to download ${runtimeText}`));
this.exit(1);
throw e;
}

@@ -189,0 +194,0 @@ spinner.succeed(chalk.dim(`Installed ${runtimeText}`));

@@ -7,3 +7,4 @@ import { Command } from "@oclif/core";

static flags: {
nologo: import("@oclif/core/interfaces").BooleanFlag<boolean>;
help: import("@oclif/core/interfaces").BooleanFlag<void>;
"no-logo": import("@oclif/core/interfaces").BooleanFlag<boolean>;
};

@@ -10,0 +11,0 @@ run(): Promise<void>;

@@ -19,4 +19,9 @@ /*

static flags = {
nologo: Flags.boolean({
aliases: ["no-logo"],
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
"no-logo": Flags.boolean({
aliases: ["nologo"],
hidden: true,

@@ -27,3 +32,3 @@ }),

const { flags } = await this.parse(SDKListCommand);
if (!flags.nologo) {
if (!flags["no-logo"]) {
this.log(getHeader(this.config.version));

@@ -30,0 +35,0 @@ }

@@ -8,2 +8,3 @@ import { Command } from "@oclif/core";

static flags: {
help: import("@oclif/core/interfaces").BooleanFlag<void>;
runtimes: import("@oclif/core/interfaces").BooleanFlag<boolean>;

@@ -18,3 +19,3 @@ force: import("@oclif/core/interfaces").BooleanFlag<boolean>;

private logError;
private confirmAction;
private abort;
}

@@ -14,3 +14,4 @@ /*

import { parseSDK, SDK } from "../../../custom/globals.js";
import { ask, clearLine, withSpinner } from "../../../util/index.js";
import { withSpinner } from "../../../util/index.js";
import * as inquirer from "@inquirer/prompts";
export default class SDKRemoveCommand extends Command {

@@ -28,2 +29,7 @@ static args = {

static flags = {
help: Flags.help({
char: "h",
helpLabel: "-h, --help",
description: "Show help message",
}),
runtimes: Flags.boolean({

@@ -61,5 +67,17 @@ char: "r",

}
if (!flags.force && !(await this.confirmAction(`Really, remove all Modus SDKs${flags.runtimes ? " and runtimes" : ""}? [y/n]`))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
if (!flags.force) {
try {
const confirmed = inquirer.confirm({
message: "Are you sure you want to remove all Modus SDKs?",
default: false,
});
if (!confirmed) {
this.abort();
}
}
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
}

@@ -87,5 +105,17 @@ for (const sdk of Object.values(SDK)) {

}
else if (!flags.force && !(await this.confirmAction(`Really, remove all Modus ${sdk} SDKs? [y/n]`))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
else if (!flags.force) {
try {
const confirmed = inquirer.confirm({
message: `Are you sure you want to remove all Modus ${sdk} SDKs?`,
default: false,
});
if (!confirmed) {
this.abort();
}
}
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
}

@@ -107,5 +137,17 @@ for (const version of versions) {

}
else if (!flags.force && !(await this.confirmAction(`Really, remove ${sdkText} ? [y/n]`))) {
this.log(chalk.dim("Aborted."));
this.exit(1);
else if (!flags.force) {
try {
const confirmed = inquirer.confirm({
message: `Are you sure you want to remove ${sdkText}?`,
default: false,
});
if (!confirmed) {
this.abort();
}
}
catch (err) {
if (err.name === "ExitPromptError") {
this.abort();
}
}
}

@@ -147,9 +189,7 @@ await this.removeSDK(sdk, args.version);

}
async confirmAction(message) {
this.log(message);
const cont = ((await ask(chalk.dim(" -> "))) || "n").toLowerCase().trim();
clearLine(2);
return cont === "yes" || cont === "y";
abort() {
this.log(chalk.dim("Aborted"));
this.exit(1);
}
}
//# sourceMappingURL=index.js.map

@@ -9,3 +9,2 @@ /*

*/
import chalk from "chalk";
import { getLogo } from "./logo.js";

@@ -16,3 +15,3 @@ export function getHeader(cliVersion) {

out += "\n";
out += chalk.dim(`Modus CLI v${cliVersion}`);
out += `Modus CLI v${cliVersion}`;
out += "\n";

@@ -19,0 +18,0 @@ return out;

@@ -20,3 +20,3 @@ /*

formatRoot() {
return `${chalk.bold("Usage:")} modus ${chalk.blueBright("<command or tool> [...flags] [...args]")}`;
return `${chalk.bold("Usage:")} modus ${"<command or tool> [flags] [args]"}`;
}

@@ -71,8 +71,25 @@ formatCommands(commands) {

}
// formatFlags(topics: Interfaces.Topic[]): string {
// let out = "";
// if (topics.find((v) => !v.hidden)) out += chalk.bold("Flags:") + "\n";
// else return out;
// for (const topic of topics) {
// if (topic.hidden) continue;
// const fullName = topic.shortName ? `${topic.shortName}, ${topic.name}` : topic.name;
// out += " " + chalk.bold.blue(fullName) + " ".repeat(Math.max(1, this.pre_pad + this.post_pad - fullName.length)) + topic.description + "\n";
// }
// return out.trim();
// }
formatFooter() {
let out = "";
out += "View the docs:" + " ".repeat(Math.max(1, this.pre_pad + this.post_pad - 12)) + chalk.blueBright("https://docs.hypermode.com/modus") + "\n";
out += "View the repo:" + " ".repeat(Math.max(1, this.pre_pad + this.post_pad - 12)) + chalk.blueBright("https://github.com/hypermodeinc/modus") + "\n";
const links = [
{ name: "Docs", url: "https://docs.hypermode.com/modus" },
{ name: "GitHub", url: "https://github.com/hypermodeinc/modus" },
{ name: "Discord", url: "https://discord.hypermode.com (#modus)" },
];
for (const link of links) {
out += `${link.name}: ${" ".repeat(Math.max(1, this.pre_pad + this.post_pad - link.name.length))}${link.url}\n`;
}
out += "\n";
out += "Made with 💖 by " + chalk.hex("#602AF8")("https://hypermode.com");
out += "Made with ♥︎ by Hypermode";
out += "\n";

@@ -124,2 +141,16 @@ return out;

}
// const globalFlagTopics: Interfaces.Topic[] = [
// {
// name: "--help",
// description: "Show help message",
// shortName: "-h",
// },
// {
// name: "--version",
// description: "Show Modus version",
// shortName: "-v",
// },
// ];
// this.log(this.formatFlags(globalFlagTopics));
// this.log();
this.log(this.formatFooter());

@@ -170,3 +201,3 @@ }

const argsStr = args.length > 0 ? " " + args.map((a) => `<${a}>`).join(" ") : "";
const flagsStr = flags.length > 0 ? " [...flags]" : "";
const flagsStr = flags.length > 0 ? " [flags]" : "";
this.log(`${chalk.bold("Usage:")} modus ${name}${chalk.blueBright(argsStr + flagsStr)}\n`);

@@ -193,3 +224,6 @@ if (args.length) {

for (const flag of Object.values(command.flags)) {
this.log(" " + chalk.bold.blueBright("--" + flag.name) + " ".repeat(margin - flag.name.length) + flag.description);
if (flag.hidden)
continue;
const flagOptions = flag.char ? `-${flag.char}, --${flag.name}` : `--${flag.name}`;
this.log(" " + chalk.bold.blueBright(flagOptions) + " ".repeat(margin + 2 - flagOptions.length) + flag.description);
}

@@ -196,0 +230,0 @@ this.log();

@@ -5,6 +5,4 @@ import { Ora } from "ora";

export declare function withSpinner<T>(text: string, fn: (spinner: Ora) => Promise<T>): Promise<T>;
export declare function ask(question: string, placeholder?: string): Promise<string>;
export declare function clearLine(n?: number): void;
export declare function downloadFile(url: string, dest: string): Promise<boolean>;
export declare function isOnline(): Promise<boolean>;
export declare function getGitHubApiHeaders(): Headers;

@@ -13,4 +13,2 @@ /*

import path from "node:path";
import readline from "node:readline";
import { isatty } from "node:tty";
import { Readable } from "node:stream";

@@ -46,31 +44,2 @@ import { finished } from "node:stream/promises";

}
export async function ask(question, placeholder) {
const rl = readline.createInterface({
input: process.stdin,
output: process.stdout,
});
try {
return await new Promise((res, _) => {
rl.question(question + (placeholder ? " " + placeholder + " " : ""), (answer) => {
res(answer);
});
});
}
finally {
rl.close();
}
}
export function clearLine(n = 1) {
const stream = process.stdout;
if (isatty(stream.fd)) {
for (let i = 0; i < n; i++) {
stream.write("\u001B[1A");
stream.write("\u001B[2K");
stream.write("\u001B[2K");
}
}
else {
stream.write("\n");
}
}
export async function downloadFile(url, dest) {

@@ -77,0 +46,0 @@ const res = await fetch(url);

@@ -13,3 +13,3 @@ /*

import * as vi from "./versioninfo.js";
import { execFile } from "./cp.js";
import { extract } from "./tar.js";
import { downloadFile, isOnline } from "./index.js";

@@ -53,5 +53,5 @@ import { GitHubOwner, GitHubRepo } from "../custom/globals.js";

await fs.mkdir(installDir, { recursive: true });
await execFile("tar", ["-xf", archivePath, "-C", installDir]);
await extract(archivePath, installDir);
await fs.rm(archivePath);
}
//# sourceMappingURL=installer.js.map

@@ -17,8 +17,16 @@ {

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -60,8 +68,16 @@ "type": "boolean"

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -83,3 +99,3 @@ "type": "boolean"

"char": "p",
"description": "Use a prerelease version of the Modus runtime. Not needed if specifying a runtime version.",
"description": "Use a prerelease version of the Modus runtime. Not needed if specifying a runtime version.",
"name": "prerelease",

@@ -89,16 +105,24 @@ "allowNo": false,

},
"nowatch": {
"no-build": {
"aliases": [
"no-watch"
"nobuild"
],
"description": "Don't build the app before running (or when watching for changes)",
"name": "no-build",
"allowNo": false,
"type": "boolean"
},
"no-watch": {
"aliases": [
"nowatch"
],
"description": "Don't watch app code for changes",
"name": "nowatch",
"name": "no-watch",
"allowNo": false,
"type": "boolean"
},
"freq": {
"char": "f",
"description": "Frequency to check for changes when using --watch",
"name": "freq",
"default": 3000,
"delay": {
"description": "Delay (in milliseconds) between file change detection and rebuild",
"name": "delay",
"default": 500,
"hasDynamicHelp": false,

@@ -125,2 +149,44 @@ "multiple": false,

},
"info": {
"aliases": [],
"args": {},
"description": "Show Modus info",
"examples": [
"modus info"
],
"flags": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"nologo"
],
"hidden": true,
"name": "no-logo",
"allowNo": false,
"type": "boolean"
}
},
"hasDynamicHelp": false,
"hiddenAliases": [],
"id": "info",
"pluginAlias": "@hypermode/modus-cli",
"pluginName": "@hypermode/modus-cli",
"pluginType": "core",
"strict": true,
"enableJsonFlag": false,
"isESM": true,
"relativePath": [
"dist",
"commands",
"info",
"index.js"
]
},
"new": {

@@ -136,8 +202,16 @@ "aliases": [],

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -173,10 +247,2 @@ "type": "boolean"

},
"template": {
"char": "t",
"description": "Template to use",
"name": "template",
"hasDynamicHelp": false,
"multiple": false,
"type": "option"
},
"force": {

@@ -232,8 +298,16 @@ "char": "f",

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -285,8 +359,16 @@ "type": "boolean"

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -328,2 +410,10 @@ "type": "boolean"

"flags": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"force": {

@@ -376,8 +466,16 @@ "char": "f",

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -429,8 +527,16 @@ "type": "boolean"

"flags": {
"nologo": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"no-logo": {
"aliases": [
"no-logo"
"nologo"
],
"hidden": true,
"name": "nologo",
"name": "no-logo",
"allowNo": false,

@@ -477,2 +583,10 @@ "type": "boolean"

"flags": {
"help": {
"char": "h",
"description": "Show help message",
"helpLabel": "-h, --help",
"name": "help",
"allowNo": false,
"type": "boolean"
},
"runtimes": {

@@ -511,3 +625,3 @@ "char": "r",

},
"version": "0.13.0-test5"
"version": "0.13.0"
}
{
"name": "@hypermode/modus-cli",
"version": "0.13.0-test5",
"version": "0.13.0",
"description": "The Modus CLI",

@@ -20,5 +20,2 @@ "author": "Hypermode Inc.",

"type": "module",
"engines": {
"node": ">=22"
},
"bin": {

@@ -30,2 +27,3 @@ "modus": "./bin/modus.js"

"build": "rm -rf dist && tsc -b",
"watch": "rm -rf dist && tsc -b -w",
"postpack": "rm -f oclif.manifest.json",

@@ -35,6 +33,9 @@ "prepack": "npm i && npm run build && oclif manifest"

"dependencies": {
"@inquirer/prompts": "^7.0.0",
"@oclif/core": "^4",
"chalk": "^5.3.0",
"chokidar": "^4.0.1",
"gradient-string": "^3.0.0",
"ora": "^8.1.0",
"picomatch": "^4.0.2",
"semver": "^7.6.3"

@@ -45,2 +46,3 @@ },

"@types/node": "^22",
"@types/picomatch": "^3.0.1",
"@types/semver": "^7.5.8",

@@ -69,4 +71,10 @@ "oclif": "^4",

}
}
},
"additionalHelpFlags": [
"-h"
],
"additionalVersionFlags": [
"-v"
]
}
}

@@ -9,2 +9,13 @@ # Modus CLI

Please refer to the docs at: https://docs.hypermode.com/modus/quickstart
Please refer to the docs at: https://docs.hypermode.com/modus/quickstart
## Contributing
```bash
npm i
npm run watch
```
You can make changes and run `./bin/modus.js` in a terminal to test changes.
Alternatively, you can set breakpoints and use the VS Code debug target `Debug Modus CLI` to launch the terminal to debug issues.

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc