@webprodigies/morphite 0.2.1 → 0.2.2
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/bin/morphite.mjs +44 -7
- package/package.json +1 -1
package/bin/morphite.mjs
CHANGED
|
@@ -282,10 +282,13 @@ async function main() {
|
|
|
282
282
|
const destination = join(target, `${manifest.name}.app`)
|
|
283
283
|
const work = await mkdtemp(join(tmpdir(), 'morphite-installer-'))
|
|
284
284
|
const cleanup = () => rm(work, { recursive: true, force: true }).catch(() => undefined)
|
|
285
|
-
|
|
285
|
+
const stopped = () => {
|
|
286
286
|
live.done()
|
|
287
|
+
note('Stopped. Nothing was changed.', `Run npx ${PACKAGE}@latest again when you’re ready.`)
|
|
288
|
+
say('')
|
|
287
289
|
void cleanup().then(() => process.exit(130))
|
|
288
|
-
}
|
|
290
|
+
}
|
|
291
|
+
process.once('SIGINT', stopped)
|
|
289
292
|
// A problem after the download started: keep the last line where it stopped, then say what happened.
|
|
290
293
|
const stop = (title, detail) => {
|
|
291
294
|
live.done()
|
|
@@ -317,15 +320,49 @@ async function main() {
|
|
|
317
320
|
// Fetched by this program, the app carries no download mark; clear one defensively all the same.
|
|
318
321
|
await run('/usr/bin/xattr', ['-dr', 'com.apple.quarantine', candidate]).catch(() => undefined)
|
|
319
322
|
|
|
320
|
-
// Morphite must be closed before its app is replaced
|
|
323
|
+
// Morphite must be closed before its app is replaced. The person quits it from its menu, or
|
|
324
|
+
// presses Enter and the installer asks it to quit the normal way (never a forced stop, so its
|
|
325
|
+
// work ends cleanly). No keyboard shortcut is suggested: ⌘Q here would quit Terminal.
|
|
321
326
|
let open = await runningFrom([...installed, ...earlier])
|
|
322
327
|
if (open.length) {
|
|
323
328
|
const names = open.map((app) => basename(app, '.app')).join(' and ')
|
|
324
|
-
live.
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
329
|
+
live.clear()
|
|
330
|
+
note(
|
|
331
|
+
`${names} is open.`,
|
|
332
|
+
`Quit it from its menu bar (${names} → Quit), and this ${current ? 'update' : 'install'} continues on its own.`,
|
|
333
|
+
tty ? 'Or press Return to quit it now. Control-C stops without changing anything.' : 'Control-C stops without changing anything.'
|
|
334
|
+
)
|
|
335
|
+
say('')
|
|
336
|
+
const input = tty && process.stdin.isTTY ? process.stdin : null
|
|
337
|
+
const key = (data) => {
|
|
338
|
+
const text = String(data)
|
|
339
|
+
if (text.includes('\u0003')) return stopped()
|
|
340
|
+
if (!/[\r\n]/.test(text)) return
|
|
341
|
+
live.set(grey(`Quitting ${names}…`))
|
|
342
|
+
for (const app of open) {
|
|
343
|
+
const id = earlier.includes(app) ? EARLIER_APP_ID : manifest.bundleId
|
|
344
|
+
void run('/usr/bin/osascript', ['-e', `tell application id ${JSON.stringify(id)} to quit`]).catch(() => undefined)
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (input) {
|
|
348
|
+
input.setRawMode(true)
|
|
349
|
+
input.resume()
|
|
350
|
+
input.on('data', key)
|
|
351
|
+
}
|
|
352
|
+
live.set(grey(`Waiting for ${names} to quit…`))
|
|
353
|
+
try {
|
|
354
|
+
while (open.length) {
|
|
355
|
+
await new Promise((resolve) => setTimeout(resolve, 700))
|
|
356
|
+
open = await runningFrom([...installed, ...earlier])
|
|
357
|
+
}
|
|
358
|
+
} finally {
|
|
359
|
+
if (input) {
|
|
360
|
+
input.off('data', key)
|
|
361
|
+
input.setRawMode(false)
|
|
362
|
+
input.pause()
|
|
363
|
+
}
|
|
328
364
|
}
|
|
365
|
+
live.done(grey(`${names} quit`))
|
|
329
366
|
live.set(grey(`${current ? 'Updating' : 'Installing'} in ${place}…`))
|
|
330
367
|
}
|
|
331
368
|
|