shiplocal 0.1.2 → 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 +47 -14
- package/dist/index.js.map +3 -3
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -4071,7 +4071,7 @@ var DEFAULT_TUNNEL_PORT = 3e3;
|
|
|
4071
4071
|
// ../shared/dist/protocol.js
|
|
4072
4072
|
var TUNNEL_WS_PATH = "/tunnel";
|
|
4073
4073
|
var DEFAULT_TUNNEL_EXPIRY_MS = 2 * 60 * 60 * 1e3;
|
|
4074
|
-
var MAX_BODY_BYTES =
|
|
4074
|
+
var MAX_BODY_BYTES = 50 * 1024 * 1024;
|
|
4075
4075
|
var headersSchema = external_exports.record(external_exports.union([external_exports.string(), external_exports.array(external_exports.string())]));
|
|
4076
4076
|
var registerMessageSchema = external_exports.object({
|
|
4077
4077
|
type: external_exports.literal("register"),
|
|
@@ -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,7 +4169,10 @@ var STRIP_RESPONSE_HEADERS = /* @__PURE__ */ new Set([
|
|
|
4168
4169
|
"content-encoding",
|
|
4169
4170
|
"content-length"
|
|
4170
4171
|
]);
|
|
4171
|
-
function
|
|
4172
|
+
function isConnectionRefused(err) {
|
|
4173
|
+
return err instanceof Error && "code" in err && err.code === "ECONNREFUSED";
|
|
4174
|
+
}
|
|
4175
|
+
function sanitizeRequestHeaders(headers, localPort) {
|
|
4172
4176
|
const result = {};
|
|
4173
4177
|
for (const [key, value] of Object.entries(headers)) {
|
|
4174
4178
|
const lower = key.toLowerCase();
|
|
@@ -4177,6 +4181,7 @@ function sanitizeRequestHeaders(headers) {
|
|
|
4177
4181
|
}
|
|
4178
4182
|
result[key] = value;
|
|
4179
4183
|
}
|
|
4184
|
+
result["host"] = `localhost:${String(localPort)}`;
|
|
4180
4185
|
return result;
|
|
4181
4186
|
}
|
|
4182
4187
|
function sanitizeResponseHeaders(headers) {
|
|
@@ -4191,16 +4196,14 @@ function sanitizeResponseHeaders(headers) {
|
|
|
4191
4196
|
}
|
|
4192
4197
|
return result;
|
|
4193
4198
|
}
|
|
4194
|
-
|
|
4195
|
-
const body = decodeBody(message.body);
|
|
4196
|
-
const pathWithQuery = message.query ? `${message.path}?${message.query}` : message.path;
|
|
4199
|
+
function forwardToHost(hostname, localPort, message, body, pathWithQuery) {
|
|
4197
4200
|
return new Promise((resolve, reject) => {
|
|
4198
4201
|
const req = http.request({
|
|
4199
|
-
hostname
|
|
4202
|
+
hostname,
|
|
4200
4203
|
port: localPort,
|
|
4201
4204
|
method: message.method,
|
|
4202
4205
|
path: pathWithQuery,
|
|
4203
|
-
headers: sanitizeRequestHeaders(message.headers)
|
|
4206
|
+
headers: sanitizeRequestHeaders(message.headers, localPort)
|
|
4204
4207
|
}, (res) => {
|
|
4205
4208
|
const chunks = [];
|
|
4206
4209
|
let totalSize = 0;
|
|
@@ -4233,6 +4236,23 @@ async function forwardToLocal(localPort, message) {
|
|
|
4233
4236
|
req.end();
|
|
4234
4237
|
});
|
|
4235
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
|
+
}
|
|
4236
4256
|
|
|
4237
4257
|
// ../tunnel-client/dist/client.js
|
|
4238
4258
|
function toWebSocketUrl(serverUrl) {
|
|
@@ -4246,9 +4266,11 @@ function toWebSocketUrl(serverUrl) {
|
|
|
4246
4266
|
function formatLocalProxyError(err, localPort) {
|
|
4247
4267
|
if (err instanceof Error && "code" in err && err.code === "ECONNREFUSED") {
|
|
4248
4268
|
return [
|
|
4249
|
-
`Nothing is
|
|
4269
|
+
`Nothing is listening on port ${String(localPort)} (tried 127.0.0.1 and ::1).`,
|
|
4250
4270
|
"",
|
|
4251
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).",
|
|
4252
4274
|
`If your app uses a different port, restart the CLI with that port (e.g. shiplocal ${String(localPort)}).`
|
|
4253
4275
|
].join("\n");
|
|
4254
4276
|
}
|
|
@@ -4358,7 +4380,9 @@ function createTunnelClient(options) {
|
|
|
4358
4380
|
ws.close();
|
|
4359
4381
|
}
|
|
4360
4382
|
}
|
|
4361
|
-
const socket = new WebSocket(toWebSocketUrl(options.serverUrl)
|
|
4383
|
+
const socket = new WebSocket(toWebSocketUrl(options.serverUrl), {
|
|
4384
|
+
maxPayload: 64 * 1024 * 1024
|
|
4385
|
+
});
|
|
4362
4386
|
ws = socket;
|
|
4363
4387
|
socket.on("open", () => {
|
|
4364
4388
|
socket.send(JSON.stringify({
|
|
@@ -4462,7 +4486,7 @@ async function resolveToken() {
|
|
|
4462
4486
|
}
|
|
4463
4487
|
|
|
4464
4488
|
// src/api.ts
|
|
4465
|
-
function
|
|
4489
|
+
function isConnectionRefused2(err) {
|
|
4466
4490
|
if (!(err instanceof Error)) return false;
|
|
4467
4491
|
const cause = err.cause;
|
|
4468
4492
|
if (cause instanceof Error && "code" in cause && cause.code === "ECONNREFUSED") {
|
|
@@ -4474,7 +4498,7 @@ function isConnectionRefused(err) {
|
|
|
4474
4498
|
return err.message.includes("ECONNREFUSED") || err.message.includes("fetch failed");
|
|
4475
4499
|
}
|
|
4476
4500
|
function formatServerConnectionError(apiUrl, err) {
|
|
4477
|
-
if (
|
|
4501
|
+
if (isConnectionRefused2(err)) {
|
|
4478
4502
|
return [
|
|
4479
4503
|
`Cannot reach ShipLocal server at ${apiUrl}.`,
|
|
4480
4504
|
"",
|
|
@@ -4505,9 +4529,10 @@ async function postJson(path, body, apiUrl) {
|
|
|
4505
4529
|
|
|
4506
4530
|
// src/local-port.ts
|
|
4507
4531
|
import net from "node:net";
|
|
4508
|
-
|
|
4532
|
+
var LOOPBACK_HOSTS2 = ["127.0.0.1", "::1"];
|
|
4533
|
+
function canConnect(host, port, timeoutMs) {
|
|
4509
4534
|
return new Promise((resolve) => {
|
|
4510
|
-
const socket = net.connect({ port, host
|
|
4535
|
+
const socket = net.connect({ port, host });
|
|
4511
4536
|
const finish = (open) => {
|
|
4512
4537
|
socket.removeAllListeners();
|
|
4513
4538
|
socket.destroy();
|
|
@@ -4525,10 +4550,18 @@ function isLocalPortOpen(port, timeoutMs = 2e3) {
|
|
|
4525
4550
|
});
|
|
4526
4551
|
});
|
|
4527
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
|
+
}
|
|
4528
4561
|
|
|
4529
4562
|
// src/index.ts
|
|
4530
4563
|
var program = new Command();
|
|
4531
|
-
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");
|
|
4532
4565
|
program.command("login").description("Authenticate with ShipLocal Cloud").action(async () => {
|
|
4533
4566
|
const rl = createInterface({ input, output });
|
|
4534
4567
|
const apiUrl = await resolveApiUrlAsync();
|