ledung 1.2.0 → 1.4.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.
- package/CHANGELOG.md +1 -0
- package/dist/cli.js +0 -0
- package/dist/main.js +36 -8
- package/npm-shrinkwrap.json +2 -2
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -10,6 +10,7 @@ that changes `src/`, `web/` (not `web/dist/`) or `scripts/` without one (a commi
|
|
|
10
10
|
is nothing user-facing in it).
|
|
11
11
|
|
|
12
12
|
## 2026-11-02
|
|
13
|
+
- A request whose address doesn't parse is now refused with a 400, also on the live connection, without an error in the log (Fluffy-Fluffy-and-Bouncy/Project-Ledung#467)
|
|
13
14
|
- Started at sign-in on macOS or Linux, or from Ledung.app, Ledung now gets the same PATH as in your terminal, so Update Ledung, Ledung's GitHub features and the tools your sessions use work after a login too; a shell profile that hangs delays the start by about ten seconds instead of stopping it. Switch Start Ledung when I sign in off and on in Settings to get it (#464)
|
|
14
15
|
- Settings → About has an update channel, Public or Dev: on Dev an npm-installed Ledung gets dev builds before they go to everyone, and Update & restart now checks npm and updates an npm install with one click (#461)
|
|
15
16
|
|
package/dist/cli.js
CHANGED
|
File without changes
|
package/dist/main.js
CHANGED
|
@@ -15318,6 +15318,7 @@ var LINK_PAIRINGS_KEPT = 20;
|
|
|
15318
15318
|
var LINK_PAIR_TIMES_KEY = "link-pair-times";
|
|
15319
15319
|
var WAITING_POLL_MS = 3e4;
|
|
15320
15320
|
var WAITING_PUSH_MS = 1e3;
|
|
15321
|
+
var exercised463 = false;
|
|
15321
15322
|
var LINKED_HERE = "Computers are linked and unlinked";
|
|
15322
15323
|
var MAX_BODY2 = 1024 * 1024;
|
|
15323
15324
|
var NOT_PAIRED = "This device is not paired with Ledung. Pair it from Settings \u2192 Phones in Ledung on the computer.";
|
|
@@ -15540,12 +15541,16 @@ var LedungServer = class {
|
|
|
15540
15541
|
this.handle(req, res).catch((e) => this.fail(res, e));
|
|
15541
15542
|
});
|
|
15542
15543
|
server.on("upgrade", (req, socket, head) => {
|
|
15543
|
-
const
|
|
15544
|
-
|
|
15545
|
-
|
|
15544
|
+
const refuse = (status) => {
|
|
15545
|
+
socket.end(`HTTP/1.1 ${status}\r
|
|
15546
|
+
Connection: close\r
|
|
15547
|
+
\r
|
|
15548
|
+
`);
|
|
15546
15549
|
setTimeout(() => socket.destroy(), 1e3).unref();
|
|
15547
|
-
|
|
15548
|
-
|
|
15550
|
+
};
|
|
15551
|
+
const url = requestUrl(req);
|
|
15552
|
+
if (!url) return refuse("400 Bad Request");
|
|
15553
|
+
if (url.pathname !== "/ws" || !this.guard.hostAllowed(req) || !this.guard.originAllowed(req) || !this.guard.mayUse(req)) return refuse("403 Forbidden");
|
|
15549
15554
|
const device = this.guard.deviceOf(req)?.id ?? null;
|
|
15550
15555
|
const viaPublic = this.guard.isPublic(req);
|
|
15551
15556
|
this.wss.handleUpgrade(req, socket, head, (ws) => this.onClient(ws, device, viaPublic));
|
|
@@ -15697,6 +15702,7 @@ var LedungServer = class {
|
|
|
15697
15702
|
if (this.remote) this.setRemote(this.remote);
|
|
15698
15703
|
}
|
|
15699
15704
|
close() {
|
|
15705
|
+
this.closed = true;
|
|
15700
15706
|
if (this.waitingPoll) clearInterval(this.waitingPoll);
|
|
15701
15707
|
if (this.waitingPush) clearTimeout(this.waitingPush);
|
|
15702
15708
|
for (const ws of this.clients) ws.close(1001, "Ledung is shutting down.");
|
|
@@ -15815,8 +15821,9 @@ var LedungServer = class {
|
|
|
15815
15821
|
return computers;
|
|
15816
15822
|
}
|
|
15817
15823
|
async handle(req, res) {
|
|
15824
|
+
const url = requestUrl(req);
|
|
15825
|
+
if (!url) throw new HttpError(400, "Bad request path.");
|
|
15818
15826
|
if (!this.guard.hostAllowed(req)) throw new HttpError(403, "Unknown host.");
|
|
15819
|
-
const url = new URL(req.url ?? "/", "http://127.0.0.1");
|
|
15820
15827
|
const remote = this.guard.isPublic(req);
|
|
15821
15828
|
if (remote) {
|
|
15822
15829
|
this.publicResponses.add(res);
|
|
@@ -16051,6 +16058,11 @@ var LedungServer = class {
|
|
|
16051
16058
|
waitingThere = /* @__PURE__ */ new Map();
|
|
16052
16059
|
waitingPoll = null;
|
|
16053
16060
|
waitingPush = null;
|
|
16061
|
+
/**
|
|
16062
|
+
* Set by close: an exchange still on its way then changes nothing and starts no new one, as the database may be
|
|
16063
|
+
* closed by the time its answer comes (#463: it threw "database is not open" after a test's end).
|
|
16064
|
+
*/
|
|
16065
|
+
closed = false;
|
|
16054
16066
|
/** The count last sent to the linked computers, so an unchanged one isn't sent again. */
|
|
16055
16067
|
waitingSent = null;
|
|
16056
16068
|
/** What waits for the user here, as this computer's page counts it (App: questions, prompts, cards). */
|
|
@@ -16059,7 +16071,7 @@ var LedungServer = class {
|
|
|
16059
16071
|
}
|
|
16060
16072
|
/** Something that may change the count happened: sent to the linked computers shortly, if it did change. */
|
|
16061
16073
|
waitingChanged() {
|
|
16062
|
-
if (this.waitingPush || !this.linked || !this.servers.length) return;
|
|
16074
|
+
if (this.closed || this.waitingPush || !this.linked || !this.servers.length) return;
|
|
16063
16075
|
this.waitingPush = setTimeout(() => {
|
|
16064
16076
|
this.waitingPush = null;
|
|
16065
16077
|
if (this.waitingNow() !== this.waitingSent) this.exchangeWaiting();
|
|
@@ -16069,7 +16081,7 @@ var LedungServer = class {
|
|
|
16069
16081
|
/** Sends this computer's count to every linked one and keeps theirs; one that doesn't answer loses its badge. */
|
|
16070
16082
|
exchangeWaiting() {
|
|
16071
16083
|
const linked = this.linked;
|
|
16072
|
-
if (!linked) return;
|
|
16084
|
+
if (!linked || this.closed) return;
|
|
16073
16085
|
const count = this.waitingNow();
|
|
16074
16086
|
this.waitingSent = count;
|
|
16075
16087
|
for (const link of linked.list()) {
|
|
@@ -16078,6 +16090,13 @@ var LedungServer = class {
|
|
|
16078
16090
|
}
|
|
16079
16091
|
/** A linked computer's count, or undefined when it is offline: the open pages get its tab's badge at once. */
|
|
16080
16092
|
noteWaiting(id, raw) {
|
|
16093
|
+
if (this.closed) {
|
|
16094
|
+
if (!exercised463) {
|
|
16095
|
+
exercised463 = true;
|
|
16096
|
+
exercisedLine("EXERCISED #463 a linked computer's answer after close was let go");
|
|
16097
|
+
}
|
|
16098
|
+
return;
|
|
16099
|
+
}
|
|
16081
16100
|
const count = typeof raw === "number" && Number.isInteger(raw) && raw >= 0 && raw < 1e6 ? raw : void 0;
|
|
16082
16101
|
if (this.waitingThere.get(id) === count) return;
|
|
16083
16102
|
if (count === void 0) this.waitingThere.delete(id);
|
|
@@ -16963,6 +16982,15 @@ var LedungServer = class {
|
|
|
16963
16982
|
}
|
|
16964
16983
|
};
|
|
16965
16984
|
var bodies = /* @__PURE__ */ new WeakMap();
|
|
16985
|
+
var badPathTraced = false;
|
|
16986
|
+
function requestUrl(req) {
|
|
16987
|
+
const url = URL.parse(req.url ?? "/", "http://127.0.0.1");
|
|
16988
|
+
if (!url && !badPathTraced) {
|
|
16989
|
+
badPathTraced = true;
|
|
16990
|
+
exercisedLine("EXERCISED #467 refused a request path that does not parse");
|
|
16991
|
+
}
|
|
16992
|
+
return url;
|
|
16993
|
+
}
|
|
16966
16994
|
function fromThisComputer(req) {
|
|
16967
16995
|
const from = req.socket.remoteAddress ?? "";
|
|
16968
16996
|
return from === "::1" || from.startsWith("127.") || from.startsWith("::ffff:127.");
|
package/npm-shrinkwrap.json
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ledung",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.4.0",
|
|
4
4
|
"lockfileVersion": 3,
|
|
5
5
|
"requires": true,
|
|
6
6
|
"packages": {
|
|
7
7
|
"": {
|
|
8
8
|
"name": "ledung",
|
|
9
|
-
"version": "1.
|
|
9
|
+
"version": "1.4.0",
|
|
10
10
|
"license": "AGPL-3.0-only",
|
|
11
11
|
"dependencies": {
|
|
12
12
|
"@anthropic-ai/claude-agent-sdk": "0.3.295",
|
package/package.json
CHANGED