theseus/bundled-addons/pithos/index.js

58 lines
2 KiB
JavaScript
Raw Normal View History

// Pithos for Theseus. The add-on runs the same control server as the web
// console and desktop app, in Theseus's main process, and opens its UI in a
// normal tab at a random loopback port. The first URL carries a one-time
// secret that the server swaps for an HttpOnly cookie.
//
// Loaded with require() by the add-on host; core/ is ESM, hence import().
const path = require("node:path");
const { pathToFileURL } = require("node:url");
let pithos = null;
let starting = null;
module.exports = {
activate(api) {
// The pinned s3d release lands in the per-add-on data folder, never in the
// add-on folder itself (that one is replaced on update).
const dataDir = path.join(api.dataDir || path.join(api.folder, "..", "..", "extensions-data"), "pithos");
async function ensureServer() {
if (pithos) return pithos;
if (!starting) {
starting = (async () => {
const { createPithos } = await import(pathToFileURL(path.join(__dirname, "core", "server.js")).href);
pithos = await createPithos({
host: "127.0.0.1",
port: 0,
hostName: "theseus",
binDir: path.join(dataDir, "bin"),
openExternal: (url) => api.openTab(url),
});
api.log(`control server on ${pithos.url}`);
return pithos;
})().finally(() => { starting = null; });
}
return starting;
}
api.onMessage("menu-select", async (payload) => {
const id = payload && payload.id;
if (id === "open") {
const p = await ensureServer();
api.openTab(p.authUrl);
} else if (id === "stop") {
if (pithos) await pithos.daemon.stop();
}
});
// The host has no quit hook for add-ons; without this an s3d we started
// would outlive Theseus.
process.on("exit", () => { try { pithos && pithos.daemon.child && pithos.daemon.child.kill(); } catch {} });
},
async deactivate() {
if (pithos) { const p = pithos; pithos = null; await p.close(); }
},
};