kennel 0.2.28 → 0.2.30
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/package/preview.d.ts +1 -1
- package/dist/package/preview.js +89 -107
- package/dist/site/terminal.js +9 -10
- package/package.json +2 -2
- package/web/assets/{abnfDiagram-VRR7QNED-Bn80ZKWr.js → abnfDiagram-VRR7QNED-DPZyna8O.js} +1 -1
- package/web/assets/{arc-DYtldBwv.js → arc-BAcU9y_V.js} +1 -1
- package/web/assets/{architectureDiagram-ZJ3FMSHR-Q8wivs2p.js → architectureDiagram-ZJ3FMSHR-D5yd7Cag.js} +1 -1
- package/web/assets/{ask-tray-PMT6VVXN-DNWm9l0M.js → ask-tray-PMT6VVXN-C4dJH21Q.js} +3 -3
- package/web/assets/{blockDiagram-677ZJIJ3-VzYV-AA6.js → blockDiagram-677ZJIJ3-C7LSGyxV.js} +1 -1
- package/web/assets/{c4Diagram-LMCZKHZV-BEh1NlA0.js → c4Diagram-LMCZKHZV-BW2KfoQr.js} +1 -1
- package/web/assets/channel-um92dqpm.js +1 -0
- package/web/assets/{chunk-2Q5K7J3B-VMcfJfhB.js → chunk-2Q5K7J3B-4Og6VAFG.js} +1 -1
- package/web/assets/{chunk-32BRIVSS-CnIckQlR.js → chunk-32BRIVSS-BYOowQl5.js} +1 -1
- package/web/assets/{chunk-5VM5RSS4-B7NdDHyk.js → chunk-5VM5RSS4-C1m-lq64.js} +1 -1
- package/web/assets/{chunk-EX3LRPZG-CLmNzhNw.js → chunk-EX3LRPZG-B2hriRpJ.js} +1 -1
- package/web/assets/{chunk-JWPE2WC7-CB7J3YAt.js → chunk-JWPE2WC7-C6RsnzVA.js} +1 -1
- package/web/assets/{chunk-MOJQB5TN-NHmi6U-6.js → chunk-MOJQB5TN-yKbMmUWf.js} +1 -1
- package/web/assets/{chunk-RYQCIY6F-D8mdIHdH.js → chunk-RYQCIY6F-BOokm3Qc.js} +1 -1
- package/web/assets/{chunk-V7JOEXUC-ebyFygjO.js → chunk-V7JOEXUC-CKW-H5An.js} +1 -1
- package/web/assets/{chunk-VR4S4FIN-DdRcpv9A.js → chunk-VR4S4FIN-BU5pFrup.js} +1 -1
- package/web/assets/{chunk-XXDRQBXY-CaDFu2On.js → chunk-XXDRQBXY-DYtdSJHU.js} +1 -1
- package/web/assets/classDiagram-OUVF2IWQ-h7sFEJBg.js +1 -0
- package/web/assets/classDiagram-v2-EOCWNBFH-h7sFEJBg.js +1 -0
- package/web/assets/{cose-bilkent-JH36ORCC-PjfFnCxS.js → cose-bilkent-JH36ORCC-BZeXtC6E.js} +1 -1
- package/web/assets/{cynefin-VYW2F7L2-DRgOkHBE.js → cynefin-VYW2F7L2-BSDVyzMI.js} +1 -1
- package/web/assets/{cynefinDiagram-TSTJHNR4-DrY10Xz3.js → cynefinDiagram-TSTJHNR4-CReoDBYo.js} +1 -1
- package/web/assets/{dagre-VKFMJZFB-Bscwbkne.js → dagre-VKFMJZFB-CBLLzMxd.js} +1 -1
- package/web/assets/{diagram-FQU43EPY-CEagDGS8.js → diagram-FQU43EPY-BcGWiZXZ.js} +1 -1
- package/web/assets/{diagram-G47NLZAW-BZhMoJam.js → diagram-G47NLZAW-BXUYZA9N.js} +1 -1
- package/web/assets/{diagram-NH7WQ7WH-Cj6Bu-O4.js → diagram-NH7WQ7WH-BrvrZs7N.js} +1 -1
- package/web/assets/{diagram-OA4YK3LP-Bnr8Sd0b.js → diagram-OA4YK3LP-7lnVcjXL.js} +1 -1
- package/web/assets/{diagram-WEI45ONY-CRMqzsgH.js → diagram-WEI45ONY-s58_bMFf.js} +1 -1
- package/web/assets/{ebnfDiagram-CCIWWBDH-CAbB-8JZ.js → ebnfDiagram-CCIWWBDH-BemWecoD.js} +1 -1
- package/web/assets/{entity-search-page-G6QEQNXT-CRfdTtti.js → entity-search-page-G6QEQNXT--sKP5dP3.js} +1 -1
- package/web/assets/{erDiagram-Q63AITRT-C8RUnhzS.js → erDiagram-Q63AITRT-ClVJddch.js} +1 -1
- package/web/assets/{flowDiagram-23GEKE2U-Bsr7qout.js → flowDiagram-23GEKE2U-xzUJu-i_.js} +1 -1
- package/web/assets/{ganttDiagram-NO4QXBWP-Cj4c0JYQ.js → ganttDiagram-NO4QXBWP-CXQmtF5g.js} +1 -1
- package/web/assets/{gitGraphDiagram-IHSO6WYX-Bs314gD3.js → gitGraphDiagram-IHSO6WYX-DCdljcLl.js} +1 -1
- package/web/assets/{index-CSVH3QUs.js → index-CtTx1o2d.js} +43 -43
- package/web/assets/{infoDiagram-FWYZ7A6U-DH-cmVkX.js → infoDiagram-FWYZ7A6U-B11SJYSK.js} +1 -1
- package/web/assets/{ishikawaDiagram-FXEZZL3T-BDJNBoGn.js → ishikawaDiagram-FXEZZL3T-B2CCGlAm.js} +1 -1
- package/web/assets/{journeyDiagram-5HDEW3XC-BPzolpTl.js → journeyDiagram-5HDEW3XC-CBPETzOk.js} +1 -1
- package/web/assets/{kanban-definition-HUTT4EX6-Cbwk3hWN.js → kanban-definition-HUTT4EX6-unhQ3RPE.js} +1 -1
- package/web/assets/{linear-C_hmEwuP.js → linear-DuP_pG51.js} +1 -1
- package/web/assets/{linked-session-header-M7WY6IGF-wWopBTMB.js → linked-session-header-M7WY6IGF-DwlNCJlj.js} +1 -1
- package/web/assets/{mermaid.core-C_STxONh.js → mermaid.core-BlYNzkpn.js} +4 -4
- package/web/assets/{mindmap-definition-LN4V7U3C-t11NOd4O.js → mindmap-definition-LN4V7U3C-CtKHN6O1.js} +1 -1
- package/web/assets/{pegDiagram-2B236MQR-DJfAH7lH.js → pegDiagram-2B236MQR-CRyz6XWY.js} +1 -1
- package/web/assets/{pieDiagram-ENE6RG2P-CWUBmV0d.js → pieDiagram-ENE6RG2P-BXfkPm3Q.js} +1 -1
- package/web/assets/{plugin-host-modules-DJHbqQhr.js → plugin-host-modules-5NQgs5Cq.js} +1 -1
- package/web/assets/{project-search-dialog-HJFGW4DG-BXLg3396.js → project-search-dialog-HJFGW4DG-DPly4OiB.js} +1 -1
- package/web/assets/{project-search-page-NKQEBGPF-vTDDUXOQ.js → project-search-page-NKQEBGPF-Cc6HV7BN.js} +1 -1
- package/web/assets/{quadrantDiagram-ABIIQ3AL-D3VESec_.js → quadrantDiagram-ABIIQ3AL-Drb_qWex.js} +1 -1
- package/web/assets/{railroadDiagram-RFXS5EU6-n_5zh_mW.js → railroadDiagram-RFXS5EU6-DCKk2Pix.js} +1 -1
- package/web/assets/{requirementDiagram-TGXJPOKE-DOEJVC4O.js → requirementDiagram-TGXJPOKE-6WwZwcpD.js} +1 -1
- package/web/assets/{sankeyDiagram-HTMAVEWB-p-X5ZPgN.js → sankeyDiagram-HTMAVEWB-DGGk3WCE.js} +1 -1
- package/web/assets/{selection-popup-532EHNCZ-DR8C-3fL.js → selection-popup-532EHNCZ-yPhTrk7L.js} +1 -1
- package/web/assets/{sequenceDiagram-DBY2YBRQ-BAas_TGB.js → sequenceDiagram-DBY2YBRQ-a4tGi3DH.js} +1 -1
- package/web/assets/{sizeCapture-X5ZJPWSS-CgQwiack.js → sizeCapture-X5ZJPWSS-CHehBmy9.js} +1 -1
- package/web/assets/{stateDiagram-2N3HPSRC-DRizvoeL.js → stateDiagram-2N3HPSRC-Bn9GSWgV.js} +1 -1
- package/web/assets/{stateDiagram-v2-6OUMAXLB-BJdHb7cS.js → stateDiagram-v2-6OUMAXLB-DI7fdBd7.js} +1 -1
- package/web/assets/{swimlanes-5IMT3BWC-CuKRbnuf.js → swimlanes-5IMT3BWC-BX0WRzfR.js} +2 -2
- package/web/assets/swimlanesDiagram-G3AALYLV-OGHC9nqi.js +8 -0
- package/web/assets/{timeline-definition-FHXFAJF6-BKzroj6g.js → timeline-definition-FHXFAJF6-9Ni2kIzq.js} +1 -1
- package/web/assets/{vennDiagram-L72KCM5P-DO-bKMoT.js → vennDiagram-L72KCM5P-rfBSNh3U.js} +1 -1
- package/web/assets/{wardleyDiagram-EHGQE667-BQQVafvV.js → wardleyDiagram-EHGQE667-CzziImCC.js} +1 -1
- package/web/assets/{xychartDiagram-FW5EYKEG-TZiE1TnS.js → xychartDiagram-FW5EYKEG-DTLI4h5R.js} +1 -1
- package/web/index.html +1 -1
- package/web/assets/channel-CPeCBcEl.js +0 -1
- package/web/assets/classDiagram-OUVF2IWQ-3AGK8leR.js +0 -1
- package/web/assets/classDiagram-v2-EOCWNBFH-3AGK8leR.js +0 -1
- package/web/assets/swimlanesDiagram-G3AALYLV-CjKn7pGa.js +0 -8
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
* sources, while staying type-checked against that source of truth.
|
|
8
8
|
*/
|
|
9
9
|
export declare function share(input: string[]): Promise<void>;
|
|
10
|
-
export declare function
|
|
10
|
+
export declare function startPreviewShare(target: {
|
|
11
11
|
root: string;
|
|
12
12
|
target?: string;
|
|
13
13
|
}): Promise<import("kennel-preview/terminal").PreviewShare>;
|
package/dist/package/preview.js
CHANGED
|
@@ -297,7 +297,7 @@ function previewTerminal(url, target, startShare) {
|
|
|
297
297
|
`));
|
|
298
298
|
};
|
|
299
299
|
const shareFolder = async () => {
|
|
300
|
-
status = "Preparing a
|
|
300
|
+
status = "Preparing a private Tailscale link…";
|
|
301
301
|
render();
|
|
302
302
|
try {
|
|
303
303
|
share ??= startShare();
|
|
@@ -310,18 +310,17 @@ function previewTerminal(url, target, startShare) {
|
|
|
310
310
|
}
|
|
311
311
|
if (finished)
|
|
312
312
|
return;
|
|
313
|
-
status = `
|
|
313
|
+
status = `Tailscale link: ${active.url}
|
|
314
314
|
Username: ${active.username} · Password: ${active.password}
|
|
315
|
-
Password required. Send the password separately.
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
${active.fingerprint}
|
|
315
|
+
Password required. Send the password separately.
|
|
316
|
+
Connect Tailscale on your phone to the same tailnet.
|
|
317
|
+
Trusted HTTPS; no certificate installation required.
|
|
319
318
|
Keep this command running. Ctrl+C stops sharing.`;
|
|
320
319
|
render();
|
|
321
320
|
try {
|
|
322
321
|
await copyPreviewLink(active.url);
|
|
323
322
|
status += `
|
|
324
|
-
|
|
323
|
+
Tailscale link copied to clipboard (without the password).`;
|
|
325
324
|
} catch (error) {
|
|
326
325
|
status += `
|
|
327
326
|
Could not copy link: ${terminalText(error instanceof Error ? error.message : String(error))}`;
|
|
@@ -348,7 +347,7 @@ function previewTerminal(url, target, startShare) {
|
|
|
348
347
|
}
|
|
349
348
|
if (share) {
|
|
350
349
|
share.then((active) => active.close()).catch((error) => {
|
|
351
|
-
console.error(`
|
|
350
|
+
console.error(` Could not stop the Tailscale share: ${error instanceof Error ? error.message : error}`);
|
|
352
351
|
}).finally(() => resolveClosed());
|
|
353
352
|
} else
|
|
354
353
|
resolveClosed();
|
|
@@ -6342,7 +6341,7 @@ async function hotViewer(options) {
|
|
|
6342
6341
|
const reuse = async () => {
|
|
6343
6342
|
const terminal = previewTerminal(viewerUrl, options, async () => {
|
|
6344
6343
|
await Promise.resolve().then(() => init_share());
|
|
6345
|
-
return
|
|
6344
|
+
return startPreviewShare(options);
|
|
6346
6345
|
});
|
|
6347
6346
|
if (options.open)
|
|
6348
6347
|
openPreview(viewerUrl);
|
|
@@ -6401,7 +6400,7 @@ async function hotViewer(options) {
|
|
|
6401
6400
|
});
|
|
6402
6401
|
const terminal = previewTerminal(viewerUrl, options, async () => {
|
|
6403
6402
|
await Promise.resolve().then(() => init_share());
|
|
6404
|
-
return
|
|
6403
|
+
return startPreviewShare(options);
|
|
6405
6404
|
});
|
|
6406
6405
|
terminal.closed.then(() => {
|
|
6407
6406
|
if (child.exitCode === null && child.signalCode === null)
|
|
@@ -40703,7 +40702,7 @@ async function viewer(input) {
|
|
|
40703
40702
|
const viewerUrl = popUrl(displayHost, options.port, options);
|
|
40704
40703
|
const terminal = previewTerminal(viewerUrl, options, async () => {
|
|
40705
40704
|
await Promise.resolve().then(() => init_share());
|
|
40706
|
-
return
|
|
40705
|
+
return startPreviewShare(options);
|
|
40707
40706
|
});
|
|
40708
40707
|
if (options.open)
|
|
40709
40708
|
openPreview(viewerUrl);
|
|
@@ -40734,7 +40733,7 @@ async function viewer(input) {
|
|
|
40734
40733
|
const viewerUrl = popUrl(displayHost, options.port, options);
|
|
40735
40734
|
const terminal = previewTerminal(viewerUrl, options, async () => {
|
|
40736
40735
|
await Promise.resolve().then(() => init_share());
|
|
40737
|
-
return
|
|
40736
|
+
return startPreviewShare(options);
|
|
40738
40737
|
});
|
|
40739
40738
|
if (options.open)
|
|
40740
40739
|
openPreview(viewerUrl);
|
|
@@ -40763,57 +40762,15 @@ var init_viewer = __esm(() => {
|
|
|
40763
40762
|
});
|
|
40764
40763
|
|
|
40765
40764
|
// packages/preview/src/protected-share.ts
|
|
40766
|
-
import {
|
|
40767
|
-
import {
|
|
40768
|
-
|
|
40769
|
-
import { createServer as createServer3 } from "node:https";
|
|
40770
|
-
import { isIP as isIP2 } from "node:net";
|
|
40771
|
-
import { tmpdir as tmpdir2 } from "node:os";
|
|
40772
|
-
import { join as join5 } from "node:path";
|
|
40773
|
-
import { promisify } from "node:util";
|
|
40774
|
-
async function previewCertificate(host) {
|
|
40775
|
-
if (!isIP2(host))
|
|
40776
|
-
throw new Error("The Wi-Fi share requires an IP address");
|
|
40777
|
-
const directory = await mkdtemp(join5(tmpdir2(), "kennel-preview-tls-"));
|
|
40778
|
-
const keyFile = join5(directory, "key.pem");
|
|
40779
|
-
const certFile = join5(directory, "cert.pem");
|
|
40780
|
-
try {
|
|
40781
|
-
await run("openssl", [
|
|
40782
|
-
"req",
|
|
40783
|
-
"-x509",
|
|
40784
|
-
"-newkey",
|
|
40785
|
-
"rsa:2048",
|
|
40786
|
-
"-nodes",
|
|
40787
|
-
"-days",
|
|
40788
|
-
"1",
|
|
40789
|
-
"-keyout",
|
|
40790
|
-
keyFile,
|
|
40791
|
-
"-out",
|
|
40792
|
-
certFile,
|
|
40793
|
-
"-subj",
|
|
40794
|
-
"/CN=Kennel Wi-Fi preview",
|
|
40795
|
-
"-addext",
|
|
40796
|
-
`subjectAltName=IP:${host}`
|
|
40797
|
-
]);
|
|
40798
|
-
const [key, cert] = await Promise.all([readFile11(keyFile), readFile11(certFile)]);
|
|
40799
|
-
return { key, cert, fingerprint: new X509Certificate(cert).fingerprint256 };
|
|
40800
|
-
} catch (error) {
|
|
40801
|
-
if (error instanceof Error && "code" in error && error.code === "ENOENT") {
|
|
40802
|
-
throw new Error("Password-protected sharing requires OpenSSL on PATH");
|
|
40803
|
-
}
|
|
40804
|
-
throw error;
|
|
40805
|
-
} finally {
|
|
40806
|
-
await rm2(directory, { recursive: true, force: true });
|
|
40807
|
-
}
|
|
40808
|
-
}
|
|
40809
|
-
async function startProtectedShare(host, handle) {
|
|
40810
|
-
const { key, cert, fingerprint } = await previewCertificate(host);
|
|
40765
|
+
import { createHash as createHash6, randomBytes, timingSafeEqual } from "node:crypto";
|
|
40766
|
+
import { createServer as createServer3 } from "node:http";
|
|
40767
|
+
async function startProtectedShare(handle) {
|
|
40811
40768
|
const username = "kennel";
|
|
40812
40769
|
const password = randomBytes(12).toString("base64url");
|
|
40813
40770
|
const authorization = `Basic ${Buffer.from(`${username}:${password}`).toString("base64")}`;
|
|
40814
40771
|
const expected = createHash6("sha256").update(authorization).digest();
|
|
40815
40772
|
const attempts = new Map;
|
|
40816
|
-
const server = createServer3(
|
|
40773
|
+
const server = createServer3((request, response) => {
|
|
40817
40774
|
response.setHeader("Cache-Control", "no-store");
|
|
40818
40775
|
response.setHeader("X-Content-Type-Options", "nosniff");
|
|
40819
40776
|
const address = request.socket.remoteAddress ?? "unknown";
|
|
@@ -40849,7 +40806,7 @@ async function startProtectedShare(host, handle) {
|
|
|
40849
40806
|
try {
|
|
40850
40807
|
await new Promise((done, fail) => {
|
|
40851
40808
|
server.once("error", fail);
|
|
40852
|
-
server.listen(0,
|
|
40809
|
+
server.listen(0, "127.0.0.1", () => {
|
|
40853
40810
|
server.off("error", fail);
|
|
40854
40811
|
done();
|
|
40855
40812
|
});
|
|
@@ -40857,14 +40814,58 @@ async function startProtectedShare(host, handle) {
|
|
|
40857
40814
|
const address = server.address();
|
|
40858
40815
|
if (!address || typeof address === "string")
|
|
40859
40816
|
throw new Error("No Wi-Fi server address");
|
|
40860
|
-
return { port: address.port, username, password, authorization,
|
|
40817
|
+
return { port: address.port, username, password, authorization, close };
|
|
40818
|
+
} catch (error) {
|
|
40819
|
+
await close();
|
|
40820
|
+
throw error;
|
|
40821
|
+
}
|
|
40822
|
+
}
|
|
40823
|
+
var init_protected_share = () => {};
|
|
40824
|
+
|
|
40825
|
+
// packages/preview/src/tailscale-share.ts
|
|
40826
|
+
import { execFile as execFile6 } from "node:child_process";
|
|
40827
|
+
import { promisify } from "node:util";
|
|
40828
|
+
async function serveConfig() {
|
|
40829
|
+
const { stdout } = await run("tailscale", ["serve", "status", "--json"]);
|
|
40830
|
+
return JSON.parse(stdout);
|
|
40831
|
+
}
|
|
40832
|
+
async function tailscaleHostname() {
|
|
40833
|
+
const { stdout } = await run("tailscale", ["status", "--json"]);
|
|
40834
|
+
const status = JSON.parse(stdout);
|
|
40835
|
+
const host = status.Self?.DNSName?.replace(/\.$/, "");
|
|
40836
|
+
if (status.BackendState !== "Running" || !host || !host.endsWith(".ts.net")) {
|
|
40837
|
+
throw new Error("Connect Tailscale on this Mac, then share again. The phone must use the same tailnet.");
|
|
40838
|
+
}
|
|
40839
|
+
return host;
|
|
40840
|
+
}
|
|
40841
|
+
async function startTailscaleProxy(host, port) {
|
|
40842
|
+
const authority = `${host}:${port}`;
|
|
40843
|
+
const target = `http://127.0.0.1:${port}`;
|
|
40844
|
+
const before = await serveConfig();
|
|
40845
|
+
if (before.TCP?.[String(port)] || before.Web?.[authority] || before.AllowFunnel?.[authority]) {
|
|
40846
|
+
throw new Error("This Tailscale port is already configured. Share again to select another port.");
|
|
40847
|
+
}
|
|
40848
|
+
const close = async () => {
|
|
40849
|
+
const current = await serveConfig();
|
|
40850
|
+
const handlers = current.Web?.[authority]?.Handlers;
|
|
40851
|
+
if (handlers?.["/"]?.Proxy === target && Object.keys(handlers).length === 1) {
|
|
40852
|
+
await run("tailscale", ["serve", `--https=${port}`, "off"]);
|
|
40853
|
+
}
|
|
40854
|
+
};
|
|
40855
|
+
try {
|
|
40856
|
+
await run("tailscale", ["serve", "--bg", "--yes", `--https=${port}`, target], { timeout: 30000 });
|
|
40857
|
+
const current = await serveConfig();
|
|
40858
|
+
if (current.AllowFunnel?.[authority] || current.Web?.[authority]?.Handlers?.["/"]?.Proxy !== target) {
|
|
40859
|
+
throw new Error("Tailscale did not create the expected private HTTPS proxy");
|
|
40860
|
+
}
|
|
40861
|
+
return { origin: `https://${authority}`, close };
|
|
40861
40862
|
} catch (error) {
|
|
40862
40863
|
await close();
|
|
40863
40864
|
throw error;
|
|
40864
40865
|
}
|
|
40865
40866
|
}
|
|
40866
40867
|
var run;
|
|
40867
|
-
var
|
|
40868
|
+
var init_tailscale_share = __esm(() => {
|
|
40868
40869
|
run = promisify(execFile6);
|
|
40869
40870
|
});
|
|
40870
40871
|
|
|
@@ -40872,7 +40873,6 @@ var init_protected_share = __esm(() => {
|
|
|
40872
40873
|
import { dirname as dirname12, resolve as resolve15 } from "node:path";
|
|
40873
40874
|
import { existsSync as existsSync7, realpathSync as realpathSync4 } from "node:fs";
|
|
40874
40875
|
import { fileURLToPath as fileURLToPath4 } from "node:url";
|
|
40875
|
-
import { get } from "node:https";
|
|
40876
40876
|
function splitShareArgs(input) {
|
|
40877
40877
|
const options = {
|
|
40878
40878
|
folder: undefined,
|
|
@@ -40941,84 +40941,65 @@ async function runningViewerRoot(port = plainViewerPort) {
|
|
|
40941
40941
|
}
|
|
40942
40942
|
return;
|
|
40943
40943
|
}
|
|
40944
|
-
async function
|
|
40944
|
+
async function startPreviewShare(target) {
|
|
40945
40945
|
const root = realpathSync4(target.root);
|
|
40946
40946
|
const web = resolve15(dirname12(fileURLToPath4(import.meta.url)), "../../web");
|
|
40947
40947
|
if (!existsSync7(resolve15(web, "index.html"))) {
|
|
40948
40948
|
throw new Error("Kennel web app not found. Run the CLI build first.");
|
|
40949
40949
|
}
|
|
40950
|
-
const host =
|
|
40950
|
+
const host = await tailscaleHostname();
|
|
40951
40951
|
await Promise.resolve().then(() => init_server4());
|
|
40952
40952
|
process.env.KENNEL_VIEWER_HOSTS = [process.env.KENNEL_VIEWER_HOSTS, host].filter(Boolean).join(",");
|
|
40953
40953
|
const api = createKennelApi({
|
|
40954
40954
|
root,
|
|
40955
|
-
host: "
|
|
40955
|
+
host: "127.0.0.1",
|
|
40956
40956
|
remoteAccess: true,
|
|
40957
40957
|
restrictToRoot: true,
|
|
40958
40958
|
lockedFile: target.target ? realpathSync4(target.target) : undefined,
|
|
40959
40959
|
webRoot: web
|
|
40960
40960
|
});
|
|
40961
40961
|
let shared;
|
|
40962
|
+
let proxy;
|
|
40962
40963
|
const close = async () => {
|
|
40963
40964
|
try {
|
|
40964
|
-
await
|
|
40965
|
+
await proxy?.close();
|
|
40965
40966
|
} finally {
|
|
40966
|
-
|
|
40967
|
+
try {
|
|
40968
|
+
await shared?.close();
|
|
40969
|
+
} finally {
|
|
40970
|
+
await api.close();
|
|
40971
|
+
}
|
|
40967
40972
|
}
|
|
40968
40973
|
};
|
|
40969
40974
|
try {
|
|
40970
|
-
shared = await startProtectedShare(
|
|
40975
|
+
shared = await startProtectedShare((request, response) => {
|
|
40971
40976
|
api.handle(request, response);
|
|
40972
40977
|
});
|
|
40973
|
-
|
|
40978
|
+
proxy = await startTailscaleProxy(host, shared.port);
|
|
40979
|
+
const path = new URL(popUrl(host, String(shared.port), {
|
|
40974
40980
|
dryRun: false,
|
|
40975
|
-
host: "
|
|
40981
|
+
host: "127.0.0.1",
|
|
40976
40982
|
hot: false,
|
|
40977
|
-
lan:
|
|
40983
|
+
lan: false,
|
|
40978
40984
|
open: false,
|
|
40979
40985
|
root,
|
|
40980
40986
|
port: String(shared.port),
|
|
40981
40987
|
tailscale: false,
|
|
40982
40988
|
watch: false,
|
|
40983
40989
|
target: target.target
|
|
40984
|
-
}));
|
|
40985
|
-
url
|
|
40986
|
-
const
|
|
40987
|
-
|
|
40988
|
-
|
|
40989
|
-
ca: cert,
|
|
40990
|
-
agent: false,
|
|
40991
|
-
headers: { Authorization: authorization }
|
|
40992
|
-
}, (response) => {
|
|
40993
|
-
let body = "";
|
|
40994
|
-
response.setEncoding("utf8");
|
|
40995
|
-
response.on("error", fail);
|
|
40996
|
-
response.on("data", (chunk) => {
|
|
40997
|
-
body += chunk;
|
|
40998
|
-
});
|
|
40999
|
-
response.on("end", () => {
|
|
41000
|
-
try {
|
|
41001
|
-
if (response.statusCode !== 200)
|
|
41002
|
-
throw new Error("The Wi-Fi server did not respond");
|
|
41003
|
-
done(JSON.parse(body));
|
|
41004
|
-
} catch (error) {
|
|
41005
|
-
fail(error);
|
|
41006
|
-
}
|
|
41007
|
-
});
|
|
41008
|
-
});
|
|
41009
|
-
request.setTimeout(5000, () => request.destroy(new Error("The Wi-Fi server did not respond")));
|
|
41010
|
-
request.on("error", fail);
|
|
40990
|
+
})).pathname;
|
|
40991
|
+
const url = new URL(path, proxy.origin);
|
|
40992
|
+
const response = await fetch(new URL("/api/health", url), {
|
|
40993
|
+
headers: { Authorization: shared.authorization },
|
|
40994
|
+
signal: AbortSignal.timeout(30000)
|
|
41011
40995
|
});
|
|
40996
|
+
if (!response.ok)
|
|
40997
|
+
throw new Error("The Tailscale share did not respond");
|
|
40998
|
+
const health = await response.json();
|
|
41012
40999
|
if (health.viewer !== "kennel-core" || health.root !== root) {
|
|
41013
|
-
throw new Error("The
|
|
41000
|
+
throw new Error("The Tailscale share is not serving the selected folder");
|
|
41014
41001
|
}
|
|
41015
|
-
return {
|
|
41016
|
-
url: url.href,
|
|
41017
|
-
username: shared.username,
|
|
41018
|
-
password: shared.password,
|
|
41019
|
-
fingerprint: shared.fingerprint,
|
|
41020
|
-
close
|
|
41021
|
-
};
|
|
41002
|
+
return { url: url.href, username: shared.username, password: shared.password, close };
|
|
41022
41003
|
} catch (error) {
|
|
41023
41004
|
await close();
|
|
41024
41005
|
throw error;
|
|
@@ -41049,6 +41030,7 @@ var plainViewerPort = "5180";
|
|
|
41049
41030
|
var init_share = __esm(() => {
|
|
41050
41031
|
init_viewer();
|
|
41051
41032
|
init_protected_share();
|
|
41033
|
+
init_tailscale_share();
|
|
41052
41034
|
});
|
|
41053
41035
|
init_share();
|
|
41054
41036
|
|
|
@@ -41057,5 +41039,5 @@ export {
|
|
|
41057
41039
|
runningViewerRoot,
|
|
41058
41040
|
share,
|
|
41059
41041
|
splitShareArgs,
|
|
41060
|
-
|
|
41042
|
+
startPreviewShare
|
|
41061
41043
|
};
|
package/dist/site/terminal.js
CHANGED
|
@@ -86,7 +86,7 @@ function previewTerminal(url, target, startShare) {
|
|
|
86
86
|
`));
|
|
87
87
|
};
|
|
88
88
|
const shareFolder = async () => {
|
|
89
|
-
status = "Preparing a
|
|
89
|
+
status = "Preparing a private Tailscale link…";
|
|
90
90
|
render();
|
|
91
91
|
try {
|
|
92
92
|
share ??= startShare();
|
|
@@ -99,18 +99,17 @@ function previewTerminal(url, target, startShare) {
|
|
|
99
99
|
}
|
|
100
100
|
if (finished)
|
|
101
101
|
return;
|
|
102
|
-
status = `
|
|
102
|
+
status = `Tailscale link: ${active.url}
|
|
103
103
|
Username: ${active.username} · Password: ${active.password}
|
|
104
|
-
Password required. Send the password separately.
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
${active.fingerprint}
|
|
104
|
+
Password required. Send the password separately.
|
|
105
|
+
Connect Tailscale on your phone to the same tailnet.
|
|
106
|
+
Trusted HTTPS; no certificate installation required.
|
|
108
107
|
Keep this command running. Ctrl+C stops sharing.`;
|
|
109
108
|
render();
|
|
110
109
|
try {
|
|
111
110
|
await copyPreviewLink(active.url);
|
|
112
111
|
status += `
|
|
113
|
-
|
|
112
|
+
Tailscale link copied to clipboard (without the password).`;
|
|
114
113
|
} catch (error) {
|
|
115
114
|
status += `
|
|
116
115
|
Could not copy link: ${terminalText(error instanceof Error ? error.message : String(error))}`;
|
|
@@ -137,7 +136,7 @@ function previewTerminal(url, target, startShare) {
|
|
|
137
136
|
}
|
|
138
137
|
if (share) {
|
|
139
138
|
share.then((active) => active.close()).catch((error) => {
|
|
140
|
-
console.error(`
|
|
139
|
+
console.error(` Could not stop the Tailscale share: ${error instanceof Error ? error.message : error}`);
|
|
141
140
|
}).finally(() => resolveClosed());
|
|
142
141
|
} else
|
|
143
142
|
resolveClosed();
|
|
@@ -209,8 +208,8 @@ function previewTerminal(url, target, startShare) {
|
|
|
209
208
|
// packages/cli/src/site/terminal.ts
|
|
210
209
|
function previewTerminal2(url, target) {
|
|
211
210
|
return previewTerminal(url, target, async () => {
|
|
212
|
-
const {
|
|
213
|
-
return
|
|
211
|
+
const { startPreviewShare } = await import(new URL("../package/preview.js", import.meta.url).href);
|
|
212
|
+
return startPreviewShare(target);
|
|
214
213
|
});
|
|
215
214
|
}
|
|
216
215
|
export {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kennel",
|
|
3
|
-
"version": "0.2.
|
|
3
|
+
"version": "0.2.30",
|
|
4
4
|
"description": "Open-source pop-up previews for AI output: markdown, HTML artifacts, email, images, code, tables, notes, and calendars, from the terminal or your agent session.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "MIT",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"effect": "^3.19.7",
|
|
68
68
|
"esbuild": "^0.27.0",
|
|
69
69
|
"kennel-mcp": "https://registry.npmjs.org/%40raggle-ai%2fkennel-mcp/-/kennel-mcp-0.1.8.tgz",
|
|
70
|
-
"kennel-plugins": "0.1.
|
|
70
|
+
"kennel-plugins": "0.1.13",
|
|
71
71
|
"koffi": "^3.3.1",
|
|
72
72
|
"lucide-react": "^0.562.0",
|
|
73
73
|
"radix-ui": "^1.6.7",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-
|
|
1
|
+
import{g as p,r as u,d as a}from"./chunk-MOJQB5TN-yKbMmUWf.js";import{p as f}from"./chunk-JWPE2WC7-C6RsnzVA.js";import{_ as n,l as o}from"./mermaid.core-BlYNzkpn.js";import{b as c,M as d}from"./cynefin-VYW2F7L2-BSDVyzMI.js";import"./index-CtTx1o2d.js";import"./react-DELVxLrX.js";import"./markdown-BP-54rPU.js";import"./tanstack-CRaSxWtK.js";var v=c().RailroadAbnf.parser.LangiumParser,i=n(e=>{const r=e.alternatives.map(g);return r.length===1?r[0]:{type:"choice",alternatives:r}},"transformAlternation"),g=n(e=>{const r=e.elements.map(y);return r.length===1?r[0]:{type:"sequence",elements:r}},"transformConcatenation"),b=n(e=>{if(e.includes("*")){const[t,s]=e.split("*"),m=t?parseInt(t,10):0,l=s?parseInt(s,10):1/0;return{min:m,max:l}}const r=parseInt(e,10);return{min:r,max:r}},"parseRepeat"),y=n(e=>{const r=A(e.primary);if(!e.repeat)return r;const{min:t,max:s}=b(e.repeat);return t===0&&s===1?{type:"optional",element:r}:{type:"repetition",element:r,min:t,max:s}},"transformElement"),A=n(e=>{switch(e.$type){case"AbnfStringLiteral":return{type:"terminal",value:e.value};case"AbnfNumVal":return{type:"terminal",value:e.value};case"AbnfRuleName":return{type:"nonterminal",name:e.name};case"AbnfGroup":return i(e.element);case"AbnfOptionalGroup":return{type:"optional",element:i(e.element)};default:throw new Error(`Unsupported ABNF primary node: ${e.$type}`)}},"transformPrimary"),P=n(e=>({name:e.name,definition:i(e.definition)}),"transformRule"),h=n(e=>{f(e,a),e.title&&a.setTitle(e.title),e.rules.map(r=>a.addRule(P(r)))},"populateDb"),R={parse:n(e=>{a.clear(),o.debug("[ABNF Parser] Starting Langium parse");const r=v.parse(e);if(r.lexerErrors.length>0||r.parserErrors.length>0)throw new d(r);const t=r.value;o.debug("[ABNF Parser] Parsed rules:",t.rules.length),h(t),o.debug("[ABNF Parser] Parse complete")},"parse"),parser:{yy:a}},C={parser:R,db:a,renderer:u,styles:p};export{C as diagram};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as sn,ab as on,ac as fn}from"./mermaid.core-
|
|
1
|
+
import{Y as ln,$ as an,a0 as F,a1 as q,a2 as j,a3 as un,a4 as y,a5 as tn,a6 as J,a7 as _,a8 as rn,a9 as o,aa as sn,ab as on,ac as fn}from"./mermaid.core-BlYNzkpn.js";function cn(l){return l.innerRadius}function yn(l){return l.outerRadius}function gn(l){return l.startAngle}function dn(l){return l.endAngle}function mn(l){return l&&l.padAngle}function pn(l,h,I,D,v,A,z,a){var O=I-l,i=D-h,n=z-v,d=a-A,u=d*O-n*i;if(!(u*u<y))return u=(n*(h-A)-d*(l-v))/u,[l+u*O,h+u*i]}function U(l,h,I,D,v,A,z){var a=l-I,O=h-D,i=(z?A:-A)/J(a*a+O*O),n=i*O,d=-i*a,u=l+n,s=h+d,f=I+n,c=D+d,B=(u+f)/2,t=(s+c)/2,m=f-u,g=c-s,R=m*m+g*g,T=v-A,P=u*c-f*s,S=(g<0?-1:1)*J(on(0,T*T*R-P*P)),Y=(P*g-m*S)/R,$=(-P*m-g*S)/R,w=(P*g+m*S)/R,p=(-P*m+g*S)/R,x=Y-B,e=$-t,r=w-B,C=p-t;return x*x+e*e>r*r+C*C&&(Y=w,$=p),{cx:Y,cy:$,x01:-n,y01:-d,x11:Y*(v/T-1),y11:$*(v/T-1)}}function hn(){var l=cn,h=yn,I=j(0),D=null,v=gn,A=dn,z=mn,a=null,O=ln(i);function i(){var n,d,u=+l.apply(this,arguments),s=+h.apply(this,arguments),f=v.apply(this,arguments)-un,c=A.apply(this,arguments)-un,B=rn(c-f),t=c>f;if(a||(a=n=O()),s<u&&(d=s,s=u,u=d),!(s>y))a.moveTo(0,0);else if(B>tn-y)a.moveTo(s*F(f),s*q(f)),a.arc(0,0,s,f,c,!t),u>y&&(a.moveTo(u*F(c),u*q(c)),a.arc(0,0,u,c,f,t));else{var m=f,g=c,R=f,T=c,P=B,S=B,Y=z.apply(this,arguments)/2,$=Y>y&&(D?+D.apply(this,arguments):J(u*u+s*s)),w=_(rn(s-u)/2,+I.apply(this,arguments)),p=w,x=w,e,r;if($>y){var C=sn($/u*q(Y)),K=sn($/s*q(Y));(P-=C*2)>y?(C*=t?1:-1,R+=C,T-=C):(P=0,R=T=(f+c)/2),(S-=K*2)>y?(K*=t?1:-1,m+=K,g-=K):(S=0,m=g=(f+c)/2)}var G=s*F(m),H=s*q(m),L=u*F(T),M=u*q(T);if(w>y){var N=s*F(g),Q=s*q(g),V=u*F(R),W=u*q(R),E;if(B<an)if(E=pn(G,H,V,W,N,Q,L,M)){var X=G-E[0],Z=H-E[1],b=N-E[0],k=Q-E[1],nn=1/q(fn((X*b+Z*k)/(J(X*X+Z*Z)*J(b*b+k*k)))/2),en=J(E[0]*E[0]+E[1]*E[1]);p=_(w,(u-en)/(nn-1)),x=_(w,(s-en)/(nn+1))}else p=x=0}S>y?x>y?(e=U(V,W,G,H,s,x,t),r=U(N,Q,L,M,s,x,t),a.moveTo(e.cx+e.x01,e.cy+e.y01),x<w?a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,x,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,s,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),!t),a.arc(r.cx,r.cy,x,o(r.y11,r.x11),o(r.y01,r.x01),!t))):(a.moveTo(G,H),a.arc(0,0,s,m,g,!t)):a.moveTo(G,H),!(u>y)||!(P>y)?a.lineTo(L,M):p>y?(e=U(L,M,N,Q,u,-p,t),r=U(G,H,V,W,u,-p,t),a.lineTo(e.cx+e.x01,e.cy+e.y01),p<w?a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(r.y01,r.x01),!t):(a.arc(e.cx,e.cy,p,o(e.y01,e.x01),o(e.y11,e.x11),!t),a.arc(0,0,u,o(e.cy+e.y11,e.cx+e.x11),o(r.cy+r.y11,r.cx+r.x11),t),a.arc(r.cx,r.cy,p,o(r.y11,r.x11),o(r.y01,r.x01),!t))):a.arc(0,0,u,T,R,t)}if(a.closePath(),n)return a=null,n+""||null}return i.centroid=function(){var n=(+l.apply(this,arguments)+ +h.apply(this,arguments))/2,d=(+v.apply(this,arguments)+ +A.apply(this,arguments))/2-an/2;return[F(d)*n,q(d)*n]},i.innerRadius=function(n){return arguments.length?(l=typeof n=="function"?n:j(+n),i):l},i.outerRadius=function(n){return arguments.length?(h=typeof n=="function"?n:j(+n),i):h},i.cornerRadius=function(n){return arguments.length?(I=typeof n=="function"?n:j(+n),i):I},i.padRadius=function(n){return arguments.length?(D=n==null?null:typeof n=="function"?n:j(+n),i):D},i.startAngle=function(n){return arguments.length?(v=typeof n=="function"?n:j(+n),i):v},i.endAngle=function(n){return arguments.length?(A=typeof n=="function"?n:j(+n),i):A},i.padAngle=function(n){return arguments.length?(z=typeof n=="function"?n:j(+n),i):z},i.context=function(n){return arguments.length?(a=n??null,i):a},i}export{hn as d};
|