diff --git a/package.json b/package.json index 887508af..dbb0a50a 100644 --- a/package.json +++ b/package.json @@ -31,12 +31,10 @@ "dependencies": { "@electron/asar": "^3.2.1", "debug": "^4.1.1", - "fs-extra": "^7.0.1", "lodash": "^4.17.21", "semver": "^7.6.3" }, "devDependencies": { - "@types/fs-extra": "^5.0.5", "@types/lodash": "^4.17.0", "@types/node": "^20.6.0", "@typescript-eslint/eslint-plugin": "^5.62.0", diff --git a/spec/helpers/helpers.ts b/spec/helpers/helpers.ts index 8fddb127..e7395f41 100644 --- a/spec/helpers/helpers.ts +++ b/spec/helpers/helpers.ts @@ -1,5 +1,5 @@ import path from 'path'; -import fs from 'fs-extra'; +import fs from 'fs/promises'; import { createTempDir } from '../../src/temp-utils'; @@ -7,6 +7,6 @@ export const FIXTURE_APP_DIR = path.join(__dirname, '../fixtures/app'); export async function createTempAppDirectory(): Promise { const appDirectory = await createTempDir('electron-winstaller-ad-'); - await fs.copy(FIXTURE_APP_DIR, appDirectory); + await fs.cp(FIXTURE_APP_DIR, appDirectory); return appDirectory; } diff --git a/spec/helpers/windowsSignHook.js b/spec/helpers/windowsSignHook.js index b62317f7..1cc2ef8b 100644 --- a/spec/helpers/windowsSignHook.js +++ b/spec/helpers/windowsSignHook.js @@ -1,4 +1,4 @@ -const fs = require('fs-extra'); +const fs = require('fs'); const path = require('path'); module.exports = function(args) { diff --git a/spec/installer-spec.ts b/spec/installer-spec.ts index 15a03cd9..1dd76701 100644 --- a/spec/installer-spec.ts +++ b/spec/installer-spec.ts @@ -1,7 +1,7 @@ import test from 'ava'; import path from 'path'; import { createTempDir } from '../src/temp-utils'; -import fs from 'fs-extra'; +import fs from 'fs/promises'; import { createWindowsInstaller } from '../src'; import spawn from '../src/spawn-promise'; import { createTempAppDirectory } from './helpers/helpers'; @@ -16,6 +16,8 @@ function spawn7z(args: string[]): Promise { : spawn(sevenZipPath, args); } +const exists = (p: string) => fs.access(p).then(() => true).catch(() => false); + test.serial('creates a nuget package and installer', async (t): Promise => { const outputDirectory = await createTempDir('ei-'); @@ -29,15 +31,15 @@ test.serial('creates a nuget package and installer', async (t): Promise => const nupkgPath = path.join(outputDirectory, 'myapp-1.0.0-full.nupkg'); - t.true(await fs.pathExists(nupkgPath)); - t.true(await fs.pathExists(path.join(outputDirectory, 'MyAppSetup.exe'))); + t.true(await exists(nupkgPath)); + t.true(await exists(path.join(outputDirectory, 'MyAppSetup.exe'))); if (process.platform === 'win32') { - t.true(await fs.pathExists(path.join(outputDirectory, 'MyAppSetup.msi'))); + t.true(await exists(path.join(outputDirectory, 'MyAppSetup.msi'))); } log('Verifying Update.exe'); - t.true(await fs.pathExists(path.join(appDirectory, 'Squirrel.exe'))); + t.true(await exists(path.join(appDirectory, 'Squirrel.exe'))); log('Verifying contents of .nupkg'); @@ -53,10 +55,10 @@ test.serial('creates an installer when swiftshader files are missing', async (t) const options = { appDirectory, outputDirectory }; // Remove swiftshader folder and swiftshader json file, simulating Electron < 10.0 - await fs.remove(path.join(appDirectory, 'swiftshader', 'libEGL.dll')); - await fs.remove(path.join(appDirectory, 'swiftshader', 'libGLESv2.dll')); - await fs.rmdir(path.join(appDirectory, 'swiftshader')); - await fs.remove(path.join(appDirectory, 'vk_swiftshader_icd.json')); + await fs.rm(path.join(appDirectory, 'swiftshader', 'libEGL.dll'), { force: true, recursive: true }); + await fs.rm(path.join(appDirectory, 'swiftshader', 'libGLESv2.dll'), { force: true, recursive: true }); + await fs.rm(path.join(appDirectory, 'swiftshader'), { force: true, recursive: true }); + await fs.rm(path.join(appDirectory, 'vk_swiftshader_icd.json'), { force: true, recursive: true }); await createWindowsInstaller(options); diff --git a/spec/sign-spec.ts b/spec/sign-spec.ts index f6307af2..11cdc20d 100644 --- a/spec/sign-spec.ts +++ b/spec/sign-spec.ts @@ -1,7 +1,7 @@ import test from 'ava'; import path from 'path'; import { createTempDir } from '../src/temp-utils'; -import fs from 'fs-extra'; +import fs from 'fs/promises'; import { createWindowsInstaller } from '../src'; import { createTempAppDirectory } from './helpers/helpers'; import { SignToolOptions } from '@electron/windows-sign'; @@ -9,6 +9,8 @@ import semver from 'semver'; const log = require('debug')('electron-windows-installer:spec'); +const exists = (p: string) => fs.access(p).then(() => true).catch(() => false); + if (process.platform === 'win32' && semver.gte(process.version, '20.0.0')) { test.serial('creates a signtool.exe and uses it to sign', async (t): Promise => { @@ -20,7 +22,7 @@ if (process.platform === 'win32' && semver.gte(process.version, '20.0.0')) { const options = { appDirectory, outputDirectory, windowsSign }; // Reset - await fs.remove(hookLogPath); + await fs.rm(hookLogPath, { force: true, recursive: true }); // Test await createWindowsInstaller(options); @@ -30,15 +32,15 @@ if (process.platform === 'win32' && semver.gte(process.version, '20.0.0')) { const nupkgPath = path.join(outputDirectory, 'myapp-1.0.0-full.nupkg'); - t.true(await fs.pathExists(nupkgPath)); - t.true(await fs.pathExists(path.join(outputDirectory, 'MyAppSetup.exe'))); + t.true(await exists(nupkgPath)); + t.true(await exists(path.join(outputDirectory, 'MyAppSetup.exe'))); if (process.platform === 'win32') { - t.true(await fs.pathExists(path.join(outputDirectory, 'MyAppSetup.msi'))); + t.true(await exists(path.join(outputDirectory, 'MyAppSetup.msi'))); } log('Verifying Update.exe'); - t.true(await fs.pathExists(path.join(appDirectory, 'Squirrel.exe'))); + t.true(await exists(path.join(appDirectory, 'Squirrel.exe'))); log('Verifying that our hook got to "sign" all files'); const hookLog = await fs.readFile(hookLogPath, { encoding: 'utf8' }); diff --git a/src/index.ts b/src/index.ts index c3148696..e6b58dae 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,6 @@ import * as asar from '@electron/asar'; import { createTempDir } from './temp-utils'; -import * as fs from 'fs-extra'; +import fs from 'fs/promises'; import { Metadata, SquirrelWindowsOptions, PersonMetadata } from './options'; import * as path from 'path'; import * as os from 'os'; @@ -14,6 +14,8 @@ export { SquirrelWindowsOptions as Options} from './options'; const log = require('debug')('electron-windows-installer:main'); +const exists = (p: string) => fs.access(p).then(() => true).catch(() => false); + /** * A utility function to convert SemVer version strings into NuGet-compatible * version strings. @@ -96,7 +98,8 @@ export async function createWindowsInstaller(options: SquirrelWindowsOptions): P const vendorUpdate = path.join(vendorPath, 'Squirrel.exe'); const appUpdate = path.join(appDirectory, 'Squirrel.exe'); - await fs.copy(vendorUpdate, appUpdate); + await fs.cp(vendorUpdate, appUpdate); + if (options.setupIcon && (options.skipUpdateIcon !== true)) { let cmd = path.join(vendorPath, 'rcedit.exe'); const args = [ @@ -127,10 +130,11 @@ export async function createWindowsInstaller(options: SquirrelWindowsOptions): P const asarFile = path.join(appResources, 'app.asar'); let appMetadata; - if (await fs.pathExists(asarFile)) { + if (await exists(asarFile)) { appMetadata = JSON.parse(asar.extractFile(asarFile, 'package.json').toString()); } else { - appMetadata = await fs.readJson(path.join(appResources, 'app', 'package.json')); + const pkgBuffer = await fs.readFile(path.join(appResources, 'app', 'package.json'), 'utf8'); + appMetadata = JSON.parse(pkgBuffer); } Object.assign(metadata, { @@ -161,11 +165,11 @@ export async function createWindowsInstaller(options: SquirrelWindowsOptions): P // See https://github.com/electron/windows-installer/issues/389 metadata.authors = sanitizeAuthors(metadata.authors as string); - if (await fs.pathExists(path.join(appDirectory, 'swiftshader'))) { + if (await exists(path.join(appDirectory, 'swiftshader'))) { metadata.additionalFiles.push({ src: 'swiftshader\\**', target: 'lib\\net45\\swiftshader' }); } - if (await fs.pathExists(path.join(appDirectory, 'vk_swiftshader_icd.json'))) { + if (await exists(path.join(appDirectory, 'vk_swiftshader_icd.json'))) { metadata.additionalFiles.push({ src: 'vk_swiftshader_icd.json', target: 'lib\\net45' }); } @@ -284,7 +288,7 @@ export async function createWindowsInstaller(options: SquirrelWindowsOptions): P if (metadata.productName || options.setupMsi) { const msiPath = path.join(outputDirectory, options.setupMsi || `${metadata.productName}Setup.msi`); const unfixedMsiPath = path.join(outputDirectory, 'Setup.msi'); - if (await fs.pathExists(unfixedMsiPath)) { + if (await exists(unfixedMsiPath)) { log(`Renaming ${unfixedMsiPath} => ${msiPath}`); await fs.rename(unfixedMsiPath, msiPath); } diff --git a/src/sign.ts b/src/sign.ts index 9712df82..deeba968 100644 --- a/src/sign.ts +++ b/src/sign.ts @@ -1,7 +1,7 @@ import type { createSeaSignTool as createSeaSignToolType } from '@electron/windows-sign'; import path from 'path'; import semver from 'semver'; -import fs from 'fs-extra'; +import fs from 'fs/promises'; import { SquirrelWindowsOptions } from './options'; @@ -10,6 +10,8 @@ let ORIGINAL_SIGN_TOOL_PATH: string; let BACKUP_SIGN_TOOL_PATH: string; let SIGN_LOG_PATH: string; +const exists = (p: string) => fs.access(p).then(() => true).catch(() => false); + /** * This method uses @electron/windows-sign to create a fake signtool.exe * that can be called by Squirrel - but then just calls @electron/windows-sign @@ -31,10 +33,10 @@ export async function createSignTool(options: SquirrelWindowsOptions): Promise