New:Socket for Asana Is Now Available.Learn more
Get Started

@mearl/cloud-server

Package Overview
Dependencies
Maintainers
2
Versions
27
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@mearl/cloud-server - npm Package Compare versions

Comparing version
2.8.2
to
2.9.0
+12
-1
dist/cli.d.ts
#!/usr/bin/env node
export {};
import type { CloudServerOptions } from './index.js';
import { type CloudServerCommand } from './qoder.js';
export interface ParsedCloudServerArgs {
command: CloudServerCommand;
daemonArgs: string[];
foreground: boolean;
help: boolean;
options: CloudServerOptions;
version: boolean;
}
export declare function parseCloudServerArgs(argv: string[]): ParsedCloudServerArgs;
export declare function main(argv?: string[]): Promise<number>;
+146
-79

@@ -9,2 +9,7 @@ #!/usr/bin/env node

// src/cli.ts
import path from "node:path";
import { fileURLToPath as fileURLToPath2 } from "node:url";
import { Command, CommanderError, InvalidArgumentError } from "commander";
// src/daemon.ts

@@ -18,7 +23,7 @@ import { fileURLToPath } from "node:url";

if (config.port) lines.push(` port: ${config.port}`);
const command2 = config.publicUrl ? `npx @mearl/cloud-connector start "${config.publicUrl}"` : config.connectorCommand;
if (command2) {
const command = config.publicUrl ? `npx @mearl/cloud-connector start "${config.publicUrl}"` : config.connectorCommand;
if (command) {
lines.push("");
lines.push(" Connect from your local machine:");
lines.push(` ${command2}`);
lines.push(` ${command}`);
}

@@ -152,5 +157,5 @@ return lines.length ? lines.join("\n") : null;

}
async function runQoderCloudServerCommand(command2, dependencies) {
async function runQoderCloudServerCommand(command, dependencies) {
const writeLine = dependencies.writeLine ?? console.log;
switch (command2) {
switch (command) {
case "start":

@@ -179,20 +184,14 @@ case "restart":

// src/cli.ts
var CLOUD_SERVER_VERSION = true ? "2.8.2" : "unknown";
var argv = process.argv.slice(2);
if (argv.includes("--version") || argv.includes("-v")) {
console.log(CLOUD_SERVER_VERSION);
process.exit(0);
}
if (argv.includes("--help") || argv.includes("-h")) {
showHelp();
process.exit(0);
}
var CLOUD_SERVER_VERSION = true ? "2.9.0" : "unknown";
var COMMANDS = ["start", "stop", "restart", "status", "logs"];
var command = "start";
var rest = argv;
if (argv[0] && COMMANDS.includes(argv[0])) {
command = argv[0];
rest = argv.slice(1);
}
var foreground = rest.includes("--foreground") || rest.includes("-f");
var START_OPTION_NAMES = /* @__PURE__ */ new Set([
"foreground",
"port",
"agentPort",
"path",
"token",
"heartbeat",
"maxConnections",
"allowRemoteAgent"
]);
function showHelp() {

@@ -212,3 +211,3 @@ console.log(`mearl-cloud-server v${CLOUD_SERVER_VERSION}

Options:
--foreground, -f Run in the foreground instead of daemonizing
--foreground, -f Run start in the foreground instead of daemonizing
--port <port> Connector (network) port (default: 8080)

@@ -220,58 +219,116 @@ --agent-port <port> Agent port, bound to 127.0.0.1 only (default: port + 1)

--max-connections <n> Max concurrent connections (default: 100)
--allow-remote-agent Allow command-issuing agents to connect from the
network (default: off; agents must be local)
--allow-remote-agent Allow command-issuing agents to connect from the network
--version, -v Show version
--help, -h Show this help message
Environment Variables:
MEARL_TOKEN Authentication token (overrides --token if set)
CLOUD_SERVER_HOST Host name for WebSocket URL (default: localhost)
Examples:
# Start in the background (default) and print the connector command
mearl-cloud-server
# Check status / connect info, then stop
mearl-cloud-server status
mearl-cloud-server stop
# Start with a custom port and token
mearl-cloud-server start --port 9000 --token your-secret-token
# Run in the foreground (e.g. under systemd / Docker / PM2)
mearl-cloud-server --foreground
`);
}
function parseOptions(args) {
const options = {};
for (let i = 0; i < args.length; i++) {
const arg = args[i];
if (arg === "--port" && i + 1 < args.length) {
options.port = parseInt(args[++i], 10);
} else if (arg === "--agent-port" && i + 1 < args.length) {
options.agentPort = parseInt(args[++i], 10);
} else if (arg === "--path" && i + 1 < args.length) {
options.path = args[++i];
} else if (arg === "--token" && i + 1 < args.length) {
options.token = args[++i];
} else if (arg === "--heartbeat" && i + 1 < args.length) {
options.heartbeatTimeout = parseInt(args[++i], 10);
} else if (arg === "--max-connections" && i + 1 < args.length) {
options.maxConnections = parseInt(args[++i], 10);
} else if (arg === "--allow-remote-agent") {
options.allowRemoteAgent = true;
function integerOption(label, minimum, maximum = Number.MAX_SAFE_INTEGER) {
return (value) => {
const parsed = Number(value);
if (!Number.isInteger(parsed) || parsed < minimum || parsed > maximum) {
throw new InvalidArgumentError(`${label} must be an integer from ${minimum} to ${maximum}`);
}
return parsed;
};
}
function optionUsed(program, name) {
return program.getOptionValueSource(name) === "cli";
}
function assertAllowedOptions(program, command) {
const allowed = command === "start" || command === "restart" ? START_OPTION_NAMES : /* @__PURE__ */ new Set();
for (const option of program.options) {
const name = option.attributeName();
if (optionUsed(program, name) && !allowed.has(name) && name !== "help" && name !== "version") {
throw new Error(`${option.long ?? option.flags} is not available for ${command}`);
}
}
if (!options.token) {
const envToken = process.env.MEARL_TOKEN;
if (envToken) {
options.token = envToken;
if (command === "restart" && optionUsed(program, "foreground")) {
throw new Error("--foreground is only available for start");
}
}
function daemonArgs(program, options) {
const args = [];
const add = (name, flag) => {
const value = options[name];
if (optionUsed(program, String(name)) && value !== void 0) args.push(flag, String(value));
};
add("port", "--port");
add("agentPort", "--agent-port");
add("path", "--path");
add("token", "--token");
add("heartbeat", "--heartbeat");
add("maxConnections", "--max-connections");
if (options.allowRemoteAgent) args.push("--allow-remote-agent");
return args;
}
function parseCloudServerArgs(argv) {
const program = new Command().name("mearl-cloud-server").helpOption(false).allowExcessArguments(false).exitOverride().configureOutput({ writeErr: () => {
}, writeOut: () => {
} }).argument("[command]").option("-f, --foreground").option("--port <port>", "connector port", integerOption("port", 1, 65535)).option("--agent-port <port>", "agent port", integerOption("agent-port", 1, 65535)).option("--path <path>").option("--token <token>").option("--heartbeat <seconds>", "heartbeat timeout", integerOption("heartbeat", 1)).option("--max-connections <n>", "connection limit", integerOption("max-connections", 1)).option("--allow-remote-agent").option("-v, --version").option("-h, --help");
try {
program.parse(["node", "mearl-cloud-server", ...argv]);
} catch (error) {
if (error instanceof CommanderError) {
throw new Error(error.message.replace(/^error:\s*/i, ""), { cause: error });
}
throw error;
}
return options;
const cliOptions = program.opts();
if (cliOptions.help || cliOptions.version) {
return {
command: "start",
daemonArgs: [],
foreground: false,
help: cliOptions.help === true,
options: {},
version: cliOptions.version === true
};
}
const commandArg = program.processedArgs[0];
if (commandArg && !COMMANDS.includes(commandArg)) {
throw new Error(`Unknown command: ${commandArg}`);
}
const command = commandArg ?? "start";
assertAllowedOptions(program, command);
if (cliOptions.token !== void 0 && cliOptions.token.length === 0) {
throw new Error("--token requires a non-empty value");
}
const options = {
...cliOptions.port !== void 0 ? { port: cliOptions.port } : {},
...cliOptions.agentPort !== void 0 ? { agentPort: cliOptions.agentPort } : {},
...cliOptions.path !== void 0 ? { path: cliOptions.path } : {},
...cliOptions.token !== void 0 ? { token: cliOptions.token } : process.env.MEARL_TOKEN ? { token: process.env.MEARL_TOKEN } : {},
...cliOptions.heartbeat !== void 0 ? { heartbeatTimeout: cliOptions.heartbeat } : {},
...cliOptions.maxConnections !== void 0 ? { maxConnections: cliOptions.maxConnections } : {},
...cliOptions.allowRemoteAgent ? { allowRemoteAgent: true } : {}
};
return {
command,
daemonArgs: daemonArgs(program, cliOptions),
foreground: cliOptions.foreground === true,
help: false,
options,
version: false
};
}
async function main() {
async function main(argv = process.argv.slice(2)) {
let parsed;
try {
parsed = parseCloudServerArgs(argv);
} catch (error) {
console.error(`Error: ${error instanceof Error ? error.message : String(error)}`);
showHelp();
return 2;
}
if (parsed.help) {
showHelp();
return 0;
}
if (parsed.version) {
console.log(CLOUD_SERVER_VERSION);
return 0;
}
const mode = resolveCloudServerMode();
if (mode === "qoder") {
await runQoderCloudServerCommand(command, {
await runQoderCloudServerCommand(parsed.command, {
isServerRunning: isDaemonRunning,

@@ -282,11 +339,11 @@ stopServer: stopDaemon,

});
return;
return 0;
}
if (foreground) {
await runForeground(parseOptions(rest));
return;
if (parsed.foreground) {
await runForeground(parsed.options);
return 0;
}
switch (command) {
switch (parsed.command) {
case "start":
await startDaemon(rest);
await startDaemon(parsed.daemonArgs);
break;

@@ -297,3 +354,3 @@ case "stop":

case "restart":
await restartDaemon(rest);
await restartDaemon(parsed.daemonArgs);
break;

@@ -307,6 +364,16 @@ case "status":

}
return 0;
}
main().catch((error) => {
console.error("[CloudServer] Fatal error:", error);
process.exit(1);
});
var currentFile = fileURLToPath2(import.meta.url);
if (process.argv[1] && path.resolve(process.argv[1]) === currentFile) {
main().then((code) => {
process.exitCode = code;
}).catch((error) => {
console.error("[CloudServer] Fatal error:", error);
process.exitCode = 1;
});
}
export {
main,
parseCloudServerArgs
};
{
"name": "@mearl/cloud-server",
"version": "2.8.2",
"version": "2.9.0",
"description": "Cloud WebSocket server for Mearl — bridges cloud agents to local connectors",
"type": "module",
"engines": {
"node": ">=18"
"node": ">=22.12.0"
},

@@ -36,6 +36,7 @@ "main": "dist/index.js",

"dependencies": {
"commander": "^15.0.0",
"ws": "^8.18.0",
"@mearl/client": "2.8.2",
"@mearl/cloud-types": "2.8.2",
"@mearl/daemon-core": "2.8.2"
"@mearl/client": "2.9.0",
"@mearl/daemon-core": "2.9.0",
"@mearl/cloud-types": "2.9.0"
},

@@ -42,0 +43,0 @@ "devDependencies": {