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

Function makeLaunchdBackend

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

Source from the content-addressed store, hash-verified

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