happy-stacks 0.1.2 → 0.3.0
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/README.md +164 -89
- package/bin/happys.mjs +70 -10
- package/docs/edison.md +381 -0
- package/docs/happy-development.md +733 -0
- package/docs/menubar.md +54 -0
- package/docs/paths-and-env.md +141 -0
- package/docs/stacks.md +39 -0
- package/extras/swiftbar/auth-login.sh +5 -2
- package/extras/swiftbar/git-cache-refresh.sh +130 -0
- package/extras/swiftbar/happy-stacks.5s.sh +131 -81
- package/extras/swiftbar/happys-term.sh +15 -38
- package/extras/swiftbar/happys.sh +15 -32
- package/extras/swiftbar/install.sh +99 -13
- package/extras/swiftbar/lib/git.sh +309 -1
- package/extras/swiftbar/lib/icons.sh +2 -2
- package/extras/swiftbar/lib/render.sh +209 -80
- package/extras/swiftbar/lib/system.sh +27 -4
- package/extras/swiftbar/lib/utils.sh +311 -28
- package/extras/swiftbar/pnpm.sh +2 -1
- package/extras/swiftbar/set-interval.sh +10 -5
- package/extras/swiftbar/set-server-flavor.sh +11 -2
- package/extras/swiftbar/wt-pr.sh +9 -2
- package/package.json +2 -1
- package/scripts/auth.mjs +521 -226
- package/scripts/build.mjs +29 -10
- package/scripts/cli-link.mjs +6 -6
- package/scripts/completion.mjs +18 -11
- package/scripts/daemon.mjs +133 -31
- package/scripts/dev.mjs +196 -137
- package/scripts/doctor.mjs +44 -55
- package/scripts/edison.mjs +1853 -0
- package/scripts/happy.mjs +10 -25
- package/scripts/init.mjs +46 -31
- package/scripts/install.mjs +21 -15
- package/scripts/lint.mjs +124 -0
- package/scripts/menubar.mjs +76 -10
- package/scripts/migrate.mjs +35 -35
- package/scripts/mobile.mjs +24 -17
- package/scripts/run.mjs +122 -35
- package/scripts/self.mjs +13 -35
- package/scripts/server_flavor.mjs +7 -7
- package/scripts/service.mjs +31 -28
- package/scripts/setup.mjs +694 -0
- package/scripts/setup_pr.mjs +165 -0
- package/scripts/stack.mjs +1851 -363
- package/scripts/stop.mjs +9 -6
- package/scripts/tailscale.mjs +23 -11
- package/scripts/test.mjs +123 -0
- package/scripts/tui.mjs +526 -0
- package/scripts/typecheck.mjs +10 -31
- package/scripts/ui_gateway.mjs +3 -3
- package/scripts/uninstall.mjs +21 -13
- package/scripts/utils/auth/dev_key.mjs +163 -0
- package/scripts/utils/auth/files.mjs +56 -0
- package/scripts/utils/auth/handy_master_secret.mjs +68 -0
- package/scripts/utils/auth/login_ux.mjs +76 -0
- package/scripts/utils/auth/sources.mjs +12 -0
- package/scripts/utils/{cli_registry.mjs → cli/cli_registry.mjs} +48 -0
- package/scripts/utils/cli/flags.mjs +17 -0
- package/scripts/utils/cli/normalize.mjs +16 -0
- package/scripts/utils/{smoke_help.mjs → cli/smoke_help.mjs} +2 -2
- package/scripts/utils/{wizard.mjs → cli/wizard.mjs} +1 -1
- package/scripts/utils/crypto/tokens.mjs +14 -0
- package/scripts/utils/dev/daemon.mjs +104 -0
- package/scripts/utils/dev/expo_web.mjs +112 -0
- package/scripts/utils/dev/server.mjs +183 -0
- package/scripts/utils/{config.mjs → env/config.mjs} +8 -3
- package/scripts/utils/{dotenv.mjs → env/dotenv.mjs} +3 -0
- package/scripts/utils/{env.mjs → env/env.mjs} +64 -13
- package/scripts/utils/{env_file.mjs → env/env_file.mjs} +38 -1
- package/scripts/utils/{env_local.mjs → env/env_local.mjs} +1 -0
- package/scripts/utils/env/read.mjs +30 -0
- package/scripts/utils/env/sandbox.mjs +14 -0
- package/scripts/utils/env/values.mjs +13 -0
- package/scripts/utils/{expo.mjs → expo/expo.mjs} +7 -11
- package/scripts/utils/fs/json.mjs +25 -0
- package/scripts/utils/fs/ops.mjs +29 -0
- package/scripts/utils/fs/package_json.mjs +8 -0
- package/scripts/utils/fs/tail.mjs +12 -0
- package/scripts/utils/git/refs.mjs +26 -0
- package/scripts/utils/{worktrees.mjs → git/worktrees.mjs} +60 -4
- package/scripts/utils/net/dns.mjs +10 -0
- package/scripts/utils/{ports.mjs → net/ports.mjs} +3 -5
- package/scripts/utils/paths/canonical_home.mjs +20 -0
- package/scripts/utils/paths/localhost_host.mjs +9 -0
- package/scripts/utils/{paths.mjs → paths/paths.mjs} +14 -8
- package/scripts/utils/{runtime.mjs → paths/runtime.mjs} +4 -4
- package/scripts/utils/proc/commands.mjs +34 -0
- package/scripts/utils/proc/ownership.mjs +135 -0
- package/scripts/utils/proc/package_scripts.mjs +31 -0
- package/scripts/utils/proc/pids.mjs +11 -0
- package/scripts/utils/proc/pm.mjs +317 -0
- package/scripts/utils/{proc.mjs → proc/proc.mjs} +30 -2
- package/scripts/utils/proc/watch.mjs +63 -0
- package/scripts/utils/{happy_server_infra.mjs → server/infra/happy_server_infra.mjs} +109 -94
- package/scripts/utils/server/port.mjs +68 -0
- package/scripts/utils/{server.mjs → server/server.mjs} +36 -0
- package/scripts/utils/server/urls.mjs +91 -0
- package/scripts/utils/{validate.mjs → server/validate.mjs} +1 -1
- package/scripts/utils/service/autostart_darwin.mjs +142 -0
- package/scripts/utils/stack/context.mjs +23 -0
- package/scripts/utils/stack/dirs.mjs +27 -0
- package/scripts/utils/stack/editor_workspace.mjs +152 -0
- package/scripts/utils/stack/names.mjs +12 -0
- package/scripts/utils/stack/runtime_state.mjs +87 -0
- package/scripts/utils/stack/stacks.mjs +45 -0
- package/scripts/utils/stack/startup.mjs +208 -0
- package/scripts/utils/{stack_stop.mjs → stack/stop.mjs} +85 -42
- package/scripts/utils/ui/browser.mjs +22 -0
- package/scripts/utils/ui/text.mjs +16 -0
- package/scripts/where.mjs +17 -10
- package/scripts/worktrees.mjs +110 -64
- package/scripts/utils/pm.mjs +0 -303
- /package/scripts/utils/{args.mjs → cli/args.mjs} +0 -0
- /package/scripts/utils/{cli.mjs → cli/cli.mjs} +0 -0
- /package/scripts/utils/{fs.mjs → fs/fs.mjs} +0 -0
package/scripts/utils/pm.mjs
DELETED
|
@@ -1,303 +0,0 @@
|
|
|
1
|
-
import { homedir } from 'node:os';
|
|
2
|
-
import { dirname, join, resolve, sep } from 'node:path';
|
|
3
|
-
import { existsSync } from 'node:fs';
|
|
4
|
-
import { chmod, mkdir, rm, stat, writeFile } from 'node:fs/promises';
|
|
5
|
-
|
|
6
|
-
import { pathExists } from './fs.mjs';
|
|
7
|
-
import { run, runCapture, spawnProc } from './proc.mjs';
|
|
8
|
-
import { getDefaultAutostartPaths, getHappyStacksHomeDir } from './paths.mjs';
|
|
9
|
-
import { resolveInstalledPath, resolveInstalledCliRoot } from './runtime.mjs';
|
|
10
|
-
|
|
11
|
-
async function commandExists(cmd, options = {}) {
|
|
12
|
-
try {
|
|
13
|
-
await runCapture(cmd, ['--version'], options);
|
|
14
|
-
return true;
|
|
15
|
-
} catch {
|
|
16
|
-
return false;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
export async function requirePnpm() {
|
|
21
|
-
if (await commandExists('pnpm')) {
|
|
22
|
-
return;
|
|
23
|
-
}
|
|
24
|
-
throw new Error(
|
|
25
|
-
'[local] pnpm is required to install dependencies for Happy Stacks.\n' +
|
|
26
|
-
'Install it via Corepack: `corepack enable && corepack prepare pnpm@latest --activate`'
|
|
27
|
-
);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
async function getComponentPm(dir) {
|
|
31
|
-
const yarnLock = join(dir, 'yarn.lock');
|
|
32
|
-
if (await pathExists(yarnLock)) {
|
|
33
|
-
// IMPORTANT: when happy-stacks itself is pinned to pnpm via Corepack, running `yarn`
|
|
34
|
-
// from the happy-stacks cwd can be blocked. Always probe yarn with cwd=componentDir.
|
|
35
|
-
if (!(await commandExists('yarn', { cwd: dir }))) {
|
|
36
|
-
throw new Error(`[local] yarn is required for component at ${dir} (yarn.lock present). Install it via Corepack: \`corepack enable\``);
|
|
37
|
-
}
|
|
38
|
-
return { name: 'yarn', cmd: 'yarn' };
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
// Default fallback if no yarn.lock: use pnpm.
|
|
42
|
-
await requirePnpm();
|
|
43
|
-
return { name: 'pnpm', cmd: 'pnpm' };
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
export async function requireDir(label, dir) {
|
|
47
|
-
if (await pathExists(dir)) {
|
|
48
|
-
return;
|
|
49
|
-
}
|
|
50
|
-
throw new Error(
|
|
51
|
-
`[local] missing ${label} at ${dir}\n` +
|
|
52
|
-
`Run: happys bootstrap (auto-clones missing components), or place the repo under components/`
|
|
53
|
-
);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
export async function ensureDepsInstalled(dir, label) {
|
|
57
|
-
const pkgJson = join(dir, 'package.json');
|
|
58
|
-
if (!(await pathExists(pkgJson))) {
|
|
59
|
-
return;
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
const nodeModules = join(dir, 'node_modules');
|
|
63
|
-
const pnpmModulesMeta = join(dir, 'node_modules', '.modules.yaml');
|
|
64
|
-
const pm = await getComponentPm(dir);
|
|
65
|
-
|
|
66
|
-
if (await pathExists(nodeModules)) {
|
|
67
|
-
const yarnLock = join(dir, 'yarn.lock');
|
|
68
|
-
const yarnIntegrity = join(nodeModules, '.yarn-integrity');
|
|
69
|
-
const pnpmLock = join(dir, 'pnpm-lock.yaml');
|
|
70
|
-
|
|
71
|
-
// If this repo is Yarn-managed (yarn.lock present) but node_modules was created by pnpm,
|
|
72
|
-
// reinstall with Yarn to restore upstream-locked dependency versions.
|
|
73
|
-
if (pm.name === 'yarn' && (await pathExists(pnpmModulesMeta))) {
|
|
74
|
-
// eslint-disable-next-line no-console
|
|
75
|
-
console.log(`[local] converting ${label} dependencies back to yarn (reinstalling node_modules)...`);
|
|
76
|
-
await rm(nodeModules, { recursive: true, force: true });
|
|
77
|
-
await run(pm.cmd, ['install'], { cwd: dir });
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
// If dependencies changed since the last install, re-run install even if node_modules exists.
|
|
81
|
-
const mtimeMs = async (p) => {
|
|
82
|
-
try {
|
|
83
|
-
const s = await stat(p);
|
|
84
|
-
return s.mtimeMs ?? 0;
|
|
85
|
-
} catch {
|
|
86
|
-
return 0;
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
|
|
90
|
-
if (pm.name === 'yarn' && (await pathExists(yarnLock))) {
|
|
91
|
-
const lockM = await mtimeMs(yarnLock);
|
|
92
|
-
const pkgM = await mtimeMs(pkgJson);
|
|
93
|
-
const intM = await mtimeMs(yarnIntegrity);
|
|
94
|
-
if (!intM || lockM > intM || pkgM > intM) {
|
|
95
|
-
// eslint-disable-next-line no-console
|
|
96
|
-
console.log(`[local] refreshing ${label} dependencies (yarn.lock/package.json changed)...`);
|
|
97
|
-
await run(pm.cmd, ['install'], { cwd: dir });
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (pm.name === 'pnpm' && (await pathExists(pnpmLock))) {
|
|
102
|
-
const lockM = await mtimeMs(pnpmLock);
|
|
103
|
-
const metaM = await mtimeMs(pnpmModulesMeta);
|
|
104
|
-
if (!metaM || lockM > metaM) {
|
|
105
|
-
// eslint-disable-next-line no-console
|
|
106
|
-
console.log(`[local] refreshing ${label} dependencies (pnpm-lock changed)...`);
|
|
107
|
-
await run(pm.cmd, ['install'], { cwd: dir });
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
|
|
111
|
-
return;
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// eslint-disable-next-line no-console
|
|
115
|
-
console.log(`[local] installing ${label} dependencies (first run)...`);
|
|
116
|
-
await run(pm.cmd, ['install'], { cwd: dir });
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export async function ensureCliBuilt(cliDir, { buildCli }) {
|
|
120
|
-
await ensureDepsInstalled(cliDir, 'happy-cli');
|
|
121
|
-
if (!buildCli) {
|
|
122
|
-
return;
|
|
123
|
-
}
|
|
124
|
-
// eslint-disable-next-line no-console
|
|
125
|
-
console.log('[local] building happy-cli...');
|
|
126
|
-
const pm = await getComponentPm(cliDir);
|
|
127
|
-
await run(pm.cmd, ['build'], { cwd: cliDir });
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
function getPathEntries() {
|
|
131
|
-
const raw = process.env.PATH ?? '';
|
|
132
|
-
const delimiter = process.platform === 'win32' ? ';' : ':';
|
|
133
|
-
return raw.split(delimiter).filter(Boolean);
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
function isPathInside(path, dir) {
|
|
137
|
-
const p = resolve(path);
|
|
138
|
-
const d = resolve(dir);
|
|
139
|
-
return p === d || p.startsWith(d.endsWith(sep) ? d : d + sep);
|
|
140
|
-
}
|
|
141
|
-
|
|
142
|
-
export async function ensureHappyCliLocalNpmLinked(rootDir, { npmLinkCli }) {
|
|
143
|
-
if (!npmLinkCli) {
|
|
144
|
-
return;
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
const homeDir = getHappyStacksHomeDir();
|
|
148
|
-
const binDir = join(homeDir, 'bin');
|
|
149
|
-
await mkdir(binDir, { recursive: true });
|
|
150
|
-
|
|
151
|
-
const happysShim = join(binDir, 'happys');
|
|
152
|
-
const happyShim = join(binDir, 'happy');
|
|
153
|
-
|
|
154
|
-
const shim = `#!/bin/bash
|
|
155
|
-
set -euo pipefail
|
|
156
|
-
HOME_DIR="\${HAPPY_STACKS_HOME_DIR:-$HOME/.happy-stacks}"
|
|
157
|
-
HAPPYS="$HOME_DIR/bin/happys"
|
|
158
|
-
if [[ -x "$HAPPYS" ]]; then
|
|
159
|
-
exec "$HAPPYS" happy "$@"
|
|
160
|
-
fi
|
|
161
|
-
exec happys happy "$@"
|
|
162
|
-
`;
|
|
163
|
-
|
|
164
|
-
await writeFile(happyShim, shim, 'utf-8');
|
|
165
|
-
await chmod(happyShim, 0o755).catch(() => {});
|
|
166
|
-
|
|
167
|
-
// eslint-disable-next-line no-console
|
|
168
|
-
console.log(`[local] installed 'happy' shim at ${happyShim}`);
|
|
169
|
-
if (!existsSync(happysShim)) {
|
|
170
|
-
// eslint-disable-next-line no-console
|
|
171
|
-
console.log(`[local] note: run \`happys init\` to install a stable ${happysShim} shim for services/SwiftBar.`);
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
export async function pmSpawnScript({ label, dir, script, env, options = {} }) {
|
|
176
|
-
const pm = await getComponentPm(dir);
|
|
177
|
-
if (pm.name === 'yarn') {
|
|
178
|
-
return spawnProc(label, pm.cmd, ['-s', script], env, { ...options, cwd: dir });
|
|
179
|
-
}
|
|
180
|
-
return spawnProc(label, pm.cmd, ['--silent', script], env, { ...options, cwd: dir });
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
export async function pmSpawnBin({ label, dir, bin, args, env, options = {} }) {
|
|
184
|
-
const pm = await getComponentPm(dir);
|
|
185
|
-
if (pm.name === 'yarn') {
|
|
186
|
-
return spawnProc(label, pm.cmd, [bin, ...args], env, { ...options, cwd: dir });
|
|
187
|
-
}
|
|
188
|
-
return spawnProc(label, pm.cmd, ['exec', bin, ...args], env, { ...options, cwd: dir });
|
|
189
|
-
}
|
|
190
|
-
|
|
191
|
-
export async function pmExecBin({ dir, bin, args, env }) {
|
|
192
|
-
const pm = await getComponentPm(dir);
|
|
193
|
-
if (pm.name === 'yarn') {
|
|
194
|
-
await run(pm.cmd, [bin, ...args], { env, cwd: dir });
|
|
195
|
-
return;
|
|
196
|
-
}
|
|
197
|
-
await run(pm.cmd, ['exec', bin, ...args], { env, cwd: dir });
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
export async function ensureMacAutostartEnabled({ rootDir, label = 'com.happy.local', env = {} }) {
|
|
201
|
-
if (process.platform !== 'darwin') {
|
|
202
|
-
throw new Error('[local] autostart is currently only implemented for macOS (LaunchAgents).');
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
const {
|
|
206
|
-
logsDir,
|
|
207
|
-
stdoutPath,
|
|
208
|
-
stderrPath,
|
|
209
|
-
plistPath,
|
|
210
|
-
primaryLabel,
|
|
211
|
-
legacyLabel,
|
|
212
|
-
primaryPlistPath,
|
|
213
|
-
legacyPlistPath,
|
|
214
|
-
primaryStdoutPath,
|
|
215
|
-
primaryStderrPath,
|
|
216
|
-
legacyStdoutPath,
|
|
217
|
-
legacyStderrPath,
|
|
218
|
-
} = getDefaultAutostartPaths();
|
|
219
|
-
await mkdir(logsDir, { recursive: true });
|
|
220
|
-
|
|
221
|
-
const nodePath = process.env.HAPPY_STACKS_NODE?.trim()
|
|
222
|
-
? process.env.HAPPY_STACKS_NODE.trim()
|
|
223
|
-
: process.env.HAPPY_LOCAL_NODE?.trim()
|
|
224
|
-
? process.env.HAPPY_LOCAL_NODE.trim()
|
|
225
|
-
: process.execPath;
|
|
226
|
-
const installedRoot = resolveInstalledCliRoot(rootDir);
|
|
227
|
-
const happysEntrypoint = resolveInstalledPath(rootDir, join('bin', 'happys.mjs'));
|
|
228
|
-
const happysShim = join(getHappyStacksHomeDir(), 'bin', 'happys');
|
|
229
|
-
const useShim = existsSync(happysShim);
|
|
230
|
-
|
|
231
|
-
// Ensure we write to the plist path that matches the label we're installing, instead of the
|
|
232
|
-
// "active" plist path (which might be legacy and cause filename/label mismatches).
|
|
233
|
-
const resolvedPlistPath =
|
|
234
|
-
label === primaryLabel ? primaryPlistPath : label === legacyLabel ? legacyPlistPath : join(homedir(), 'Library', 'LaunchAgents', `${label}.plist`);
|
|
235
|
-
const resolvedStdoutPath = label === primaryLabel ? primaryStdoutPath : label === legacyLabel ? legacyStdoutPath : stdoutPath;
|
|
236
|
-
const resolvedStderrPath = label === primaryLabel ? primaryStderrPath : label === legacyLabel ? legacyStderrPath : stderrPath;
|
|
237
|
-
|
|
238
|
-
const plist = `<?xml version="1.0" encoding="UTF-8"?>
|
|
239
|
-
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
240
|
-
<plist version="1.0">
|
|
241
|
-
<dict>
|
|
242
|
-
<key>Label</key>
|
|
243
|
-
<string>${label}</string>
|
|
244
|
-
<key>ProgramArguments</key>
|
|
245
|
-
<array>
|
|
246
|
-
${useShim ? `<string>${happysShim}</string>` : `<string>${nodePath}</string>\n <string>${happysEntrypoint}</string>`}
|
|
247
|
-
<string>start</string>
|
|
248
|
-
</array>
|
|
249
|
-
<key>WorkingDirectory</key>
|
|
250
|
-
<string>${installedRoot}</string>
|
|
251
|
-
<key>RunAtLoad</key>
|
|
252
|
-
<true/>
|
|
253
|
-
<key>KeepAlive</key>
|
|
254
|
-
<true/>
|
|
255
|
-
<key>StandardOutPath</key>
|
|
256
|
-
<string>${resolvedStdoutPath}</string>
|
|
257
|
-
<key>StandardErrorPath</key>
|
|
258
|
-
<string>${resolvedStderrPath}</string>
|
|
259
|
-
<key>EnvironmentVariables</key>
|
|
260
|
-
<dict>
|
|
261
|
-
${Object.entries(env)
|
|
262
|
-
.map(([k, v]) => ` <key>${k}</key>\n <string>${String(v)}</string>`)
|
|
263
|
-
.join('\n')}
|
|
264
|
-
</dict>
|
|
265
|
-
</dict>
|
|
266
|
-
</plist>
|
|
267
|
-
`;
|
|
268
|
-
|
|
269
|
-
await mkdir(dirname(resolvedPlistPath), { recursive: true });
|
|
270
|
-
await writeFile(resolvedPlistPath, plist, 'utf-8');
|
|
271
|
-
|
|
272
|
-
// Best-effort (works on most macOS setups). If it fails, the plist still exists and can be loaded manually.
|
|
273
|
-
try {
|
|
274
|
-
await run('launchctl', ['unload', '-w', resolvedPlistPath]);
|
|
275
|
-
} catch {
|
|
276
|
-
// ignore
|
|
277
|
-
}
|
|
278
|
-
await run('launchctl', ['load', '-w', resolvedPlistPath]);
|
|
279
|
-
}
|
|
280
|
-
|
|
281
|
-
export async function ensureMacAutostartDisabled({ label = 'com.happy.local' }) {
|
|
282
|
-
if (process.platform !== 'darwin') {
|
|
283
|
-
return;
|
|
284
|
-
}
|
|
285
|
-
const { primaryLabel, legacyLabel, primaryPlistPath, legacyPlistPath } = getDefaultAutostartPaths();
|
|
286
|
-
const resolvedPlistPath =
|
|
287
|
-
label === primaryLabel ? primaryPlistPath : label === legacyLabel ? legacyPlistPath : join(homedir(), 'Library', 'LaunchAgents', `${label}.plist`);
|
|
288
|
-
try {
|
|
289
|
-
await run('launchctl', ['unload', '-w', resolvedPlistPath]);
|
|
290
|
-
} catch {
|
|
291
|
-
// Old-style unload can fail on newer macOS; fall back to modern bootout.
|
|
292
|
-
try {
|
|
293
|
-
const uid = typeof process.getuid === 'function' ? process.getuid() : null;
|
|
294
|
-
if (uid != null) {
|
|
295
|
-
await run('launchctl', ['bootout', `gui/${uid}/${label}`]);
|
|
296
|
-
}
|
|
297
|
-
} catch {
|
|
298
|
-
// ignore
|
|
299
|
-
}
|
|
300
|
-
}
|
|
301
|
-
// eslint-disable-next-line no-console
|
|
302
|
-
console.log(`[local] autostart disabled (${label})`);
|
|
303
|
-
}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|