@pmelab/gtd 10.8.0 → 10.9.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/dist/gtd.bundle.mjs +75 -30
- package/package.json +1 -1
- package/schema.json +1 -1
package/dist/gtd.bundle.mjs
CHANGED
|
@@ -53693,7 +53693,7 @@ const uiJsonSchema = {
|
|
|
53693
53693
|
properties: {
|
|
53694
53694
|
port: {
|
|
53695
53695
|
type: "integer",
|
|
53696
|
-
description: "
|
|
53696
|
+
description: "For ui, the tailscale serve port (default: the first free of 8443, 10000, 443), or the bind port when --host opts out of serve (default: a free port)."
|
|
53697
53697
|
},
|
|
53698
53698
|
host: {
|
|
53699
53699
|
type: "string",
|
|
@@ -210495,7 +210495,19 @@ var UiListener = class UiListener extends Tag("UiListener")() {
|
|
|
210495
210495
|
});
|
|
210496
210496
|
}) });
|
|
210497
210497
|
};
|
|
210498
|
-
|
|
210498
|
+
/**
|
|
210499
|
+
* The tailscale serve front door's fixed candidate list, walked in order:
|
|
210500
|
+
* a default tailnet permits HTTPS serve only on 443, 8443 and 10000 unless
|
|
210501
|
+
* its policy file says otherwise — an arbitrary high port simply fails to
|
|
210502
|
+
* publish, so nothing outside this list is worth trying.
|
|
210503
|
+
*/
|
|
210504
|
+
const SERVE_PORT_CANDIDATES = [
|
|
210505
|
+
8443,
|
|
210506
|
+
1e4,
|
|
210507
|
+
443
|
|
210508
|
+
];
|
|
210509
|
+
/** `0` means "auto-pick" for both `--port`/`ui.port` — identical to giving no port at all, and kept out of `publishServe --https=0`, which cannot publish. */
|
|
210510
|
+
const normalizePort = (port) => port === 0 ? void 0 : port;
|
|
210499
210511
|
/**
|
|
210500
210512
|
* `--dev` needs the gtd SOURCE checkout (its `src/web/`, its `tsdown.config.ts`,
|
|
210501
210513
|
* its devDependencies) to rebuild against — never the invoking directory,
|
|
@@ -210648,20 +210660,25 @@ const probeLiveServeMapping = (servePort) => gen(function* () {
|
|
|
210648
210660
|
* check, our own) is stale — cleared via `unpublishServe` before a fresh
|
|
210649
210661
|
* publish; a record naming another LIVE gtd ui is left alone too, since two
|
|
210650
210662
|
* instances racing the same port is exactly the case ownership exists to
|
|
210651
|
-
* prevent. Returns `
|
|
210652
|
-
* `
|
|
210663
|
+
* prevent. Returns `"clear"` when it's safe to proceed to `publishServe`;
|
|
210664
|
+
* `"occupied"` (a foreign live mapping) and `"unknowable"` (a probe that
|
|
210665
|
+
* failed to answer) are both "don't publish", but the caller's candidate
|
|
210666
|
+
* walk (Task 2) treats them differently — `"occupied"` is per-port and
|
|
210667
|
+
* walkable, `"unknowable"` says nothing about any port and would only
|
|
210668
|
+
* re-run the same failing subprocess against every remaining candidate, so
|
|
210669
|
+
* it aborts the walk instead of advancing it.
|
|
210653
210670
|
*/
|
|
210654
210671
|
const clearOrphanForPublish = (servePort) => gen(function* () {
|
|
210655
210672
|
const record = readServeRecord(servePort);
|
|
210656
210673
|
if (record === void 0) {
|
|
210657
210674
|
const probe = yield* probeLiveServeMapping(servePort);
|
|
210658
|
-
if (!probe.ok) return
|
|
210659
|
-
return probe.mapping === void 0;
|
|
210675
|
+
if (!probe.ok) return "unknowable";
|
|
210676
|
+
return probe.mapping === void 0 ? "clear" : "occupied";
|
|
210660
210677
|
}
|
|
210661
|
-
if (isPidAlive(record.pid) && record.pid !== process.pid) return
|
|
210678
|
+
if (isPidAlive(record.pid) && record.pid !== process.pid) return "occupied";
|
|
210662
210679
|
yield* unpublishServe(servePort).pipe(catchAll(() => succeed$3(void 0)));
|
|
210663
210680
|
deleteServeRecord(servePort);
|
|
210664
|
-
return
|
|
210681
|
+
return "clear";
|
|
210665
210682
|
});
|
|
210666
210683
|
/**
|
|
210667
210684
|
* Task 3's serve-first path: probe for a tailnet hostname, run the Task 4
|
|
@@ -210679,12 +210696,20 @@ const attemptServe = (servePort, worktree, uiListener, handler) => gen(function*
|
|
|
210679
210696
|
const tailscaleStatus = yield* probeTailscaleStatus();
|
|
210680
210697
|
if (tailscaleStatus === void 0) return {
|
|
210681
210698
|
ok: false,
|
|
210699
|
+
retry: false,
|
|
210682
210700
|
reason: "no Tailscale backend detected"
|
|
210683
210701
|
};
|
|
210684
|
-
|
|
210702
|
+
const orphanStatus = yield* clearOrphanForPublish(servePort);
|
|
210703
|
+
if (orphanStatus === "occupied") return {
|
|
210685
210704
|
ok: false,
|
|
210705
|
+
retry: true,
|
|
210686
210706
|
reason: `port ${servePort} already carries a tailscale serve mapping this instance does not own`
|
|
210687
210707
|
};
|
|
210708
|
+
if (orphanStatus === "unknowable") return {
|
|
210709
|
+
ok: false,
|
|
210710
|
+
retry: false,
|
|
210711
|
+
reason: `could not confirm port ${servePort} is free — tailscale serve status --json failed`
|
|
210712
|
+
};
|
|
210688
210713
|
const boundAttempt = yield* uiListener.listen({
|
|
210689
210714
|
host: "127.0.0.1",
|
|
210690
210715
|
port: 0,
|
|
@@ -210698,6 +210723,7 @@ const attemptServe = (servePort, worktree, uiListener, handler) => gen(function*
|
|
|
210698
210723
|
})));
|
|
210699
210724
|
if (!boundAttempt.ok) return {
|
|
210700
210725
|
ok: false,
|
|
210726
|
+
retry: false,
|
|
210701
210727
|
reason: `could not bind the loopback listener: ${boundAttempt.reason}`
|
|
210702
210728
|
};
|
|
210703
210729
|
const bound = boundAttempt.bound;
|
|
@@ -210713,6 +210739,7 @@ const attemptServe = (servePort, worktree, uiListener, handler) => gen(function*
|
|
|
210713
210739
|
yield* sync$1(() => bound.close());
|
|
210714
210740
|
return {
|
|
210715
210741
|
ok: false,
|
|
210742
|
+
retry: true,
|
|
210716
210743
|
reason: `tailscale serve failed: ${publishResult.reason}`
|
|
210717
210744
|
};
|
|
210718
210745
|
}
|
|
@@ -210726,7 +210753,8 @@ const attemptServe = (servePort, worktree, uiListener, handler) => gen(function*
|
|
|
210726
210753
|
return {
|
|
210727
210754
|
ok: true,
|
|
210728
210755
|
bound,
|
|
210729
|
-
url: servePort === 443 ? `https://${tailscaleStatus.hostname}/` : `https://${tailscaleStatus.hostname}:${servePort}
|
|
210756
|
+
url: servePort === 443 ? `https://${tailscaleStatus.hostname}/` : `https://${tailscaleStatus.hostname}:${servePort}/`,
|
|
210757
|
+
servePort
|
|
210730
210758
|
};
|
|
210731
210759
|
});
|
|
210732
210760
|
/**
|
|
@@ -210756,17 +210784,20 @@ const teardownServe = (servePort) => gen(function* () {
|
|
|
210756
210784
|
* so that function's own cyclomatic/cognitive complexity stays flat (mirrors
|
|
210757
210785
|
* why `resolveHostsAndCert` was pulled out for Package 02): an explicit
|
|
210758
210786
|
* `--host`/`ui.host` or `--self-signed` skips serve entirely (step 1);
|
|
210759
|
-
* otherwise
|
|
210760
|
-
*
|
|
210787
|
+
* otherwise Task 2's candidate walk is tried first — a one-element list when
|
|
210788
|
+
* `explicitPort` was given, `SERVE_PORT_CANDIDATES` otherwise — printing the
|
|
210789
|
+
* LAST candidate's failure reason (prefixed with every port tried, when more
|
|
210790
|
+
* than one was) above the URL before falling back — never a refusal either
|
|
210791
|
+
* way.
|
|
210761
210792
|
*/
|
|
210762
210793
|
const resolveListener = (args) => gen(function* () {
|
|
210763
|
-
const { options, config,
|
|
210794
|
+
const { options, config, explicitPort, explicitHost, worktree, uiListener, handler, out } = args;
|
|
210764
210795
|
const directBind = () => gen(function* () {
|
|
210765
210796
|
const { bindHost, displayHost, certPair } = yield* resolveHostsAndCert(options, config);
|
|
210766
210797
|
const bound = yield* uiListener.listen({
|
|
210767
210798
|
tls: certPair,
|
|
210768
210799
|
host: bindHost,
|
|
210769
|
-
port,
|
|
210800
|
+
port: explicitPort ?? 0,
|
|
210770
210801
|
handler
|
|
210771
210802
|
});
|
|
210772
210803
|
return {
|
|
@@ -210782,13 +210813,24 @@ const resolveListener = (args) => gen(function* () {
|
|
|
210782
210813
|
teardown: _void
|
|
210783
210814
|
};
|
|
210784
210815
|
}
|
|
210785
|
-
const
|
|
210786
|
-
|
|
210787
|
-
|
|
210788
|
-
|
|
210789
|
-
|
|
210790
|
-
|
|
210791
|
-
|
|
210816
|
+
const candidates = explicitPort !== void 0 ? [explicitPort] : SERVE_PORT_CANDIDATES;
|
|
210817
|
+
const tried = [];
|
|
210818
|
+
for (const candidate of candidates) {
|
|
210819
|
+
const attempt = yield* attemptServe(candidate, worktree, uiListener, handler);
|
|
210820
|
+
if (attempt.ok) return {
|
|
210821
|
+
bound: attempt.bound,
|
|
210822
|
+
url: attempt.url,
|
|
210823
|
+
teardown: teardownServe(attempt.servePort)
|
|
210824
|
+
};
|
|
210825
|
+
tried.push({
|
|
210826
|
+
port: candidate,
|
|
210827
|
+
reason: attempt.reason
|
|
210828
|
+
});
|
|
210829
|
+
if (!attempt.retry) break;
|
|
210830
|
+
}
|
|
210831
|
+
const last = tried[tried.length - 1];
|
|
210832
|
+
const reason = tried.length > 1 ? `tried ${tried.map((t) => t.port).join(", ")} — ${last.reason}` : last.reason;
|
|
210833
|
+
out.write(`gtd ui: not using tailscale serve — ${reason}\n`);
|
|
210792
210834
|
const { bound, url } = yield* directBind();
|
|
210793
210835
|
return {
|
|
210794
210836
|
bound,
|
|
@@ -210815,7 +210857,7 @@ const runUiCommand = (options, config, out) => gen(function* () {
|
|
|
210815
210857
|
const fs = yield* FileSystem;
|
|
210816
210858
|
const uiListener = yield* UiListener;
|
|
210817
210859
|
const runtime$5 = yield* runtime();
|
|
210818
|
-
const
|
|
210860
|
+
const explicitPort = normalizePort(options.port ?? config?.port);
|
|
210819
210861
|
const explicitHost = options.host ?? config?.host;
|
|
210820
210862
|
const clientHtml = yield* resolveClientHtml(options.dev, runner, fs);
|
|
210821
210863
|
const writeDeps = {
|
|
@@ -210894,7 +210936,7 @@ const runUiCommand = (options, config, out) => gen(function* () {
|
|
|
210894
210936
|
const { bound, url, teardown } = yield* resolveListener({
|
|
210895
210937
|
options,
|
|
210896
210938
|
config,
|
|
210897
|
-
|
|
210939
|
+
explicitPort,
|
|
210898
210940
|
explicitHost,
|
|
210899
210941
|
worktree: cwd.root,
|
|
210900
210942
|
uiListener,
|
|
@@ -225915,7 +225957,8 @@ const FLAGS = [
|
|
|
225915
225957
|
help: [
|
|
225916
225958
|
"(gtd visualize/gtd ui only) port to serve on: a free port",
|
|
225917
225959
|
"for visualize; for ui, the tailscale serve port (default:",
|
|
225918
|
-
"8443), or the bind port when
|
|
225960
|
+
"the first free of 8443, 10000, 443), or the bind port when",
|
|
225961
|
+
"--host opts out of serve (default: a free port)"
|
|
225919
225962
|
]
|
|
225920
225963
|
},
|
|
225921
225964
|
{
|
|
@@ -226196,12 +226239,14 @@ const COMMAND_ROWS = [
|
|
|
226196
226239
|
"refuses outside a repository like every other state command.",
|
|
226197
226240
|
"By default, publishes through `tailscale serve` (reachable",
|
|
226198
226241
|
"from anywhere on the tailnet, including over a DERP relay)",
|
|
226199
|
-
"with tailscaled terminating TLS
|
|
226200
|
-
"
|
|
226201
|
-
"
|
|
226202
|
-
"
|
|
226203
|
-
"
|
|
226204
|
-
"
|
|
226242
|
+
"with tailscaled terminating TLS, walking 8443, then 10000,",
|
|
226243
|
+
"then 443 until one publishes; falls back to binding a local",
|
|
226244
|
+
"HTTPS server directly, never refusing, when none of the",
|
|
226245
|
+
"three works. --host <addr> opts out of serve and binds that",
|
|
226246
|
+
"address directly instead; --port <n> overrides the serve",
|
|
226247
|
+
"port (default: the first free of 8443, 10000, 443), or the",
|
|
226248
|
+
"bind port when --host is given (default: a free port);",
|
|
226249
|
+
"--self-signed also opts out of serve, generating a",
|
|
226205
226250
|
"throwaway TLS certificate instead of the configured",
|
|
226206
226251
|
"ui.cert/ui.key; --dev runs against local development sources",
|
|
226207
226252
|
"instead of the packaged build"
|
package/package.json
CHANGED
package/schema.json
CHANGED
|
@@ -278,7 +278,7 @@
|
|
|
278
278
|
"properties": {
|
|
279
279
|
"port": {
|
|
280
280
|
"type": "integer",
|
|
281
|
-
"description": "
|
|
281
|
+
"description": "For ui, the tailscale serve port (default: the first free of 8443, 10000, 443), or the bind port when --host opts out of serve (default: a free port)."
|
|
282
282
|
},
|
|
283
283
|
"host": {
|
|
284
284
|
"type": "string",
|