locadot 2.3.0 → 2.5.0

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.
@@ -11,7 +11,7 @@ const path_1 = __importDefault(require("path"));
11
11
  const child_process_1 = require("child_process");
12
12
  const constants_1 = __importDefault(require("../constants"));
13
13
  const logger_1 = __importDefault(require("../utils/logger"));
14
- const hub_tunnel_1 = require("./hub-tunnel");
14
+ const cloudflare_logins_1 = require("./cloudflare-logins");
15
15
  /**
16
16
  * Public sharing through Cloudflare quick tunnels (https://<random>.trycloudflare.com, no account),
17
17
  * or through a named tunnel per mapping on the user's own hostname (`tunnelDomain`).
@@ -37,15 +37,17 @@ exports.cloudflaredPath = cloudflaredPath;
37
37
  // The dashboard polls status every few seconds; don't spawn cloudflared --version each time.
38
38
  let cached;
39
39
  const cloudflaredInfo = (fresh = false) => {
40
+ // Logins change when a share signs in, and reading them is cheap; only the version check is cached.
41
+ const zones = (0, cloudflare_logins_1.loggedInZones)();
42
+ const loggedIn = zones.length > 0 || fs_1.default.existsSync(path_1.default.join(os_1.default.homedir(), ".cloudflared", "cert.pem"));
40
43
  if (!fresh && cached && Date.now() - cached.at < 60000)
41
- return cached.info;
44
+ return { ...cached.info, loggedIn, zones };
42
45
  const file = (0, exports.cloudflaredPath)();
43
- const loggedIn = fs_1.default.existsSync(path_1.default.join(os_1.default.homedir(), ".cloudflared", "cert.pem"));
44
- let info = { installed: false, loggedIn };
46
+ let info = { installed: false, loggedIn, zones };
45
47
  if (file) {
46
48
  const result = (0, child_process_1.spawnSync)(file, ["--version"], { encoding: "utf8", timeout: 5000, windowsHide: true });
47
49
  const version = `${result.stdout || ""}${result.stderr || ""}`.match(/version\s+(\S+)/i)?.[1];
48
- info = { installed: result.status === 0, loggedIn, path: file, ...(version ? { version } : {}) };
50
+ info = { installed: result.status === 0, loggedIn, zones, path: file, ...(version ? { version } : {}) };
49
51
  }
50
52
  cached = { at: Date.now(), info };
51
53
  return info;
@@ -136,7 +138,7 @@ class TunnelManager {
136
138
  const tunnel = this.tunnels.get(host);
137
139
  if (!tunnel)
138
140
  return { enabled: false, status: "off" };
139
- const { child, publicHost, ...state } = tunnel;
141
+ const { child, publicHost, abort, ...state } = tunnel;
140
142
  return state;
141
143
  }
142
144
  /** Starts and stops tunnels to match the registry; `retry` also restarts ones that failed. */
@@ -176,15 +178,17 @@ class TunnelManager {
176
178
  startCustom(file, host, domain, tunnel) {
177
179
  const name = `locadot-${host.replace(/[^a-z0-9-]/gi, "-")}`;
178
180
  tunnel.publicHost = domain;
179
- (0, hub_tunnel_1.setupNamedTunnel)(domain, name, (loginUrl) => {
181
+ tunnel.abort = new AbortController();
182
+ (0, cloudflare_logins_1.setupDomainTunnel)(domain, name, (loginUrl) => {
180
183
  if (this.tunnels.get(host) === tunnel)
181
184
  Object.assign(tunnel, { status: "login", loginUrl });
182
- })
183
- .then(() => {
185
+ }, tunnel.abort.signal)
186
+ .then(({ cert, credentials }) => {
184
187
  if (this.tunnels.get(host) !== tunnel)
185
188
  return;
186
- Object.assign(tunnel, { status: "starting", loginUrl: undefined });
187
- this.run(host, tunnel, file, ["tunnel", "--no-autoupdate", "run", "--url", this.origin(), name], (text) => {
189
+ Object.assign(tunnel, { status: "starting", loginUrl: undefined, abort: undefined });
190
+ const args = ["tunnel", "--no-autoupdate", "--origincert", cert, "run", ...(credentials ? ["--credentials-file", credentials] : []), "--url", this.origin(), name];
191
+ this.run(host, tunnel, file, args, (text) => {
188
192
  if (REGISTERED_PATTERN.test(text))
189
193
  Object.assign(tunnel, { status: "up", url: `https://${domain}` });
190
194
  });
@@ -228,6 +232,7 @@ class TunnelManager {
228
232
  if (tunnel?.child || tunnel?.status === "login")
229
233
  logger_1.default.info(`🌍 ${host} is no longer public`);
230
234
  tunnel?.child?.kill();
235
+ tunnel?.abort?.abort();
231
236
  }
232
237
  stopAll() {
233
238
  for (const host of [...this.tunnels.keys()])
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "locadot",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "description": "Secure your local development environment with HTTPS and custom domains like dev.localhost.",
5
5
  "homepage": "https://www.npmjs.com/package/locadot",
6
6
  "main": "dist/index.js",