@puddle-code/cli 0.2.0 → 0.2.2
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 +10 -21
- package/dist/host-control.mjs +43 -5
- package/dist/index.js +172 -87
- package/dist/install.sh +13 -0
- package/dist/public/assets/App-DYF0TQ7N.js +2 -0
- package/dist/public/assets/Dashboard-BLWy1kHm.js +1 -0
- package/dist/public/assets/{EditorTabClose-Dxz8ZjM9.js → EditorTabClose-CtInp1cT.js} +1 -1
- package/dist/public/assets/{LazyTerminal-CvkHRHQo.js → LazyTerminal-BrJnGoEX.js} +2 -2
- package/dist/public/assets/{ModelRefcount-C0ZeHnBJ.js → ModelRefcount-BNtD7p2m.js} +1 -1
- package/dist/public/assets/{NewProjectDialog-CHQ7EJYr.js → NewProjectDialog-BHIvFpCo.js} +1 -1
- package/dist/public/assets/{PaneEditorBody-Bco44A9M.js → PaneEditorBody--HKVd4ce.js} +4 -4
- package/dist/public/assets/{PdfViewer-Xg7NGubF.js → PdfViewer-DhO008IQ.js} +2 -2
- package/dist/public/assets/SettingsDialog-rfDhJoO1.js +8 -0
- package/dist/public/assets/Terminal-CttD7XcZ.js +60 -0
- package/dist/public/assets/Workspace-BB4IS8EP.js +20 -0
- package/dist/public/assets/Workspace-DgLBQU_0.css +1 -0
- package/dist/public/assets/{abnfDiagram-VCTEODGH-B9xm0g0V.js → abnfDiagram-VCTEODGH-CTMUfqGq.js} +1 -1
- package/dist/public/assets/architecture-7GRP2DOG-D65OB2im.js +1 -0
- package/dist/public/assets/{architectureDiagram-5GKGNRK7-DrrWczea.js → architectureDiagram-5GKGNRK7-B-L0EtRZ.js} +1 -1
- package/dist/public/assets/{blockDiagram-I7D4REHJ-CYEP6Dnn.js → blockDiagram-I7D4REHJ-CnmmDFsq.js} +1 -1
- package/dist/public/assets/{buffer-store-pvgusTv-.js → buffer-store-DzO77p-K.js} +2 -2
- package/dist/public/assets/{c4Diagram-7LVT6UL2-BAkFUfYR.js → c4Diagram-7LVT6UL2-DU4HXNd-.js} +1 -1
- package/dist/public/assets/channel-DDYJkwWS.js +1 -0
- package/dist/public/assets/{chunk-2E4U76K2-sXcn0WDZ.js → chunk-2E4U76K2-B8o6iRzd.js} +1 -1
- package/dist/public/assets/{chunk-4HAMMTFA-CPPsfbHS.js → chunk-4HAMMTFA-CfxkhHyC.js} +1 -1
- package/dist/public/assets/{chunk-75Z2AOVW-Cp3T9-mM.js → chunk-75Z2AOVW-D8v_0vko.js} +1 -1
- package/dist/public/assets/{chunk-CLGD4ZFX-aqUnXBfy.js → chunk-CLGD4ZFX-DPBjX4jg.js} +1 -1
- package/dist/public/assets/{chunk-DU6HZSFF-BKPHVNGu.js → chunk-DU6HZSFF-CuwQaNw0.js} +1 -1
- package/dist/public/assets/{chunk-F27PBJKO-IqOkPRK3.js → chunk-F27PBJKO-lg02cTVZ.js} +1 -1
- package/dist/public/assets/{chunk-GMAD6QVW-c9P8ntLy.js → chunk-GMAD6QVW-DICB0y-D.js} +1 -1
- package/dist/public/assets/{chunk-GVQU2GXP-DmZAhaXk.js → chunk-GVQU2GXP-9ghjwcoq.js} +1 -1
- package/dist/public/assets/{chunk-IMKFNOWR-CXrrJ9cb.js → chunk-IMKFNOWR-i_YIFBJX.js} +1 -1
- package/dist/public/assets/{chunk-L3NEJ4N5-Pn0OM8Or.js → chunk-L3NEJ4N5-gR7gj1U0.js} +1 -1
- package/dist/public/assets/{chunk-OSK3NFVY-CSxO-Bhw.js → chunk-OSK3NFVY-DHyaWigk.js} +1 -1
- package/dist/public/assets/{chunk-P2QGCYS3-DpTPoZQU.js → chunk-P2QGCYS3-ykV2meK0.js} +1 -1
- package/dist/public/assets/{chunk-POPQ4Y6H-V45h95Rz.js → chunk-POPQ4Y6H-BfpRTc3s.js} +1 -1
- package/dist/public/assets/{chunk-PWAF6VOD-aG71yphl.js → chunk-PWAF6VOD-gWIwGh8g.js} +1 -1
- package/dist/public/assets/{chunk-SHT3W25Y-8X6FPG54.js → chunk-SHT3W25Y-BQ_pTF0Z.js} +1 -1
- package/dist/public/assets/{chunk-SVP7TREG-x6ifISIm.js → chunk-SVP7TREG-SQwLD6DT.js} +1 -1
- package/dist/public/assets/{chunk-TICWLB2K-D9KB9pY5.js → chunk-TICWLB2K-B2zBy15L.js} +1 -1
- package/dist/public/assets/{chunk-TLUHSLCS-GPGNxyxD.js → chunk-TLUHSLCS-Bd2UG2tZ.js} +2 -2
- package/dist/public/assets/classDiagram-ZZMXUADV-DiYOyJFb.js +1 -0
- package/dist/public/assets/classDiagram-v2-VYDZK3BY-DiYOyJFb.js +1 -0
- package/dist/public/assets/{context-menu-Dt7h9y20.js → context-menu-Brk2htuk.js} +1 -1
- package/dist/public/assets/{cssMode-F3TrjQ2Y.js → cssMode-DqPCL8gS.js} +1 -1
- package/dist/public/assets/{cynefin-OW5HDTMX-BCcHZD-7.js → cynefin-OW5HDTMX-CSAZrmjo.js} +1 -1
- package/dist/public/assets/{cynefinDiagram-5FMLGOSQ-hEFQTinv.js → cynefinDiagram-5FMLGOSQ-CGKlzaPC.js} +1 -1
- package/dist/public/assets/{dagre-GXQ25YYZ-Dj7c-z9-.js → dagre-GXQ25YYZ-CgRwIpkl.js} +1 -1
- package/dist/public/assets/{diagram-S7CK7UJ4-i3ABTGXD.js → diagram-S7CK7UJ4-BMP1KOBu.js} +1 -1
- package/dist/public/assets/{diagram-UQ7AKVKN-BClHr071.js → diagram-UQ7AKVKN-DNcOIF4W.js} +1 -1
- package/dist/public/assets/{diagram-VSXAHHWV-_NoikNWl.js → diagram-VSXAHHWV-BGdHvK5Q.js} +1 -1
- package/dist/public/assets/{diagram-VX7I27RA-BxznNmgf.js → diagram-VX7I27RA-F7PfwNlr.js} +1 -1
- package/dist/public/assets/{diagram-Z3DM3KII-Dp_Elrik.js → diagram-Z3DM3KII-CPE4T9mi.js} +1 -1
- package/dist/public/assets/{dialog-GYBse2vm.js → dialog-B08M5Cgz.js} +2 -2
- package/dist/public/assets/disclosure-Bc6Ydabz.js +1 -0
- package/dist/public/assets/{dist-BB_jCiks.js → dist-CE40EiFY.js} +1 -1
- package/dist/public/assets/{dist-Dd_gMYta.js → dist-w0M7y9KX.js} +1 -1
- package/dist/public/assets/{ebnfDiagram-PWID7BFC-BrhXAUqf.js → ebnfDiagram-PWID7BFC-CqTR9kTI.js} +1 -1
- package/dist/public/assets/{erDiagram-RLTQ6QDP-DpvzwcpF.js → erDiagram-RLTQ6QDP-CVqix4AT.js} +1 -1
- package/dist/public/assets/eventmodeling-NTZA5JFV-BoPTLqKJ.js +1 -0
- package/dist/public/assets/flowDiagram-HODETNUW-2TNtc6rJ.js +1 -0
- package/dist/public/assets/{ganttDiagram-EL5Y4UJY-MwZQW2Ab.js → ganttDiagram-EL5Y4UJY-CFSX0WK6.js} +1 -1
- package/dist/public/assets/{gitGraph-4MIJSDKK-wD3tQrBr.js → gitGraph-4MIJSDKK-Doy-w5G0.js} +1 -1
- package/dist/public/assets/{gitGraphDiagram-WWUBYQGX-RZqAMYtF.js → gitGraphDiagram-WWUBYQGX-fQM29HOw.js} +1 -1
- package/dist/public/assets/{hotkeys-Bpeih0PX.js → hotkeys-DQNqRgOb.js} +1 -1
- package/dist/public/assets/{htmlMode-BQanlpBa.js → htmlMode-DE4OLLtJ.js} +1 -1
- package/dist/public/assets/index-CQ-7fSnd.css +2 -0
- package/dist/public/assets/{index-D96JjECU.js → index-CmEI98Do.js} +2 -2
- package/dist/public/assets/{info-A6RAGUB7-ie0E4iIr.js → info-A6RAGUB7-DPiPYEQe.js} +1 -1
- package/dist/public/assets/{infoDiagram-27XIBGKW-u5u8byqk.js → infoDiagram-27XIBGKW-DY5LKiBl.js} +1 -1
- package/dist/public/assets/{input-AzsFYZ3g.js → input-CRHttNr9.js} +1 -1
- package/dist/public/assets/{ishikawaDiagram-5VMMS53U-4GHMY6KJ.js → ishikawaDiagram-5VMMS53U-DwSURfQE.js} +1 -1
- package/dist/public/assets/{journeyDiagram-3NMN7TZE-Cwe5PRBP.js → journeyDiagram-3NMN7TZE-B0OCkFis.js} +1 -1
- package/dist/public/assets/{jsonMode-CRZXV6U_.js → jsonMode-F58eqVfl.js} +1 -1
- package/dist/public/assets/{kanban-definition-UXKFOSKX-CS-A9ZNT.js → kanban-definition-UXKFOSKX-CAQw3qWz.js} +1 -1
- package/dist/public/assets/{line-kZmQKU6y.js → line-Bcu_KJDQ.js} +1 -1
- package/dist/public/assets/{media-refresh-store-B_VyvYfl.js → media-refresh-store-B8Wdlks-.js} +1 -1
- package/dist/public/assets/{mermaid-parser.core-BEcx5De7.js → mermaid-parser.core-PSjhnHbq.js} +3 -3
- package/dist/public/assets/{mermaid.core-ZFBf3aP8.js → mermaid.core-CVDKsXhB.js} +3 -3
- package/dist/public/assets/{mindmap-definition-YA3MSWOX-ti5sUvQf.js → mindmap-definition-YA3MSWOX-CVAY5896.js} +1 -1
- package/dist/public/assets/{notification-permission-Car54v17.js → notification-permission-CbLpN3ev.js} +1 -1
- package/dist/public/assets/{packet-AYTQ26CC-BFLiDvUG.js → packet-AYTQ26CC-CTdFnPq7.js} +1 -1
- package/dist/public/assets/{pdf-CDunFg56.js → pdf-CNnH2qu8.js} +1 -1
- package/dist/public/assets/{pegDiagram-XKGWAZYB-L1VUrE59.js → pegDiagram-XKGWAZYB-DjAvebfq.js} +1 -1
- package/dist/public/assets/{pie-WAS4IAKB-BxBZGMsV.js → pie-WAS4IAKB-DGj7H0HD.js} +1 -1
- package/dist/public/assets/{pieDiagram-E7YTZNPT-D_z8Ah38.js → pieDiagram-E7YTZNPT-ZsMHxQiN.js} +1 -1
- package/dist/public/assets/{project-abbrev-B7pHIhbk.js → project-abbrev-CaGbOWtr.js} +1 -1
- package/dist/public/assets/{quadrantDiagram-AXDQQJYC-DEU0wyvb.js → quadrantDiagram-AXDQQJYC-DVxSJgm4.js} +1 -1
- package/dist/public/assets/{radar-RG4KPBEZ-C7ijJa3G.js → radar-RG4KPBEZ-D7tOXZhy.js} +1 -1
- package/dist/public/assets/{railroad-74A4TZTK-BR2-uhMp.js → railroad-74A4TZTK-EI9jAf_f.js} +1 -1
- package/dist/public/assets/railroad-abnf-HS5TGJTU-DnezvAFa.js +1 -0
- package/dist/public/assets/railroad-ebnf-LZEXJU2U-DHOzgi4x.js +1 -0
- package/dist/public/assets/railroad-peg-WCYAUIDC-C28W4OGa.js +1 -0
- package/dist/public/assets/{railroadDiagram-O6MQD6OU-BO2RgHB_.js → railroadDiagram-O6MQD6OU-uqpSPQV1.js} +1 -1
- package/dist/public/assets/{requirementDiagram-BXWQKSXE-DedAgdgA.js → requirementDiagram-BXWQKSXE-BlP0G3V7.js} +1 -1
- package/dist/public/assets/{sankeyDiagram-P5KCCOFB-XS4y44C-.js → sankeyDiagram-P5KCCOFB-BcxykWWD.js} +1 -1
- package/dist/public/assets/{sequenceDiagram-WJ2MYXX4-BgGPuhmx.js → sequenceDiagram-WJ2MYXX4-BleK5ON1.js} +1 -1
- package/dist/public/assets/{stateDiagram-D77RDMKH-t92luW0k.js → stateDiagram-D77RDMKH-C3Ojitqe.js} +1 -1
- package/dist/public/assets/stateDiagram-v2-MP3YSRHH-KLRu_NXG.js +1 -0
- package/dist/public/assets/{swimlanes-42K2YHIH-BTLMw_Zs.js → swimlanes-42K2YHIH-Bebu_xn2.js} +1 -1
- package/dist/public/assets/swimlanesDiagram-VR7AAH4N-BmvrlXmd.js +8 -0
- package/dist/public/assets/{switch-DFcV6j9m.js → switch-CaIM4dwn.js} +1 -1
- package/dist/public/assets/{timeline-definition-24CTP7MA-Buej45ei.js → timeline-definition-24CTP7MA-BKUpL8jk.js} +1 -1
- package/dist/public/assets/{treeView-Q6P3EWNA-CsmFV7PP.js → treeView-Q6P3EWNA-C7zCIwpV.js} +1 -1
- package/dist/public/assets/{treemap-WGGIJYW6-C7p2D31t.js → treemap-WGGIJYW6-6M3fRwft.js} +1 -1
- package/dist/public/assets/{tsMode-CkssN7v1.js → tsMode-DQRFLRMD.js} +1 -1
- package/dist/public/assets/{use-find-controls-o8dHk3Ai.js → use-find-controls-SI1t9mHH.js} +1 -1
- package/dist/public/assets/{use-ui-state-GQIbFm75.js → use-ui-state-D-3P_8P_.js} +1 -1
- package/dist/public/assets/{vennDiagram-4TSXK5OY-CabgcJgI.js → vennDiagram-4TSXK5OY-DxK4ozKb.js} +1 -1
- package/dist/public/assets/{wardley-WFR3VGLG-nDvUESM8.js → wardley-WFR3VGLG-B2zERAcS.js} +1 -1
- package/dist/public/assets/{wardleyDiagram-VM6X3IG4-lH7COUmu.js → wardleyDiagram-VM6X3IG4-Ctiwf9vH.js} +1 -1
- package/dist/public/assets/{ws-CvBEQDJB.js → ws-DK8JadaZ.js} +1 -1
- package/dist/public/assets/{xychartDiagram-S5SC5T6Z-c7fu3ePF.js → xychartDiagram-S5SC5T6Z-CxqvnL8v.js} +1 -1
- package/dist/public/index.html +2 -2
- package/package.json +1 -1
- package/dist/public/assets/App-4wHC7AhU.js +0 -2
- package/dist/public/assets/Dashboard-BTqiSGSr.js +0 -1
- package/dist/public/assets/SettingsDialog-BbqSqnMS.js +0 -8
- package/dist/public/assets/Terminal-DEVWotwh.js +0 -60
- package/dist/public/assets/Workspace-9Ke8tXhO.css +0 -1
- package/dist/public/assets/Workspace-D0vmiCsp.js +0 -20
- package/dist/public/assets/architecture-7GRP2DOG-B8geJhni.js +0 -1
- package/dist/public/assets/channel-B2boMkNJ.js +0 -1
- package/dist/public/assets/classDiagram-ZZMXUADV-D8W4ja-y.js +0 -1
- package/dist/public/assets/classDiagram-v2-VYDZK3BY-D8W4ja-y.js +0 -1
- package/dist/public/assets/eventmodeling-NTZA5JFV-DpPAlVka.js +0 -1
- package/dist/public/assets/flowDiagram-HODETNUW-emcn6VnU.js +0 -1
- package/dist/public/assets/index-BsSnxNPl.css +0 -2
- package/dist/public/assets/railroad-abnf-HS5TGJTU-Q_zhOWAR.js +0 -1
- package/dist/public/assets/railroad-ebnf-LZEXJU2U-BNV11-bx.js +0 -1
- package/dist/public/assets/railroad-peg-WCYAUIDC-D1whgDil.js +0 -1
- package/dist/public/assets/session-seed-exhI-dnY.js +0 -1
- package/dist/public/assets/stateDiagram-v2-MP3YSRHH-BVx0pqBn.js +0 -1
- package/dist/public/assets/swimlanesDiagram-VR7AAH4N-BaHPNnEm.js +0 -8
package/dist/index.js
CHANGED
|
@@ -3756,7 +3756,7 @@ var init_wrapper = __esm({
|
|
|
3756
3756
|
|
|
3757
3757
|
// src/lib/ws-client.ts
|
|
3758
3758
|
function connectGateway(port, authority) {
|
|
3759
|
-
return new Promise((
|
|
3759
|
+
return new Promise((resolve5, reject) => {
|
|
3760
3760
|
const ws = new wrapper_default(`ws://127.0.0.1:${port}/ws`, {
|
|
3761
3761
|
headers: { host: `localhost:${port}` }
|
|
3762
3762
|
});
|
|
@@ -3781,7 +3781,7 @@ function connectGateway(port, authority) {
|
|
|
3781
3781
|
}
|
|
3782
3782
|
if (parsed.t === "authenticated") {
|
|
3783
3783
|
clearTimeout(timer);
|
|
3784
|
-
|
|
3784
|
+
resolve5({
|
|
3785
3785
|
send(message) {
|
|
3786
3786
|
if (resource.valid() && ws.readyState === wrapper_default.OPEN)
|
|
3787
3787
|
ws.send(JSON.stringify(message));
|
|
@@ -3855,7 +3855,7 @@ async function attachSession(opts) {
|
|
|
3855
3855
|
rows: streams.stdout.rows ?? 24
|
|
3856
3856
|
});
|
|
3857
3857
|
gateway.send({ t: "attach", session: session.id, term, ...dims2() });
|
|
3858
|
-
return new Promise((
|
|
3858
|
+
return new Promise((resolve5) => {
|
|
3859
3859
|
let settled = false;
|
|
3860
3860
|
const finish = (outcome) => {
|
|
3861
3861
|
if (settled) return;
|
|
@@ -3864,7 +3864,7 @@ async function attachSession(opts) {
|
|
|
3864
3864
|
stdin.removeListener("data", onStdin);
|
|
3865
3865
|
unResize?.();
|
|
3866
3866
|
gateway.close();
|
|
3867
|
-
|
|
3867
|
+
resolve5(outcome);
|
|
3868
3868
|
};
|
|
3869
3869
|
gateway.onMessage((message) => {
|
|
3870
3870
|
switch (message.t) {
|
|
@@ -3925,7 +3925,7 @@ import { createInterface } from "node:readline";
|
|
|
3925
3925
|
import { Writable } from "node:stream";
|
|
3926
3926
|
|
|
3927
3927
|
// ../shared/src/protocol.ts
|
|
3928
|
-
var PROTOCOL_VERSION = { major:
|
|
3928
|
+
var PROTOCOL_VERSION = { major: 20, minor: 0 };
|
|
3929
3929
|
|
|
3930
3930
|
// ../../node_modules/.pnpm/zod@4.4.3/node_modules/zod/v4/classic/external.js
|
|
3931
3931
|
var external_exports = {};
|
|
@@ -19807,19 +19807,25 @@ var remoteChunkSchema = external_exports.object({
|
|
|
19807
19807
|
}).strict();
|
|
19808
19808
|
|
|
19809
19809
|
// ../shared/src/api/cockpit-remote.ts
|
|
19810
|
-
var
|
|
19810
|
+
var connectorLocalRequestSchema = external_exports.union([
|
|
19811
19811
|
remoteAdminRequestSchema,
|
|
19812
|
+
external_exports.object({ t: external_exports.literal("delete_registration") }).strict()
|
|
19813
|
+
]);
|
|
19814
|
+
var cockpitRemoteRequestSchema = external_exports.union([
|
|
19815
|
+
connectorLocalRequestSchema,
|
|
19812
19816
|
external_exports.object({
|
|
19813
19817
|
t: external_exports.literal("enable"),
|
|
19814
19818
|
registration: external_exports.object({ service: remoteOriginSchema, app: remoteOriginSchema, code: remoteSecretSchema }).strict().optional()
|
|
19815
19819
|
}).strict(),
|
|
19816
19820
|
external_exports.object({ t: external_exports.literal("reset") }).strict()
|
|
19817
19821
|
]);
|
|
19822
|
+
var cockpitRegistrationCheckSchema = external_exports.object({ service: remoteOriginSchema, code: remoteSecretSchema }).strict();
|
|
19818
19823
|
var cockpitRemoteStatusSchema = external_exports.object({
|
|
19819
19824
|
availability: external_exports.enum(["ready", "not_installed", "upgrade_required"]),
|
|
19820
19825
|
configured: external_exports.boolean(),
|
|
19821
19826
|
enabled: external_exports.boolean(),
|
|
19822
19827
|
connected: external_exports.boolean(),
|
|
19828
|
+
canDeleteRegistration: external_exports.boolean().optional(),
|
|
19823
19829
|
supervisor: external_exports.enum(["systemd", "launchd"]).nullable(),
|
|
19824
19830
|
host: remoteIdSchema.optional(),
|
|
19825
19831
|
peer: remotePeerSchema.optional(),
|
|
@@ -19932,6 +19938,14 @@ var remoteLoginStateSchema = external_exports.object({
|
|
|
19932
19938
|
var registerHostRequestSchema = external_exports.object({ label: remoteLabelSchema }).strict();
|
|
19933
19939
|
var registrationResponseSchema = external_exports.object({ host: remoteIdSchema, code: remoteSecretSchema, expires: external_exports.number() }).strict();
|
|
19934
19940
|
var redeemRegistrationSchema = external_exports.object({ code: remoteSecretSchema }).strict();
|
|
19941
|
+
var desktopRegistrationSchema = external_exports.object({
|
|
19942
|
+
challenge: remoteSecretSchema,
|
|
19943
|
+
label: remoteLabelSchema,
|
|
19944
|
+
service: remoteOriginSchema,
|
|
19945
|
+
app: remoteOriginSchema,
|
|
19946
|
+
expires: external_exports.number().int().positive()
|
|
19947
|
+
}).strict();
|
|
19948
|
+
var registrationStatusSchema = external_exports.object({ ready: external_exports.boolean() }).strict();
|
|
19935
19949
|
var connectorRegistrationSchema = external_exports.object({
|
|
19936
19950
|
host: remoteIdSchema,
|
|
19937
19951
|
account: remoteAccountSchema,
|
|
@@ -19987,7 +20001,7 @@ var LocalTransport = class {
|
|
|
19987
20001
|
kind = "local";
|
|
19988
20002
|
label = "this machine";
|
|
19989
20003
|
exec(command, opts = {}) {
|
|
19990
|
-
return new Promise((
|
|
20004
|
+
return new Promise((resolve5) => {
|
|
19991
20005
|
const child = spawn("sh", ["-c", command], { stdio: ["pipe", "pipe", "pipe"] });
|
|
19992
20006
|
let stdout = "";
|
|
19993
20007
|
let stderr = "";
|
|
@@ -20004,11 +20018,11 @@ var LocalTransport = class {
|
|
|
20004
20018
|
child.stderr.on("data", (chunk) => stderr += chunk.toString());
|
|
20005
20019
|
child.on("error", (err) => {
|
|
20006
20020
|
if (timer) clearTimeout(timer);
|
|
20007
|
-
|
|
20021
|
+
resolve5({ code: -1, stdout, stderr: stderr + String(err) });
|
|
20008
20022
|
});
|
|
20009
20023
|
child.on("close", (code) => {
|
|
20010
20024
|
if (timer) clearTimeout(timer);
|
|
20011
|
-
|
|
20025
|
+
resolve5({ code: code ?? -1, stdout, stderr });
|
|
20012
20026
|
});
|
|
20013
20027
|
child.stdin.on("error", () => {
|
|
20014
20028
|
});
|
|
@@ -20102,7 +20116,7 @@ var SshTransport = class {
|
|
|
20102
20116
|
* live control socket behind.
|
|
20103
20117
|
*/
|
|
20104
20118
|
open() {
|
|
20105
|
-
return new Promise((
|
|
20119
|
+
return new Promise((resolve5, reject) => {
|
|
20106
20120
|
const child = spawn2(this.ssh, this.args(this.host, "true"), {
|
|
20107
20121
|
// A GUI has no useful inherited terminal; OpenSSH calls its askpass
|
|
20108
20122
|
// helper instead. The terminal CLI keeps byte-for-byte inheritance.
|
|
@@ -20114,7 +20128,7 @@ var SshTransport = class {
|
|
|
20114
20128
|
(err) => reject(new CliError("ssh_unreachable", `could not run ${this.ssh}: ${err.message}`))
|
|
20115
20129
|
);
|
|
20116
20130
|
child.on("close", (code) => {
|
|
20117
|
-
if (code === 0)
|
|
20131
|
+
if (code === 0) resolve5();
|
|
20118
20132
|
else {
|
|
20119
20133
|
reject(
|
|
20120
20134
|
new CliError(
|
|
@@ -20130,13 +20144,13 @@ var SshTransport = class {
|
|
|
20130
20144
|
/** Whether the master connection is still alive (-O check). */
|
|
20131
20145
|
isAlive() {
|
|
20132
20146
|
if (!this.hasControlMaster) return Promise.resolve(true);
|
|
20133
|
-
return new Promise((
|
|
20147
|
+
return new Promise((resolve5) => {
|
|
20134
20148
|
const child = spawn2(this.ssh, this.args("-O", "check", this.host), {
|
|
20135
20149
|
stdio: "ignore",
|
|
20136
20150
|
env: this.spawnEnv()
|
|
20137
20151
|
});
|
|
20138
|
-
child.on("error", () =>
|
|
20139
|
-
child.on("close", (code) =>
|
|
20152
|
+
child.on("error", () => resolve5(false));
|
|
20153
|
+
child.on("close", (code) => resolve5(code === 0));
|
|
20140
20154
|
});
|
|
20141
20155
|
}
|
|
20142
20156
|
/**
|
|
@@ -20149,18 +20163,18 @@ var SshTransport = class {
|
|
|
20149
20163
|
*/
|
|
20150
20164
|
cancelForward(localPort, remotePort) {
|
|
20151
20165
|
if (!this.hasControlMaster) return Promise.resolve();
|
|
20152
|
-
return new Promise((
|
|
20166
|
+
return new Promise((resolve5) => {
|
|
20153
20167
|
const spec = `${localPort}:127.0.0.1:${remotePort}`;
|
|
20154
20168
|
const child = spawn2(this.ssh, this.args("-O", "cancel", "-L", spec, this.host), {
|
|
20155
20169
|
stdio: "ignore",
|
|
20156
20170
|
env: this.spawnEnv()
|
|
20157
20171
|
});
|
|
20158
|
-
child.on("error", () =>
|
|
20159
|
-
child.on("close", () =>
|
|
20172
|
+
child.on("error", () => resolve5());
|
|
20173
|
+
child.on("close", () => resolve5());
|
|
20160
20174
|
});
|
|
20161
20175
|
}
|
|
20162
20176
|
exec(command, opts = {}) {
|
|
20163
|
-
return new Promise((
|
|
20177
|
+
return new Promise((resolve5) => {
|
|
20164
20178
|
const child = spawn2(this.ssh, this.args(this.host, "--", `sh -c ${shellQuote(command)}`), {
|
|
20165
20179
|
stdio: ["pipe", "pipe", "pipe"],
|
|
20166
20180
|
env: this.spawnEnv()
|
|
@@ -20180,11 +20194,11 @@ var SshTransport = class {
|
|
|
20180
20194
|
child.stderr.on("data", (chunk) => stderr += chunk.toString());
|
|
20181
20195
|
child.on("error", (err) => {
|
|
20182
20196
|
if (timer) clearTimeout(timer);
|
|
20183
|
-
|
|
20197
|
+
resolve5({ code: -1, stdout, stderr: stderr + String(err) });
|
|
20184
20198
|
});
|
|
20185
20199
|
child.on("close", (code) => {
|
|
20186
20200
|
if (timer) clearTimeout(timer);
|
|
20187
|
-
|
|
20201
|
+
resolve5({ code: code ?? -1, stdout, stderr });
|
|
20188
20202
|
});
|
|
20189
20203
|
child.stdin.on("error", () => {
|
|
20190
20204
|
});
|
|
@@ -20204,11 +20218,11 @@ var SshTransport = class {
|
|
|
20204
20218
|
});
|
|
20205
20219
|
let stdout = "";
|
|
20206
20220
|
let stderr = "";
|
|
20207
|
-
const result = new Promise((
|
|
20221
|
+
const result = new Promise((resolve5) => {
|
|
20208
20222
|
child.stdout.on("data", (chunk) => stdout += chunk.toString());
|
|
20209
20223
|
child.stderr.on("data", (chunk) => stderr += chunk.toString());
|
|
20210
|
-
child.on("error", (err) =>
|
|
20211
|
-
child.on("close", (code) =>
|
|
20224
|
+
child.on("error", (err) => resolve5({ code: -1, stdout, stderr: stderr + String(err) }));
|
|
20225
|
+
child.on("close", (code) => resolve5({ code: code ?? -1, stdout, stderr }));
|
|
20212
20226
|
});
|
|
20213
20227
|
return {
|
|
20214
20228
|
result,
|
|
@@ -20223,14 +20237,14 @@ var SshTransport = class {
|
|
|
20223
20237
|
}
|
|
20224
20238
|
async copyTo(localPath, destPath) {
|
|
20225
20239
|
await this.exec(`mkdir -p $(dirname ${destPath})`, { timeoutMs: 15e3 });
|
|
20226
|
-
await new Promise((
|
|
20240
|
+
await new Promise((resolve5, reject) => {
|
|
20227
20241
|
const child = spawn2(this.scp, [...this.controlArgs, localPath, `${this.host}:${destPath}`], {
|
|
20228
20242
|
stdio: ["ignore", "ignore", "inherit"],
|
|
20229
20243
|
env: this.spawnEnv()
|
|
20230
20244
|
});
|
|
20231
20245
|
child.on("error", reject);
|
|
20232
20246
|
child.on("close", (code) => {
|
|
20233
|
-
if (code === 0)
|
|
20247
|
+
if (code === 0) resolve5();
|
|
20234
20248
|
else reject(new CliError("ssh_unreachable", `scp to ${this.host} failed (exit ${code})`));
|
|
20235
20249
|
});
|
|
20236
20250
|
});
|
|
@@ -20331,7 +20345,7 @@ async function registrationCode() {
|
|
|
20331
20345
|
const readline = createInterface({ input: process.stdin, output: silent, terminal: true });
|
|
20332
20346
|
try {
|
|
20333
20347
|
return remoteSecretSchema.parse(
|
|
20334
|
-
await new Promise((
|
|
20348
|
+
await new Promise((resolve5) => readline.question("", resolve5))
|
|
20335
20349
|
);
|
|
20336
20350
|
} finally {
|
|
20337
20351
|
readline.close();
|
|
@@ -20733,6 +20747,9 @@ import { createHash, randomBytes } from "node:crypto";
|
|
|
20733
20747
|
import {
|
|
20734
20748
|
chmodSync,
|
|
20735
20749
|
closeSync,
|
|
20750
|
+
constants,
|
|
20751
|
+
fchmodSync,
|
|
20752
|
+
fstatSync,
|
|
20736
20753
|
fsyncSync,
|
|
20737
20754
|
lstatSync,
|
|
20738
20755
|
mkdirSync as mkdirSync3,
|
|
@@ -20744,7 +20761,7 @@ import {
|
|
|
20744
20761
|
writeFileSync
|
|
20745
20762
|
} from "node:fs";
|
|
20746
20763
|
import { connect, createServer } from "node:net";
|
|
20747
|
-
import { dirname as dirname2, join as join2 } from "node:path";
|
|
20764
|
+
import { dirname as dirname2, join as join2, resolve } from "node:path";
|
|
20748
20765
|
var digest = (value) => createHash("sha256").update(value).digest("hex");
|
|
20749
20766
|
var secret = (prefix = "") => prefix + randomBytes(32).toString("hex");
|
|
20750
20767
|
function privatePath(path, directory = false) {
|
|
@@ -20757,6 +20774,27 @@ function privateDirectory(path) {
|
|
|
20757
20774
|
mkdirSync3(path, { recursive: true, mode: 448 });
|
|
20758
20775
|
privatePath(path, true);
|
|
20759
20776
|
}
|
|
20777
|
+
function initialisePrivateHome(home) {
|
|
20778
|
+
const path = resolve(home);
|
|
20779
|
+
mkdirSync3(path, { recursive: true, mode: 448 });
|
|
20780
|
+
if (process.platform === "win32") {
|
|
20781
|
+
privatePath(path, true);
|
|
20782
|
+
return;
|
|
20783
|
+
}
|
|
20784
|
+
const fd = openSync(path, constants.O_RDONLY | constants.O_DIRECTORY | constants.O_NOFOLLOW);
|
|
20785
|
+
try {
|
|
20786
|
+
const st = fstatSync(fd);
|
|
20787
|
+
if (!st.isDirectory() || st.uid !== process.getuid() || (st.mode & 18) !== 0) {
|
|
20788
|
+
throw new Error(
|
|
20789
|
+
`Puddle home must be owned by the current user and not writable by other users: ${path}`
|
|
20790
|
+
);
|
|
20791
|
+
}
|
|
20792
|
+
if ((st.mode & 63) !== 0) fchmodSync(fd, 448);
|
|
20793
|
+
} finally {
|
|
20794
|
+
closeSync(fd);
|
|
20795
|
+
}
|
|
20796
|
+
privatePath(path, true);
|
|
20797
|
+
}
|
|
20760
20798
|
function atomicPrivateJson(path, value) {
|
|
20761
20799
|
privateDirectory(dirname2(path));
|
|
20762
20800
|
const tmp = `${path}.${secret()}.tmp`;
|
|
@@ -20778,7 +20816,7 @@ function readPrivateJson(path) {
|
|
|
20778
20816
|
return JSON.parse(readFileSync2(path, "utf8"));
|
|
20779
20817
|
}
|
|
20780
20818
|
function ipcPath(home, scope) {
|
|
20781
|
-
|
|
20819
|
+
initialisePrivateHome(home);
|
|
20782
20820
|
const key = digest(`${realpathSync(home)}\0${scope}`).slice(0, 24);
|
|
20783
20821
|
if (process.platform === "win32") return `\\\\.\\pipe\\puddle-${key}`;
|
|
20784
20822
|
const dir = join2("/tmp", `puddle-${process.getuid()}-${key}`);
|
|
@@ -20791,14 +20829,14 @@ async function listenPrivate(path, onConnection) {
|
|
|
20791
20829
|
privatePath(path);
|
|
20792
20830
|
const before = lstatSync(path);
|
|
20793
20831
|
if (!before.isSocket()) throw new Error("Puddle control path is not a socket");
|
|
20794
|
-
const stale = await new Promise((
|
|
20832
|
+
const stale = await new Promise((resolve5, reject) => {
|
|
20795
20833
|
const probe = connect(path);
|
|
20796
20834
|
probe.once("connect", () => {
|
|
20797
20835
|
probe.destroy();
|
|
20798
|
-
|
|
20836
|
+
resolve5(false);
|
|
20799
20837
|
});
|
|
20800
20838
|
probe.once("error", (err) => {
|
|
20801
|
-
if (err.code === "ECONNREFUSED" || err.code === "ENOENT")
|
|
20839
|
+
if (err.code === "ECONNREFUSED" || err.code === "ENOENT") resolve5(true);
|
|
20802
20840
|
else reject(err);
|
|
20803
20841
|
});
|
|
20804
20842
|
});
|
|
@@ -20811,11 +20849,11 @@ async function listenPrivate(path, onConnection) {
|
|
|
20811
20849
|
}
|
|
20812
20850
|
}
|
|
20813
20851
|
const server = createServer(onConnection);
|
|
20814
|
-
await new Promise((
|
|
20852
|
+
await new Promise((resolve5, reject) => {
|
|
20815
20853
|
server.once("error", reject);
|
|
20816
20854
|
server.listen(path, () => {
|
|
20817
20855
|
server.off("error", reject);
|
|
20818
|
-
|
|
20856
|
+
resolve5();
|
|
20819
20857
|
});
|
|
20820
20858
|
});
|
|
20821
20859
|
if (process.platform !== "win32") chmodSync(path, 384);
|
|
@@ -20929,7 +20967,7 @@ var HostControlClient = class {
|
|
|
20929
20967
|
}
|
|
20930
20968
|
this.channel = channel;
|
|
20931
20969
|
this.until = performance.now() + CONNECTION_POLICY.leaseMs;
|
|
20932
|
-
await new Promise((
|
|
20970
|
+
await new Promise((resolve5, reject) => {
|
|
20933
20971
|
let pendingAt = null;
|
|
20934
20972
|
let initial = true;
|
|
20935
20973
|
const send = (message, sentAt = performance.now()) => {
|
|
@@ -20982,7 +21020,7 @@ var HostControlClient = class {
|
|
|
20982
21020
|
if (this.channel !== channel) return;
|
|
20983
21021
|
this.status = "ready";
|
|
20984
21022
|
this.emit();
|
|
20985
|
-
|
|
21023
|
+
resolve5();
|
|
20986
21024
|
}).catch(() => channel.destroy());
|
|
20987
21025
|
}
|
|
20988
21026
|
},
|
|
@@ -21103,7 +21141,7 @@ async function inspectHostLocally(home) {
|
|
|
21103
21141
|
}
|
|
21104
21142
|
const socket = connect2(path);
|
|
21105
21143
|
try {
|
|
21106
|
-
const grant = await new Promise((
|
|
21144
|
+
const grant = await new Promise((resolve5, reject) => {
|
|
21107
21145
|
socket.setTimeout(5e3, () => socket.destroy(new Error("Host inspection timed out")));
|
|
21108
21146
|
socket.once("error", reject);
|
|
21109
21147
|
socket.once("close", () => reject(new Error("Host control closed")));
|
|
@@ -21113,7 +21151,7 @@ async function inspectHostLocally(home) {
|
|
|
21113
21151
|
const message = controlResponseSchema.parse(value);
|
|
21114
21152
|
if (message.t !== "authority" || !message.token)
|
|
21115
21153
|
throw new Error("Host authority unavailable");
|
|
21116
|
-
|
|
21154
|
+
resolve5(message);
|
|
21117
21155
|
},
|
|
21118
21156
|
() => socket.destroy(new Error("Invalid host control response"))
|
|
21119
21157
|
);
|
|
@@ -21254,12 +21292,12 @@ import {
|
|
|
21254
21292
|
renameSync as renameSync2,
|
|
21255
21293
|
writeFileSync as writeFileSync2
|
|
21256
21294
|
} from "node:fs";
|
|
21257
|
-
import { dirname as dirname6, join as join7, resolve } from "node:path";
|
|
21295
|
+
import { dirname as dirname6, join as join7, resolve as resolve2 } from "node:path";
|
|
21258
21296
|
|
|
21259
21297
|
// src/lib/desktop-update.ts
|
|
21260
21298
|
import { createHash as createHash2 } from "node:crypto";
|
|
21261
21299
|
import { spawn as spawn4 } from "node:child_process";
|
|
21262
|
-
import { constants, createReadStream, createWriteStream } from "node:fs";
|
|
21300
|
+
import { constants as constants2, createReadStream, createWriteStream } from "node:fs";
|
|
21263
21301
|
import { access, chmod, mkdir, readdir, rm, writeFile } from "node:fs/promises";
|
|
21264
21302
|
import { dirname as dirname5, join as join6 } from "node:path";
|
|
21265
21303
|
import { Readable } from "node:stream";
|
|
@@ -21271,7 +21309,7 @@ import { readFileSync as readFileSync4 } from "node:fs";
|
|
|
21271
21309
|
import { dirname as dirname4, join as join5 } from "node:path";
|
|
21272
21310
|
import { fileURLToPath as fileURLToPath2 } from "node:url";
|
|
21273
21311
|
function cliVersion() {
|
|
21274
|
-
if (true) return "0.2.
|
|
21312
|
+
if (true) return "0.2.2";
|
|
21275
21313
|
const here = dirname4(fileURLToPath2(import.meta.url));
|
|
21276
21314
|
for (const candidate of [
|
|
21277
21315
|
join5(here, "..", "..", "package.json"),
|
|
@@ -21539,7 +21577,7 @@ async function desktopAppInstallPath(opts = {}) {
|
|
|
21539
21577
|
const systemApplications = opts.systemApplicationsDir ?? "/Applications";
|
|
21540
21578
|
const canWrite = opts.canWrite ?? (async (path) => {
|
|
21541
21579
|
try {
|
|
21542
|
-
await access(path,
|
|
21580
|
+
await access(path, constants2.W_OK);
|
|
21543
21581
|
return true;
|
|
21544
21582
|
} catch {
|
|
21545
21583
|
return false;
|
|
@@ -21551,12 +21589,12 @@ async function desktopAppInstallPath(opts = {}) {
|
|
|
21551
21589
|
return join6(userApplications, "Puddle.app");
|
|
21552
21590
|
}
|
|
21553
21591
|
function isDesktopAppRunning(appPath) {
|
|
21554
|
-
return new Promise((
|
|
21592
|
+
return new Promise((resolve5) => {
|
|
21555
21593
|
const child = spawn4("/usr/bin/pgrep", ["-f", `${appPath}/Contents/MacOS/`], {
|
|
21556
21594
|
stdio: "ignore"
|
|
21557
21595
|
});
|
|
21558
|
-
child.on("error", () =>
|
|
21559
|
-
child.on("exit", (code) =>
|
|
21596
|
+
child.on("error", () => resolve5(false));
|
|
21597
|
+
child.on("exit", (code) => resolve5(code === 0));
|
|
21560
21598
|
});
|
|
21561
21599
|
}
|
|
21562
21600
|
function fileSha256(path) {
|
|
@@ -21564,12 +21602,12 @@ function fileSha256(path) {
|
|
|
21564
21602
|
return pipeline(createReadStream(path), hash2).then(() => hash2.digest("hex"));
|
|
21565
21603
|
}
|
|
21566
21604
|
function run(command, args) {
|
|
21567
|
-
return new Promise((
|
|
21605
|
+
return new Promise((resolve5, reject) => {
|
|
21568
21606
|
const child = spawn4(command, args, { stdio: "ignore" });
|
|
21569
21607
|
child.on("error", reject);
|
|
21570
21608
|
child.on(
|
|
21571
21609
|
"exit",
|
|
21572
|
-
(code) => code === 0 ?
|
|
21610
|
+
(code) => code === 0 ? resolve5() : reject(new CliError("not_installed", `${command} exited with ${code ?? "signal"}`))
|
|
21573
21611
|
);
|
|
21574
21612
|
});
|
|
21575
21613
|
}
|
|
@@ -21644,7 +21682,9 @@ var RELEASE_PROTOCOLS = {
|
|
|
21644
21682
|
"0.1.11": { major: 17, minor: 3 },
|
|
21645
21683
|
"0.1.12": { major: 17, minor: 3 },
|
|
21646
21684
|
"0.1.13": { major: 17, minor: 3 },
|
|
21647
|
-
"0.2.0": { major: 19, minor: 0 }
|
|
21685
|
+
"0.2.0": { major: 19, minor: 0 },
|
|
21686
|
+
"0.2.1": { major: 19, minor: 0 },
|
|
21687
|
+
"0.2.2": { major: 20, minor: 0 }
|
|
21648
21688
|
};
|
|
21649
21689
|
function validProtocol(value) {
|
|
21650
21690
|
if (typeof value !== "object" || value === null) return false;
|
|
@@ -21732,7 +21772,7 @@ async function installedComponentVersions(opts = {}) {
|
|
|
21732
21772
|
};
|
|
21733
21773
|
}
|
|
21734
21774
|
}
|
|
21735
|
-
const legacyLinuxPath =
|
|
21775
|
+
const legacyLinuxPath = resolve2(home, "..", "puddle", "Puddle.AppImage");
|
|
21736
21776
|
const legacyLinuxDesktop = desktopInstallation === null && (opts.platform ?? process.platform) === "linux" && existsSync2(legacyLinuxPath);
|
|
21737
21777
|
const desktopProtocol = desktopInstallation?.protocol ?? (desktopInstallation ? componentProtocolForVersion(desktopInstallation.version) : void 0);
|
|
21738
21778
|
const desktop = desktopInstallation !== null ? {
|
|
@@ -21761,7 +21801,7 @@ import { randomUUID } from "node:crypto";
|
|
|
21761
21801
|
|
|
21762
21802
|
// src/lib/bootstrap.ts
|
|
21763
21803
|
import { existsSync as existsSync3, readFileSync as readFileSync6 } from "node:fs";
|
|
21764
|
-
import { dirname as dirname7, join as join8, resolve as
|
|
21804
|
+
import { dirname as dirname7, join as join8, resolve as resolve3 } from "node:path";
|
|
21765
21805
|
import { fileURLToPath as fileURLToPath3 } from "node:url";
|
|
21766
21806
|
init_types();
|
|
21767
21807
|
async function installedVersion(transport) {
|
|
@@ -21780,9 +21820,9 @@ async function installDaemon(transport, opts = {}) {
|
|
|
21780
21820
|
throw new CliError("not_installed", `tarball not found: ${opts.tarball}`);
|
|
21781
21821
|
}
|
|
21782
21822
|
if (transport.kind === "local") {
|
|
21783
|
-
args.push("--tarball",
|
|
21823
|
+
args.push("--tarball", resolve3(opts.tarball));
|
|
21784
21824
|
const localSums = `${opts.tarball}.sha256`;
|
|
21785
|
-
if (existsSync3(localSums)) args.push("--sums",
|
|
21825
|
+
if (existsSync3(localSums)) args.push("--sums", resolve3(localSums));
|
|
21786
21826
|
} else {
|
|
21787
21827
|
const base = opts.tarball.split("/").pop() ?? "puddled.tar.gz";
|
|
21788
21828
|
const destTarball = `.puddle/cache/${base}`;
|
|
@@ -21847,22 +21887,22 @@ function readInstallScript() {
|
|
|
21847
21887
|
// src/lib/net.ts
|
|
21848
21888
|
import { connect as connect4, createServer as createServer2 } from "node:net";
|
|
21849
21889
|
function findFreePort() {
|
|
21850
|
-
return new Promise((
|
|
21890
|
+
return new Promise((resolve5, reject) => {
|
|
21851
21891
|
const srv = createServer2();
|
|
21852
21892
|
srv.once("error", reject);
|
|
21853
21893
|
srv.listen(0, "127.0.0.1", () => {
|
|
21854
21894
|
const address = srv.address();
|
|
21855
21895
|
const port = typeof address === "object" && address !== null ? address.port : 0;
|
|
21856
|
-
srv.close(() =>
|
|
21896
|
+
srv.close(() => resolve5(port));
|
|
21857
21897
|
});
|
|
21858
21898
|
});
|
|
21859
21899
|
}
|
|
21860
21900
|
function tcpListening(port, timeoutMs = 500) {
|
|
21861
|
-
return new Promise((
|
|
21901
|
+
return new Promise((resolve5) => {
|
|
21862
21902
|
const sock = connect4({ host: "127.0.0.1", port });
|
|
21863
21903
|
const done = (ok) => {
|
|
21864
21904
|
sock.destroy();
|
|
21865
|
-
|
|
21905
|
+
resolve5(ok);
|
|
21866
21906
|
};
|
|
21867
21907
|
sock.setTimeout(timeoutMs, () => done(false));
|
|
21868
21908
|
sock.once("connect", () => done(true));
|
|
@@ -22311,7 +22351,7 @@ async function startLauncher(home, identity, invite) {
|
|
|
22311
22351
|
path,
|
|
22312
22352
|
close: async () => {
|
|
22313
22353
|
for (const socket of sockets) socket.destroy();
|
|
22314
|
-
await new Promise((
|
|
22354
|
+
await new Promise((resolve5) => server.close(() => resolve5()));
|
|
22315
22355
|
}
|
|
22316
22356
|
};
|
|
22317
22357
|
}
|
|
@@ -22321,14 +22361,14 @@ async function requestInvitation(home, path) {
|
|
|
22321
22361
|
const stored = readPrivateJson(secretFile(home, path));
|
|
22322
22362
|
pipeSecret = stored.secret;
|
|
22323
22363
|
} else privatePath(path);
|
|
22324
|
-
return new Promise((
|
|
22364
|
+
return new Promise((resolve5, reject) => {
|
|
22325
22365
|
const socket = connect5(path);
|
|
22326
22366
|
socket.setTimeout(5e3, () => socket.destroy(new Error("Launcher did not answer")));
|
|
22327
22367
|
jsonLines(
|
|
22328
22368
|
socket,
|
|
22329
22369
|
(value) => {
|
|
22330
22370
|
const message = launcherResponseSchema.parse(value);
|
|
22331
|
-
|
|
22371
|
+
resolve5(message.url);
|
|
22332
22372
|
socket.end();
|
|
22333
22373
|
},
|
|
22334
22374
|
() => socket.destroy(new Error("Invalid launcher reply"))
|
|
@@ -22548,7 +22588,7 @@ function writeStore(file2, store) {
|
|
|
22548
22588
|
renameSync3(tmp, file2);
|
|
22549
22589
|
}
|
|
22550
22590
|
function readBody(req) {
|
|
22551
|
-
return new Promise((
|
|
22591
|
+
return new Promise((resolve5, reject) => {
|
|
22552
22592
|
let size = 0;
|
|
22553
22593
|
const chunks = [];
|
|
22554
22594
|
req.on("data", (chunk) => {
|
|
@@ -22560,7 +22600,7 @@ function readBody(req) {
|
|
|
22560
22600
|
}
|
|
22561
22601
|
chunks.push(chunk);
|
|
22562
22602
|
});
|
|
22563
|
-
req.on("end", () =>
|
|
22603
|
+
req.on("end", () => resolve5(Buffer.concat(chunks).toString("utf8")));
|
|
22564
22604
|
req.on("error", reject);
|
|
22565
22605
|
});
|
|
22566
22606
|
}
|
|
@@ -22598,7 +22638,7 @@ function handleLocalSync(req, res, opts, authorised) {
|
|
|
22598
22638
|
|
|
22599
22639
|
// src/lib/serve/static.ts
|
|
22600
22640
|
import { createReadStream as createReadStream2, existsSync as existsSync4, statSync } from "node:fs";
|
|
22601
|
-
import { extname, join as join11, normalize, resolve as
|
|
22641
|
+
import { extname, join as join11, normalize, resolve as resolve4, sep } from "node:path";
|
|
22602
22642
|
var MIME = {
|
|
22603
22643
|
".html": "text/html; charset=utf-8",
|
|
22604
22644
|
".js": "text/javascript; charset=utf-8",
|
|
@@ -22613,7 +22653,7 @@ var MIME = {
|
|
|
22613
22653
|
".map": "application/json"
|
|
22614
22654
|
};
|
|
22615
22655
|
function createStaticHandler(rootDir) {
|
|
22616
|
-
const root =
|
|
22656
|
+
const root = resolve4(rootDir);
|
|
22617
22657
|
return (req, res) => {
|
|
22618
22658
|
if (req.method !== "GET" && req.method !== "HEAD") {
|
|
22619
22659
|
res.writeHead(405, { allow: "GET, HEAD" }).end();
|
|
@@ -23103,6 +23143,41 @@ function remoteAccessHandler(control) {
|
|
|
23103
23143
|
};
|
|
23104
23144
|
}
|
|
23105
23145
|
|
|
23146
|
+
// src/lib/serve/remote-registration.ts
|
|
23147
|
+
async function checkRemoteRegistration(req, res, authorised) {
|
|
23148
|
+
if (req.method !== "POST") return fail(res, 405, "method_not_allowed");
|
|
23149
|
+
const { service, code } = cockpitRegistrationCheckSchema.parse(await readJson(req));
|
|
23150
|
+
if (!authorised()) return fail(res, 401, "browser_rejected");
|
|
23151
|
+
try {
|
|
23152
|
+
const response = await fetch(`${service}/remote/registration-status`, {
|
|
23153
|
+
method: "POST",
|
|
23154
|
+
headers: { "content-type": "application/json" },
|
|
23155
|
+
body: JSON.stringify({ code }),
|
|
23156
|
+
redirect: "error",
|
|
23157
|
+
signal: AbortSignal.timeout(5e3)
|
|
23158
|
+
});
|
|
23159
|
+
if (!response.ok) {
|
|
23160
|
+
await response.body?.cancel();
|
|
23161
|
+
throw new Error("Service unavailable");
|
|
23162
|
+
}
|
|
23163
|
+
let body = "";
|
|
23164
|
+
for await (const chunk of response.body ?? []) {
|
|
23165
|
+
body += Buffer.from(chunk).toString("utf8");
|
|
23166
|
+
if (body.length > 1024) throw new Error("Response too large");
|
|
23167
|
+
}
|
|
23168
|
+
const status = registrationStatusSchema.parse(JSON.parse(body));
|
|
23169
|
+
if (!authorised()) return fail(res, 401, "browser_rejected");
|
|
23170
|
+
json2(res, 200, status);
|
|
23171
|
+
} catch {
|
|
23172
|
+
fail(
|
|
23173
|
+
res,
|
|
23174
|
+
503,
|
|
23175
|
+
"registration_unavailable",
|
|
23176
|
+
"Could not check browser sign-in. Check the relay address and update the deployed service, then try again."
|
|
23177
|
+
);
|
|
23178
|
+
}
|
|
23179
|
+
}
|
|
23180
|
+
|
|
23106
23181
|
// src/lib/serve/ui-server.ts
|
|
23107
23182
|
var DEFAULT_UI_PORT = 7433;
|
|
23108
23183
|
var MAX_PORT_PROBES = 50;
|
|
@@ -23162,6 +23237,10 @@ async function startUiServer(opts) {
|
|
|
23162
23237
|
return handleLocalSync(req, res, opts.localSync, () => browsers.valid(browser));
|
|
23163
23238
|
if (url2.pathname === "/cockpit/remote")
|
|
23164
23239
|
return handleRemoteAccess(req, res, () => browsers.valid(browser));
|
|
23240
|
+
if (url2.pathname === "/cockpit/remote/registration") {
|
|
23241
|
+
if (!opts.remoteAccess) return fail(res, 404, "remote_controls_unavailable");
|
|
23242
|
+
return checkRemoteRegistration(req, res, () => browsers.valid(browser));
|
|
23243
|
+
}
|
|
23165
23244
|
if (url2.pathname === "/cockpit/refresh" && req.method === "POST") {
|
|
23166
23245
|
if (!opts.control) return fail(res, 404, "refresh_unavailable");
|
|
23167
23246
|
const body = cockpitRefreshRequestSchema.parse(await readJson(req));
|
|
@@ -23246,8 +23325,8 @@ async function startUiServer(opts) {
|
|
|
23246
23325
|
browsers.close();
|
|
23247
23326
|
bridge.close();
|
|
23248
23327
|
tracker.destroyAll();
|
|
23249
|
-
await new Promise((
|
|
23250
|
-
server.close(() =>
|
|
23328
|
+
await new Promise((resolve5) => {
|
|
23329
|
+
server.close(() => resolve5());
|
|
23251
23330
|
server.closeAllConnections();
|
|
23252
23331
|
});
|
|
23253
23332
|
}
|
|
@@ -23257,15 +23336,15 @@ async function listen(server, startPort, strict, avoidPort) {
|
|
|
23257
23336
|
for (let probe = 0; probe < MAX_PORT_PROBES; probe += 1) {
|
|
23258
23337
|
const port = startPort + probe;
|
|
23259
23338
|
if (!strict && port === avoidPort) continue;
|
|
23260
|
-
const ok = await new Promise((
|
|
23339
|
+
const ok = await new Promise((resolve5, rejectListen) => {
|
|
23261
23340
|
const onError = (err) => {
|
|
23262
23341
|
server.off("listening", onListening);
|
|
23263
|
-
if (err.code === "EADDRINUSE")
|
|
23342
|
+
if (err.code === "EADDRINUSE") resolve5(false);
|
|
23264
23343
|
else rejectListen(err);
|
|
23265
23344
|
};
|
|
23266
23345
|
const onListening = () => {
|
|
23267
23346
|
server.off("error", onError);
|
|
23268
|
-
|
|
23347
|
+
resolve5(true);
|
|
23269
23348
|
};
|
|
23270
23349
|
server.once("error", onError);
|
|
23271
23350
|
server.once("listening", onListening);
|
|
@@ -23292,21 +23371,24 @@ var RemoteAccessControl = class {
|
|
|
23292
23371
|
constructor(transport) {
|
|
23293
23372
|
this.transport = transport;
|
|
23294
23373
|
}
|
|
23295
|
-
async
|
|
23374
|
+
async capabilities() {
|
|
23296
23375
|
const result = await this.transport.exec(
|
|
23297
23376
|
`if test -f ${hostPaths.current}/daemon/connector.mjs; then ${binary} --version; else exit 44; fi`,
|
|
23298
23377
|
{ timeoutMs: 1e4 }
|
|
23299
23378
|
);
|
|
23300
|
-
if (result.code === 44) return "not_installed";
|
|
23379
|
+
if (result.code === 44) return { availability: "not_installed", canDeleteRegistration: false };
|
|
23301
23380
|
if (result.code !== 0)
|
|
23302
23381
|
throw new Error("Host control is unavailable. Check the host connection.");
|
|
23303
|
-
return
|
|
23382
|
+
return {
|
|
23383
|
+
availability: result.stdout.includes("cockpit controls 1") ? "ready" : "upgrade_required",
|
|
23384
|
+
canDeleteRegistration: result.stdout.includes("delete registration 1")
|
|
23385
|
+
};
|
|
23304
23386
|
}
|
|
23305
23387
|
async status() {
|
|
23306
|
-
const
|
|
23307
|
-
if (availability !== "ready")
|
|
23388
|
+
const capabilities = await this.capabilities();
|
|
23389
|
+
if (capabilities.availability !== "ready")
|
|
23308
23390
|
return {
|
|
23309
|
-
|
|
23391
|
+
...capabilities,
|
|
23310
23392
|
configured: false,
|
|
23311
23393
|
enabled: false,
|
|
23312
23394
|
connected: false,
|
|
@@ -23315,12 +23397,15 @@ var RemoteAccessControl = class {
|
|
|
23315
23397
|
};
|
|
23316
23398
|
const result = await this.transport.exec(`${binary} --inspect`, { timeoutMs: 1e4 });
|
|
23317
23399
|
if (result.code !== 0) throw new Error("Could not read remote access status on this host.");
|
|
23318
|
-
return cockpitRemoteStatusSchema.parse(JSON.parse(result.stdout));
|
|
23400
|
+
return cockpitRemoteStatusSchema.parse({ ...JSON.parse(result.stdout), ...capabilities });
|
|
23319
23401
|
}
|
|
23320
23402
|
async request(value, authorised) {
|
|
23321
23403
|
const request = cockpitRemoteRequestSchema.parse(value);
|
|
23322
|
-
|
|
23404
|
+
const capabilities = await this.capabilities();
|
|
23405
|
+
if (capabilities.availability !== "ready")
|
|
23323
23406
|
throw new Error("Upgrade the daemon on this host to manage remote access here.");
|
|
23407
|
+
if (request.t === "delete_registration" && !capabilities.canDeleteRegistration)
|
|
23408
|
+
throw new Error("Upgrade the daemon on this host to delete its remote registration.");
|
|
23324
23409
|
if (!authorised()) throw new Error("Browser authorisation expired before dispatch.");
|
|
23325
23410
|
const flag = request.t === "enable" ? "--configure" : request.t === "reset" ? "--reset" : "--admin";
|
|
23326
23411
|
const payload = request.t === "enable" ? { ...request.registration, managed: true } : request;
|
|
@@ -24182,7 +24267,7 @@ async function ask(question, def) {
|
|
|
24182
24267
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
24183
24268
|
try {
|
|
24184
24269
|
const answer = await new Promise(
|
|
24185
|
-
(
|
|
24270
|
+
(resolve5) => rl.question(`${question} [${def}] `, resolve5)
|
|
24186
24271
|
);
|
|
24187
24272
|
return answer.trim() === "" ? def : answer.trim();
|
|
24188
24273
|
} finally {
|
|
@@ -24201,7 +24286,7 @@ async function confirm(question, opts = {}) {
|
|
|
24201
24286
|
const rl = createInterface2({ input: process.stdin, output: process.stdout });
|
|
24202
24287
|
try {
|
|
24203
24288
|
const answer = await new Promise(
|
|
24204
|
-
(
|
|
24289
|
+
(resolve5) => rl.question(`${question} [y/N] `, resolve5)
|
|
24205
24290
|
);
|
|
24206
24291
|
return /^y(es)?$/i.test(answer.trim());
|
|
24207
24292
|
} finally {
|
|
@@ -24320,7 +24405,7 @@ async function runUpgrade(cmd, logger) {
|
|
|
24320
24405
|
function upgradeCli(version2, logger) {
|
|
24321
24406
|
const spec = `@puddle-code/cli@${version2 ?? "latest"}`;
|
|
24322
24407
|
logger.info(`puddle CLI ${cliVersion()} \u2014 asking npm for ${version2 ?? "the latest release"}`);
|
|
24323
|
-
return new Promise((
|
|
24408
|
+
return new Promise((resolve5, reject) => {
|
|
24324
24409
|
const child = spawn7("npm", ["install", "-g", spec], { stdio: "inherit" });
|
|
24325
24410
|
child.on(
|
|
24326
24411
|
"error",
|
|
@@ -24335,7 +24420,7 @@ function upgradeCli(version2, logger) {
|
|
|
24335
24420
|
child.on("exit", (code) => {
|
|
24336
24421
|
if (code === 0) {
|
|
24337
24422
|
logger.info("done \u2014 `puddle --version` shows the installed version");
|
|
24338
|
-
|
|
24423
|
+
resolve5(0);
|
|
24339
24424
|
} else {
|
|
24340
24425
|
reject(new CliError("not_installed", `npm install exited with ${code ?? "a signal"}`));
|
|
24341
24426
|
}
|
|
@@ -24458,10 +24543,10 @@ async function runRemove(cmd, logger) {
|
|
|
24458
24543
|
}
|
|
24459
24544
|
}
|
|
24460
24545
|
async function removeCli(yes, logger) {
|
|
24461
|
-
const managed = await new Promise((
|
|
24546
|
+
const managed = await new Promise((resolve5) => {
|
|
24462
24547
|
const child = spawn7("npm", ["ls", "-g", "@puddle-code/cli", "--depth=0"], { stdio: "ignore" });
|
|
24463
|
-
child.on("error", () =>
|
|
24464
|
-
child.on("exit", (code) =>
|
|
24548
|
+
child.on("error", () => resolve5(false));
|
|
24549
|
+
child.on("exit", (code) => resolve5(code === 0));
|
|
24465
24550
|
});
|
|
24466
24551
|
if (!managed) {
|
|
24467
24552
|
throw new CliError(
|
|
@@ -24478,13 +24563,13 @@ async function removeCli(yes, logger) {
|
|
|
24478
24563
|
logger.info("nothing removed");
|
|
24479
24564
|
return 0;
|
|
24480
24565
|
}
|
|
24481
|
-
return new Promise((
|
|
24566
|
+
return new Promise((resolve5, reject) => {
|
|
24482
24567
|
const child = spawn7("npm", ["uninstall", "-g", "@puddle-code/cli"], { stdio: "inherit" });
|
|
24483
24568
|
child.on("error", () => reject(new CliError("not_installed", "npm is not on PATH")));
|
|
24484
24569
|
child.on("exit", (code) => {
|
|
24485
24570
|
if (code === 0) {
|
|
24486
24571
|
logger.info("removed \u2014 daemons keep running (puddle remove daemon uninstalls one)");
|
|
24487
|
-
|
|
24572
|
+
resolve5(0);
|
|
24488
24573
|
} else {
|
|
24489
24574
|
reject(new CliError("not_installed", `npm uninstall exited with ${code ?? "a signal"}`));
|
|
24490
24575
|
}
|
|
@@ -24673,7 +24758,7 @@ async function openTarget(host) {
|
|
|
24673
24758
|
};
|
|
24674
24759
|
}
|
|
24675
24760
|
function runUntilInterrupted(stop, farewell) {
|
|
24676
|
-
return new Promise((
|
|
24761
|
+
return new Promise((resolve5) => {
|
|
24677
24762
|
let stopping = false;
|
|
24678
24763
|
process.on("SIGINT", () => {
|
|
24679
24764
|
if (stopping) process.exit(130);
|
|
@@ -24681,10 +24766,10 @@ function runUntilInterrupted(stop, farewell) {
|
|
|
24681
24766
|
process.stderr.write(`
|
|
24682
24767
|
${farewell}
|
|
24683
24768
|
`);
|
|
24684
|
-
void stop().then(
|
|
24769
|
+
void stop().then(resolve5);
|
|
24685
24770
|
});
|
|
24686
24771
|
process.on("SIGTERM", () => {
|
|
24687
|
-
void stop().then(
|
|
24772
|
+
void stop().then(resolve5);
|
|
24688
24773
|
});
|
|
24689
24774
|
});
|
|
24690
24775
|
}
|