History

chore(deps): bump Electron to 44.1.0

Electron 44 turns clipboard.writeText into a Promise and removes clipboard.writeImage in favour of clipboard.write with ClipboardItem, so the shell and preview manager follow. node-abi is pinned to a release that knows the new Electron ABI so prebuilt native modules resolve during packaging, and the release-age policy excludes this exact version.

Julius Marminge committed 2 months ago

Commit 82bc5b61 parent 0d345797 files · +93 −27Browse files

Unified · Split

7 files
  1. apps/desktop/package.json +1 −1
  2. apps/desktop/src/electron/ElectronShell.test.ts +22 −0
  3. apps/desktop/src/electron/ElectronShell.ts +1 −3
  4. apps/desktop/src/preview/Manager.test.ts +36 −7
  5. apps/desktop/src/preview/Manager.ts +17 −3
  6. pnpm-lock.yaml +14 −13
  7. pnpm-workspace.yaml +2 −0
apps/desktop/package.json+1−1
@@ -22,7 +22,7 @@ · 21 unmodified lines
22 "@t3tools/ssh": "workspace:*",22 "@t3tools/ssh": "workspace:*",
23 "@t3tools/tailscale": "workspace:*",23 "@t3tools/tailscale": "workspace:*",
24 "effect": "catalog:",24 "effect": "catalog:",
25 "electron": "43.4.1",25 "electron": "44.1.0",
26 "electron-store": "^8.2.0",26 "electron-store": "^8.2.0",
27 "electron-updater": "^6.6.2",27 "electron-updater": "^6.6.2",
28 "playwright-core": "1.60.0",28 "playwright-core": "1.60.0",
apps/desktop/src/electron/ElectronShell.test.ts+22−0
@@ -36,6 +36,28 @@ describe("ElectronShell", () => { · 35 unmodified lines
36 }).pipe(Effect.provide(ElectronShell.layer)),36 }).pipe(Effect.provide(ElectronShell.layer)),
37 );37 );
38 38
39 it.effect("copies text to the system clipboard", () =>
40 Effect.gen(function* () {
41 writeTextMock.mockResolvedValue(undefined);
42
43 const electronShell = yield* ElectronShell.ElectronShell;
44 yield* electronShell.copyText("https://example.com/path");
45
46 assert.deepEqual(writeTextMock.mock.calls, [["https://example.com/path"]]);
47 }).pipe(Effect.provide(ElectronShell.layer)),
48 );
49
50 it.effect("does not fail when the clipboard write rejects", () =>
51 Effect.gen(function* () {
52 writeTextMock.mockRejectedValue(new Error("write failed"));
53
54 const electronShell = yield* ElectronShell.ElectronShell;
55 yield* electronShell.copyText("https://example.com/path");
56
57 assert.deepEqual(writeTextMock.mock.calls, [["https://example.com/path"]]);
58 }).pipe(Effect.provide(ElectronShell.layer)),
59 );
60
39 it.effect("opens the Full Disk Access settings anchor", () =>61 it.effect("opens the Full Disk Access settings anchor", () =>
40 Effect.gen(function* () {62 Effect.gen(function* () {
41 openExternalMock.mockResolvedValue(undefined);63 openExternalMock.mockResolvedValue(undefined);
apps/desktop/src/electron/ElectronShell.ts+1−3
@@ -87,9 +87,7 @@ export const make = ElectronShell.of({ · 86 unmodified lines
87 ),87 ),
88 ),88 ),
89 copyText: (text) =>89 copyText: (text) =>
90 Effect.sync(() => {90 Effect.promise(() => Electron.clipboard.writeText(text).catch(() => undefined)),
91 Electron.clipboard.writeText(text);
92 }),
93});91});
94 92
95export const layer = Layer.succeed(ElectronShell, make);93export const layer = Layer.succeed(ElectronShell, make);
apps/desktop/src/preview/Manager.test.ts+36−7
@@ -113,6 +113,7 @@ describe("previewWindowOpenAction", () => { · 112 unmodified lines
113 113
114const {114const {
115 browserWindowConstructor,115 browserWindowConstructor,
116 clipboardItemConstructor,
116 createFromPath,117 createFromPath,
117 fromId,118 fromId,
118 getFocusedWebContents,119 getFocusedWebContents,
@@ -120,23 +121,32 @@ const { · 1 unmodified line
120 showItemInFolder,121 showItemInFolder,
121 webviewSend,122 webviewSend,
122 writeFile,123 writeFile,
123 writeImage,124 writeClipboard,
124} = vi.hoisted(() => ({125} = vi.hoisted(() => ({
125 browserWindowConstructor: vi.fn(),126 browserWindowConstructor: vi.fn(),
126 createFromPath: vi.fn((): { readonly isEmpty: () => boolean } => ({ isEmpty: () => false })),127 clipboardItemConstructor: vi.fn(),
128 createFromPath: vi.fn((): { readonly isEmpty: () => boolean; readonly toPNG: () => Buffer } => ({
129 isEmpty: () => false,
130 toPNG: () => Buffer.from("png"),
131 })),
127 fromId: vi.fn<(_id?: number) => Electron.WebContents | null>((_id?: number) => null),132 fromId: vi.fn<(_id?: number) => Electron.WebContents | null>((_id?: number) => null),
128 getFocusedWebContents: vi.fn(() => null),133 getFocusedWebContents: vi.fn(() => null),
129 mkdir: vi.fn((_path: string) => undefined),134 mkdir: vi.fn((_path: string) => undefined),
130 showItemInFolder: vi.fn(),135 showItemInFolder: vi.fn(),
131 webviewSend: vi.fn(),136 webviewSend: vi.fn(),
132 writeFile: vi.fn((_path: string, _data: Uint8Array) => undefined),137 writeFile: vi.fn((_path: string, _data: Uint8Array) => undefined),
133 writeImage: vi.fn(),138 writeClipboard: vi.fn(async () => undefined),
134}));139}));
135 140
136vi.mock("electron", () => ({141vi.mock("electron", () => ({
137 BrowserWindow: browserWindowConstructor,142 BrowserWindow: browserWindowConstructor,
143 ClipboardItem: class {
144 constructor(data: Record<string, unknown>) {
145 clipboardItemConstructor(data);
146 }
147 },
138 clipboard: {148 clipboard: {
139 writeImage,149 write: writeClipboard,
140 },150 },
141 nativeImage: {151 nativeImage: {
142 createFromPath,152 createFromPath,
@@ -471,7 +481,8 @@ describe("PreviewManager", () => { · 328 unmodified lines
471 mkdir.mockClear();481 mkdir.mockClear();
472 writeFile.mockClear();482 writeFile.mockClear();
473 showItemInFolder.mockClear();483 showItemInFolder.mockClear();
474 writeImage.mockClear();484 clipboardItemConstructor.mockClear();
485 writeClipboard.mockClear();
475 createFromPath.mockClear();486 createFromPath.mockClear();
476 webviewSend.mockClear();487 webviewSend.mockClear();
477 });488 });
@@ -3671,7 +3682,10 @@ describe("PreviewManager", () => { · 3193 unmodified lines
3671 yield* manager.copyArtifactToClipboard(artifactPath);3682 yield* manager.copyArtifactToClipboard(artifactPath);
3672 3683
3673 expect(createFromPath).toHaveBeenCalledWith(artifactPath);3684 expect(createFromPath).toHaveBeenCalledWith(artifactPath);
3674 expect(writeImage).toHaveBeenCalledOnce();3685 expect(clipboardItemConstructor).toHaveBeenCalledWith({
3686 "image/png": expect.any(Blob),
3687 });
3688 expect(writeClipboard).toHaveBeenCalledOnce();
3675 const exit = yield* Effect.exit(3689 const exit = yield* Effect.exit(
3676 manager.copyArtifactToClipboard("/tmp/t3/dev/settings.json"),3690 manager.copyArtifactToClipboard("/tmp/t3/dev/settings.json"),
3677 );3691 );
@@ -3685,7 +3699,10 @@ describe("PreviewManager", () => { · 7 unmodified lines
3685 });3699 });
3686 expect("cause" in error).toBe(false);3700 expect("cause" in error).toBe(false);
3687 3701
3688 createFromPath.mockReturnValueOnce({ isEmpty: () => true });3702 createFromPath.mockReturnValueOnce({
3703 isEmpty: () => true,
3704 toPNG: () => Buffer.from("invalid"),
3705 });
3689 const invalidImageExit = yield* Effect.exit(manager.copyArtifactToClipboard(artifactPath));3706 const invalidImageExit = yield* Effect.exit(manager.copyArtifactToClipboard(artifactPath));
3690 expect(Exit.isFailure(invalidImageExit)).toBe(true);3707 expect(Exit.isFailure(invalidImageExit)).toBe(true);
3691 if (Exit.isSuccess(invalidImageExit)) return;3708 if (Exit.isSuccess(invalidImageExit)) return;
@@ -3693,6 +3710,18 @@ describe("PreviewManager", () => { · 1 unmodified line
3693 _tag: "PreviewArtifactImageLoadError",3710 _tag: "PreviewArtifactImageLoadError",
3694 artifactPath,3711 artifactPath,
3695 });3712 });
3713
3714 const writeCause = new Error("clipboard write failed");
3715 writeClipboard.mockRejectedValueOnce(writeCause);
3716 const writeExit = yield* Effect.exit(manager.copyArtifactToClipboard(artifactPath));
3717 expect(Exit.isFailure(writeExit)).toBe(true);
3718 if (Exit.isSuccess(writeExit)) return;
3719 expect(Option.getOrThrow(Cause.findErrorOption(writeExit.cause))).toMatchObject({
3720 _tag: "PreviewOperationError",
3721 operation: "copyArtifactToClipboard.write",
3722 artifactPath,
3723 cause: writeCause,
3724 });
3696 }),3725 }),
3697 ),3726 ),
3698 );3727 );
apps/desktop/src/preview/Manager.ts+17−3
@@ -32,7 +32,15 @@ import type { · 31 unmodified lines
32} from "@t3tools/contracts";32} from "@t3tools/contracts";
33import { HostProcessPlatform } from "@t3tools/shared/hostProcess";33import { HostProcessPlatform } from "@t3tools/shared/hostProcess";
34import { normalizePreviewUrl } from "@t3tools/shared/preview";34import { normalizePreviewUrl } from "@t3tools/shared/preview";
35import { BrowserWindow, type Session, clipboard, nativeImage, shell, webContents } from "electron";35import {
36 BrowserWindow,
37 ClipboardItem,
38 type Session,
39 clipboard,
40 nativeImage,
41 shell,
42 webContents,
43} from "electron";
36import * as Cause from "effect/Cause";44import * as Cause from "effect/Cause";
37import * as Clock from "effect/Clock";45import * as Clock from "effect/Clock";
38import * as Context from "effect/Context";46import * as Context from "effect/Context";
@@ -4107,8 +4115,14 @@ const makeNativeOperations = Effect.fn("PreviewManager.makeOperations")(function · 4068 unmodified lines
4107 if (image.isEmpty()) {4115 if (image.isEmpty()) {
4108 return yield* new PreviewArtifactImageLoadError({ artifactPath: resolvedPath });4116 return yield* new PreviewArtifactImageLoadError({ artifactPath: resolvedPath });
4109 }4117 }
4110 yield* attempt({ operation: "copyArtifactToClipboard.write", artifactPath: resolvedPath }, () =>4118 yield* attemptPromise(
4111 clipboard.writeImage(image),4119 { operation: "copyArtifactToClipboard.write", artifactPath: resolvedPath },
4120 () =>
4121 clipboard.write([
4122 new ClipboardItem({
4123 "image/png": new Blob([Uint8Array.from(image.toPNG())], { type: "image/png" }),
4124 }),
4125 ]),
4112 );4126 );
4113 });4127 });
4114 4128
pnpm-lock.yaml+14−13
@@ -79,6 +79,7 @@ overrides: · 78 unmodified lines
79 expo-router: 57.0.1779 expo-router: 57.0.17
80 expo-sharing>@expo/config-plugins: 57.0.980 expo-sharing>@expo/config-plugins: 57.0.9
81 expo-sharing>@expo/config-types: 57.0.281 expo-sharing>@expo/config-types: 57.0.2
82 node-abi: 4.33.0
82 lightningcss: 1.33.083 lightningcss: 1.33.0
83 tailwindcss: 4.3.384 tailwindcss: 4.3.3
84 vite: npm:@voidzero-dev/vite-plus-core@0.3.085 vite: npm:@voidzero-dev/vite-plus-core@0.3.0
@@ -129,7 +130,7 @@ importers: · 44 unmodified lines
129 dependencies:130 dependencies:
130 '@clerk/electron':131 '@clerk/electron':
131 specifier: 0.0.37132 specifier: 0.0.37
132 version: 0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@43.4.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)133 version: 0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
133 '@clerk/electron-passkeys':134 '@clerk/electron-passkeys':
134 specifier: 0.0.3135 specifier: 0.0.3
135 version: 0.0.3136 version: 0.0.3
@@ -158,8 +159,8 @@ importers: · 22 unmodified lines
158 specifier: 4.0.0-beta.103159 specifier: 4.0.0-beta.103
159 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)160 version: 4.0.0-beta.103(patch_hash=af36b7948b6f9c56623074662b51dade5699880c1a7c71245de73e13c3185fb6)
160 electron:161 electron:
161 specifier: 43.4.1162 specifier: 44.1.0
162 version: 43.4.1163 version: 44.1.0
163 electron-store:164 electron-store:
164 specifier: ^8.2.0165 specifier: ^8.2.0
165 version: 8.2.0166 version: 8.2.0
@@ -556,7 +557,7 @@ importers: · 390 unmodified lines
556 version: 1.5.0(@types/react@19.2.16)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)557 version: 1.5.0(@types/react@19.2.16)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
557 '@clerk/electron':558 '@clerk/electron':
558 specifier: 0.0.37559 specifier: 0.0.37
559 version: 0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@43.4.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)560 version: 0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
560 '@clerk/react':561 '@clerk/react':
561 specifier: 6.14.7562 specifier: 6.14.7
562 version: 6.14.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6)563 version: 6.14.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
@@ -6688,8 +6689,8 @@ packages: · 6125 unmodified lines
6688 resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}6689 resolution: {integrity: sha512-bO3y10YikuUwUuDUQRM4KfwNkKhnpVO7IPdbsrejwN9/AABJzzTQ4GeHwyzNSrVO+tEH3/Np255a3sVZpZDjvg==}
6689 engines: {node: '>=8.0.0'}6690 engines: {node: '>=8.0.0'}
6690 6691
6691 electron@43.4.1:6692 electron@44.1.0:
6692 resolution: {integrity: sha512-5b+EuiwkgG5iRcsEL34rimgRpkYp15SsfZOa0pC5kXs0Tb82TH4n95rpQzTZa7yRCbA7tm0WoEbuBL6NaAhAcA==}6693 resolution: {integrity: sha512-kmLg8axOg22DC3fXx5NCwBYW8fx0rK2zzJ3Tf67GjNCkxfoxEcd+yo0QfDjlBtHJs3xeA8fTg64b6iVzFTVErg==}
6693 engines: {node: '>= 22.12.0'}6694 engines: {node: '>= 22.12.0'}
6694 hasBin: true6695 hasBin: true
6695 6696
@@ -8573,8 +8574,8 @@ packages: · 1877 unmodified lines
8573 nlcst-to-string@4.0.0:8574 nlcst-to-string@4.0.0:
8574 resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}8575 resolution: {integrity: sha512-YKLBCcUYKAg0FNlOBT6aI91qFmSiFKiluk655WzPF+DDMA02qIyy8uiRqI8QXtcFpEvll12LpL5MXqEmAZ+dcA==}
8575 8576
8576 node-abi@4.31.0:8577 node-abi@4.33.0:
8577 resolution: {integrity: sha512-Erq5w/t3syw3s4sDsUaX4QttIdBPsGKTT1DTRsCkTonGggczhlDKm/wDX3o+HPJpQ41EjXCbcmXf0tgr5YZJXw==}8578 resolution: {integrity: sha512-vLBWCKb+7LWsX+TbfzWOkw0W81m377tyx3hOweBTjO43CXZnRGS1/JPWs20fr0PgZyDXk6ROYrylsEycK8raDA==}
8578 engines: {node: '>=22.12.0'}8579 engines: {node: '>=22.12.0'}
8579 8580
8580 node-addon-api@7.1.1:8581 node-addon-api@7.1.1:
@@ -11846,12 +11847,12 @@ snapshots: · 3265 unmodified lines
11846 '@clerk/electron-passkeys-win32-arm64-msvc': 0.0.311847 '@clerk/electron-passkeys-win32-arm64-msvc': 0.0.3
11847 '@clerk/electron-passkeys-win32-x64-msvc': 0.0.311848 '@clerk/electron-passkeys-win32-x64-msvc': 0.0.3
11848 11849
11849 '@clerk/electron@0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@43.4.1)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':11850 '@clerk/electron@0.0.37(@clerk/electron-passkeys@0.0.3)(electron-store@8.2.0)(electron@44.1.0)(react-dom@19.2.6(react@19.2.6))(react@19.2.6)':
11850 dependencies:11851 dependencies:
11851 '@clerk/clerk-js': 6.30.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)11852 '@clerk/clerk-js': 6.30.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
11852 '@clerk/react': 6.14.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6)11853 '@clerk/react': 6.14.7(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
11853 '@clerk/shared': 4.30.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)11854 '@clerk/shared': 4.30.1(react-dom@19.2.6(react@19.2.6))(react@19.2.6)
11854 electron: 43.4.111855 electron: 44.1.0
11855 react: 19.2.611856 react: 19.2.6
11856 tslib: 2.8.111857 tslib: 2.8.1
11857 optionalDependencies:11858 optionalDependencies:
@@ -12228,7 +12229,7 @@ snapshots: · 370 unmodified lines
12228 dependencies:12229 dependencies:
12229 '@malept/cross-spawn-promise': 2.0.012230 '@malept/cross-spawn-promise': 2.0.0
12230 debug: 4.4.312231 debug: 4.4.3
12231 node-abi: 4.31.012232 node-abi: 4.33.0
12232 node-api-version: 0.2.112233 node-api-version: 0.2.1
12233 node-gyp: 12.3.012234 node-gyp: 12.3.0
12234 read-binary-file-arch: 1.0.612235 read-binary-file-arch: 1.0.6
@@ -16741,7 +16742,7 @@ snapshots: · 4506 unmodified lines
16741 transitivePeerDependencies:16742 transitivePeerDependencies:
16742 - supports-color16743 - supports-color
16743 16744
16744 electron@43.4.1:16745 electron@44.1.0:
16745 dependencies:16746 dependencies:
16746 '@electron-internal/extract-zip': 1.0.516747 '@electron-internal/extract-zip': 1.0.5
16747 '@electron/get': 5.1.016748 '@electron/get': 5.1.0
@@ -19350,7 +19351,7 @@ snapshots: · 2602 unmodified lines
19350 dependencies:19351 dependencies:
19351 '@types/nlcst': 2.0.319352 '@types/nlcst': 2.0.3
19352 19353
19353 node-abi@4.31.0:19354 node-abi@4.33.0:
19354 dependencies:19355 dependencies:
19355 semver: 7.8.519356 semver: 7.8.5
19356 19357
pnpm-workspace.yaml+2−0
@@ -90,6 +90,7 @@ minimumReleaseAgeExclude: · 89 unmodified lines
90 - expo-updates@57.0.1990 - expo-updates@57.0.19
91 - expo@57.0.1891 - expo@57.0.18
92 - expo-widgets@57.0.1592 - expo-widgets@57.0.15
93 - electron@44.1.0
93 - "@anthropic-ai/claude-agent-sdk@0.3.260"94 - "@anthropic-ai/claude-agent-sdk@0.3.260"
94 95
95overrides:96overrides:
@@ -137,6 +138,7 @@ overrides: · 41 unmodified lines
137 expo-router: 57.0.17138 expo-router: 57.0.17
138 "expo-sharing>@expo/config-plugins": 57.0.9139 "expo-sharing>@expo/config-plugins": 57.0.9
139 "expo-sharing>@expo/config-types": 57.0.2140 "expo-sharing>@expo/config-types": 57.0.2
141 node-abi: 4.33.0
140 lightningcss: "catalog:"142 lightningcss: "catalog:"
141 tailwindcss: "catalog:"143 tailwindcss: "catalog:"
142 vite: "catalog:"144 vite: "catalog:"

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t