@miosa/cli 1.0.54 → 1.0.56
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/client.d.ts +1 -0
- package/dist/client.d.ts.map +1 -1
- package/dist/client.js +13 -2
- package/dist/client.js.map +1 -1
- package/dist/commands/api-keys.d.ts.map +1 -1
- package/dist/commands/api-keys.js +42 -1
- package/dist/commands/api-keys.js.map +1 -1
- package/dist/commands/billing.d.ts.map +1 -1
- package/dist/commands/billing.js +22 -30
- package/dist/commands/billing.js.map +1 -1
- package/dist/commands/cp.d.ts.map +1 -1
- package/dist/commands/cp.js +36 -5
- package/dist/commands/cp.js.map +1 -1
- package/dist/commands/desktop.js +1 -1
- package/dist/commands/desktop.js.map +1 -1
- package/dist/commands/mcp.js +2 -2
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/sandbox.d.ts.map +1 -1
- package/dist/commands/sandbox.js +217 -80
- package/dist/commands/sandbox.js.map +1 -1
- package/dist/commands/shell.js +1 -1
- package/dist/commands/shell.js.map +1 -1
- package/dist/commands/status.js +1 -1
- package/dist/commands/status.js.map +1 -1
- package/dist/commands/tunnel.js +1 -1
- package/dist/commands/tunnel.js.map +1 -1
- package/dist/errors.d.ts.map +1 -1
- package/dist/errors.js +3 -3
- package/dist/errors.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"sandbox.d.ts","sourceRoot":"","sources":["../../src/commands/sandbox.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsDzC,wBAAgB,QAAQ,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA8iE/C"}
|
package/dist/commands/sandbox.js
CHANGED
|
@@ -15,7 +15,7 @@ import { handleError, isJsonMode } from "./util.js";
|
|
|
15
15
|
import { renderTable } from "../ui/table.js";
|
|
16
16
|
import { formatDuration, hintBlock, icon, kvPanel, printBanner, printElapsed, } from "../ui/render.js";
|
|
17
17
|
import { formatBytes } from "../ui/progress.js";
|
|
18
|
-
import { UserError } from "../errors.js";
|
|
18
|
+
import { ApiResponseError, MiosaError, NetworkError, ServerError, UserError, } from "../errors.js";
|
|
19
19
|
export function register(program) {
|
|
20
20
|
// -------------------------------------------------------------------------
|
|
21
21
|
// sandbox / sandboxes command group — built manually to avoid subcommand
|
|
@@ -553,21 +553,26 @@ export function register(program) {
|
|
|
553
553
|
.option("--timeout <duration>", "Wait timeout, e.g. 180s or 3m", parseDurationSec, 180)
|
|
554
554
|
.option("--probe-path <path>", "HTTP path to probe")
|
|
555
555
|
.option("--json", "Output as JSON")
|
|
556
|
-
.action((localDir = ".", opts) =>
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
556
|
+
.action(async (localDir = ".", opts) => {
|
|
557
|
+
try {
|
|
558
|
+
const result = await deploySandbox(localDir, opts);
|
|
559
|
+
if (isJsonMode(opts)) {
|
|
560
|
+
console.log(JSON.stringify(result, null, 2));
|
|
561
|
+
return;
|
|
562
|
+
}
|
|
563
|
+
console.log();
|
|
564
|
+
console.log(` ${chalk.bold("Sandbox")} ${result.sandbox_id}`);
|
|
565
|
+
console.log(` ${chalk.bold("Port")} ${result.port}`);
|
|
566
|
+
console.log(` ${chalk.bold("Preview")} ${chalk.cyan(result.preview_url)}`);
|
|
567
|
+
console.log(` ${chalk.bold("Ready")} ${result.preview_ready
|
|
568
|
+
? chalk.green("yes")
|
|
569
|
+
: chalk.yellow("not verified")}`);
|
|
570
|
+
console.log();
|
|
561
571
|
}
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
console.log(` ${chalk.bold("Ready")} ${result.preview_ready
|
|
567
|
-
? chalk.green("yes")
|
|
568
|
-
: chalk.yellow("not verified")}`);
|
|
569
|
-
console.log();
|
|
570
|
-
}));
|
|
572
|
+
catch (err) {
|
|
573
|
+
handleSandboxDeployError(err, opts);
|
|
574
|
+
}
|
|
575
|
+
});
|
|
571
576
|
sandbox
|
|
572
577
|
.command("preview <sandbox-id>")
|
|
573
578
|
.description("Expose a sandbox port and optionally wait for the public preview to answer")
|
|
@@ -908,8 +913,7 @@ export function register(program) {
|
|
|
908
913
|
const contentBytes = fs.existsSync(contentArg)
|
|
909
914
|
? fs.readFileSync(contentArg)
|
|
910
915
|
: Buffer.from(contentArg, "utf8");
|
|
911
|
-
const
|
|
912
|
-
const result = await fetchApiRaw(apiPath(`/sandboxes/${enc(id)}/files`), { path: remotePath, content: base64 });
|
|
916
|
+
const result = await writeBytesToSandbox(client(), id, remotePath, contentBytes);
|
|
913
917
|
if (!isJsonMode(opts)) {
|
|
914
918
|
console.log(chalk.green(`Written to ${remotePath}`));
|
|
915
919
|
}
|
|
@@ -970,10 +974,8 @@ export function register(program) {
|
|
|
970
974
|
console.error(chalk.red(`File not found: ${localPath}`));
|
|
971
975
|
process.exit(1);
|
|
972
976
|
}
|
|
973
|
-
const data = fs.readFileSync(localPath);
|
|
974
|
-
const base64 = data.toString("base64");
|
|
975
977
|
const c = client();
|
|
976
|
-
const result = await c
|
|
978
|
+
const result = await writeBytesToSandbox(c, id, remotePath, fs.readFileSync(localPath));
|
|
977
979
|
if (isJsonMode(opts)) {
|
|
978
980
|
printValue(result, opts);
|
|
979
981
|
}
|
|
@@ -1499,6 +1501,18 @@ async function runSandboxPortForward(id, opts) {
|
|
|
1499
1501
|
process.stderr.write("\n");
|
|
1500
1502
|
server.close();
|
|
1501
1503
|
}
|
|
1504
|
+
class SandboxDeployPartialError extends Error {
|
|
1505
|
+
causeError;
|
|
1506
|
+
sandboxId;
|
|
1507
|
+
recoveryCommand;
|
|
1508
|
+
constructor(causeError, sandboxId, recoveryCommand) {
|
|
1509
|
+
super(causeError instanceof Error ? causeError.message : String(causeError));
|
|
1510
|
+
this.causeError = causeError;
|
|
1511
|
+
this.sandboxId = sandboxId;
|
|
1512
|
+
this.recoveryCommand = recoveryCommand;
|
|
1513
|
+
this.name = "SandboxDeployPartialError";
|
|
1514
|
+
}
|
|
1515
|
+
}
|
|
1502
1516
|
async function showSandboxWithPreview(sandboxId, port, probePath) {
|
|
1503
1517
|
const c = client();
|
|
1504
1518
|
const sandbox = unwrap(await c.apiGet(apiPath(`/sandboxes/${enc(sandboxId)}`)));
|
|
@@ -1643,69 +1657,79 @@ async function deploySandbox(localDir, opts) {
|
|
|
1643
1657
|
const start = opts.start ??
|
|
1644
1658
|
manifestStartCommand(appManifest) ??
|
|
1645
1659
|
defaultStartCommand(detection?.framework ?? appManifest?.framework, port);
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1660
|
+
let sandboxId = opts.sandbox ?? null;
|
|
1661
|
+
try {
|
|
1662
|
+
if (!sandboxId) {
|
|
1663
|
+
deployStep(opts, "Creating sandbox");
|
|
1664
|
+
sandboxId = await createSandboxForDeploy(c, opts.template ?? appManifest?.template ?? "miosa-sandbox", opts.name, {
|
|
1649
1665
|
source: opts.source,
|
|
1650
1666
|
revision: opts.revision,
|
|
1651
1667
|
depth: opts.depth,
|
|
1652
|
-
})
|
|
1653
|
-
deployStep(opts, "Waiting for sandbox");
|
|
1654
|
-
await waitForSandboxRunning(c, sandboxId, Math.min(opts.timeout, 120));
|
|
1655
|
-
if (sourceBacked) {
|
|
1656
|
-
deployStep(opts, "Waiting for source import");
|
|
1657
|
-
appManifest = await readRemoteAppManifest(c, sandboxId, opts.timeout);
|
|
1658
|
-
remoteWorkdir = normalizeRemoteWorkdir(appManifest?.workdir ?? "/workspace");
|
|
1659
|
-
}
|
|
1660
|
-
else {
|
|
1661
|
-
deployStep(opts, "Uploading files");
|
|
1662
|
-
const archivePath = createDeployArchive(sourceDir);
|
|
1663
|
-
const remoteArchive = `/tmp/miosa-deploy-${Date.now()}.tgz`;
|
|
1664
|
-
try {
|
|
1665
|
-
await uploadFileToSandbox(c, sandboxId, archivePath, remoteArchive);
|
|
1666
|
-
deployStep(opts, "Extracting workspace");
|
|
1667
|
-
await execSandbox(c, sandboxId, `mkdir -p ${shellQuote(remoteWorkdir)} && tar -xzf ${shellQuote(remoteArchive)} -C ${shellQuote(remoteWorkdir)}`, "/");
|
|
1668
|
+
});
|
|
1668
1669
|
}
|
|
1669
|
-
|
|
1670
|
-
|
|
1670
|
+
deployStep(opts, "Waiting for sandbox");
|
|
1671
|
+
await waitForSandboxRunning(c, sandboxId, Math.min(opts.timeout, 120));
|
|
1672
|
+
if (sourceBacked) {
|
|
1673
|
+
deployStep(opts, "Waiting for source import");
|
|
1674
|
+
appManifest = await readRemoteAppManifest(c, sandboxId, opts.timeout);
|
|
1675
|
+
remoteWorkdir = normalizeRemoteWorkdir(appManifest?.workdir ?? "/workspace");
|
|
1671
1676
|
}
|
|
1677
|
+
else {
|
|
1678
|
+
deployStep(opts, "Uploading files");
|
|
1679
|
+
const archivePath = createDeployArchive(sourceDir);
|
|
1680
|
+
const remoteArchive = `/tmp/miosa-deploy-${Date.now()}.tgz`;
|
|
1681
|
+
try {
|
|
1682
|
+
await uploadFileToSandbox(c, sandboxId, archivePath, remoteArchive);
|
|
1683
|
+
deployStep(opts, "Extracting workspace");
|
|
1684
|
+
await execSandbox(c, sandboxId, `mkdir -p ${shellQuote(remoteWorkdir)} && tar -xzf ${shellQuote(remoteArchive)} -C ${shellQuote(remoteWorkdir)}`, "/");
|
|
1685
|
+
}
|
|
1686
|
+
finally {
|
|
1687
|
+
fs.rmSync(archivePath, { force: true });
|
|
1688
|
+
}
|
|
1689
|
+
}
|
|
1690
|
+
const resolvedPort = opts.port ?? opts.publishPort ?? manifestPort(appManifest) ?? port;
|
|
1691
|
+
const resolvedProbePath = opts.probePath ?? manifestProbePath(appManifest) ?? probePath;
|
|
1692
|
+
const resolvedStart = opts.start ?? manifestStartCommand(appManifest) ?? start;
|
|
1693
|
+
const installCommand = opts.install === false
|
|
1694
|
+
? null
|
|
1695
|
+
: (opts.installCommand ??
|
|
1696
|
+
(appManifest?.install === false ? null : appManifest?.install) ??
|
|
1697
|
+
(sourceBacked ? "npm install" : defaultInstallCommand(sourceDir)));
|
|
1698
|
+
if (installCommand) {
|
|
1699
|
+
deployStep(opts, `Installing dependencies: ${installCommand}`);
|
|
1700
|
+
await execSandbox(c, sandboxId, installCommand, remoteWorkdir, opts.timeout);
|
|
1701
|
+
}
|
|
1702
|
+
deployStep(opts, `Starting app on port ${resolvedPort}`);
|
|
1703
|
+
await execSandbox(c, sandboxId, `fuser -k ${resolvedPort}/tcp >/dev/null 2>&1 || true; nohup sh -lc ${shellQuote(resolvedStart)} > ${shellQuote(`/tmp/miosa-app-${resolvedPort}.log`)} 2>&1 & echo $!`, remoteWorkdir);
|
|
1704
|
+
deployStep(opts, "Checking internal app readiness");
|
|
1705
|
+
const internal = await waitForInternalHttp(c, sandboxId, resolvedPort, resolvedProbePath, Math.min(opts.timeout, 60));
|
|
1706
|
+
deployStep(opts, "Creating public preview route");
|
|
1707
|
+
const exposed = await c.apiPost(apiPath(`/sandboxes/${enc(sandboxId)}/expose`), { port: resolvedPort, title: "app preview" });
|
|
1708
|
+
const previewUrl = extractUrl(unwrap(exposed));
|
|
1709
|
+
if (!previewUrl) {
|
|
1710
|
+
throw new UserError("Sandbox expose did not return a preview URL.");
|
|
1711
|
+
}
|
|
1712
|
+
if (opts.wait)
|
|
1713
|
+
deployStep(opts, "Checking public preview readiness");
|
|
1714
|
+
const edge = opts.wait
|
|
1715
|
+
? await waitForPublicPreview(previewUrl, resolvedProbePath, opts.timeout)
|
|
1716
|
+
: { ok: false, status: null };
|
|
1717
|
+
return {
|
|
1718
|
+
sandbox_id: sandboxId,
|
|
1719
|
+
port: resolvedPort,
|
|
1720
|
+
preview_url: previewUrl,
|
|
1721
|
+
preview_ready: edge.ok,
|
|
1722
|
+
internal_status: internal.status,
|
|
1723
|
+
edge_status: edge.status,
|
|
1724
|
+
latency_ms: edge.latency_ms ?? null,
|
|
1725
|
+
};
|
|
1672
1726
|
}
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1677
|
-
|
|
1678
|
-
: (opts.installCommand ??
|
|
1679
|
-
(appManifest?.install === false ? null : appManifest?.install) ??
|
|
1680
|
-
(sourceBacked ? "npm install" : defaultInstallCommand(sourceDir)));
|
|
1681
|
-
if (installCommand) {
|
|
1682
|
-
deployStep(opts, `Installing dependencies: ${installCommand}`);
|
|
1683
|
-
await execSandbox(c, sandboxId, installCommand, remoteWorkdir, opts.timeout);
|
|
1684
|
-
}
|
|
1685
|
-
deployStep(opts, `Starting app on port ${resolvedPort}`);
|
|
1686
|
-
await execSandbox(c, sandboxId, `fuser -k ${resolvedPort}/tcp >/dev/null 2>&1 || true; nohup sh -lc ${shellQuote(resolvedStart)} > ${shellQuote(`/tmp/miosa-app-${resolvedPort}.log`)} 2>&1 & echo $!`, remoteWorkdir);
|
|
1687
|
-
deployStep(opts, "Checking internal app readiness");
|
|
1688
|
-
const internal = await waitForInternalHttp(c, sandboxId, resolvedPort, resolvedProbePath, Math.min(opts.timeout, 60));
|
|
1689
|
-
deployStep(opts, "Creating public preview route");
|
|
1690
|
-
const exposed = await c.apiPost(apiPath(`/sandboxes/${enc(sandboxId)}/expose`), { port: resolvedPort, title: "app preview" });
|
|
1691
|
-
const previewUrl = extractUrl(unwrap(exposed));
|
|
1692
|
-
if (!previewUrl) {
|
|
1693
|
-
throw new UserError("Sandbox expose did not return a preview URL.");
|
|
1727
|
+
catch (err) {
|
|
1728
|
+
if (sandboxId) {
|
|
1729
|
+
throw new SandboxDeployPartialError(err, sandboxId, recoveryCommandForSandboxDeploy(sandboxId, opts, localDir));
|
|
1730
|
+
}
|
|
1731
|
+
throw err;
|
|
1694
1732
|
}
|
|
1695
|
-
if (opts.wait)
|
|
1696
|
-
deployStep(opts, "Checking public preview readiness");
|
|
1697
|
-
const edge = opts.wait
|
|
1698
|
-
? await waitForPublicPreview(previewUrl, resolvedProbePath, opts.timeout)
|
|
1699
|
-
: { ok: false, status: null };
|
|
1700
|
-
return {
|
|
1701
|
-
sandbox_id: sandboxId,
|
|
1702
|
-
port: resolvedPort,
|
|
1703
|
-
preview_url: previewUrl,
|
|
1704
|
-
preview_ready: edge.ok,
|
|
1705
|
-
internal_status: internal.status,
|
|
1706
|
-
edge_status: edge.status,
|
|
1707
|
-
latency_ms: edge.latency_ms ?? null,
|
|
1708
|
-
};
|
|
1709
1733
|
}
|
|
1710
1734
|
const NON_TERMINAL_DEPLOY_STATES = new Set([
|
|
1711
1735
|
"building",
|
|
@@ -2011,10 +2035,123 @@ function createDeployArchive(sourceDir) {
|
|
|
2011
2035
|
return archivePath;
|
|
2012
2036
|
}
|
|
2013
2037
|
async function uploadFileToSandbox(c, sandboxId, localPath, remotePath) {
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
2017
|
-
|
|
2038
|
+
return writeBytesToSandbox(c, sandboxId, remotePath, fs.readFileSync(localPath));
|
|
2039
|
+
}
|
|
2040
|
+
async function writeBytesToSandbox(c, sandboxId, remotePath, bytes) {
|
|
2041
|
+
try {
|
|
2042
|
+
return await c.apiPost(apiPath(`/sandboxes/${enc(sandboxId)}/files`), {
|
|
2043
|
+
path: remotePath,
|
|
2044
|
+
content: bytes.toString("base64"),
|
|
2045
|
+
});
|
|
2046
|
+
}
|
|
2047
|
+
catch (err) {
|
|
2048
|
+
if (!shouldFallbackSandboxUpload(err))
|
|
2049
|
+
throw err;
|
|
2050
|
+
await writeBytesToSandboxViaExec(c, sandboxId, remotePath, bytes);
|
|
2051
|
+
return {
|
|
2052
|
+
data: {
|
|
2053
|
+
sandbox_id: sandboxId,
|
|
2054
|
+
path: remotePath,
|
|
2055
|
+
size: bytes.length,
|
|
2056
|
+
transport: "exec_chunked_fallback",
|
|
2057
|
+
},
|
|
2058
|
+
};
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
async function writeBytesToSandboxViaExec(c, sandboxId, remotePath, bytes) {
|
|
2062
|
+
const base64 = bytes.toString("base64");
|
|
2063
|
+
const base64Path = `${remotePath}.b64`;
|
|
2064
|
+
const chunkSize = 48_000;
|
|
2065
|
+
await execSandbox(c, sandboxId, `mkdir -p ${shellQuote(path.posix.dirname(remotePath))} && rm -f ${shellQuote(remotePath)} ${shellQuote(base64Path)}`, "/");
|
|
2066
|
+
for (let offset = 0; offset < base64.length; offset += chunkSize) {
|
|
2067
|
+
const chunk = base64.slice(offset, offset + chunkSize);
|
|
2068
|
+
await execSandbox(c, sandboxId, `printf '%s' ${shellQuote(chunk)} >> ${shellQuote(base64Path)}`, "/");
|
|
2069
|
+
}
|
|
2070
|
+
await execSandbox(c, sandboxId, `base64 -d ${shellQuote(base64Path)} > ${shellQuote(remotePath)} && rm -f ${shellQuote(base64Path)}`, "/");
|
|
2071
|
+
}
|
|
2072
|
+
function shouldFallbackSandboxUpload(err) {
|
|
2073
|
+
if (err instanceof NetworkError || err instanceof ServerError)
|
|
2074
|
+
return true;
|
|
2075
|
+
if (err instanceof ApiResponseError) {
|
|
2076
|
+
return (err.retryable ||
|
|
2077
|
+
/AGENT_UNAVAILABLE|SANDBOX_FILE_AGENT_UNAVAILABLE/i.test(err.code));
|
|
2078
|
+
}
|
|
2079
|
+
if (err instanceof Error) {
|
|
2080
|
+
return /fetch failed|ECONNRESET|HTTP 502|AGENT_UNAVAILABLE/i.test(err.message);
|
|
2081
|
+
}
|
|
2082
|
+
return false;
|
|
2083
|
+
}
|
|
2084
|
+
function recoveryCommandForSandboxDeploy(sandboxId, opts, localDir) {
|
|
2085
|
+
const parts = [
|
|
2086
|
+
"miosa",
|
|
2087
|
+
"sandbox",
|
|
2088
|
+
"deploy",
|
|
2089
|
+
shellQuote(localDir),
|
|
2090
|
+
"--sandbox",
|
|
2091
|
+
shellQuote(sandboxId),
|
|
2092
|
+
];
|
|
2093
|
+
if (opts.port != null)
|
|
2094
|
+
parts.push("--port", String(opts.port));
|
|
2095
|
+
if (opts.publishPort != null)
|
|
2096
|
+
parts.push("--publish-port", String(opts.publishPort));
|
|
2097
|
+
if (opts.installCommand)
|
|
2098
|
+
parts.push("--install-command", shellQuote(opts.installCommand));
|
|
2099
|
+
if (opts.install === false)
|
|
2100
|
+
parts.push("--no-install");
|
|
2101
|
+
if (opts.start)
|
|
2102
|
+
parts.push("--start", shellQuote(opts.start));
|
|
2103
|
+
if (opts.wait)
|
|
2104
|
+
parts.push("--wait");
|
|
2105
|
+
if (opts.timeout != null)
|
|
2106
|
+
parts.push("--timeout", `${opts.timeout}s`);
|
|
2107
|
+
if (opts.probePath)
|
|
2108
|
+
parts.push("--probe-path", shellQuote(opts.probePath));
|
|
2109
|
+
return parts.join(" ");
|
|
2110
|
+
}
|
|
2111
|
+
function handleSandboxDeployError(err, opts) {
|
|
2112
|
+
if (err instanceof SandboxDeployPartialError) {
|
|
2113
|
+
const cause = err.causeError;
|
|
2114
|
+
const message = cause instanceof Error ? cause.message : String(cause);
|
|
2115
|
+
const retryable = cause instanceof ApiResponseError
|
|
2116
|
+
? cause.retryable
|
|
2117
|
+
: shouldFallbackSandboxUpload(cause);
|
|
2118
|
+
if (isJsonMode(opts)) {
|
|
2119
|
+
console.log(JSON.stringify({
|
|
2120
|
+
ok: false,
|
|
2121
|
+
error: {
|
|
2122
|
+
code: errorCodeForDeployCause(cause),
|
|
2123
|
+
message,
|
|
2124
|
+
retryable,
|
|
2125
|
+
...(cause instanceof MiosaError && cause.requestId
|
|
2126
|
+
? { request_id: cause.requestId }
|
|
2127
|
+
: {}),
|
|
2128
|
+
},
|
|
2129
|
+
partial_resource: {
|
|
2130
|
+
type: "sandbox",
|
|
2131
|
+
id: err.sandboxId,
|
|
2132
|
+
recovery_command: err.recoveryCommand,
|
|
2133
|
+
},
|
|
2134
|
+
}, null, 2));
|
|
2135
|
+
return process.exit(1);
|
|
2136
|
+
}
|
|
2137
|
+
console.error(chalk.red(`Error: ${message}`));
|
|
2138
|
+
console.error(chalk.yellow(`Sandbox ${err.sandboxId} exists. Retry into it with:\n ${err.recoveryCommand}`));
|
|
2139
|
+
return process.exit(1);
|
|
2140
|
+
}
|
|
2141
|
+
handleError(err);
|
|
2142
|
+
}
|
|
2143
|
+
function errorCodeForDeployCause(err) {
|
|
2144
|
+
if (err instanceof ApiResponseError)
|
|
2145
|
+
return err.code;
|
|
2146
|
+
if (err instanceof NetworkError)
|
|
2147
|
+
return "NETWORK";
|
|
2148
|
+
if (err instanceof ServerError)
|
|
2149
|
+
return "SERVER";
|
|
2150
|
+
if (err instanceof MiosaError)
|
|
2151
|
+
return err.constructor.name.toUpperCase();
|
|
2152
|
+
if (err instanceof Error && /fetch failed|ECONNRESET/i.test(err.message))
|
|
2153
|
+
return "NETWORK";
|
|
2154
|
+
return "UNEXPECTED_ERROR";
|
|
2018
2155
|
}
|
|
2019
2156
|
async function uploadDirToSandbox(sandboxId, localDir, remoteDir, opts) {
|
|
2020
2157
|
const sourceDir = path.resolve(localDir);
|