coderemote 0.3.0 → 0.3.1
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/coderemote.js +52 -15
- package/package.json +1 -1
package/dist/coderemote.js
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
import { execFile as execFile5, spawn as spawn3 } from "node:child_process";
|
|
5
5
|
import { randomBytes } from "node:crypto";
|
|
6
6
|
import fs8 from "node:fs";
|
|
7
|
+
import net2 from "node:net";
|
|
7
8
|
import os4 from "node:os";
|
|
8
9
|
import path7 from "node:path";
|
|
9
10
|
import { fileURLToPath } from "node:url";
|
|
@@ -1478,7 +1479,7 @@ function parse(out) {
|
|
|
1478
1479
|
return JSON.parse(out.slice(out.indexOf("{")));
|
|
1479
1480
|
}
|
|
1480
1481
|
function machineName(description) {
|
|
1481
|
-
return (description || "").replace(/^(coderemote|vsremote)\s+/, "").replace(/\.local
|
|
1482
|
+
return (description || "").replace(/^(coderemote|vsremote)\s+/, "").replace(/\.local\b/, "") || null;
|
|
1482
1483
|
}
|
|
1483
1484
|
function machine(tunnel, current) {
|
|
1484
1485
|
return {
|
|
@@ -1587,7 +1588,7 @@ function installCommand(installedAt) {
|
|
|
1587
1588
|
// package.json
|
|
1588
1589
|
var package_default = {
|
|
1589
1590
|
name: "coderemote",
|
|
1590
|
-
version: "0.3.
|
|
1591
|
+
version: "0.3.1",
|
|
1591
1592
|
description: "Use your computer from your iPhone: files, git and a real terminal over a secure Microsoft Dev Tunnel. No SSH, no port forwarding, no VPN.",
|
|
1592
1593
|
keywords: [
|
|
1593
1594
|
"remote",
|
|
@@ -1935,12 +1936,23 @@ function loadConfig() {
|
|
|
1935
1936
|
cfg2.token = randomBytes(32).toString("base64url");
|
|
1936
1937
|
saveConfig(cfg2);
|
|
1937
1938
|
}
|
|
1939
|
+
if (cfg2.tunnelId && !cfg2.tunnels) {
|
|
1940
|
+
cfg2.tunnels = { [DEFAULT_PORT]: cfg2.tunnelId };
|
|
1941
|
+
saveConfig(cfg2);
|
|
1942
|
+
}
|
|
1938
1943
|
return cfg2;
|
|
1939
1944
|
}
|
|
1940
1945
|
function saveConfig(cfg2) {
|
|
1941
1946
|
fs8.mkdirSync(CONFIG_DIR, { recursive: true, mode: 448 });
|
|
1942
1947
|
fs8.writeFileSync(CONFIG_FILE, JSON.stringify(cfg2, null, 2), { mode: 384 });
|
|
1943
1948
|
}
|
|
1949
|
+
function portFree(port2) {
|
|
1950
|
+
return new Promise((resolve) => {
|
|
1951
|
+
const probe = net2.createServer();
|
|
1952
|
+
probe.once("error", () => resolve(false));
|
|
1953
|
+
probe.listen(port2, "127.0.0.1", () => probe.close(() => resolve(true)));
|
|
1954
|
+
});
|
|
1955
|
+
}
|
|
1944
1956
|
function listen(token, port2, root2, tunnelToken, preview, status2) {
|
|
1945
1957
|
const server = createAgentServer({ token, root: root2, tunnelToken, preview, tunnelStatus: status2 });
|
|
1946
1958
|
return new Promise((resolve, reject) => {
|
|
@@ -2009,20 +2021,22 @@ function applyAccess(tunnelId, anonymous2) {
|
|
|
2009
2021
|
return anonymous2 ? devtunnel("access", "create", tunnelId, "--anonymous") : devtunnel("access", "reset", tunnelId);
|
|
2010
2022
|
}
|
|
2011
2023
|
async function ensureTunnel(cfg2, port2, anonymous2) {
|
|
2012
|
-
|
|
2024
|
+
const known = cfg2.tunnels?.[port2];
|
|
2025
|
+
if (known) {
|
|
2013
2026
|
const [updated, access] = await Promise.all([
|
|
2014
|
-
devtunnel("update",
|
|
2015
|
-
applyAccess(
|
|
2027
|
+
devtunnel("update", known, "--expiration", "30d", "--add-labels", MACHINE_LABEL),
|
|
2028
|
+
applyAccess(known, anonymous2)
|
|
2016
2029
|
]);
|
|
2017
2030
|
if (updated.ok) {
|
|
2018
2031
|
if (!access.ok) throw new Error(`devtunnel access failed:
|
|
2019
2032
|
${access.out}`);
|
|
2020
|
-
return
|
|
2033
|
+
return known;
|
|
2021
2034
|
}
|
|
2022
2035
|
if (!/not found/i.test(updated.out)) throw new Error(`devtunnel update failed:
|
|
2023
2036
|
${updated.out}`);
|
|
2024
2037
|
}
|
|
2025
|
-
const
|
|
2038
|
+
const name = port2 === DEFAULT_PORT ? os4.hostname() : `${os4.hostname()} :${port2}`;
|
|
2039
|
+
const createArgs = ["create", "--expiration", "30d", "-d", `coderemote ${name}`, "--labels", MACHINE_LABEL, "--json"];
|
|
2026
2040
|
if (anonymous2) createArgs.push("--allow-anonymous");
|
|
2027
2041
|
const created = await devtunnel(...createArgs);
|
|
2028
2042
|
if (!created.ok) throw new Error(`devtunnel create failed:
|
|
@@ -2033,7 +2047,8 @@ ${created.out}`);
|
|
|
2033
2047
|
const portRes = await devtunnel("port", "create", tunnelId, "-p", String(port2), "--protocol", "http");
|
|
2034
2048
|
if (!portRes.ok) throw new Error(`devtunnel port create failed:
|
|
2035
2049
|
${portRes.out}`);
|
|
2036
|
-
cfg2.
|
|
2050
|
+
cfg2.tunnels = { ...cfg2.tunnels, [port2]: tunnelId };
|
|
2051
|
+
if (port2 === DEFAULT_PORT) cfg2.tunnelId = tunnelId;
|
|
2037
2052
|
saveConfig(cfg2);
|
|
2038
2053
|
return tunnelId;
|
|
2039
2054
|
}
|
|
@@ -2131,7 +2146,8 @@ var USAGE = `Usage: coderemote <command> [options]
|
|
|
2131
2146
|
|
|
2132
2147
|
Options:
|
|
2133
2148
|
--root DIR folder to share (default: current folder)
|
|
2134
|
-
--port N local port (default: ${DEFAULT_PORT}
|
|
2149
|
+
--port N local port (default: the first free one from ${DEFAULT_PORT}; each port
|
|
2150
|
+
keeps its own tunnel URL, so a folder pairs once per port)
|
|
2135
2151
|
--allow-anonymous up: skip the sign-in, the pairing token alone grants access
|
|
2136
2152
|
(alias --no-auth)
|
|
2137
2153
|
--web up: also run \`code tunnel\` and print a vscode.dev link that opens
|
|
@@ -2149,11 +2165,32 @@ var root = path7.resolve(flag("--root") ?? process.cwd());
|
|
|
2149
2165
|
var cfg = loadConfig();
|
|
2150
2166
|
var registry = new AgentRegistry(path7.join(CONFIG_DIR, "agents"));
|
|
2151
2167
|
async function start({ tunnel }) {
|
|
2152
|
-
const
|
|
2153
|
-
if (
|
|
2154
|
-
|
|
2155
|
-
|
|
2156
|
-
|
|
2168
|
+
const agents = registry.list();
|
|
2169
|
+
if (flag("--port")) {
|
|
2170
|
+
const running = agents.find((a) => a.port === port);
|
|
2171
|
+
if (running) {
|
|
2172
|
+
console.error(`An agent already runs on port ${port} for ${running.root} (pid ${running.pid}).`);
|
|
2173
|
+
console.error("Stop it with `coderemote stop --all`, or pick another port with --port.");
|
|
2174
|
+
process.exit(1);
|
|
2175
|
+
}
|
|
2176
|
+
} else {
|
|
2177
|
+
const sharing = agents.find((a) => a.root === root);
|
|
2178
|
+
if (sharing) {
|
|
2179
|
+
console.error(`${root} is already shared on port ${sharing.port} (pid ${sharing.pid}).`);
|
|
2180
|
+
console.error("Stop it with `coderemote stop`, or start another one with --port.");
|
|
2181
|
+
process.exit(1);
|
|
2182
|
+
}
|
|
2183
|
+
const taken = async (p) => agents.some((a) => a.port === p) || !await portFree(p);
|
|
2184
|
+
const remembered = cfg.folderPorts?.[root];
|
|
2185
|
+
if (remembered && !await taken(remembered)) port = remembered;
|
|
2186
|
+
else {
|
|
2187
|
+
const claimed = new Set(Object.values(cfg.folderPorts ?? {}));
|
|
2188
|
+
while (claimed.has(port) || await taken(port)) port++;
|
|
2189
|
+
}
|
|
2190
|
+
if (port !== remembered) {
|
|
2191
|
+
cfg.folderPorts = { ...cfg.folderPorts, [root]: port };
|
|
2192
|
+
saveConfig(cfg);
|
|
2193
|
+
}
|
|
2157
2194
|
}
|
|
2158
2195
|
let server;
|
|
2159
2196
|
let tunnelId;
|
|
@@ -2193,7 +2230,7 @@ async function start({ tunnel }) {
|
|
|
2193
2230
|
account = user;
|
|
2194
2231
|
spinner.succeed();
|
|
2195
2232
|
spinner.start("Connecting to the relay");
|
|
2196
|
-
const known = cfg.
|
|
2233
|
+
const known = cfg.tunnels?.[port];
|
|
2197
2234
|
let hosting = known ? hostTunnel(known, port) : null;
|
|
2198
2235
|
hosting?.catch(() => {
|
|
2199
2236
|
});
|
package/package.json
CHANGED