shiplocal 0.1.3 → 0.1.4
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/index.js +40 -10
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4153,6 +4153,7 @@ import { WebSocket } from "ws";
|
|
|
4153
4153
|
|
|
4154
4154
|
// ../tunnel-client/dist/local-proxy.js
|
|
4155
4155
|
import http from "node:http";
|
|
4156
|
+
var LOOPBACK_HOSTS = ["127.0.0.1", "::1"];
|
|
4156
4157
|
var HOP_BY_HOP_HEADERS = /* @__PURE__ */ new Set([
|
|
4157
4158
|
"connection",
|
|
4158
4159
|
"keep-alive",
|
|
@@ -4168,6 +4169,9 @@ var STRIP_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
|
|
|
4168
4169
|
"content-encoding",
|
|
4169
4170
|
"content-length"
|
|
4170
4171
|
]);
|
|
4172
|
+
function isConnectionRefused(err) {
|
|
4173
|
+
return err instanceof Error && "code" in err && err.code === "ECONNREFUSED";
|
|
4174
|
+
}
|
|
4171
4175
|
function sanitizeRequestHeaders(headers, localPort) {
|
|
4172
4176
|
const result = {};
|
|
4173
4177
|
for (const [key, value] of Object.entries(headers)) {
|
|
@@ -4192,12 +4196,10 @@ function sanitizeResponseHeaders(headers) {
|
|
|
4192
4196
|
}
|
|
4193
4197
|
return result;
|
|
4194
4198
|
}
|
|
4195
|
-
|
|
4196
|
-
const body = decodeBody(message.body);
|
|
4197
|
-
const pathWithQuery = message.query ? `${message.path}?${message.query}` : message.path;
|
|
4199
|
+
function forwardToHost(hostname, localPort, message, body, pathWithQuery) {
|
|
4198
4200
|
return new Promise((resolve, reject) => {
|
|
4199
4201
|
const req = http.request({
|
|
4200
|
-
hostname
|
|
4202
|
+
hostname,
|
|
4201
4203
|
port: localPort,
|
|
4202
4204
|
method: message.method,
|
|
4203
4205
|
path: pathWithQuery,
|
|
@@ -4234,6 +4236,23 @@ async function forwardToLocal(localPort, message) {
|
|
|
4234
4236
|
req.end();
|
|
4235
4237
|
});
|
|
4236
4238
|
}
|
|
4239
|
+
async function forwardToLocal(localPort, message) {
|
|
4240
|
+
const body = decodeBody(message.body);
|
|
4241
|
+
const pathWithQuery = message.query ? `${message.path}?${message.query}` : message.path;
|
|
4242
|
+
let lastError;
|
|
4243
|
+
for (const hostname of LOOPBACK_HOSTS) {
|
|
4244
|
+
try {
|
|
4245
|
+
return await forwardToHost(hostname, localPort, message, body, pathWithQuery);
|
|
4246
|
+
} catch (err) {
|
|
4247
|
+
if (isConnectionRefused(err)) {
|
|
4248
|
+
lastError = err;
|
|
4249
|
+
continue;
|
|
4250
|
+
}
|
|
4251
|
+
throw err;
|
|
4252
|
+
}
|
|
4253
|
+
}
|
|
4254
|
+
throw lastError ?? new Error("Local server unreachable");
|
|
4255
|
+
}
|
|
4237
4256
|
|
|
4238
4257
|
// ../tunnel-client/dist/client.js
|
|
4239
4258
|
function toWebSocketUrl(serverUrl) {
|
|
@@ -4247,9 +4266,11 @@ function toWebSocketUrl(serverUrl) {
|
|
|
4247
4266
|
function formatLocalProxyError(err, localPort) {
|
|
4248
4267
|
if (err instanceof Error && "code" in err && err.code === "ECONNREFUSED") {
|
|
4249
4268
|
return [
|
|
4250
|
-
`Nothing is
|
|
4269
|
+
`Nothing is listening on port ${String(localPort)} (tried 127.0.0.1 and ::1).`,
|
|
4251
4270
|
"",
|
|
4252
4271
|
"Start your local server on that port, then refresh this page.",
|
|
4272
|
+
"If your browser works on localhost but the tunnel does not, your dev server may only",
|
|
4273
|
+
"listen on IPv6 \u2014 bind to 0.0.0.0 or 127.0.0.1 (e.g. next dev -H 0.0.0.0).",
|
|
4253
4274
|
`If your app uses a different port, restart the CLI with that port (e.g. shiplocal ${String(localPort)}).`
|
|
4254
4275
|
].join("\n");
|
|
4255
4276
|
}
|
|
@@ -4465,7 +4486,7 @@ async function resolveToken() {
|
|
|
4465
4486
|
}
|
|
4466
4487
|
|
|
4467
4488
|
// src/api.ts
|
|
4468
|
-
function
|
|
4489
|
+
function isConnectionRefused2(err) {
|
|
4469
4490
|
if (!(err instanceof Error)) return false;
|
|
4470
4491
|
const cause = err.cause;
|
|
4471
4492
|
if (cause instanceof Error && "code" in cause && cause.code === "ECONNREFUSED") {
|
|
@@ -4477,7 +4498,7 @@ function isConnectionRefused(err) {
|
|
|
4477
4498
|
return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed");
|
|
4478
4499
|
}
|
|
4479
4500
|
function formatServerConnectionError(apiUrl, err) {
|
|
4480
|
-
if (
|
|
4501
|
+
if (isConnectionRefused2(err)) {
|
|
4481
4502
|
return [
|
|
4482
4503
|
`Cannot reach ShipLocal server at ${apiUrl}.`,
|
|
4483
4504
|
"",
|
|
@@ -4508,9 +4529,10 @@ async function postJson(path, body, apiUrl) {
|
|
|
4508
4529
|
|
|
4509
4530
|
// src/local-port.ts
|
|
4510
4531
|
import net from "node:net";
|
|
4511
|
-
|
|
4532
|
+
var LOOPBACK_HOSTS2 = ["127.0.0.1", "::1"];
|
|
4533
|
+
function canConnect(host, port, timeoutMs) {
|
|
4512
4534
|
return new Promise((resolve) => {
|
|
4513
|
-
const socket = net.connect({ port, host
|
|
4535
|
+
const socket = net.connect({ port, host });
|
|
4514
4536
|
const finish = (open) => {
|
|
4515
4537
|
socket.removeAllListeners();
|
|
4516
4538
|
socket.destroy();
|
|
@@ -4528,10 +4550,18 @@ function isLocalPortOpen(port, timeoutMs = 2e3) {
|
|
|
4528
4550
|
});
|
|
4529
4551
|
});
|
|
4530
4552
|
}
|
|
4553
|
+
async function isLocalPortOpen(port, timeoutMs = 2e3) {
|
|
4554
|
+
for (const host of LOOPBACK_HOSTS2) {
|
|
4555
|
+
if (await canConnect(host, port, timeoutMs)) {
|
|
4556
|
+
return true;
|
|
4557
|
+
}
|
|
4558
|
+
}
|
|
4559
|
+
return false;
|
|
4560
|
+
}
|
|
4531
4561
|
|
|
4532
4562
|
// src/index.ts
|
|
4533
4563
|
var program = new Command();
|
|
4534
|
-
program.name("shiplocal").description("Share localhost with clients in seconds").version("0.1.
|
|
4564
|
+
program.name("shiplocal").description("Share localhost with clients in seconds").version("0.1.4");
|
|
4535
4565
|
program.command("login").description("Authenticate with ShipLocal Cloud").action(async () => {
|
|
4536
4566
|
const rl = createInterface({ input, output });
|
|
4537
4567
|
const apiUrl = await resolveApiUrlAsync();
|