@ghostlytools/cli 1.3.6 → 1.3.7
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/README.md +7 -1
- package/dist/assets/{api-Br3msjtR.js → api-BL0vpWGN.js} +2 -2
- package/dist/assets/{api-z9mlywrn.js → api-DlxlF4jP.js} +10 -10
- package/dist/assets/api-DlxlF4jP.js.map +1 -0
- package/dist/assets/{apiKit-lX3Xx_hY.js → apiKit-BnpVuZrZ.js} +2 -2
- package/dist/assets/{apiKit-lX3Xx_hY.js.map → apiKit-BnpVuZrZ.js.map} +1 -1
- package/dist/assets/{apps-Dn7rCafG.js → apps-B_6Q-Mq-.js} +1 -1
- package/dist/assets/{apps-BUK6bEKW.js → apps-Bs6QYQjm.js} +2 -2
- package/dist/assets/{apps-BUK6bEKW.js.map → apps-Bs6QYQjm.js.map} +1 -1
- package/dist/assets/{arkade-uqAXA5BT.js → arkade-DwgUNqCz.js} +2 -2
- package/dist/assets/{arkade-uqAXA5BT.js.map → arkade-DwgUNqCz.js.map} +1 -1
- package/dist/assets/{backup-_JnqeFZb.js → backup-BqtsbjOT.js} +1 -1
- package/dist/assets/{backup-CJQK5Miu.js → backup-DEe1NqKb.js} +4 -4
- package/dist/assets/{backup-CJQK5Miu.js.map → backup-DEe1NqKb.js.map} +1 -1
- package/dist/assets/buttons-CB1opfZP.js +2 -0
- package/dist/assets/{buttons-DDvTuViY.js → buttons-D9NQ3kV0.js} +3 -3
- package/dist/assets/{buttons-DDvTuViY.js.map → buttons-D9NQ3kV0.js.map} +1 -1
- package/dist/assets/daemonProof-B53VnZ1Z.js +100 -0
- package/dist/assets/daemonProof-B53VnZ1Z.js.map +1 -0
- package/dist/assets/{envelope-BqvBb6hC.js → envelope-WC8QWYIL.js} +2 -2
- package/dist/assets/{envelope-BqvBb6hC.js.map → envelope-WC8QWYIL.js.map} +1 -1
- package/dist/assets/{groupFiles-B1lL6wch.js → groupFiles-BrCMSXxg.js} +7 -4
- package/dist/assets/groupFiles-BrCMSXxg.js.map +1 -0
- package/dist/assets/{host-DFzlKU3P.js → host-H0IYKNoK.js} +29 -11
- package/dist/assets/{host-DFzlKU3P.js.map → host-H0IYKNoK.js.map} +1 -1
- package/dist/assets/{hyperdhtRelay-DwlOY6aD.js → hyperdhtRelay-CEfwbaCO.js} +2 -2
- package/dist/assets/{hyperdhtRelay-DwlOY6aD.js.map → hyperdhtRelay-CEfwbaCO.js.map} +1 -1
- package/dist/assets/{irohWeb-DZDCyL9b.js → irohWeb-Bn-JA2kp.js} +2 -2
- package/dist/assets/{irohWeb-DZDCyL9b.js.map → irohWeb-Bn-JA2kp.js.map} +1 -1
- package/dist/assets/{main-DgbdDDif.js → main-DiCC-Vjq.js} +111 -39
- package/dist/assets/main-DiCC-Vjq.js.map +1 -0
- package/dist/assets/{mainline-BHE5-R3A.js → mainline-gU7pE7s2.js} +2 -2
- package/dist/assets/{mainline-BHE5-R3A.js.map → mainline-gU7pE7s2.js.map} +1 -1
- package/dist/assets/{networkReason-Btv4b2C4.js → networkReason-Dl9JThBQ.js} +2 -2
- package/dist/assets/{networkReason-Btv4b2C4.js.map → networkReason-Dl9JThBQ.js.map} +1 -1
- package/dist/assets/{nwc-z0pa5zql.js → nwc-CKjZjg-q.js} +3 -3
- package/dist/assets/{nwc-z0pa5zql.js.map → nwc-CKjZjg-q.js.map} +1 -1
- package/dist/assets/{nwcProvider-C1AhPoFW.js → nwcProvider-GDrc0HM4.js} +2 -2
- package/dist/assets/{nwcProvider-C1AhPoFW.js.map → nwcProvider-GDrc0HM4.js.map} +1 -1
- package/dist/assets/{registry-JrnwUWmh.js → registry-JGOFtJDE.js} +3 -3
- package/dist/assets/{registry-JrnwUWmh.js.map → registry-JGOFtJDE.js.map} +1 -1
- package/dist/assets/{registry-C09xXyx-.js → registry-Wk7ZHuwm.js} +1 -1
- package/dist/assets/{resolve-Ssq1nDy4.js → resolve-CVpEbud3.js} +2 -2
- package/dist/assets/{resolve-Ssq1nDy4.js.map → resolve-CVpEbud3.js.map} +1 -1
- package/dist/assets/{server-D6FSznK5.js → server-CkYscxE3.js} +48 -20
- package/dist/assets/{server-D6FSznK5.js.map → server-CkYscxE3.js.map} +1 -1
- package/dist/assets/{src-XhjSWnp-.js → src-gJqfoRKI.js} +26 -2
- package/dist/assets/src-gJqfoRKI.js.map +1 -0
- package/dist/assets/{turnRefs-Cle33IoV.js → turnRefs-zUQbFkl3.js} +2 -2
- package/dist/assets/{turnRefs-Cle33IoV.js.map → turnRefs-zUQbFkl3.js.map} +1 -1
- package/dist/assets/{usdt-DO86yko2.js → usdt-BkDMGqZa.js} +3 -3
- package/dist/assets/{usdt-DO86yko2.js.map → usdt-BkDMGqZa.js.map} +1 -1
- package/dist/ghostly.mjs +1 -1
- package/package.json +1 -1
- package/dist/assets/api-z9mlywrn.js.map +0 -1
- package/dist/assets/buttons-DDB9Xdha.js +0 -2
- package/dist/assets/groupFiles-B1lL6wch.js.map +0 -1
- package/dist/assets/main-DgbdDDif.js.map +0 -1
- package/dist/assets/privateFolder-Bk9C9oFv.js +0 -38
- package/dist/assets/privateFolder-Bk9C9oFv.js.map +0 -1
- package/dist/assets/src-XhjSWnp-.js.map +0 -1
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { $n as GROUP_FILE_LIMITS, Ja as PR_CHECKS, Xa as RUN_RESULTS, Ya as PR_STATES, Za as STATUS_CARD_LIMITS, qa as ITEM_STATES, to as cardUrl } from "./src-
|
|
2
|
-
import { a as SECRET_RESULTS, i as ENGINE_READS, r as ENGINE_METHODS, t as turnRef } from "./turnRefs-
|
|
1
|
+
import { $n as GROUP_FILE_LIMITS, Ja as PR_CHECKS, Xa as RUN_RESULTS, Ya as PR_STATES, Za as STATUS_CARD_LIMITS, qa as ITEM_STATES, to as cardUrl } from "./src-gJqfoRKI.js";
|
|
2
|
+
import { a as SECRET_RESULTS, i as ENGINE_READS, r as ENGINE_METHODS, t as turnRef } from "./turnRefs-zUQbFkl3.js";
|
|
3
3
|
import { i as localFileError, n as EXIT, r as asCliError, t as CliError } from "./errors-B-zMxbcd.js";
|
|
4
|
-
import { t as CONTACT_KEY } from "./apiKit-
|
|
4
|
+
import { t as CONTACT_KEY } from "./apiKit-BnpVuZrZ.js";
|
|
5
5
|
import { a as createProfile, c as listProfiles, d as profilePaths, f as selectProfile, i as checkProfileName, l as lockOwner, o as currentProfile, s as ghostlyHome, u as profileExists } from "./profiles-gPCjLOQq.js";
|
|
6
|
-
import {
|
|
6
|
+
import { a as provesDaemon, c as ownSocket, o as readDaemonSecret, r as newNonce, t as HELLO } from "./daemonProof-B53VnZ1Z.js";
|
|
7
7
|
import { accessSync, constants, existsSync, openSync, readFileSync, renameSync, rmSync, statSync, writeFileSync } from "node:fs";
|
|
8
8
|
import { dirname, resolve } from "node:path";
|
|
9
9
|
import { spawn } from "node:child_process";
|
|
@@ -12,7 +12,7 @@ import { createInterface } from "node:readline";
|
|
|
12
12
|
import { format } from "node:util";
|
|
13
13
|
var package_default = {
|
|
14
14
|
name: "@ghostlytools/cli",
|
|
15
|
-
version: "1.3.
|
|
15
|
+
version: "1.3.7",
|
|
16
16
|
type: "module",
|
|
17
17
|
description: "Ghostly for bots and terminals: the app's own engine, headless on Node, behind a daemon and a `ghostly` command with JSON output.",
|
|
18
18
|
license: "MIT",
|
|
@@ -230,18 +230,45 @@ function liftGlobals(argv) {
|
|
|
230
230
|
}
|
|
231
231
|
//#endregion
|
|
232
232
|
//#region src/client.ts
|
|
233
|
+
/** The id of the hello on every connection: a string, so it is never one of the calls' numbers. */
|
|
234
|
+
var HELLO_ID = "hello";
|
|
235
|
+
/** The refusal of a listener that did not prove it is the profile's daemon (`isNotTheDaemon` tells it apart). */
|
|
236
|
+
function notTheDaemon(socket) {
|
|
237
|
+
return new CliError("refused", `What answers on ${socket} did not prove it is this profile's daemon, so nothing was sent to it. A daemon of an older release cannot: \`ghostly daemon restart\` starts this one's`, { reason: "not-the-daemon" });
|
|
238
|
+
}
|
|
239
|
+
function isNotTheDaemon(error) {
|
|
240
|
+
return error instanceof CliError && error.code === "refused" && error.details?.reason === "not-the-daemon";
|
|
241
|
+
}
|
|
233
242
|
/**
|
|
234
243
|
* A connection to a profile's daemon over its socket (WISP 1100 § Local control API). `null` from `connectDaemon`
|
|
235
|
-
* means no daemon answers there: a one-shot command runs the profile itself.
|
|
244
|
+
* means no daemon answers there: a one-shot command runs the profile itself. *
|
|
245
|
+
* The first line on it is a `daemon.hello`, and no call is written until its answer proves the other end read the
|
|
246
|
+
* profile's daemon secret (`daemonProof.ts`): until then every call waits, and a listener that does not prove it gets
|
|
247
|
+
* every call refused (`refused`, `isNotTheDaemon`) having read nothing but the hello. Nothing it writes before that
|
|
248
|
+
* is read either.
|
|
236
249
|
*/
|
|
237
250
|
var DaemonClient = class {
|
|
238
251
|
socket;
|
|
252
|
+
address;
|
|
239
253
|
nextId = 1;
|
|
240
254
|
pending = /* @__PURE__ */ new Map();
|
|
241
255
|
eventListener = null;
|
|
242
256
|
closedListener = null;
|
|
243
|
-
|
|
257
|
+
verified = false;
|
|
258
|
+
refusal = null;
|
|
259
|
+
ready;
|
|
260
|
+
settle;
|
|
261
|
+
constructor(socket, address) {
|
|
244
262
|
this.socket = socket;
|
|
263
|
+
this.address = address;
|
|
264
|
+
this.ready = new Promise((resolve, reject) => {
|
|
265
|
+
this.settle = {
|
|
266
|
+
resolve,
|
|
267
|
+
reject
|
|
268
|
+
};
|
|
269
|
+
});
|
|
270
|
+
this.ready.catch(() => {});
|
|
271
|
+
const nonce = newNonce();
|
|
245
272
|
createInterface({
|
|
246
273
|
input: socket,
|
|
247
274
|
crlfDelay: Infinity
|
|
@@ -252,6 +279,17 @@ var DaemonClient = class {
|
|
|
252
279
|
} catch {
|
|
253
280
|
return;
|
|
254
281
|
}
|
|
282
|
+
if (!this.verified) {
|
|
283
|
+
if (this.refusal || message?.id !== HELLO_ID) return;
|
|
284
|
+
const secret = readDaemonSecret(this.address.dir);
|
|
285
|
+
if (!message.error && secret && provesDaemon(secret, nonce, message.result)) {
|
|
286
|
+
this.verified = true;
|
|
287
|
+
this.settle.resolve();
|
|
288
|
+
return;
|
|
289
|
+
}
|
|
290
|
+
this.refuse();
|
|
291
|
+
return;
|
|
292
|
+
}
|
|
255
293
|
if (message.event) {
|
|
256
294
|
this.eventListener?.(message.event);
|
|
257
295
|
return;
|
|
@@ -263,24 +301,41 @@ var DaemonClient = class {
|
|
|
263
301
|
else waiting.resolve(message.result);
|
|
264
302
|
});
|
|
265
303
|
socket.on("close", () => {
|
|
266
|
-
|
|
304
|
+
const why = this.refusal ?? new CliError("unavailable", "The daemon went away");
|
|
305
|
+
if (!this.verified) this.settle.reject(why);
|
|
306
|
+
for (const waiting of this.pending.values()) waiting.reject(why);
|
|
267
307
|
this.pending.clear();
|
|
268
308
|
this.closedListener?.();
|
|
269
309
|
});
|
|
270
310
|
socket.on("error", () => {});
|
|
311
|
+
socket.write(JSON.stringify({
|
|
312
|
+
id: HELLO_ID,
|
|
313
|
+
method: HELLO,
|
|
314
|
+
params: { nonce }
|
|
315
|
+
}) + "\n");
|
|
316
|
+
}
|
|
317
|
+
refuse() {
|
|
318
|
+
this.refusal = notTheDaemon(this.address.socket);
|
|
319
|
+
this.settle.reject(this.refusal);
|
|
320
|
+
this.socket.destroy();
|
|
271
321
|
}
|
|
272
322
|
call(method, params = {}) {
|
|
323
|
+
if (this.socket.destroyed && this.refusal) return Promise.reject(this.refusal);
|
|
273
324
|
const id = this.nextId++;
|
|
274
325
|
return new Promise((resolve, reject) => {
|
|
275
326
|
this.pending.set(id, {
|
|
276
327
|
resolve,
|
|
277
328
|
reject
|
|
278
329
|
});
|
|
279
|
-
this.
|
|
280
|
-
id
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
330
|
+
this.ready.then(() => {
|
|
331
|
+
if (this.pending.has(id) && !this.socket.destroyed) this.socket.write(JSON.stringify({
|
|
332
|
+
id,
|
|
333
|
+
method,
|
|
334
|
+
params
|
|
335
|
+
}) + "\n");
|
|
336
|
+
}, (error) => {
|
|
337
|
+
if (this.pending.delete(id)) reject(error);
|
|
338
|
+
});
|
|
284
339
|
});
|
|
285
340
|
}
|
|
286
341
|
/** Events after `since` (replayed from the journal), then every new one, until the connection closes. */
|
|
@@ -297,7 +352,12 @@ var DaemonClient = class {
|
|
|
297
352
|
this.socket.destroy();
|
|
298
353
|
}
|
|
299
354
|
};
|
|
300
|
-
|
|
355
|
+
/**
|
|
356
|
+
* `timeoutMs` bounds the connect only. The client it gives has sent its hello; whether the listener is the daemon is
|
|
357
|
+
* known at the first call (above).
|
|
358
|
+
*/
|
|
359
|
+
function connectDaemon(address, timeoutMs = 2e3) {
|
|
360
|
+
const path = address.socket;
|
|
301
361
|
if (!ownSocket(path)) return Promise.resolve(null);
|
|
302
362
|
return new Promise((resolve) => {
|
|
303
363
|
const socket = connect(path);
|
|
@@ -307,7 +367,7 @@ function connectDaemon(path, timeoutMs = 2e3) {
|
|
|
307
367
|
}, timeoutMs);
|
|
308
368
|
socket.once("connect", () => {
|
|
309
369
|
clearTimeout(timer);
|
|
310
|
-
resolve(new DaemonClient(socket));
|
|
370
|
+
resolve(new DaemonClient(socket, address));
|
|
311
371
|
});
|
|
312
372
|
socket.once("error", () => {
|
|
313
373
|
clearTimeout(timer);
|
|
@@ -882,7 +942,7 @@ var commands$8 = {
|
|
|
882
942
|
description: "Replace the three files when they are there"
|
|
883
943
|
}
|
|
884
944
|
},
|
|
885
|
-
run: async ({ options }, a) => (await import("./apps-
|
|
945
|
+
run: async ({ options }, a) => (await import("./apps-B_6Q-Mq-.js")).initApp(a.dir, {
|
|
886
946
|
name: options.name,
|
|
887
947
|
title: options.title,
|
|
888
948
|
force: options.force === true
|
|
@@ -922,7 +982,7 @@ var commands$8 = {
|
|
|
922
982
|
description: "This version's sequence, higher than the bundle at --out's (default: one more than it)"
|
|
923
983
|
}
|
|
924
984
|
},
|
|
925
|
-
run: async ({ options }, a) => (await import("./apps-
|
|
985
|
+
run: async ({ options }, a) => (await import("./apps-B_6Q-Mq-.js")).publishApp(a.dir, keyFile(options.key, "app publish <dir> --key <file> [--out <file>] [--sequence n]"), here(options.out), options.sequence)
|
|
926
986
|
},
|
|
927
987
|
"app revoke": {
|
|
928
988
|
method: "app.revoke",
|
|
@@ -955,7 +1015,7 @@ var commands$8 = {
|
|
|
955
1015
|
description: "Allow --up-to past the bundle's own sequence (versions published from elsewhere)"
|
|
956
1016
|
}
|
|
957
1017
|
},
|
|
958
|
-
run: async ({ options }, a) => (await import("./apps-
|
|
1018
|
+
run: async ({ options }, a) => (await import("./apps-B_6Q-Mq-.js")).revokeApp(a.dir, keyFile(options.key, "app revoke <dir> --key <file> (--digest <digest>... | --up-to <sequence>) [--reason <text>]"), {
|
|
959
1019
|
digests: options.digest,
|
|
960
1020
|
upTo: options["up-to"],
|
|
961
1021
|
reason: options.reason,
|
|
@@ -1016,7 +1076,7 @@ var commands$8 = {
|
|
|
1016
1076
|
usage: "app verify <bundle|url>",
|
|
1017
1077
|
summary: "Check a .ghostlyapp as a client would, from a file or an https URL: its manifest and digest, or refused (exit 1) with the reason, revoked when the ghostly-revoke.json beside it revokes this version",
|
|
1018
1078
|
args: ["bundle"],
|
|
1019
|
-
run: async (_, a) => (await import("./apps-
|
|
1079
|
+
run: async (_, a) => (await import("./apps-B_6Q-Mq-.js")).verifyApp(a.bundle)
|
|
1020
1080
|
},
|
|
1021
1081
|
"store sign": {
|
|
1022
1082
|
method: "store.sign",
|
|
@@ -1033,7 +1093,7 @@ var commands$8 = {
|
|
|
1033
1093
|
description: "The folder to write ghostly-store.json and ghostly-store.sig in (default: the index's)"
|
|
1034
1094
|
}
|
|
1035
1095
|
},
|
|
1036
|
-
run: async ({ options }, a) => (await import("./apps-
|
|
1096
|
+
run: async ({ options }, a) => (await import("./apps-B_6Q-Mq-.js")).signStore(a.index, keyFile(options.key, "store sign <index> --key <file> [--out <dir>]"), here(options.out))
|
|
1037
1097
|
}
|
|
1038
1098
|
};
|
|
1039
1099
|
//#endregion
|
|
@@ -3241,8 +3301,8 @@ var VERSION = package_default.version;
|
|
|
3241
3301
|
* command a running daemon answers loads none of them, and starts about as fast as Node does. Statically imported, they
|
|
3242
3302
|
* cost every command ~100 ms before its socket was opened.
|
|
3243
3303
|
*/
|
|
3244
|
-
var engineApi = () => import("./api-
|
|
3245
|
-
var engineHost = () => import("./host-
|
|
3304
|
+
var engineApi = () => import("./api-BL0vpWGN.js");
|
|
3305
|
+
var engineHost = () => import("./host-H0IYKNoK.js");
|
|
3246
3306
|
var pretty = false;
|
|
3247
3307
|
function print(value) {
|
|
3248
3308
|
process.stdout.write(JSON.stringify(value, null, pretty ? 2 : void 0) + "\n");
|
|
@@ -3338,7 +3398,7 @@ function readOnly(method, params) {
|
|
|
3338
3398
|
}
|
|
3339
3399
|
async function session(g, options) {
|
|
3340
3400
|
requireProfile(g);
|
|
3341
|
-
const client = await connectDaemon(g.paths
|
|
3401
|
+
const client = await connectDaemon(g.paths);
|
|
3342
3402
|
if (client) await warnVersion(client);
|
|
3343
3403
|
if (client) return {
|
|
3344
3404
|
mode: "daemon",
|
|
@@ -3706,7 +3766,7 @@ async function profileCommand(sub, argv) {
|
|
|
3706
3766
|
const [file, name] = parsed.positionals;
|
|
3707
3767
|
if (!file || !name) throw new CliError("usage", "ghostly profile restore <file> <new profile> [--passphrase-file f] [--use]");
|
|
3708
3768
|
noMoreThan(2, parsed.positionals, "profile restore <file> <new profile> [--passphrase-file f] [--use]");
|
|
3709
|
-
const { backupFileProtection, restoreProfile } = await import("./backup-
|
|
3769
|
+
const { backupFileProtection, restoreProfile } = await import("./backup-BqtsbjOT.js");
|
|
3710
3770
|
const protection = await backupFileProtection(file);
|
|
3711
3771
|
const paths = await restoreProfile(g.home, checkProfileName(name), file, protection === "none" ? void 0 : backupPassphrase(parsed.options["passphrase-file"], RESTORE_PASSPHRASE));
|
|
3712
3772
|
if (parsed.options.use) selectProfile(g.home, name);
|
|
@@ -3769,7 +3829,7 @@ function backupPassphrase(file, missing = BACKUP_PASSPHRASE) {
|
|
|
3769
3829
|
}
|
|
3770
3830
|
async function runDaemon(g) {
|
|
3771
3831
|
requireProfile(g);
|
|
3772
|
-
if (await connectDaemon(g.paths
|
|
3832
|
+
if (await connectDaemon(g.paths)) throw new CliError("busy", `A daemon already runs profile ${g.profile}`);
|
|
3773
3833
|
const { keepServing, openHost, serve } = await engineHost();
|
|
3774
3834
|
const host = await openHost(g.paths, "daemon", VERSION);
|
|
3775
3835
|
let served;
|
|
@@ -3819,7 +3879,7 @@ async function daemonCommand(argv) {
|
|
|
3819
3879
|
].includes(sub)) noMoreThan(0, parsed.positionals, sub === "status" ? "daemon status" : sub ? `daemon ${sub} [--timeout s]` : "daemon [--detach] [--timeout s]");
|
|
3820
3880
|
if (sub === "status") {
|
|
3821
3881
|
knownProfile(g);
|
|
3822
|
-
const client = await connectDaemon(g.paths
|
|
3882
|
+
const client = await connectDaemon(g.paths);
|
|
3823
3883
|
if (!client) {
|
|
3824
3884
|
print({
|
|
3825
3885
|
running: false,
|
|
@@ -3842,7 +3902,7 @@ async function daemonCommand(argv) {
|
|
|
3842
3902
|
if (sub === "stop") {
|
|
3843
3903
|
knownProfile(g);
|
|
3844
3904
|
const stopFor = seconds(parsed, 20);
|
|
3845
|
-
const client = await connectDaemon(g.paths
|
|
3905
|
+
const client = await connectDaemon(g.paths);
|
|
3846
3906
|
if (!client) throw new CliError("not_found", `No daemon runs profile ${g.profile}`);
|
|
3847
3907
|
print({
|
|
3848
3908
|
stopped: true,
|
|
@@ -3852,7 +3912,7 @@ async function daemonCommand(argv) {
|
|
|
3852
3912
|
}
|
|
3853
3913
|
if (sub === "restart") {
|
|
3854
3914
|
const stopFor = seconds(parsed, 20), startFor = seconds(parsed, 60);
|
|
3855
|
-
const client = await connectDaemon(g.paths
|
|
3915
|
+
const client = await connectDaemon(g.paths);
|
|
3856
3916
|
const before = client ? (await client.call("status").catch(() => null))?.version ?? null : null;
|
|
3857
3917
|
print({
|
|
3858
3918
|
restarted: true,
|
|
@@ -3883,7 +3943,19 @@ function seconds(parsed, fallback) {
|
|
|
3883
3943
|
* the lock a moment before it exits); its pid.
|
|
3884
3944
|
*/
|
|
3885
3945
|
async function stopDaemon(g, client, seconds) {
|
|
3886
|
-
|
|
3946
|
+
let pid;
|
|
3947
|
+
try {
|
|
3948
|
+
({pid} = await client.call("daemon.stop"));
|
|
3949
|
+
} catch (error) {
|
|
3950
|
+
if (!isNotTheDaemon(error)) throw error;
|
|
3951
|
+
const holder = lockOwner(g.paths);
|
|
3952
|
+
if (holder === null) throw error;
|
|
3953
|
+
process.stderr.write(`ghostly: what answers on the socket did not prove it is this profile's daemon (an older release's cannot): stopping the process that holds the profile (${holder}) with SIGTERM\n`);
|
|
3954
|
+
pid = holder;
|
|
3955
|
+
try {
|
|
3956
|
+
process.kill(pid, "SIGTERM");
|
|
3957
|
+
} catch {}
|
|
3958
|
+
}
|
|
3887
3959
|
client.close();
|
|
3888
3960
|
const until = Date.now() + seconds * 1e3;
|
|
3889
3961
|
const running = () => lockOwner(g.paths) === pid || processAlive(pid);
|
|
@@ -3907,7 +3979,7 @@ function processAlive(pid) {
|
|
|
3907
3979
|
/** A daemon in the background, running this command's code, once its socket answers. */
|
|
3908
3980
|
async function startDetached(g, seconds) {
|
|
3909
3981
|
requireProfile(g);
|
|
3910
|
-
if (await connectDaemon(g.paths
|
|
3982
|
+
if (await connectDaemon(g.paths)) throw new CliError("busy", `A daemon already runs profile ${g.profile}`);
|
|
3911
3983
|
heldBy(g);
|
|
3912
3984
|
const log = openSync(g.paths.log, "a", 384);
|
|
3913
3985
|
const child = spawn(process.execPath, [
|
|
@@ -3932,7 +4004,7 @@ async function startDetached(g, seconds) {
|
|
|
3932
4004
|
while (!client && Date.now() < until) {
|
|
3933
4005
|
if (child.exitCode !== null) break;
|
|
3934
4006
|
await new Promise((resolve) => setTimeout(resolve, 200));
|
|
3935
|
-
client = await connectDaemon(g.paths
|
|
4007
|
+
client = await connectDaemon(g.paths, 500);
|
|
3936
4008
|
}
|
|
3937
4009
|
if (!client) {
|
|
3938
4010
|
heldBy(g, child.pid);
|
|
@@ -4030,11 +4102,11 @@ async function listenCommand(argv) {
|
|
|
4030
4102
|
});
|
|
4031
4103
|
};
|
|
4032
4104
|
requireProfile(g);
|
|
4033
|
-
const client = await connectDaemon(g.paths
|
|
4105
|
+
const client = await connectDaemon(g.paths);
|
|
4034
4106
|
if (client) await warnVersion(client);
|
|
4035
4107
|
if (client) {
|
|
4036
4108
|
const handle = await start((m, p) => client.call(m, p), async (chat) => {
|
|
4037
|
-
const c = await connectDaemon(g.paths
|
|
4109
|
+
const c = await connectDaemon(g.paths, 1e3);
|
|
4038
4110
|
if (!c) return null;
|
|
4039
4111
|
try {
|
|
4040
4112
|
return (await c.call("chat.get", { chat })).peer || null;
|
|
@@ -4051,7 +4123,7 @@ async function listenCommand(argv) {
|
|
|
4051
4123
|
await new Promise((resolve) => setTimeout(resolve, wait));
|
|
4052
4124
|
wait = 1e3;
|
|
4053
4125
|
if (current || feed.paused) return;
|
|
4054
|
-
const next = await connectDaemon(g.paths
|
|
4126
|
+
const next = await connectDaemon(g.paths, 1e3);
|
|
4055
4127
|
if (next) {
|
|
4056
4128
|
current = next;
|
|
4057
4129
|
await follow(next).catch(() => {
|
|
@@ -4233,7 +4305,7 @@ async function textCommand(name, argv) {
|
|
|
4233
4305
|
};
|
|
4234
4306
|
if (spec.target === "group") params.mentions = parsed.options.mention ?? [];
|
|
4235
4307
|
if (parsed.options.reply !== void 0) params.reply = parsed.options.reply;
|
|
4236
|
-
if (!spec.message) Object.assign(params, (await import("./buttons-
|
|
4308
|
+
if (!spec.message) Object.assign(params, (await import("./buttons-CB1opfZP.js")).buttonsOf(parsed.options));
|
|
4237
4309
|
print(await withSession(g, (s) => {
|
|
4238
4310
|
if (spec.target === "chat") {
|
|
4239
4311
|
params.wait = parsed.options.wait ?? (s.mode === "one-shot" ? spec.message ? "confirmed" : "sent" : "none");
|
|
@@ -4291,10 +4363,10 @@ async function identityAddCommand(argv) {
|
|
|
4291
4363
|
if (event.type === "identity.approval" || event.type === "identity.progress") process.stderr.write(JSON.stringify(event) + "\n");
|
|
4292
4364
|
};
|
|
4293
4365
|
requireProfile(g);
|
|
4294
|
-
const client = await connectDaemon(g.paths
|
|
4366
|
+
const client = await connectDaemon(g.paths);
|
|
4295
4367
|
if (client) {
|
|
4296
4368
|
await warnVersion(client);
|
|
4297
|
-
const watcher = await connectDaemon(g.paths
|
|
4369
|
+
const watcher = await connectDaemon(g.paths);
|
|
4298
4370
|
await watcher?.subscribe(void 0, tell);
|
|
4299
4371
|
try {
|
|
4300
4372
|
print(await client.call("identity.add", params));
|
|
@@ -4369,7 +4441,7 @@ async function callPipeCommand(argv) {
|
|
|
4369
4441
|
const parsed = parseArgs(argv, {}, idSlot({ args: ["call...?"] }));
|
|
4370
4442
|
const g = globals(parsed);
|
|
4371
4443
|
const ref = parsed.positionals.join(" ") || void 0;
|
|
4372
|
-
const client = await connectDaemon(g.paths
|
|
4444
|
+
const client = await connectDaemon(g.paths);
|
|
4373
4445
|
if (!client) throw new CliError("unavailable", `No daemon runs profile ${g.profile}: calls need one (ghostly daemon --detach)`);
|
|
4374
4446
|
let call;
|
|
4375
4447
|
try {
|
|
@@ -4517,4 +4589,4 @@ async function run(argv) {
|
|
|
4517
4589
|
//#endregion
|
|
4518
4590
|
export { run };
|
|
4519
4591
|
|
|
4520
|
-
//# sourceMappingURL=main-
|
|
4592
|
+
//# sourceMappingURL=main-DiCC-Vjq.js.map
|