mirinjs 0.1.0-alpha.8 → 0.1.0-alpha.9

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.
Files changed (2) hide show
  1. package/package.json +1 -1
  2. package/src/updater.ts +37 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mirinjs",
3
- "version": "0.1.0-alpha.8",
3
+ "version": "0.1.0-alpha.9",
4
4
  "description": "Build desktop apps with Bun, TypeScript, and Chromium (CEF). The Bun-native Electron alternative.",
5
5
  "type": "module",
6
6
  "license": "MIT",
package/src/updater.ts CHANGED
@@ -221,8 +221,11 @@ export class Updater {
221
221
  // to exit (the exe/bundle is locked while running), swaps the folder, relaunches.
222
222
  if (IS_WINDOWS) {
223
223
  const runningApp = join(this.#resourcesDir()!, "..");
224
- const exe = join(runningApp, `${this.#version()!.name}.exe`);
225
- const script = join(tmpdir(), `mirin-apply-${this.#version()!.name}.ps1`);
224
+ const name = this.#version()!.name;
225
+ const exe = join(runningApp, `${name}.exe`);
226
+ const script = join(tmpdir(), `mirin-apply-${name}.ps1`);
227
+ const applyVbs = join(tmpdir(), `mirin-apply-${name}.vbs`);
228
+ const launchVbs = join(tmpdir(), `mirin-launch-${name}.vbs`);
226
229
  const ps = [
227
230
  `$ErrorActionPreference='SilentlyContinue'`,
228
231
  // Never let the app dir be this process's cwd (Windows can't delete a cwd).
@@ -235,22 +238,41 @@ export class Updater {
235
238
  `for ($i=0; $i -lt 50; $i++) { Remove-Item -Recurse -Force ${psq(runningApp)}; if (-not (Test-Path ${psq(runningApp)})) { break }; Start-Sleep -Milliseconds 200 }`,
236
239
  `Move-Item -Force ${psq(this.#staged)} ${psq(runningApp)}`,
237
240
  `Start-Process -FilePath ${psq(exe)} -WorkingDirectory ${psq(runningApp)}`,
238
- `Remove-Item -Force ${psq(script)}`, // self-clean
241
+ // self-clean the temp launch scripts (this .ps1 + the two .vbs shims)
242
+ `Remove-Item -Force ${psq(script)},${psq(applyVbs)},${psq(launchVbs)}`,
239
243
  ].join("\n");
240
244
  writeFileSync(script, ps, "utf8");
241
- // The swap MUST outlive this process. A Bun.spawn child is in our job object
242
- // and is killed when we quit — even with unref/detached (verified). So spawn
243
- // the swap via WMI Win32_Process.Create: the WMI service launches it, outside
244
- // our job, so it survives. `await` the short launcher so the swap process
245
- // exists before core.quit() (no race), then quit.
246
- const wmiPath = script.replace(/'/g, "''");
247
- const wmi =
248
- `([wmiclass]'Win32_Process').Create('powershell -NoProfile -NonInteractive ` +
249
- `-WindowStyle Hidden -ExecutionPolicy Bypass -File "${wmiPath}"') | Out-Null`;
250
- const launcher = Bun.spawn(
251
- ["powershell", "-NoProfile", "-NonInteractive", "-Command", wmi],
252
- { stdin: "ignore", stdout: "ignore", stderr: "ignore" },
245
+
246
+ // No terminal window may appear during the update. powershell.exe is a
247
+ // console-subsystem program: launching it directly (even with
248
+ // -WindowStyle Hidden) flashes a console, because the OS allocates the
249
+ // console before powershell can hide it. wscript.exe is a GUI-subsystem
250
+ // host with no console; its Shell.Run(cmd, 0) starts powershell with
251
+ // SW_HIDE in the initial STARTUPINFO, so no window is ever shown.
252
+ writeFileSync(
253
+ applyVbs,
254
+ `CreateObject("WScript.Shell").Run "powershell -NoProfile -NonInteractive ` +
255
+ `-ExecutionPolicy Bypass -WindowStyle Hidden -File ""${script}""", 0, False\n`,
256
+ "utf8",
257
+ );
258
+
259
+ // The swap MUST outlive this process. A Bun.spawn child is in our job
260
+ // object and is killed when we quit — even with unref/detached (verified).
261
+ // WMI's Win32_Process.Create has the WMI service spawn it, outside our job,
262
+ // so it survives. Issue that WMI call from a console-less wscript host too,
263
+ // so the launcher itself never flashes a window. `await` the short launcher
264
+ // so the swap process exists before core.quit() (no race), then quit.
265
+ writeFileSync(
266
+ launchVbs,
267
+ `GetObject("winmgmts:Win32_Process").Create ` +
268
+ `"wscript.exe //B //Nologo ""${applyVbs}""", Null, Null, pid\n`,
269
+ "utf8",
253
270
  );
271
+ const launcher = Bun.spawn(["wscript.exe", "//B", "//Nologo", launchVbs], {
272
+ stdin: "ignore",
273
+ stdout: "ignore",
274
+ stderr: "ignore",
275
+ });
254
276
  await launcher.exited;
255
277
  } else {
256
278
  const runningApp = join(this.#resourcesDir()!, "..", "..");