MCPcopy Create free account
hub / github.com/UsefulSoftwareCo/executor / makeLaunchdBackend

Function makeLaunchdBackend

apps/cli/src/service.ts:326–410  ·  view source on GitHub ↗
()

Source from the content-addressed store, hash-verified

324};
325
326const makeLaunchdBackend = (): ServiceBackend => {
327 const serviceTarget = (uid: number): string => `gui/${uid}/${SERVICE_LABEL}`;
328
329 return {
330 platform: "darwin",
331 automated: true,
332 install: (descriptor) =>
333 Effect.gen(function* () {
334 const fs = yield* FileSystem.FileSystem;
335 const path = yield* Path.Path;
336 const uid = currentUid();
337 const dataDir = resolveExecutorDataDir(path);
338 const logs = serviceLogDir(path);
339
340 yield* fs.makeDirectory(launchAgentsDir(path), { recursive: true });
341 yield* fs.makeDirectory(logs, { recursive: true });
342
343 const plist = generateLaunchdPlist({
344 label: SERVICE_LABEL,
345 programArguments: serviceProgramArguments(descriptor),
346 environment: serviceEnvironment(descriptor, dataDir),
347 stdoutPath: path.join(logs, "daemon.log"),
348 stderrPath: path.join(logs, "daemon.error.log"),
349 workingDirectory: dataDir,
350 });
351 const plistFile = launchdPlistPath(path);
352 // 0600: the plist is owner-only. It carries no secret — the daemon reads
353 // the bearer from auth.json at boot — but stays tight regardless.
354 yield* fs.writeFileString(plistFile, plist, { mode: 0o600 });
355
356 // Re-bootstrap cleanly: a stale registration from a prior install would
357 // make `bootstrap` fail with "service already loaded". `service
358 // uninstall` also records the label as disabled in launchd's override
359 // database; clear that before bootstrapping or a reinstall can fail with
360 // launchctl's generic "Bootstrap failed: 5" error.
361 yield* runCommand("launchctl", ["bootout", serviceTarget(uid)]).pipe(Effect.ignore);
362 yield* runCommand("launchctl", ["enable", serviceTarget(uid)]).pipe(Effect.ignore);
363 const bootstrap = yield* runCommand("launchctl", ["bootstrap", `gui/${uid}`, plistFile]);
364 if (bootstrap.code !== 0) {
365 return yield* Effect.fail(
366 new Error(
367 `launchctl bootstrap failed (exit ${bootstrap.code}): ${bootstrap.stderr.trim() || bootstrap.stdout.trim()}`,
368 ),
369 );
370 }
371 }),
372 uninstall: () =>
373 Effect.gen(function* () {
374 const fs = yield* FileSystem.FileSystem;
375 const path = yield* Path.Path;
376 const uid = currentUid();
377 yield* runCommand("launchctl", ["bootout", serviceTarget(uid)]).pipe(Effect.ignore);
378 yield* runCommand("launchctl", ["disable", serviceTarget(uid)]).pipe(Effect.ignore);
379 yield* fs.remove(launchdPlistPath(path), { force: true });
380 }),
381 status: () =>
382 Effect.gen(function* () {
383 const fs = yield* FileSystem.FileSystem;

Callers 1

getServiceBackendFunction · 0.85

Calls 12

resolveExecutorDataDirFunction · 0.90
serviceLogDirFunction · 0.85
launchAgentsDirFunction · 0.85
generateLaunchdPlistFunction · 0.85
serviceProgramArgumentsFunction · 0.85
serviceEnvironmentFunction · 0.85
launchdPlistPathFunction · 0.85
parseLaunchctlPidFunction · 0.85
currentUidFunction · 0.70
runCommandFunction · 0.70
serviceTargetFunction · 0.70
removeMethod · 0.65

Tested by

no test coverage detected