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

Function makeLaunchdBackend

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

Source from the content-addressed store, hash-verified

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