hatchee 0.1.3 → 0.1.5
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/cli.mjs +75 -24
- package/package.json +1 -1
package/dist/cli.mjs
CHANGED
|
@@ -11942,7 +11942,13 @@ class Daemon {
|
|
|
11942
11942
|
});
|
|
11943
11943
|
const hooks = createServer((req, res) => {
|
|
11944
11944
|
const url = req.url ?? "";
|
|
11945
|
-
|
|
11945
|
+
const ctEssence = String(req.headers["content-type"] ?? "").split(";")[0].trim().toLowerCase();
|
|
11946
|
+
const jsonPost = req.method === "POST" && ctEssence === "application/json";
|
|
11947
|
+
if (url === "/pair") {
|
|
11948
|
+
if (!jsonPost) {
|
|
11949
|
+
res.writeHead(415).end("expected application/json");
|
|
11950
|
+
return;
|
|
11951
|
+
}
|
|
11946
11952
|
try {
|
|
11947
11953
|
res.writeHead(200, { "content-type": "application/json" });
|
|
11948
11954
|
res.end(JSON.stringify(self.pairingPayload()));
|
|
@@ -11952,7 +11958,7 @@ class Daemon {
|
|
|
11952
11958
|
}
|
|
11953
11959
|
return;
|
|
11954
11960
|
}
|
|
11955
|
-
if (
|
|
11961
|
+
if (!jsonPost || url !== "/hook") {
|
|
11956
11962
|
res.writeHead(404).end("not found");
|
|
11957
11963
|
return;
|
|
11958
11964
|
}
|
|
@@ -12140,7 +12146,12 @@ function installHooks(droverBin) {
|
|
|
12140
12146
|
return settingsPath();
|
|
12141
12147
|
}
|
|
12142
12148
|
function isOurs(x) {
|
|
12143
|
-
|
|
12149
|
+
if (typeof x?.command !== "string")
|
|
12150
|
+
return false;
|
|
12151
|
+
const cmd = x.command.trimEnd();
|
|
12152
|
+
if (!/\bhook'?\s*$/.test(cmd))
|
|
12153
|
+
return false;
|
|
12154
|
+
return cmd.includes("hatchee") || cmd.includes("drover") || cmd.includes("daemon/src/cli.ts");
|
|
12144
12155
|
}
|
|
12145
12156
|
function uninstallHooks() {
|
|
12146
12157
|
if (!existsSync2(settingsPath()))
|
|
@@ -12158,12 +12169,22 @@ function uninstallHooks() {
|
|
|
12158
12169
|
function readStdin() {
|
|
12159
12170
|
return new Promise((resolve) => {
|
|
12160
12171
|
let data = "";
|
|
12172
|
+
let done = false;
|
|
12173
|
+
const finish = () => {
|
|
12174
|
+
if (!done) {
|
|
12175
|
+
done = true;
|
|
12176
|
+
resolve(data);
|
|
12177
|
+
}
|
|
12178
|
+
};
|
|
12161
12179
|
process.stdin.setEncoding("utf8");
|
|
12162
12180
|
process.stdin.on("data", (c) => {
|
|
12163
12181
|
data += c;
|
|
12164
12182
|
});
|
|
12165
|
-
process.stdin.on("end",
|
|
12166
|
-
setTimeout(() =>
|
|
12183
|
+
process.stdin.on("end", finish);
|
|
12184
|
+
setTimeout(() => {
|
|
12185
|
+
if (data === "")
|
|
12186
|
+
finish();
|
|
12187
|
+
}, 2000);
|
|
12167
12188
|
});
|
|
12168
12189
|
}
|
|
12169
12190
|
async function runHook(hookPort) {
|
|
@@ -12211,18 +12232,20 @@ var LABEL = "cloud.hatchee.daemon";
|
|
|
12211
12232
|
var PLIST = join3(HOME, "Library", "LaunchAgents", `${LABEL}.plist`);
|
|
12212
12233
|
var UNIT = join3(HOME, ".config", "systemd", "user", "hatchee.service");
|
|
12213
12234
|
function servicePath(node) {
|
|
12214
|
-
|
|
12235
|
+
const system = ["/usr/bin", "/bin", "/usr/sbin", "/sbin"];
|
|
12236
|
+
const userTool = [
|
|
12215
12237
|
dirname(node),
|
|
12216
|
-
join3(HOME, ".bun/bin"),
|
|
12217
|
-
join3(HOME, ".npm-global/bin"),
|
|
12218
|
-
join3(HOME, ".local/bin"),
|
|
12219
12238
|
"/opt/homebrew/bin",
|
|
12220
12239
|
"/usr/local/bin",
|
|
12221
|
-
"/
|
|
12222
|
-
"/bin",
|
|
12223
|
-
"/
|
|
12224
|
-
|
|
12225
|
-
|
|
12240
|
+
join3(HOME, ".bun/bin"),
|
|
12241
|
+
join3(HOME, ".npm-global/bin"),
|
|
12242
|
+
join3(HOME, ".local/bin")
|
|
12243
|
+
];
|
|
12244
|
+
const seen = new Set;
|
|
12245
|
+
return [...system, ...userTool].filter((p) => p && !seen.has(p) && seen.add(p)).join(":");
|
|
12246
|
+
}
|
|
12247
|
+
function xmlEsc(s) {
|
|
12248
|
+
return s.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
12226
12249
|
}
|
|
12227
12250
|
function copyStableBin() {
|
|
12228
12251
|
mkdirSync3(BIN_DIR, { recursive: true });
|
|
@@ -12233,7 +12256,7 @@ function copyStableBin() {
|
|
|
12233
12256
|
}
|
|
12234
12257
|
}
|
|
12235
12258
|
function plistContent(node, bin) {
|
|
12236
|
-
const args = [node, bin, "up"].map((s) => ` <string>${s}</string>`).join(`
|
|
12259
|
+
const args = [node, bin, "up"].map((s) => ` <string>${xmlEsc(s)}</string>`).join(`
|
|
12237
12260
|
`);
|
|
12238
12261
|
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
12239
12262
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
@@ -12247,10 +12270,10 @@ ${args}
|
|
|
12247
12270
|
<key>RunAtLoad</key><true/>
|
|
12248
12271
|
<key>KeepAlive</key><true/>
|
|
12249
12272
|
<key>ThrottleInterval</key><integer>10</integer>
|
|
12250
|
-
<key>StandardOutPath</key><string>${LOG}</string>
|
|
12251
|
-
<key>StandardErrorPath</key><string>${LOG}</string>
|
|
12273
|
+
<key>StandardOutPath</key><string>${xmlEsc(LOG)}</string>
|
|
12274
|
+
<key>StandardErrorPath</key><string>${xmlEsc(LOG)}</string>
|
|
12252
12275
|
<key>EnvironmentVariables</key>
|
|
12253
|
-
<dict><key>PATH</key><string>${servicePath(node)}</string></dict>
|
|
12276
|
+
<dict><key>PATH</key><string>${xmlEsc(servicePath(node))}</string></dict>
|
|
12254
12277
|
</dict>
|
|
12255
12278
|
</plist>
|
|
12256
12279
|
`;
|
|
@@ -12261,10 +12284,10 @@ Description=Hatchee — watch & approve your coding agents from your phone
|
|
|
12261
12284
|
After=network-online.target
|
|
12262
12285
|
|
|
12263
12286
|
[Service]
|
|
12264
|
-
ExecStart
|
|
12287
|
+
ExecStart="${node}" "${bin}" up
|
|
12265
12288
|
Restart=always
|
|
12266
12289
|
RestartSec=10
|
|
12267
|
-
Environment=PATH=${servicePath(node)}
|
|
12290
|
+
Environment="PATH=${servicePath(node)}"
|
|
12268
12291
|
|
|
12269
12292
|
[Install]
|
|
12270
12293
|
WantedBy=default.target
|
|
@@ -12273,12 +12296,22 @@ WantedBy=default.target
|
|
|
12273
12296
|
function run(cmd, args) {
|
|
12274
12297
|
try {
|
|
12275
12298
|
execFileSync(cmd, args, { stdio: "pipe" });
|
|
12299
|
+
return true;
|
|
12276
12300
|
} catch (e) {
|
|
12277
12301
|
console.log(` · ${cmd} ${args.join(" ")} → ${String(e?.stderr || e?.message || e).trim().slice(0, 200)}`);
|
|
12302
|
+
return false;
|
|
12278
12303
|
}
|
|
12279
12304
|
}
|
|
12280
12305
|
function installService(print = false) {
|
|
12281
12306
|
const node = process.execPath;
|
|
12307
|
+
const src = process.argv[1] ?? "";
|
|
12308
|
+
if (!print && src && !/\.(mjs|cjs|js)$/.test(src)) {
|
|
12309
|
+
console.log(`
|
|
12310
|
+
⚠ running from source (${src}); the service needs the built bundle.`);
|
|
12311
|
+
console.log(` use \`npx hatchee install-service\` for a real install.
|
|
12312
|
+
`);
|
|
12313
|
+
return;
|
|
12314
|
+
}
|
|
12282
12315
|
if (process.platform === "darwin") {
|
|
12283
12316
|
const content = plistContent(node, STABLE_BIN);
|
|
12284
12317
|
if (print) {
|
|
@@ -12296,8 +12329,15 @@ ${content}
|
|
|
12296
12329
|
writeFileSync3(PLIST, content);
|
|
12297
12330
|
const uid = String(process.getuid?.() ?? "");
|
|
12298
12331
|
run("launchctl", ["bootout", `gui/${uid}/${LABEL}`]);
|
|
12299
|
-
run("launchctl", ["bootstrap", `gui/${uid}`, PLIST]);
|
|
12332
|
+
const ok = run("launchctl", ["bootstrap", `gui/${uid}`, PLIST]);
|
|
12300
12333
|
run("launchctl", ["enable", `gui/${uid}/${LABEL}`]);
|
|
12334
|
+
if (!ok) {
|
|
12335
|
+
console.log(`
|
|
12336
|
+
⚠ wrote ${PLIST} but launchctl bootstrap failed (see the message above).`);
|
|
12337
|
+
console.log(` try manually: launchctl bootstrap gui/${uid} ${PLIST}
|
|
12338
|
+
`);
|
|
12339
|
+
return;
|
|
12340
|
+
}
|
|
12301
12341
|
console.log(`
|
|
12302
12342
|
✓ Hatchee will now run in the background (launchd: ${LABEL})`);
|
|
12303
12343
|
console.log(` logs ${LOG}`);
|
|
@@ -12324,8 +12364,15 @@ ${content}
|
|
|
12324
12364
|
mkdirSync3(dirname(UNIT), { recursive: true });
|
|
12325
12365
|
writeFileSync3(UNIT, content);
|
|
12326
12366
|
run("systemctl", ["--user", "daemon-reload"]);
|
|
12327
|
-
run("systemctl", ["--user", "enable", "--now", "hatchee.service"]);
|
|
12367
|
+
const ok = run("systemctl", ["--user", "enable", "--now", "hatchee.service"]);
|
|
12328
12368
|
run("loginctl", ["enable-linger", process.env.USER ?? ""]);
|
|
12369
|
+
if (!ok) {
|
|
12370
|
+
console.log(`
|
|
12371
|
+
⚠ wrote ${UNIT} but \`systemctl --user enable --now\` failed (see above).`);
|
|
12372
|
+
console.log(` is the user systemd bus available? try manually: systemctl --user enable --now hatchee.service
|
|
12373
|
+
`);
|
|
12374
|
+
return;
|
|
12375
|
+
}
|
|
12329
12376
|
console.log(`
|
|
12330
12377
|
✓ Hatchee will now run in the background (systemd --user: hatchee.service)`);
|
|
12331
12378
|
console.log(` logs journalctl --user -u hatchee.service -f`);
|
|
@@ -12361,7 +12408,7 @@ function uninstallService() {
|
|
|
12361
12408
|
}
|
|
12362
12409
|
|
|
12363
12410
|
// src/cli.ts
|
|
12364
|
-
var VERSION2 = "0.1.
|
|
12411
|
+
var VERSION2 = "0.1.5";
|
|
12365
12412
|
var cmd = process.argv[2] ?? "help";
|
|
12366
12413
|
switch (cmd) {
|
|
12367
12414
|
case "up": {
|
|
@@ -12473,7 +12520,11 @@ function banner() {
|
|
|
12473
12520
|
}
|
|
12474
12521
|
async function remotePair(hookPort) {
|
|
12475
12522
|
try {
|
|
12476
|
-
const r = await fetch(`http://127.0.0.1:${hookPort}/pair`, {
|
|
12523
|
+
const r = await fetch(`http://127.0.0.1:${hookPort}/pair`, {
|
|
12524
|
+
method: "POST",
|
|
12525
|
+
headers: { "content-type": "application/json" },
|
|
12526
|
+
signal: AbortSignal.timeout(2500)
|
|
12527
|
+
});
|
|
12477
12528
|
if (!r.ok)
|
|
12478
12529
|
return null;
|
|
12479
12530
|
const info = await r.json();
|
package/package.json
CHANGED