| ... | @@ -3,6 +3,7 @@ import * as NodeCrypto from "node:crypto"; | ... | @@ -3,6 +3,7 @@ import * as NodeCrypto from "node:crypto"; |
| 3 | import * as NodePath from "node:path"; | 3 | import * as NodePath from "node:path"; |
| 4 | | 4 | |
| 5 | import * as NodeServices from "@effect/platform-node/NodeServices"; | 5 | import * as NodeServices from "@effect/platform-node/NodeServices"; |
| | 6 | import { extractFile } from "@electron/asar"; |
| 6 | import { assert, it } from "@effect/vitest"; | 7 | import { assert, it } from "@effect/vitest"; |
| 7 | import * as ConfigProvider from "effect/ConfigProvider"; | 8 | import * as ConfigProvider from "effect/ConfigProvider"; |
| 8 | import * as FileSystem from "effect/FileSystem"; | 9 | import * as FileSystem from "effect/FileSystem"; |
| ... | @@ -197,7 +198,7 @@ const makeWindowsPayloadFixture = Effect.fn("test.makeWindowsPayloadFixture")(fu | ... | @@ -197,7 +198,7 @@ const makeWindowsPayloadFixture = Effect.fn("test.makeWindowsPayloadFixture")(fu |
| 197 | yield* fs.makeDirectory(path.dirname(serverEntryPath), { recursive: true }); | 198 | yield* fs.makeDirectory(path.dirname(serverEntryPath), { recursive: true }); |
| 198 | yield* fs.makeDirectory(path.dirname(nativePath), { recursive: true }); | 199 | yield* fs.makeDirectory(path.dirname(nativePath), { recursive: true }); |
| 199 | yield* fs.writeFileString(serverEntryPath, input.serverEntrySource ?? "console.log('server');\n"); | 200 | yield* fs.writeFileString(serverEntryPath, input.serverEntrySource ?? "console.log('server');\n"); |
| 200 | yield* fs.writeFileString(nativePath, "native-binary"); | 201 | yield* fs.writeFileString(nativePath, "MZ native-binary"); |
| 201 | | 202 | |
| 202 | const generatedAsarPath = path.join(tempDir, WINDOWS_SERVER_ASAR_RESOURCE); | 203 | const generatedAsarPath = path.join(tempDir, WINDOWS_SERVER_ASAR_RESOURCE); |
| 203 | yield* packWindowsServerAsar({ sourceDir, asarPath: generatedAsarPath, arch: "x64" }); | 204 | yield* packWindowsServerAsar({ sourceDir, asarPath: generatedAsarPath, arch: "x64" }); |
| ... | @@ -888,7 +889,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | ... | @@ -888,7 +889,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { |
| 888 | ]); | 889 | ]); |
| 889 | }); | 890 | }); |
| 890 | | 891 | |
| 891 | it.effect("keeps target native files while excluding the other Windows architecture", () => | 892 | it.effect("unpacks target Windows natives while excluding the other architecture", () => |
| 892 | Effect.scoped( | 893 | Effect.scoped( |
| 893 | Effect.gen(function* () { | 894 | Effect.gen(function* () { |
| 894 | const fs = yield* FileSystem.FileSystem; | 895 | const fs = yield* FileSystem.FileSystem; |
| ... | @@ -902,12 +903,14 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | ... | @@ -902,12 +903,14 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { |
| 902 | "node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe", | 903 | "node_modules/node-pty/prebuilds/win32-arm64/conpty/OpenConsole.exe", |
| 903 | "node_modules/node-pty/third_party/conpty/1.0.0/win10-x64/OpenConsole.exe", | 904 | "node_modules/node-pty/third_party/conpty/1.0.0/win10-x64/OpenConsole.exe", |
| 904 | "node_modules/node-pty/third_party/conpty/1.0.0/win10-arm64/OpenConsole.exe", | 905 | "node_modules/node-pty/third_party/conpty/1.0.0/win10-arm64/OpenConsole.exe", |
| | 906 | "node_modules/node-pty/prebuilds/win32-x64/pty.node", |
| | 907 | "node_modules/node-pty/prebuilds/linux-x64/pty.node", |
| 905 | ]; | 908 | ]; |
| 906 | | 909 | |
| 907 | for (const nativeFile of nativeFiles) { | 910 | for (const nativeFile of nativeFiles) { |
| 908 | const nativePath = path.join(sourceDir, nativeFile); | 911 | const nativePath = path.join(sourceDir, nativeFile); |
| 909 | yield* fs.makeDirectory(path.dirname(nativePath), { recursive: true }); | 912 | yield* fs.makeDirectory(path.dirname(nativePath), { recursive: true }); |
| 910 | yield* fs.writeFileString(nativePath, "native"); | 913 | yield* fs.writeFileString(nativePath, nativeFile.includes("linux") ? "\x7fELF" : "MZ"); |
| 911 | } | 914 | } |
| 912 | | 915 | |
| 913 | const asarPath = path.join(tempDir, "server.asar"); | 916 | const asarPath = path.join(tempDir, "server.asar"); |
| ... | @@ -922,6 +925,22 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | ... | @@ -922,6 +925,22 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { |
| 922 | ), | 925 | ), |
| 923 | ), | 926 | ), |
| 924 | ); | 927 | ); |
| | 928 | assert.isTrue( |
| | 929 | yield* fs.exists( |
| | 930 | path.join(unpackedRoot, "node_modules/node-pty/prebuilds/win32-x64/pty.node"), |
| | 931 | ), |
| | 932 | ); |
| | 933 | // Signed builds sign every unpacked .node, so the ELF prebuild stays packed. |
| | 934 | assert.isFalse( |
| | 935 | yield* fs.exists(path.join(unpackedRoot, "node_modules/node-pty/prebuilds/linux-x64")), |
| | 936 | ); |
| | 937 | assert.equal( |
| | 938 | extractFile( |
| | 939 | asarPath, |
| | 940 | path.join("node_modules", "node-pty", "prebuilds", "linux-x64", "pty.node"), |
| | 941 | ).toString(), |
| | 942 | "\x7fELF", |
| | 943 | ); |
| 925 | assert.isFalse( | 944 | assert.isFalse( |
| 926 | yield* fs.exists(path.join(unpackedRoot, "node_modules/node-pty/prebuilds/win32-arm64")), | 945 | yield* fs.exists(path.join(unpackedRoot, "node_modules/node-pty/prebuilds/win32-arm64")), |
| 927 | ); | 946 | ); |
| ... | @@ -2126,7 +2145,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | ... | @@ -2126,7 +2145,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { |
| 2126 | }).pipe(Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })))), | 2145 | }).pipe(Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })))), |
| 2127 | ); | 2146 | ); |
| 2128 | | 2147 | |
| 2129 | it.effect("keeps executable resource editing enabled for unsigned Windows builds", () => | 2148 | it.effect("configures Windows executable metadata and native signing extensions", () => |
| 2130 | Effect.gen(function* () { | 2149 | Effect.gen(function* () { |
| 2131 | const config = yield* createBuildConfig( | 2150 | const config = yield* createBuildConfig( |
| 2132 | "win", | 2151 | "win", |
| ... | @@ -2140,6 +2159,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { | ... | @@ -2140,6 +2159,7 @@ it.layer(NodeServices.layer)("build-desktop-artifact", (it) => { |
| 2140 | | 2159 | |
| 2141 | const win = config.win as Record<string, unknown>; | 2160 | const win = config.win as Record<string, unknown>; |
| 2142 | assert.equal(win.icon, "icon.ico"); | 2161 | assert.equal(win.icon, "icon.ico"); |
| | 2162 | assert.deepStrictEqual(win.signExts, [".node", ".dll"]); |
| 2143 | assert.equal(win.signAndEditExecutable, true); | 2163 | assert.equal(win.signAndEditExecutable, true); |
| 2144 | assert.notProperty(win, "azureSignOptions"); | 2164 | assert.notProperty(win, "azureSignOptions"); |
| 2145 | }).pipe(Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })))), | 2165 | }).pipe(Effect.provide(ConfigProvider.layer(ConfigProvider.fromEnv({ env: {} })))), |