amaprice 1.0.14 → 1.0.15
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/package.json +1 -1
- package/src/background/service.js +72 -31
package/package.json
CHANGED
|
@@ -114,15 +114,17 @@ function isLaunchdSupported(platform = process.platform) {
|
|
|
114
114
|
return platform === 'darwin';
|
|
115
115
|
}
|
|
116
116
|
|
|
117
|
-
function
|
|
117
|
+
function getLaunchdDomains() {
|
|
118
118
|
if (typeof process.getuid !== 'function') {
|
|
119
119
|
throw new Error('launchd requires a POSIX uid');
|
|
120
120
|
}
|
|
121
|
-
|
|
121
|
+
const uid = process.getuid();
|
|
122
|
+
return [`gui/${uid}`, `user/${uid}`];
|
|
122
123
|
}
|
|
123
124
|
|
|
124
|
-
function buildServiceTarget(label) {
|
|
125
|
-
|
|
125
|
+
function buildServiceTarget(label, domain = null) {
|
|
126
|
+
const safeDomain = domain || getLaunchdDomains()[0];
|
|
127
|
+
return `${safeDomain}/${label}`;
|
|
126
128
|
}
|
|
127
129
|
|
|
128
130
|
async function runLaunchctl(args, { allowFailure = false } = {}) {
|
|
@@ -233,24 +235,38 @@ async function getLaunchdServiceStatus({ label }) {
|
|
|
233
235
|
backend: 'launchd',
|
|
234
236
|
label,
|
|
235
237
|
plistPath,
|
|
238
|
+
domain: null,
|
|
236
239
|
installed: false,
|
|
237
240
|
loaded: false,
|
|
238
241
|
running: false,
|
|
239
242
|
};
|
|
240
243
|
}
|
|
241
244
|
|
|
242
|
-
const
|
|
243
|
-
const
|
|
244
|
-
|
|
245
|
-
|
|
245
|
+
const domains = getLaunchdDomains();
|
|
246
|
+
for (const domain of domains) {
|
|
247
|
+
const print = await runLaunchctl(['print', buildServiceTarget(label, domain)], { allowFailure: true });
|
|
248
|
+
if (!print.ok) continue;
|
|
249
|
+
const output = `${print.stdout}\n${print.stderr}`;
|
|
250
|
+
const running = /state = running/i.test(output) || /pid = \d+/i.test(output);
|
|
251
|
+
return {
|
|
252
|
+
backend: 'launchd',
|
|
253
|
+
label,
|
|
254
|
+
plistPath,
|
|
255
|
+
domain,
|
|
256
|
+
installed: true,
|
|
257
|
+
loaded: true,
|
|
258
|
+
running,
|
|
259
|
+
};
|
|
260
|
+
}
|
|
246
261
|
|
|
247
262
|
return {
|
|
248
263
|
backend: 'launchd',
|
|
249
264
|
label,
|
|
250
265
|
plistPath,
|
|
266
|
+
domain: domains[0] || null,
|
|
251
267
|
installed: true,
|
|
252
|
-
loaded,
|
|
253
|
-
running,
|
|
268
|
+
loaded: false,
|
|
269
|
+
running: false,
|
|
254
270
|
};
|
|
255
271
|
}
|
|
256
272
|
|
|
@@ -263,7 +279,6 @@ async function enableLaunchdService({
|
|
|
263
279
|
const plistPath = getLaunchdPlistPath(label);
|
|
264
280
|
const logPath = getDaemonLogPath();
|
|
265
281
|
const daemonEntry = getDaemonEntryPath();
|
|
266
|
-
const target = buildServiceTarget(label);
|
|
267
282
|
|
|
268
283
|
await fs.mkdir(path.dirname(plistPath), { recursive: true });
|
|
269
284
|
await fs.mkdir(path.dirname(logPath), { recursive: true });
|
|
@@ -284,33 +299,53 @@ async function enableLaunchdService({
|
|
|
284
299
|
});
|
|
285
300
|
await fs.writeFile(plistPath, plist, 'utf8');
|
|
286
301
|
|
|
287
|
-
|
|
288
|
-
|
|
302
|
+
const domains = getLaunchdDomains();
|
|
303
|
+
const errors = [];
|
|
289
304
|
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
await runLaunchctl(['
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
if (!bootstrap.ok && !isAlreadyLoadedError(bootstrap)) {
|
|
298
|
-
throw new Error(`Could not bootstrap launchd service: ${bootstrap.stderr || bootstrap.stdout || 'unknown error'}`);
|
|
299
|
-
}
|
|
305
|
+
for (const domain of domains) {
|
|
306
|
+
const domainTarget = buildServiceTarget(label, domain);
|
|
307
|
+
|
|
308
|
+
// Clean stale state first, then bootstrap fresh.
|
|
309
|
+
await runLaunchctl(['bootout', domainTarget], { allowFailure: true });
|
|
310
|
+
await runLaunchctl(['disable', domainTarget], { allowFailure: true });
|
|
311
|
+
await runLaunchctl(['enable', domainTarget], { allowFailure: true });
|
|
300
312
|
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
313
|
+
let bootstrap = await runLaunchctl(['bootstrap', domain, plistPath], { allowFailure: true });
|
|
314
|
+
if (!bootstrap.ok && !isAlreadyLoadedError(bootstrap)) {
|
|
315
|
+
await runLaunchctl(['bootout', domainTarget], { allowFailure: true });
|
|
316
|
+
await runLaunchctl(['enable', domainTarget], { allowFailure: true });
|
|
317
|
+
bootstrap = await runLaunchctl(['bootstrap', domain, plistPath], { allowFailure: true });
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
if (!bootstrap.ok && !isAlreadyLoadedError(bootstrap)) {
|
|
321
|
+
errors.push(`${domain}: ${bootstrap.stderr || bootstrap.stdout || 'unknown error'}`);
|
|
322
|
+
continue;
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
await runLaunchctl(['enable', domainTarget], { allowFailure: true });
|
|
326
|
+
const kick = await runLaunchctl(['kickstart', '-k', domainTarget], { allowFailure: true });
|
|
327
|
+
if (!kick.ok) {
|
|
328
|
+
await runLaunchctl(['start', label], { allowFailure: true });
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
const status = await getLaunchdServiceStatus({ label });
|
|
332
|
+
if (status.loaded) {
|
|
333
|
+
return status;
|
|
334
|
+
}
|
|
335
|
+
errors.push(`${domain}: bootstrapped but service not loaded`);
|
|
305
336
|
}
|
|
306
337
|
|
|
307
|
-
|
|
338
|
+
const msg = errors.length > 0 ? errors.join(' | ') : 'unknown error';
|
|
339
|
+
throw new Error(`Could not bootstrap launchd service: ${msg}`);
|
|
308
340
|
}
|
|
309
341
|
|
|
310
342
|
async function disableLaunchdService({ label }) {
|
|
311
343
|
const plistPath = getLaunchdPlistPath(label);
|
|
312
|
-
|
|
313
|
-
|
|
344
|
+
for (const domain of getLaunchdDomains()) {
|
|
345
|
+
const target = buildServiceTarget(label, domain);
|
|
346
|
+
await runLaunchctl(['bootout', target], { allowFailure: true });
|
|
347
|
+
await runLaunchctl(['disable', target], { allowFailure: true });
|
|
348
|
+
}
|
|
314
349
|
try {
|
|
315
350
|
await fs.unlink(plistPath);
|
|
316
351
|
} catch (err) {
|
|
@@ -342,7 +377,7 @@ async function ensureBackgroundOn({
|
|
|
342
377
|
const { collector, statePath } = await ensureCollectorEnabled({
|
|
343
378
|
userId,
|
|
344
379
|
collectorName,
|
|
345
|
-
status: '
|
|
380
|
+
status: 'paused',
|
|
346
381
|
});
|
|
347
382
|
|
|
348
383
|
const service = await enableLaunchdService({
|
|
@@ -352,6 +387,10 @@ async function ensureBackgroundOn({
|
|
|
352
387
|
userId,
|
|
353
388
|
});
|
|
354
389
|
|
|
390
|
+
if (!service.loaded) {
|
|
391
|
+
throw new Error('launchd service did not load');
|
|
392
|
+
}
|
|
393
|
+
|
|
355
394
|
await heartbeatCollector({
|
|
356
395
|
collectorId: collector.id,
|
|
357
396
|
status: 'active',
|
|
@@ -510,6 +549,8 @@ module.exports.__test = {
|
|
|
510
549
|
resolvePollSeconds,
|
|
511
550
|
getLaunchdLabel,
|
|
512
551
|
getLaunchdPlistPath,
|
|
552
|
+
getLaunchdDomains,
|
|
553
|
+
buildServiceTarget,
|
|
513
554
|
renderLaunchdPlist,
|
|
514
555
|
isLaunchdSupported,
|
|
515
556
|
};
|