diff --git a/.changeset/config.release-v27.json b/.changeset/config.release-v27.json new file mode 100644 index 00000000000..a5d628bbcf7 --- /dev/null +++ b/.changeset/config.release-v27.json @@ -0,0 +1,23 @@ +{ + "$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json", + "changelog": ["changesets-changelog-clean", { "repo": "electron-userland/electron-builder" }], + "commit": false, + "linked": [[ + "app-builder-lib", + "builder-util", + "dmg-builder", + "electron-builder", + "electron-builder-squirrel-windows", + "electron-publish" + ]], + "access": "public", + "baseBranch": "release/v27", + "updateInternalDependencies": "patch", + "ignore": [ + "electron-forge-maker-appimage", + "electron-forge-maker-nsis", + "electron-forge-maker-nsis-web", + "electron-forge-maker-snap", + "@electron-builder/test" + ] +} \ No newline at end of file diff --git a/.changeset/pre.json b/.changeset/pre.json new file mode 100644 index 00000000000..bb23527de2d --- /dev/null +++ b/.changeset/pre.json @@ -0,0 +1,20 @@ +{ + "mode": "pre", + "tag": "alpha", + "initialVersions": { + "app-builder-lib": "26.8.0", + "builder-util": "26.8.0", + "builder-util-runtime": "9.5.1", + "dmg-builder": "26.8.0", + "electron-builder": "26.8.0", + "electron-builder-squirrel-windows": "26.8.0", + "electron-forge-maker-appimage": "26.8.0", + "electron-forge-maker-nsis": "26.8.0", + "electron-forge-maker-nsis-web": "26.8.0", + "electron-forge-maker-snap": "26.8.0", + "electron-publish": "26.8.0", + "electron-updater": "6.8.3", + "@electron-builder/test": "0.0.0" + }, + "changesets": [] +} diff --git a/.changeset/small-times-scream.md b/.changeset/small-times-scream.md new file mode 100644 index 00000000000..891d81b92c1 --- /dev/null +++ b/.changeset/small-times-scream.md @@ -0,0 +1,12 @@ +--- +"electron-builder-squirrel-windows": major +"builder-util-runtime": major +"electron-builder": major +"electron-publish": major +"electron-updater": major +"app-builder-lib": major +"builder-util": major +"dmg-builder": major +--- + +chore(node): migrating to ESM and updating all engines to node 22 to support latest versions of `electron/*` packages diff --git a/.github/workflows/pr-release.yml b/.github/workflows/pr-release.yml index 83fb98085f7..a689fd46222 100644 --- a/.github/workflows/pr-release.yml +++ b/.github/workflows/pr-release.yml @@ -4,7 +4,8 @@ on: push: branches: - master - - release/v* + - release/v27 + concurrency: group: ${{ github.workflow }}-${{ github.ref }} cancel-in-progress: false diff --git a/.gitignore b/.gitignore index a00c7e29ab6..0d9764f33a3 100644 --- a/.gitignore +++ b/.gitignore @@ -29,3 +29,4 @@ _vitest-smart-cache.json yalc.lock .claude +test/vitest-scripts/_vitest-smart-cache.json \ No newline at end of file diff --git a/.prettierignore b/.prettierignore index 561556b2710..346f08df379 100644 --- a/.prettierignore +++ b/.prettierignore @@ -1,2 +1,3 @@ *.d.ts -out \ No newline at end of file +out +dist \ No newline at end of file diff --git a/eslint.config.mjs b/eslint.config.mjs index d5655a5bc02..68e5b2b3082 100644 --- a/eslint.config.mjs +++ b/eslint.config.mjs @@ -18,6 +18,7 @@ export default [{ ignores: [ "**/*.d.ts", "**/out", + "**/dist", // used for CLI "**/main.js", "test/vitest-setup.ts", @@ -25,6 +26,7 @@ export default [{ "packages/electron-builder/cli.js", "packages/electron-builder/install-app-deps.js", "packages/app-builder-lib/src/node-module-collector/hoist.ts", // @yarn/pkg vendor code + "**/tsup.config.ts", "test/fixtures/**", "test/src/helpers/**", "test/src/generated/**", @@ -59,7 +61,7 @@ export default [{ "@typescript-eslint/prefer-promise-reject-errors": "off", "curly": ["error", "all"], - "nonblock-statement-body-position": ["error", "below"], + "nonblock-statement-body-position": "off", "@stylistic/member-delimiter-style": ["error", { multiline: { @@ -89,4 +91,12 @@ export default [{ "@typescript-eslint/explicit-function-return-type": ["off", {}], "@typescript-eslint/no-redundant-type-constituents": "off", }, +}, { + files: ["test/src/**/*.ts"], + rules: { + // Test helpers often use async without await for framework compatibility + "@typescript-eslint/require-await": "off", + // Test code routinely passes methods as callbacks without binding + "@typescript-eslint/unbound-method": "off", + }, }]; \ No newline at end of file diff --git a/package.json b/package.json index 759906d8145..139be01de5a 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,9 @@ "license": "MIT", "scripts": { "//": "do not wrap into single quotes - windows doesn't unwrap arg in this case", - "compile": "pnpm ci:test:generate && tsc --build", + "compile": "pnpm ci:test:generate && pnpm run -r --if-present --filter builder-util-runtime --filter builder-util --filter electron-publish --filter app-builder-lib build && pnpm run -r --if-present --filter '!@electron-builder/website' --filter '!@electron-builder/test' --filter '!app-builder-lib' --filter '!builder-util' --filter '!builder-util-runtime' --filter '!electron-publish' build", + "compile:watch": "pnpm compile && pnpm run -r --if-present --parallel --filter '!@electron-builder/website' --filter '!@electron-builder/test' watch", + "typecheck": "tsc --build", "lint": "eslint packages test/src --ext .ts,.js", "lint-deps": "node ./scripts/checkDeps.js", "pretest": "pnpm lint-deps && pnpm lint", @@ -12,9 +14,9 @@ "///": "Please see https://github.com/electron-userland/electron-builder/blob/master/CONTRIBUTING.md#run-test-using-cli how to run particular test instead full (and very slow) run", "test-all": "pnpm compile && pnpm pretest && pnpm ci:test", "test-linux": "bash docker/run-tests.sh", - "ci:test": "ts-node test/vitest-scripts/run-vitest.ts", - "ci:test:generate": "ts-node test/vitest-scripts/generate-tests.ts", - "ci:test:count": "ts-node test/vitest-scripts/smart-shard-count.ts", + "ci:test": "tsx test/vitest-scripts/run-vitest.ts", + "ci:test:generate": "tsx test/vitest-scripts/generate-tests.ts", + "ci:test:count": "tsx test/vitest-scripts/smart-shard-count.ts", "ci:validate": "pnpm compile && pnpm pretest && pnpm generate:all", "ci:version": "pnpm i && changeset version && node scripts/update-package-version-export.js && pnpm changelog && pnpm compile && pnpm generate:all && git add .", "ci:publish": "pnpm i && pnpm compile && pnpm publish -r --tag ${NPM_DIST_TAG:-next} && changeset tag", @@ -22,7 +24,7 @@ "docker-push": "bash docker/push.sh", "changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -t electron-builder@ --pkg packages/electron-builder/package.json && git add CHANGELOG.md", "generate:changeset": "pnpm changeset", - "generate:schema": "typescript-json-schema packages/app-builder-lib/tsconfig-scheme.json Configuration --out packages/app-builder-lib/scheme.json --noExtraProps --useTypeOfKeyword --strictNullChecks --required && node ./scripts/fix-schema.js", + "generate:schema": "typescript-json-schema packages/app-builder-lib/tsconfig-scheme.json Configuration --out packages/app-builder-lib/scheme.json --noExtraProps --useTypeOfKeyword --strictNullChecks --required --ignoreErrors && node ./scripts/fix-schema.js", "generate:all": "pnpm generate:schema && pnpm prettier", "docs:prebuild": "docker build -t docs-dockerfile -f website/dockerfile .", "docs:build": "pnpm compile && docker run --rm -v ${PWD}:/app -w /app/website -v $(pwd)/node-modules-docker-web:/app/node_modules docs-dockerfile sh -c 'pnpm install --frozen-lockfile && pnpm build'", @@ -40,6 +42,7 @@ "@eslint/eslintrc": "^3.3.1", "@eslint/js": "^9.37.0", "@stylistic/eslint-plugin": "^2.8.0", + "@tsconfig/node22": "^22.0.5", "@types/node": "^22.7.4", "@typescript-eslint/eslint-plugin": "8.17.0", "@typescript-eslint/parser": "8.17.0", @@ -50,17 +53,18 @@ "eslint": "9.39.2", "eslint-config-prettier": "^9.1.0", "eslint-plugin-prettier": "^5.2.1", + "fs-extra": "^10.1.0", "is-ci": "^4.1.0", "prettier": "3.7.4", - "ts-node": "^10.9.2", + "tsx": "^4.0.0", + "typedoc": "^0.28.19", "typescript": "^5.6.2", "typescript-json-schema": "0.64.0", - "typedoc": "^0.28.19", "vitest": "^3.2.2" }, "engines": { - "node": ">=14.14", - "pnpm": ">=10" + "node": ">=22.12.0", + "pnpm": ">=11.1.0" }, "packageManager": "pnpm@11.1.0+sha512.0c44e842e5686b2c061a81adda8b2258bd8818e9704b2cf2c63d56b931a7b2e910092e085027003b96ca3911ab56a07f6df5abaed2be9925034cdd686a535b14" } diff --git a/packages/app-builder-lib/helpers/dynamic-import.js b/packages/app-builder-lib/helpers/dynamic-import.cjs similarity index 100% rename from packages/app-builder-lib/helpers/dynamic-import.js rename to packages/app-builder-lib/helpers/dynamic-import.cjs diff --git a/packages/app-builder-lib/helpers/package.json b/packages/app-builder-lib/helpers/package.json new file mode 100644 index 00000000000..b731bd61b9c --- /dev/null +++ b/packages/app-builder-lib/helpers/package.json @@ -0,0 +1 @@ +{"type": "commonjs"} diff --git a/packages/app-builder-lib/helpers/remote-rebuild.cjs b/packages/app-builder-lib/helpers/remote-rebuild.cjs new file mode 100644 index 00000000000..7d82d390e5f --- /dev/null +++ b/packages/app-builder-lib/helpers/remote-rebuild.cjs @@ -0,0 +1,36 @@ +if (!process.send) { + console.error("The remote rebuilder expects to be spawned with an IPC channel") + process.exit(1) +} + +const rebuilder = rebuilder => { + rebuilder.lifecycle.on("module-found", moduleName => process.send?.({ msg: "module-found", moduleName })) + rebuilder.lifecycle.on("module-done", moduleName => process.send?.({ msg: "module-done", moduleName })) + rebuilder.lifecycle.on("module-skip", moduleName => process.send?.({ msg: "module-skip", moduleName })) + + return rebuilder + .then(() => { + process.send?.({ msg: "rebuild-done" }) + return process.exit(0) + }) + .catch(err => { + process.send?.({ + msg: "rebuild-error", + err: { + message: err.message, + stack: err.stack, + }, + }) + process.exit(0) + }) +} + +const main = async () => { + const options = JSON.parse(process.argv[2]) + return import("@electron/rebuild").then(module => { + const { rebuild } = module + return rebuilder(rebuild(options)) + }) +} + +main() diff --git a/packages/app-builder-lib/helpers/remote-rebuild.js b/packages/app-builder-lib/helpers/remote-rebuild.js index 58fea60009c..7d82d390e5f 100644 --- a/packages/app-builder-lib/helpers/remote-rebuild.js +++ b/packages/app-builder-lib/helpers/remote-rebuild.js @@ -25,11 +25,9 @@ const rebuilder = rebuilder => { }) } -const main = () => { +const main = async () => { const options = JSON.parse(process.argv[2]) - - const dynamicImport = require("./dynamic-import").dynamicImportMaybe - return dynamicImport("@electron/rebuild").then(module => { + return import("@electron/rebuild").then(module => { const { rebuild } = module return rebuilder(rebuild(options)) }) diff --git a/packages/app-builder-lib/package.json b/packages/app-builder-lib/package.json index 0152c05d960..0a379c9fd12 100644 --- a/packages/app-builder-lib/package.json +++ b/packages/app-builder-lib/package.json @@ -2,9 +2,23 @@ "name": "app-builder-lib", "description": "electron-builder lib", "version": "26.14.0", - "main": "out/index.js", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "files": [ - "out", + "dist", "templates", "helpers", "scheme.json", @@ -16,7 +30,7 @@ "directory": "packages/app-builder-lib" }, "engines": { - "node": ">=14.0.0" + "node": ">=22.12.0" }, "keywords": [ "electron", @@ -70,7 +84,7 @@ "dotenv-expand": "^11.0.6", "ejs": "^3.1.8", "electron-publish": "workspace:*", - "fs-extra": "^10.1.0", + "fs-extra": "^11.3.0", "hosted-git-info": "^4.1.0", "isbinaryfile": "^5.0.0", "jiti": "^2.4.2", @@ -125,9 +139,13 @@ "toml": "^3.0.0" }, "peerDependencies": { - "dmg-builder": "workspace:*", - "electron-builder-squirrel-windows": "workspace:*" + "dmg-builder": "*", + "electron-builder-squirrel-windows": "*" }, "//": "electron-builder-squirrel-windows and dmg-builder added as dev dep for tests (as otherwise `require` doesn't work using Yarn 2)", - "typings": "./out/index.d.ts" + "types": "./dist/index.d.ts", + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + } } diff --git a/packages/app-builder-lib/scheme.json b/packages/app-builder-lib/scheme.json index 56e3fb797c4..0da4c95cd41 100644 --- a/packages/app-builder-lib/scheme.json +++ b/packages/app-builder-lib/scheme.json @@ -9247,10 +9247,10 @@ "electronDownload": { "anyOf": [ { - "$ref": "#/definitions/ElectronDownloadOptions" + "$ref": "#/definitions/ElectronGetOptions" }, { - "$ref": "#/definitions/ElectronGetOptions" + "$ref": "#/definitions/ElectronDownloadOptions" }, { "type": "null" diff --git a/packages/app-builder-lib/src/Framework.ts b/packages/app-builder-lib/src/Framework.ts index a875efe8c1e..1b80ec53f38 100644 --- a/packages/app-builder-lib/src/Framework.ts +++ b/packages/app-builder-lib/src/Framework.ts @@ -1,6 +1,9 @@ import { FileTransformer } from "builder-util" -import { AsarIntegrity } from "./asar/integrity" -import { AfterPackContext, ElectronPlatformName, Platform, PlatformPackager } from "./index" +import { AsarIntegrity } from "./asar/integrity.js" +import { AfterPackContext } from "./configuration.js" +import { Platform } from "./core.js" +import { ElectronPlatformName } from "./electron/ElectronFramework.js" +import type { PlatformPackager } from "./platformPackager.js" export interface Framework { readonly name: string diff --git a/packages/app-builder-lib/src/ProtonFramework.ts b/packages/app-builder-lib/src/ProtonFramework.ts index 0933eab8b9d..84068a0ac19 100644 --- a/packages/app-builder-lib/src/ProtonFramework.ts +++ b/packages/app-builder-lib/src/ProtonFramework.ts @@ -1,9 +1,12 @@ +import { createRequire } from "node:module" import { FileTransformer, log } from "builder-util" + +const require = createRequire(import.meta.url) import { safeStringifyJson } from "builder-util-runtime" -import { Platform } from "./core" -import { NODE_MODULES_PATTERN } from "./fileTransformer" -import { LibUiFramework } from "./frameworks/LibUiFramework" -import { getTemplatePath } from "./util/pathManager" +import { Platform } from "./core.js" +import { NODE_MODULES_PATTERN } from "./fileTransformer.js" +import { LibUiFramework } from "./frameworks/LibUiFramework.js" +import { getTemplatePath } from "./util/pathManager.js" export class ProtonFramework extends LibUiFramework { readonly name = "proton" diff --git a/packages/app-builder-lib/src/appInfo.ts b/packages/app-builder-lib/src/appInfo.ts index 1b053977d64..3cb6b2435e2 100644 --- a/packages/app-builder-lib/src/appInfo.ts +++ b/packages/app-builder-lib/src/appInfo.ts @@ -1,10 +1,10 @@ import { isEmptyOrSpaces, log } from "builder-util" +import { sanitizeFileName } from "builder-util/internal" import { Nullish } from "builder-util-runtime" -import { sanitizeFileName } from "builder-util/out/filename" import { prerelease } from "semver" -import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions" -import { Packager } from "./packager" -import { expandMacro } from "./util/macroExpander" +import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions.js" +import { Packager } from "./packager.js" +import { expandMacro } from "./util/macroExpander.js" // fpm bug - rpm build --description is not escaped, well... decided to replace quite to smart quote // http://leancrew.com/all-this/2010/11/smart-quotes-in-javascript/ @@ -21,7 +21,7 @@ export function smarten(s: string): string { } export class AppInfo { - readonly description = smarten(this.info.metadata.description || "") + readonly description: string readonly version: string readonly type: string | undefined readonly shortVersion: string | undefined @@ -40,6 +40,7 @@ export class AppInfo { private readonly platformSpecificOptions: PlatformSpecificBuildOptions | null = null, normalizeNfd = false ) { + this.description = smarten(this.info.metadata.description || "") this.version = info.metadata.version! this.type = info.metadata.type diff --git a/packages/app-builder-lib/src/asar/asar.ts b/packages/app-builder-lib/src/asar/asar.ts index b86d3cdd41a..ac08625e5c9 100644 --- a/packages/app-builder-lib/src/asar/asar.ts +++ b/packages/app-builder-lib/src/asar/asar.ts @@ -1,5 +1,5 @@ -import { createFromBuffer } from "chromium-pickle-js" -import { close, open, read, readFile, Stats } from "fs-extra" +import * as chromiumPickleJs from "chromium-pickle-js" +import fsExtra from "fs-extra" import * as path from "path" export interface ReadAsarHeader { @@ -88,7 +88,7 @@ export class AsarFilesystem { return result } - addFileNode(file: string, dirNode: Node, size: number, unpacked: boolean, stat: Stats, integrity?: NodeIntegrity): Node { + addFileNode(file: string, dirNode: Node, size: number, unpacked: boolean, stat: fsExtra.Stats, integrity?: NodeIntegrity): Node { if (size > 4294967295) { throw new Error(`${file}: file size cannot be larger than 4.2GB`) } @@ -147,26 +147,26 @@ export class AsarFilesystem { } export async function readAsarHeader(archive: string): Promise { - const fd = await open(archive, "r") + const fd = await fsExtra.open(archive, "r") let size: number let headerBuf try { const sizeBuf = Buffer.allocUnsafe(8) - if ((await read(fd, sizeBuf, 0, 8, null as any)).bytesRead !== 8) { + if ((await fsExtra.read(fd, sizeBuf, 0, 8, null as any)).bytesRead !== 8) { throw new Error("Unable to read header size") } - const sizePickle = createFromBuffer(sizeBuf) + const sizePickle = chromiumPickleJs.createFromBuffer(sizeBuf) size = sizePickle.createIterator().readUInt32() headerBuf = Buffer.allocUnsafe(size) - if ((await read(fd, headerBuf, 0, size, null as any)).bytesRead !== size) { + if ((await fsExtra.read(fd, headerBuf, 0, size, null as any)).bytesRead !== size) { throw new Error("Unable to read header") } } finally { - await close(fd) + await fsExtra.close(fd) } - const headerPickle = createFromBuffer(headerBuf) + const headerPickle = chromiumPickleJs.createFromBuffer(headerBuf) return { header: headerPickle.createIterator().readString(), size } } @@ -188,15 +188,15 @@ async function readFileFromAsar(filesystem: AsarFilesystem, filename: string, in } if (info.unpacked) { - return await readFile(path.join(`${filesystem.src}.unpacked`, filename)) + return await fsExtra.readFile(path.join(`${filesystem.src}.unpacked`, filename)) } - const fd = await open(filesystem.src, "r") + const fd = await fsExtra.open(filesystem.src, "r") try { const offset = 8 + filesystem.headerSize + parseInt(info.offset!, 10) - await read(fd, buffer, 0, size, offset) + await fsExtra.read(fd, buffer, 0, size, offset) } finally { - await close(fd) + await fsExtra.close(fd) } return buffer } diff --git a/packages/app-builder-lib/src/asar/asarFileChecker.ts b/packages/app-builder-lib/src/asar/asarFileChecker.ts index f589d66b7ab..34cb548e400 100644 --- a/packages/app-builder-lib/src/asar/asarFileChecker.ts +++ b/packages/app-builder-lib/src/asar/asarFileChecker.ts @@ -1,5 +1,5 @@ import type { FilesystemEntry, FilesystemFileEntry } from "@electron/asar/lib/filesystem" -import { dynamicImport } from "../util/dynamicImport" +import { dynamicImport } from "../util/dynamicImport.js" export async function checkFileInArchive(asarFile: string, relativeFile: string, messagePrefix: string): Promise { const asar = await dynamicImport("@electron/asar") diff --git a/packages/app-builder-lib/src/asar/asarUtil.ts b/packages/app-builder-lib/src/asar/asarUtil.ts index fbaec935185..2bef37241e3 100644 --- a/packages/app-builder-lib/src/asar/asarUtil.ts +++ b/packages/app-builder-lib/src/asar/asarUtil.ts @@ -1,16 +1,16 @@ import type { AsarStreamType, AsarDirectory } from "@electron/asar" -import { isEmptyOrSpaces, log } from "builder-util" -import { dynamicImport } from "../util/dynamicImport" -import { exists, Filter, FilterStats } from "builder-util/out/fs" -import * as fs from "fs-extra" -import { readlink } from "fs-extra" +import { exists, Filter, FilterStats, isEmptyOrSpaces, log } from "builder-util" +import { dynamicImport } from "../util/dynamicImport.js" +import fs from "fs-extra" + import * as path from "path" -import { AsarOptions } from "../options/PlatformSpecificBuildOptions" -import { PlatformPackager } from "../platformPackager" -import { ResolvedFileSet, getDestinationPath } from "../util/appFileCopier" -import { detectUnpackedDirs } from "./unpackDetector" +import { AsarOptions } from "../options/PlatformSpecificBuildOptions.js" +import { PlatformPackager } from "../platformPackager.js" +import { ResolvedFileSet, getDestinationPath } from "../util/appFileCopier.js" +import { detectUnpackedDirs } from "./unpackDetector.js" import { Readable } from "stream" import * as os from "os" +const { readlink } = fs const resolvePath = async (file: string | undefined): Promise => (file && (await exists(file)) ? fs.realpath(file).catch(() => path.resolve(file)) : undefined) const resolvePaths = async (filepaths: (string | undefined)[]) => { diff --git a/packages/app-builder-lib/src/asar/integrity.ts b/packages/app-builder-lib/src/asar/integrity.ts index 10012924b94..868285d10db 100644 --- a/packages/app-builder-lib/src/asar/integrity.ts +++ b/packages/app-builder-lib/src/asar/integrity.ts @@ -2,8 +2,8 @@ import { FilterStats, log, statOrNull, walk } from "builder-util" import { createHash } from "crypto" import { readdir } from "fs/promises" import * as path from "path" -import { FileMatcher } from "../fileMatcher" -import { readAsarHeader } from "./asar" +import { FileMatcher } from "../fileMatcher.js" +import { readAsarHeader } from "./asar.js" export interface AsarIntegrityOptions { readonly resourcesPath: string diff --git a/packages/app-builder-lib/src/asar/unpackDetector.ts b/packages/app-builder-lib/src/asar/unpackDetector.ts index fce460c4c2d..5be0d6d2c88 100644 --- a/packages/app-builder-lib/src/asar/unpackDetector.ts +++ b/packages/app-builder-lib/src/asar/unpackDetector.ts @@ -1,7 +1,7 @@ import { FilterStats, log } from "builder-util" import { isBinaryFileSync } from "isbinaryfile" import * as path from "path" -import { ResolvedFileSet } from "../util/appFileCopier" +import { ResolvedFileSet } from "../util/appFileCopier.js" export function isLibOrExe(file: string): boolean { // https://github.com/electron-userland/electron-builder/issues/3038 diff --git a/packages/app-builder-lib/src/binDownload.ts b/packages/app-builder-lib/src/binDownload.ts index 75663aba8fe..785d00dc3fb 100644 --- a/packages/app-builder-lib/src/binDownload.ts +++ b/packages/app-builder-lib/src/binDownload.ts @@ -1,10 +1,10 @@ import * as fs from "fs/promises" import { log, parseValidEnvVarUrl } from "builder-util" -import { dynamicImport } from "./util/dynamicImport" +import { dynamicImport } from "./util/dynamicImport.js" import { Nullish } from "builder-util-runtime" -import { sanitizeFileName } from "builder-util/out/filename" +import { sanitizeFileName } from "builder-util/internal" import * as path from "path" -import { downloadBuilderToolset, getBinariesMirrorUrl, getCacheDirectory } from "./util/electronGet" +import { downloadBuilderToolset, getBinariesMirrorUrl, getCacheDirectory } from "./util/electronGet.js" const versionToPromise = new Map>() diff --git a/packages/app-builder-lib/src/codeSign/certInfo.ts b/packages/app-builder-lib/src/codeSign/certInfo.ts index 47fe518acce..eb87e79ba88 100644 --- a/packages/app-builder-lib/src/codeSign/certInfo.ts +++ b/packages/app-builder-lib/src/codeSign/certInfo.ts @@ -2,8 +2,10 @@ import { createDecipheriv, createHash } from "crypto" import * as asn1js from "asn1js" import * as pkijs from "pkijs" import { Crypto as PeculiarCrypto } from "@peculiar/webcrypto" -import { readFile } from "fs-extra" + import { log } from "builder-util" +import _fsExtra from "fs-extra" +const { readFile } = _fsExtra // OID for codeSigning extended key usage const CODE_SIGNING_OID = "1.3.6.1.5.5.7.3.3" diff --git a/packages/app-builder-lib/src/codeSign/codesign.ts b/packages/app-builder-lib/src/codeSign/codesign.ts index ad3c6561a2a..0507a3f684c 100644 --- a/packages/app-builder-lib/src/codeSign/codesign.ts +++ b/packages/app-builder-lib/src/codeSign/codesign.ts @@ -1,7 +1,9 @@ import { decodeCscLinkBase64, InvalidConfigurationError, resolveCscLinkPath, statOrNull } from "builder-util" -import { outputFile } from "fs-extra" + import { TmpDir } from "temp-file" -import { download } from "../binDownload" +import { download } from "../binDownload.js" +import _fsExtra from "fs-extra" +const { outputFile } = _fsExtra /** @private */ export async function importCertificate(cscLink: string, tmpDir: TmpDir, currentDir: string): Promise { diff --git a/packages/app-builder-lib/src/codeSign/macCodeSign.ts b/packages/app-builder-lib/src/codeSign/macCodeSign.ts index 8f717dfda93..80ce2ec4e24 100644 --- a/packages/app-builder-lib/src/codeSign/macCodeSign.ts +++ b/packages/app-builder-lib/src/codeSign/macCodeSign.ts @@ -1,6 +1,6 @@ import type { SignOptions } from "@electron/osx-sign/dist/cjs/types" import { copyFile, exec, Fields, InvalidConfigurationError, isEmptyOrSpaces, isEnvTrue, isPullRequest, log, Logger, retry, TmpDir, unlinkIfExists } from "builder-util" -import { dynamicImport } from "../util/dynamicImport" +import { dynamicImport } from "../util/dynamicImport.js" import { Nullish } from "builder-util-runtime" import { createHash, randomBytes } from "crypto" import { rename } from "fs/promises" @@ -8,8 +8,8 @@ import { Lazy } from "lazy-val" import { homedir, tmpdir } from "os" import * as path from "path" import { getTempName } from "temp-file" -import { isAutoDiscoveryCodeSignIdentity } from "../util/flags" -import { importCertificate } from "./codesign" +import { isAutoDiscoveryCodeSignIdentity } from "../util/flags.js" +import { importCertificate } from "./codesign.js" export const appleCertificatePrefixes = ["Developer ID Application:", "Developer ID Installer:", "3rd Party Mac Developer Application:", "3rd Party Mac Developer Installer:"] @@ -107,7 +107,7 @@ const bundledCertKeychainAdded = new Lazy(async () => { const keychainPath = path.join(cacheDir, "electron-builder-root-certs.keychain") const results = await Promise.all([ listUserKeychains(), - copyFile(path.join(__dirname, "..", "..", "certs", "root_certs.keychain"), tmpKeychainPath).then(() => rename(tmpKeychainPath, keychainPath)), + copyFile(path.join(import.meta.dirname, "..", "..", "certs", "root_certs.keychain"), tmpKeychainPath).then(() => rename(tmpKeychainPath, keychainPath)), ]) const list = results[0] if (!list.includes(keychainPath)) { diff --git a/packages/app-builder-lib/src/codeSign/signManager.ts b/packages/app-builder-lib/src/codeSign/signManager.ts index 6825c355017..ee6ac00ed8b 100644 --- a/packages/app-builder-lib/src/codeSign/signManager.ts +++ b/packages/app-builder-lib/src/codeSign/signManager.ts @@ -1,9 +1,9 @@ import { MemoLazy, Nullish } from "builder-util-runtime" import { Lazy } from "lazy-val" -import { Target } from "../core" -import { WindowsConfiguration } from "../options/winOptions" -import { WindowsSignOptions } from "./windowsCodeSign" -import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager" +import { Target } from "../core.js" +import { WindowsConfiguration } from "../options/winOptions.js" +import { WindowsSignOptions } from "./windowsCodeSign.js" +import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager.js" export interface SignManager { readonly computedPublisherName: Lazy | null> diff --git a/packages/app-builder-lib/src/codeSign/windowsCodeSign.ts b/packages/app-builder-lib/src/codeSign/windowsCodeSign.ts index 8eb63b66774..71a196dd3cf 100644 --- a/packages/app-builder-lib/src/codeSign/windowsCodeSign.ts +++ b/packages/app-builder-lib/src/codeSign/windowsCodeSign.ts @@ -1,6 +1,6 @@ import { log, retry } from "builder-util" -import { WindowsConfiguration } from "../options/winOptions" -import { WinPackager } from "../winPackager" +import { WindowsConfiguration } from "../options/winOptions.js" +import { WinPackager } from "../winPackager.js" export interface WindowsSignOptions { readonly path: string diff --git a/packages/app-builder-lib/src/codeSign/windowsSignAzureManager.ts b/packages/app-builder-lib/src/codeSign/windowsSignAzureManager.ts index ba81309a33c..e5edbcaea7b 100644 --- a/packages/app-builder-lib/src/codeSign/windowsSignAzureManager.ts +++ b/packages/app-builder-lib/src/codeSign/windowsSignAzureManager.ts @@ -1,11 +1,11 @@ import { asArray, log } from "builder-util" import { MemoLazy } from "builder-util-runtime" import { Lazy } from "lazy-val" -import { WindowsAzureSigningConfiguration, WindowsConfiguration } from "../options/winOptions" -import { WinPackager } from "../winPackager" -import { SignManager } from "./signManager" -import { WindowsSignOptions } from "./windowsCodeSign" -import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager" +import { WindowsAzureSigningConfiguration, WindowsConfiguration } from "../options/winOptions.js" +import { WinPackager } from "../winPackager.js" +import { SignManager } from "./signManager.js" +import { WindowsSignOptions } from "./windowsCodeSign.js" +import { CertificateFromStoreInfo, FileCodeSigningInfo } from "./windowsSignToolManager.js" export class WindowsSignAzureManager implements SignManager { private readonly platformSpecificBuildOptions: WindowsConfiguration diff --git a/packages/app-builder-lib/src/codeSign/windowsSignToolManager.ts b/packages/app-builder-lib/src/codeSign/windowsSignToolManager.ts index c04126871dc..5457d7f2e9d 100644 --- a/packages/app-builder-lib/src/codeSign/windowsSignToolManager.ts +++ b/packages/app-builder-lib/src/codeSign/windowsSignToolManager.ts @@ -1,20 +1,22 @@ import { asArray, InvalidConfigurationError, log, retry } from "builder-util" import { MemoLazy, parseDn } from "builder-util-runtime" -import { rename } from "fs-extra" + import { Lazy } from "lazy-val" import * as path from "path" -import { Target } from "../core" -import { WindowsConfiguration } from "../options/winOptions" -import AppXTarget from "../targets/AppxTarget" -import { getSignToolPath } from "../toolsets/windows" -import { ToolInfo } from "../util/bundledTool" -import { resolveFunction } from "../util/resolve" -import { readCertInfo } from "./certInfo" -import { VmManager } from "../vm/vm" -import { WinPackager } from "../winPackager" -import { importCertificate } from "./codesign" -import { SignManager } from "./signManager" -import { WindowsSignOptions } from "./windowsCodeSign" +import { Target } from "../core.js" +import { WindowsConfiguration } from "../options/winOptions.js" +import AppXTarget from "../targets/AppxTarget.js" +import { getSignToolPath } from "../toolsets/windows.js" +import { ToolInfo } from "../util/bundledTool.js" +import { resolveFunction } from "../util/resolve.js" +import { readCertInfo } from "./certInfo.js" +import { VmManager } from "../vm/vm.js" +import { WinPackager } from "../winPackager.js" +import { importCertificate } from "./codesign.js" +import { SignManager } from "./signManager.js" +import { WindowsSignOptions } from "./windowsCodeSign.js" +import _fsExtra from "fs-extra" +const { rename } = _fsExtra export type CustomWindowsSign = (configuration: CustomWindowsSignTaskConfiguration, packager?: WinPackager) => Promise diff --git a/packages/app-builder-lib/src/configuration.ts b/packages/app-builder-lib/src/configuration.ts index fa309ae9bec..ffa26fe9cbc 100644 --- a/packages/app-builder-lib/src/configuration.ts +++ b/packages/app-builder-lib/src/configuration.ts @@ -1,22 +1,22 @@ import { Arch } from "builder-util" -import { BeforeBuildContext, Target } from "./core" -import { ElectronBrandingOptions } from "./electron/ElectronFramework" -import { PrepareApplicationStageDirectoryOptions } from "./Framework" -import { AppXOptions } from "./options/AppXOptions" -import { AppImageOptions, DebOptions, FlatpakOptions, LinuxConfiguration, LinuxTargetSpecificOptions, PacmanOptions, RpmOptions } from "./options/linuxOptions" -import { DmgOptions, MacConfiguration, MasConfiguration } from "./options/macOptions" -import { MsiOptions } from "./options/MsiOptions" -import { MsiWrappedOptions } from "./options/MsiWrappedOptions" -import { PkgOptions } from "./options/pkgOptions" -import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions" -import { SnapcraftOptions, SnapOptions } from "./options/SnapOptions" -import { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions" -import { WindowsConfiguration } from "./options/winOptions" -import { BuildResult } from "./packager" -import { ArtifactBuildStarted, ArtifactCreated } from "./packagerApi" -import { PlatformPackager } from "./platformPackager" -import { NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions" -import { ElectronDownloadOptions, ElectronGetOptions } from "./util/electronGet" +import { BeforeBuildContext, Target } from "./core.js" +import { ElectronBrandingOptions } from "./electron/ElectronFramework.js" +import { PrepareApplicationStageDirectoryOptions } from "./Framework.js" +import { AppXOptions } from "./options/AppXOptions.js" +import { AppImageOptions, DebOptions, FlatpakOptions, LinuxConfiguration, LinuxTargetSpecificOptions, PacmanOptions, RpmOptions } from "./options/linuxOptions.js" +import { DmgOptions, MacConfiguration, MasConfiguration } from "./options/macOptions.js" +import { MsiOptions } from "./options/MsiOptions.js" +import { MsiWrappedOptions } from "./options/MsiWrappedOptions.js" +import { PkgOptions } from "./options/pkgOptions.js" +import { PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions.js" +import { SnapcraftOptions, SnapOptions } from "./options/SnapOptions.js" +import { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions.js" +import { WindowsConfiguration } from "./options/winOptions.js" +import { BuildResult } from "./packager.js" +import { ArtifactBuildStarted, ArtifactCreated } from "./packagerApi.js" +import { PlatformPackager } from "./platformPackager.js" +import { NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions.js" +import { ElectronDownloadOptions, ElectronGetOptions } from "./util/electronGet.js" // duplicate appId here because it is important /** diff --git a/packages/app-builder-lib/src/electron/ElectronFramework.ts b/packages/app-builder-lib/src/electron/ElectronFramework.ts index 652c8b0282b..6937ea9fff9 100644 --- a/packages/app-builder-lib/src/electron/ElectronFramework.ts +++ b/packages/app-builder-lib/src/electron/ElectronFramework.ts @@ -12,22 +12,24 @@ import { to7zaOutputSwitch, unlinkIfExists, } from "builder-util" -import { emptyDir, readdir, rename, rm } from "fs-extra" + import * as path from "path" import asyncPool from "tiny-async-pool" -import { Configuration } from "../configuration" -import { BeforeCopyExtraFilesOptions, Framework, PrepareApplicationStageDirectoryOptions } from "../Framework" -import { Packager, Platform } from "../index" -import { LinuxPackager } from "../linuxPackager" -import { MacPackager } from "../macPackager" -import { getTemplatePath } from "../util/pathManager" -import { resolveFunction } from "../util/resolve" -import { downloadElectronArtifactZip, ElectronDownloadOptions, ElectronGetOptions, extractArchive } from "../util/electronGet" +import { Configuration } from "../configuration.js" +import { BeforeCopyExtraFilesOptions, Framework, PrepareApplicationStageDirectoryOptions } from "../Framework.js" +import { Packager, Platform } from "../index.js" +import { LinuxPackager } from "../linuxPackager.js" +import { MacPackager } from "../macPackager.js" +import { getTemplatePath } from "../util/pathManager.js" +import { resolveFunction } from "../util/resolve.js" +import { downloadElectronArtifactZip, ElectronDownloadOptions, ElectronGetOptions, extractArchive } from "../util/electronGet.js" export { ElectronDownloadOptions } -import { createMacApp } from "./electronMac" -import { computeElectronVersion, getElectronVersionFromInstalled } from "./electronVersion" -import { addWinAsarIntegrity } from "./electronWin" -import { FFMPEGInjector } from "./injectFFMPEG" +import { createMacApp } from "./electronMac.js" +import { computeElectronVersion, getElectronVersionFromInstalled } from "./electronVersion.js" +import { addWinAsarIntegrity } from "./electronWin.js" +import { FFMPEGInjector } from "./injectFFMPEG.js" +import _fsExtra from "fs-extra" +const { emptyDir, readdir, rename, rm } = _fsExtra export type ElectronPlatformName = "darwin" | "linux" | "win32" | "mas" @@ -197,7 +199,7 @@ export async function createElectronFrameworkSupport(configuration: Configuratio /** * Unpacks a custom or default Electron distribution into the app output directory. */ -async function unpack(prepareOptions: PrepareApplicationStageDirectoryOptions, downloadOptions: ElectronDownloadOptions, distMacOsAppName: string): Promise { +async function unpack(prepareOptions: PrepareApplicationStageDirectoryOptions, downloadOptions: ElectronDownloadOptions, _distMacOsAppName: string): Promise { async function selectElectron(filepath: string) { const resolvedDist = path.isAbsolute(filepath) ? filepath : path.resolve(packager.projectDir, filepath) diff --git a/packages/app-builder-lib/src/electron/electronMac.ts b/packages/app-builder-lib/src/electron/electronMac.ts index 5b46b793fd3..8f252cf55bf 100644 --- a/packages/app-builder-lib/src/electron/electronMac.ts +++ b/packages/app-builder-lib/src/electron/electronMac.ts @@ -2,12 +2,12 @@ import { asArray, copyOrLinkFile, getPlatformIconFileName, InvalidConfigurationE import { rename, utimes } from "fs/promises" import * as path from "path" import * as fs from "fs" -import { filterCFBundleIdentifier } from "../appInfo" -import { AsarIntegrity } from "../asar/integrity" -import { MacPackager } from "../macPackager" -import { normalizeExt } from "../platformPackager" -import { savePlistFile, parsePlistFile, PlistObject, PlistValue } from "../util/plist" -import { createBrandingOpts } from "./ElectronFramework" +import { filterCFBundleIdentifier } from "../appInfo.js" +import { AsarIntegrity } from "../asar/integrity.js" +import { MacPackager } from "../macPackager.js" +import { normalizeExt } from "../platformPackager.js" +import { savePlistFile, parsePlistFile, PlistObject, PlistValue } from "../util/plist.js" +import { createBrandingOpts } from "./ElectronFramework.js" function doRename(basePath: string, oldName: string, newName: string) { return rename(path.join(basePath, oldName), path.join(basePath, newName)) diff --git a/packages/app-builder-lib/src/electron/electronVersion.ts b/packages/app-builder-lib/src/electron/electronVersion.ts index 7324a0d9a20..d7bb1b0a764 100644 --- a/packages/app-builder-lib/src/electron/electronVersion.ts +++ b/packages/app-builder-lib/src/electron/electronVersion.ts @@ -1,13 +1,13 @@ import { httpExecutor, InvalidConfigurationError, log } from "builder-util" import { parseXml } from "builder-util-runtime" -import { readJson } from "fs-extra" +import fsExtra from "fs-extra" import { Lazy } from "lazy-val" import * as path from "path" import * as semver from "semver" -import { Configuration } from "../configuration" -import { getConfig } from "../util/config/config" -import { orNullIfFileNotExist } from "../util/config/load" -import { getProjectRootPath } from "./search-module" +import { Configuration } from "../configuration.js" +import { getConfig } from "../util/config/config.js" +import { orNullIfFileNotExist } from "../util/config/load.js" +import { getProjectRootPath } from "./search-module.js" export type MetadataValue = Lazy | null> @@ -26,7 +26,7 @@ export async function getElectronVersion(projectDir: string, config?: Configurat export async function getElectronVersionFromInstalled(projectDir: string): Promise { for (const name of electronPackages) { try { - return (await readJson(path.join(projectDir, "node_modules", name, "package.json"))).version + return (await fsExtra.readJson(path.join(projectDir, "node_modules", name, "package.json"))).version } catch (e: any) { if (e.code !== "ENOENT") { log.warn({ name, error: e }, `cannot read electron version package.json`) @@ -39,7 +39,7 @@ export async function getElectronVersionFromInstalled(projectDir: string): Promi export async function getElectronPackage(projectDir: string) { for (const name of electronPackages) { try { - return await readJson(path.join(projectDir, "node_modules", name, "package.json")) + return await fsExtra.readJson(path.join(projectDir, "node_modules", name, "package.json")) } catch (e: any) { if (e.code !== "ENOENT") { log.warn({ name, error: e }, `cannot find electron in package.json`) @@ -59,7 +59,7 @@ export async function computeElectronVersion(projectDir: string): Promise { diff --git a/packages/app-builder-lib/src/fileMatcher.ts b/packages/app-builder-lib/src/fileMatcher.ts index e1703c0b334..00cf89dca02 100644 --- a/packages/app-builder-lib/src/fileMatcher.ts +++ b/packages/app-builder-lib/src/fileMatcher.ts @@ -3,9 +3,11 @@ import { Nullish } from "builder-util-runtime" import { mkdir } from "fs/promises" import { Minimatch } from "minimatch" import * as path from "path" -import { Configuration, FileSet, Packager, PlatformSpecificBuildOptions } from "./index" -import { PlatformPackager } from "./platformPackager" -import { createFilter, hasMagic } from "./util/filter" +import type { Configuration } from "./configuration.js" +import type { Packager } from "./packager.js" +import { FileSet, PlatformSpecificBuildOptions } from "./options/PlatformSpecificBuildOptions.js" +import { PlatformPackager } from "./platformPackager.js" +import { createFilter, hasMagic } from "./util/filter.js" // https://github.com/electron-userland/electron-builder/issues/733 const minimatchOptions = { dot: true } diff --git a/packages/app-builder-lib/src/fileTransformer.ts b/packages/app-builder-lib/src/fileTransformer.ts index 076108a026a..2b57a0b32cf 100644 --- a/packages/app-builder-lib/src/fileTransformer.ts +++ b/packages/app-builder-lib/src/fileTransformer.ts @@ -1,8 +1,8 @@ import { debug, FileTransformer, log } from "builder-util" import { readFile } from "fs/promises" import * as path from "path" -import { Configuration } from "./configuration" -import { Packager } from "./packager" +import { Configuration } from "./configuration.js" +import { Packager } from "./packager.js" import { deepAssign } from "builder-util-runtime" /** @internal */ diff --git a/packages/app-builder-lib/src/forge-maker.ts b/packages/app-builder-lib/src/forge-maker.ts index 9b1f17d09ac..a56f36400da 100644 --- a/packages/app-builder-lib/src/forge-maker.ts +++ b/packages/app-builder-lib/src/forge-maker.ts @@ -1,6 +1,6 @@ import * as path from "path" -import { build } from "./index" -import { PackagerOptions } from "./packagerApi" +import { build } from "./index.js" +import { PackagerOptions } from "./packagerApi.js" export interface ForgeOptions { readonly dir: string diff --git a/packages/app-builder-lib/src/frameworks/LibUiFramework.ts b/packages/app-builder-lib/src/frameworks/LibUiFramework.ts index 523a47f7665..a032eb4bb53 100644 --- a/packages/app-builder-lib/src/frameworks/LibUiFramework.ts +++ b/packages/app-builder-lib/src/frameworks/LibUiFramework.ts @@ -1,13 +1,13 @@ import { executeAppBuilder } from "builder-util" -import { emptyDir } from "fs-extra" +import fsExtra from "fs-extra" import { chmod, mkdir, rename, writeFile } from "fs/promises" import * as path from "path" -import { AfterPackContext } from "../configuration" -import { Platform } from "../core" -import { Framework, PrepareApplicationStageDirectoryOptions } from "../Framework" -import { LinuxPackager } from "../linuxPackager" -import { MacPackager } from "../macPackager" -import { savePlistFile } from "../util/plist" +import { AfterPackContext } from "../configuration.js" +import { Platform } from "../core.js" +import { Framework, PrepareApplicationStageDirectoryOptions } from "../Framework.js" +import { LinuxPackager } from "../linuxPackager.js" +import { MacPackager } from "../macPackager.js" +import { savePlistFile } from "../util/plist.js" export class LibUiFramework implements Framework { readonly name: string = "libui" @@ -33,7 +33,7 @@ export class LibUiFramework implements Framework { } async prepareApplicationStageDirectory(options: PrepareApplicationStageDirectoryOptions) { - await emptyDir(options.appOutDir) + await fsExtra.emptyDir(options.appOutDir) const packager = options.packager const platform = packager.platform diff --git a/packages/app-builder-lib/src/index.ts b/packages/app-builder-lib/src/index.ts index 57ce77277eb..4d07e14047e 100644 --- a/packages/app-builder-lib/src/index.ts +++ b/packages/app-builder-lib/src/index.ts @@ -1,13 +1,13 @@ import { InvalidConfigurationError, executeFinally, log } from "builder-util" import { asArray } from "builder-util-runtime" import { PublishOptions } from "electron-publish" -import { Packager } from "./packager" -import { PackagerOptions } from "./packagerApi" -import { PublishManager } from "./publish/PublishManager" -import { resolveFunction } from "./util/resolve" +import { Packager } from "./packager.js" +import { PackagerOptions } from "./packagerApi.js" +import { PublishManager } from "./publish/PublishManager.js" +import { resolveFunction } from "./util/resolve.js" export { Arch, archFromString, getArchSuffix } from "builder-util" -export { AppInfo } from "./appInfo" +export { AppInfo } from "./appInfo.js" export { AfterExtractContext, AfterPackContext, @@ -20,7 +20,7 @@ export { MetadataDirectories, PackContext, ToolsetConfig, -} from "./configuration" +} from "./configuration.js" export { BeforeBuildContext, CompressionLevel, @@ -32,12 +32,12 @@ export { TargetConfigType, TargetConfiguration, TargetSpecificOptions, -} from "./core" -export { ElectronBrandingOptions, ElectronPlatformName } from "./electron/ElectronFramework" -export { ElectronDownloadOptions } from "./util/electronGet" -export { AppXOptions } from "./options/AppXOptions" -export { CommonWindowsInstallerConfiguration } from "./options/CommonWindowsInstallerConfiguration" -export { FileAssociation } from "./options/FileAssociation" +} from "./core.js" +export { ElectronBrandingOptions, ElectronPlatformName } from "./electron/ElectronFramework.js" +export { ElectronDownloadOptions } from "./util/electronGet.js" +export { AppXOptions } from "./options/AppXOptions.js" +export { CommonWindowsInstallerConfiguration } from "./options/CommonWindowsInstallerConfiguration.js" +export { FileAssociation } from "./options/FileAssociation.js" export { AppImageOptions, CommonLinuxOptions, @@ -48,23 +48,23 @@ export { LinuxTargetSpecificOptions, PacmanOptions, RpmOptions, -} from "./options/linuxOptions" -export { DmgContent, DmgOptions, DmgWindow, MacConfiguration, MacOsTargetName, MasConfiguration } from "./options/macOptions" -export { AuthorMetadata, Metadata, RepositoryInfo } from "./options/metadata" -export { MsiOptions } from "./options/MsiOptions" -export { MsiWrappedOptions } from "./options/MsiWrappedOptions" -export { BackgroundAlignment, BackgroundScaling, PkgBackgroundOptions, PkgOptions } from "./options/pkgOptions" -export { AsarOptions, FileSet, FilesBuildOptions, PlatformSpecificBuildOptions, Protocol, ReleaseInfo } from "./options/PlatformSpecificBuildOptions" -export { PlugDescriptor, SlotDescriptor, SnapcraftOptions, SnapOptions } from "./options/SnapOptions" -export { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions" -export { WindowsAzureSigningConfiguration, WindowsConfiguration, WindowsSigntoolConfiguration } from "./options/winOptions" -export { BuildResult, Packager } from "./packager" -export { ArtifactBuildStarted, ArtifactCreated, PackagerOptions } from "./packagerApi" -export { CommonNsisOptions, CustomNsisBinary, NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions" +} from "./options/linuxOptions.js" +export type { DmgContent, DmgOptions, DmgWindow, MacConfiguration, MacOsTargetName, MasConfiguration } from "./options/macOptions.js" +export { AuthorMetadata, Metadata, RepositoryInfo } from "./options/metadata.js" +export { MsiOptions } from "./options/MsiOptions.js" +export { MsiWrappedOptions } from "./options/MsiWrappedOptions.js" +export { BackgroundAlignment, BackgroundScaling, PkgBackgroundOptions, PkgOptions } from "./options/pkgOptions.js" +export { AsarOptions, FileSet, FilesBuildOptions, PlatformSpecificBuildOptions, Protocol, ReleaseInfo } from "./options/PlatformSpecificBuildOptions.js" +export { PlugDescriptor, SlotDescriptor, SnapcraftOptions, SnapOptions } from "./options/SnapOptions.js" +export { SquirrelWindowsOptions } from "./options/SquirrelWindowsOptions.js" +export { WindowsAzureSigningConfiguration, WindowsConfiguration, WindowsSigntoolConfiguration } from "./options/winOptions.js" +export { BuildResult, Packager } from "./packager.js" +export { ArtifactBuildStarted, ArtifactCreated, PackagerOptions } from "./packagerApi.js" +export { CommonNsisOptions, CustomNsisBinary, NsisOptions, NsisWebOptions, PortableOptions } from "./targets/nsis/nsisOptions.js" export { CancellationToken, ProgressInfo } from "builder-util-runtime" export { PublishOptions, UploadTask } from "electron-publish" -export { WindowsSignOptions } from "./codeSign/windowsCodeSign" +export { WindowsSignOptions } from "./codeSign/windowsCodeSign.js" export { CertificateFromStoreInfo, CustomWindowsSign, @@ -72,15 +72,15 @@ export { FileCodeSigningInfo, WindowsSignTaskConfiguration, WindowsSignToolManager, -} from "./codeSign/windowsSignToolManager" -export { ToolInfo } from "./util/bundledTool" -export { ForgeOptions, buildForge } from "./forge-maker" -export { Framework, PrepareApplicationStageDirectoryOptions } from "./Framework" -export { LinuxPackager } from "./linuxPackager" -export { CustomMacSign, CustomMacSignOptions, MacPackager } from "./macPackager" -export { PlatformPackager } from "./platformPackager" -export { PublishManager } from "./publish/PublishManager" -export { WinPackager } from "./winPackager" +} from "./codeSign/windowsSignToolManager.js" +export { ToolInfo } from "./util/bundledTool.js" +export { ForgeOptions, buildForge } from "./forge-maker.js" +export { Framework, PrepareApplicationStageDirectoryOptions } from "./Framework.js" +export { LinuxPackager } from "./linuxPackager.js" +export { CustomMacSign, CustomMacSignOptions, MacPackager } from "./macPackager.js" +export { PlatformPackager } from "./platformPackager.js" +export { PublishManager } from "./publish/PublishManager.js" +export { WinPackager } from "./winPackager.js" const expectedOptions = new Set(["publish", "targets", "mac", "win", "linux", "projectDir", "platformPackagerFactory", "config", "effectiveOptionComputed", "prepackaged"]) diff --git a/packages/app-builder-lib/src/indexInternal.ts b/packages/app-builder-lib/src/indexInternal.ts new file mode 100644 index 00000000000..ed2c6b293ff --- /dev/null +++ b/packages/app-builder-lib/src/indexInternal.ts @@ -0,0 +1,64 @@ +export { AsarFilesystem, readAsar, readAsarJson } from "./asar/asar.js" +export { AsarIntegrity } from "./asar/integrity.js" +export { getBin, getBinFromCustomLoc, getBinFromUrl } from "./binDownload.js" +export { readCertInfo, _testingOnly } from "./codeSign/certInfo.js" +export { createKeychain, findIdentity, isSignAllowed, removeKeychain } from "./codeSign/macCodeSign.js" +export type { Identity } from "./codeSign/macCodeSign.js" +export { CustomWindowsSign, WindowsSignTaskConfiguration } from "./codeSign/windowsSignToolManager.js" +export { Configuration, ToolsetConfig } from "./configuration.js" +export { Publish } from "./core.js" +export { getElectronVersion } from "./electron/electronVersion.js" +export { FileMatcher, getFileMatchers, GetFileMatchersOptions } from "./fileMatcher.js" +export { MacTargetHelper } from "./mac/MacTargetHelper.js" +export { HoisterDependencyKind, HoisterResult, HoisterTree, hoist } from "./node-module-collector/hoist.js" +export { + determinePackageManagerEnv, + getCollectorByPackageManager, + PnpmNodeModulesCollector, + YarnNodeModulesCollector, + YarnBerryNodeModulesCollector, + BunNodeModulesCollector, + TraversalNodeModulesCollector, +} from "./node-module-collector/index.js" +export { LogMessageByKey, ModuleManager } from "./node-module-collector/moduleManager.js" +export { NodeModulesCollector } from "./node-module-collector/nodeModulesCollector.js" +export { detectPackageManager, PM } from "./node-module-collector/packageManager.js" +export { DoPackOptions, computeSafeArtifactNameIfNeeded } from "./platformPackager.js" +export { createPublisher } from "./publish/PublishManager.js" +export { createUpdateInfoTasks, writeUpdateInfoFiles, UpdateInfoFileTask } from "./publish/updateInfoBuilder.js" +export { validateCriticalPathString } from "./targets/appimage/appImageUtil.js" +export { copyMimeTypes } from "./targets/appimage/appLauncher.js" +export { buildBlockMap } from "./targets/blockmap/blockmap.js" +export { createBlockmap } from "./targets/differentialUpdateInfoBuilder.js" +export type { Defines } from "./targets/nsis/Defines.js" +export { NsisScriptGenerator, nsisEscapeString } from "./targets/nsis/nsisScriptGenerator.js" +export { checkMakensisOutput, verifyInstallerSize } from "./targets/nsis/nsisValidation.js" +export { computeArchToTargetNamesMap } from "./targets/targetFactory.js" +export { getLinuxToolsMacToolset, getLinuxToolsPath } from "./toolsets/linux.js" +export { getWindowsKitsBundle } from "./toolsets/windows.js" +export { CacheState } from "./util/cacheState.js" +export { computeDefaultAppDirectory, doMergeConfigs, getConfig, validateConfiguration } from "./util/config/config.js" +export { orNullIfFileNotExist, loadEnv } from "./util/config/load.js" +export { validateSchema } from "./util/config/schemaValidator.js" +export { + ArtifactDownloadOptions, + ElectronDownloadOptions, + ElectronGetOptions, + downloadBuilderToolset, + downloadElectronArtifact, + getCacheDirectory, + getBinariesMirrorUrl, +} from "./util/electronGet.js" +export { buildSourceCandidates, convertIcon, getPngSize } from "./util/iconConverter.js" +export { getLicenseAssets, getLicenseFiles } from "./util/license.js" +export { expandMacro } from "./util/macroExpander.js" +export type { NodeModuleInfo } from "./util/packageDependencies.js" +export { PlistObject, parsePlistFile } from "./util/plist.js" +export { getRepositoryInfo } from "./util/repositoryInfo.js" +export { ResourceEditOptions, editWindowsResources } from "./util/resEdit.js" +export { withToolsetLock } from "./util/toolsetLock.js" +export { installDependencies, installOrRebuild, nodeGypRebuild } from "./util/yarn.js" +export { PACKAGE_VERSION } from "./version.js" +export { ParallelsVmManager } from "./vm/ParallelsVm.js" +export { VmManager, getWindowsVm, getLinuxVm } from "./vm/vm.js" +export { execWine } from "./wine.js" diff --git a/packages/app-builder-lib/src/linuxPackager.ts b/packages/app-builder-lib/src/linuxPackager.ts index 5ec467f50ea..c2023e7bc0d 100644 --- a/packages/app-builder-lib/src/linuxPackager.ts +++ b/packages/app-builder-lib/src/linuxPackager.ts @@ -1,15 +1,15 @@ import { Arch } from "builder-util" -import { sanitizeFileName } from "builder-util/out/filename" -import { DIR_TARGET, Platform, Target } from "./core" -import { LinuxConfiguration } from "./options/linuxOptions" -import { Packager } from "./packager" -import { PlatformPackager } from "./platformPackager" -import AppImageTarget from "./targets/appimage/AppImageTarget" -import FlatpakTarget from "./targets/FlatpakTarget" -import FpmTarget from "./targets/FpmTarget" -import { LinuxTargetHelper } from "./targets/LinuxTargetHelper" -import SnapTarget from "./targets/snap/SnapTarget" -import { createCommonTarget } from "./targets/targetFactory" +import { sanitizeFileName } from "builder-util/internal" +import { DIR_TARGET, Platform, Target } from "./core.js" +import { LinuxConfiguration } from "./options/linuxOptions.js" +import { Packager } from "./packager.js" +import { PlatformPackager } from "./platformPackager.js" +import AppImageTarget from "./targets/appimage/AppImageTarget.js" +import FlatpakTarget from "./targets/FlatpakTarget.js" +import FpmTarget from "./targets/FpmTarget.js" +import { LinuxTargetHelper } from "./targets/LinuxTargetHelper.js" +import SnapTarget from "./targets/snap/SnapTarget.js" +import { createCommonTarget } from "./targets/targetFactory.js" export class LinuxPackager extends PlatformPackager { readonly executableName: string @@ -42,11 +42,11 @@ export class LinuxPackager extends PlatformPackager { const targetClass: typeof AppImageTarget | typeof SnapTarget | typeof FlatpakTarget | typeof FpmTarget | null = (() => { switch (name) { case "appimage": - return require("./targets/appimage/AppImageTarget").default + return AppImageTarget case "snap": - return require("./targets/snap/SnapTarget").default + return SnapTarget case "flatpak": - return require("./targets/FlatpakTarget").default + return FlatpakTarget case "deb": case "rpm": case "sh": @@ -54,7 +54,7 @@ export class LinuxPackager extends PlatformPackager { case "pacman": case "apk": case "p5p": - return require("./targets/FpmTarget").default + return FpmTarget default: return null } diff --git a/packages/app-builder-lib/src/mac/MacTargetHelper.ts b/packages/app-builder-lib/src/mac/MacTargetHelper.ts index e46ec6e4c07..1d5e5019f08 100644 --- a/packages/app-builder-lib/src/mac/MacTargetHelper.ts +++ b/packages/app-builder-lib/src/mac/MacTargetHelper.ts @@ -2,13 +2,13 @@ import type { NotarizeOptionsNotaryTool, NotaryToolKeychainCredentials } from "@ import type { PerFileSignOptions, SigningDistributionType, SignOptions } from "@electron/osx-sign/dist/cjs/types" import type { Identity } from "@electron/osx-sign/dist/cjs/util-identities" import { Arch, InvalidConfigurationError, log, statOrNull } from "builder-util" -import { dynamicImport } from "../util/dynamicImport" +import { dynamicImport } from "../util/dynamicImport.js" import { Nullish } from "builder-util-runtime" import * as path from "path" -import { CertType, findIdentity, reportError } from "../codeSign/macCodeSign" -import type { MacPackager } from "../macPackager" -import { MacConfiguration, MasConfiguration } from "../options/macOptions" -import { getTemplatePath } from "../util/pathManager" +import { CertType, findIdentity, reportError } from "../codeSign/macCodeSign.js" +import type { MacPackager } from "../macPackager.js" +import { MacConfiguration, MasConfiguration } from "../options/macOptions.js" +import { getTemplatePath } from "../util/pathManager.js" export type PlatformType = "mas" | "mas-dev" | "mac" @@ -249,8 +249,12 @@ export class MacTargetHelper { } static getPlatformTypeFromTarget(targetName: string): PlatformType { - if (targetName === "mas") return "mas" - if (targetName === "mas-dev") return "mas-dev" + if (targetName === "mas") { + return "mas" + } + if (targetName === "mas-dev") { + return "mas-dev" + } return "mac" } diff --git a/packages/app-builder-lib/src/macPackager.ts b/packages/app-builder-lib/src/macPackager.ts index ecc6690b8f6..8f95bc2ad95 100644 --- a/packages/app-builder-lib/src/macPackager.ts +++ b/packages/app-builder-lib/src/macPackager.ts @@ -1,5 +1,8 @@ +import { createRequire } from "node:module" import { SignOptions } from "@electron/osx-sign/dist/cjs/types" -import { Identity } from "@electron/osx-sign/dist/cjs/util-identities" +import type { Identity } from "@electron/osx-sign/dist/cjs/util-identities" + +const _require = createRequire(import.meta.url) import { Arch, AsyncTaskManager, @@ -20,21 +23,21 @@ import * as fs from "fs/promises" import { mkdir, readdir } from "fs/promises" import { Lazy } from "lazy-val" import * as path from "path" -import { AppInfo } from "./appInfo" -import { CodeSigningInfo, createKeychain, CreateKeychainOptions, isSignAllowed, removeKeychain, sign } from "./codeSign/macCodeSign" -import { DIR_TARGET, Platform, Target } from "./core" -import { AfterPackContext, ElectronPlatformName } from "./index" -import { MacTargetHelper, PlatformType } from "./mac/MacTargetHelper" -import { MacConfiguration, MasConfiguration } from "./options/macOptions" -import { Packager } from "./packager" -import { chooseNotNull, DoPackOptions, PlatformPackager } from "./platformPackager" -import { ArchiveTarget } from "./targets/ArchiveTarget" -import { PkgTarget, prepareProductBuildArgs } from "./targets/pkg" -import { createCommonTarget, NoOpTarget } from "./targets/targetFactory" -import { dynamicImport } from "./util/dynamicImport" -import { isMacOsHighSierra } from "./util/macosVersion" -import { expandMacro as doExpandMacro } from "./util/macroExpander" -import { resolveFunction } from "./util/resolve" +import { AppInfo } from "./appInfo.js" +import { CodeSigningInfo, createKeychain, CreateKeychainOptions, isSignAllowed, removeKeychain, sign } from "./codeSign/macCodeSign.js" +import { DIR_TARGET, Platform, Target } from "./core.js" +import { AfterPackContext, ElectronPlatformName } from "./index.js" +import { MacTargetHelper, PlatformType } from "./mac/MacTargetHelper.js" +import { MacConfiguration, MasConfiguration } from "./options/macOptions.js" +import { Packager } from "./packager.js" +import { chooseNotNull, DoPackOptions, PlatformPackager } from "./platformPackager.js" +import { ArchiveTarget } from "./targets/ArchiveTarget.js" +import { PkgTarget, prepareProductBuildArgs } from "./targets/pkg.js" +import { createCommonTarget, NoOpTarget } from "./targets/targetFactory.js" +import { dynamicImport } from "./util/dynamicImport.js" +import { isMacOsHighSierra } from "./util/macosVersion.js" +import { expandMacro as doExpandMacro } from "./util/macroExpander.js" +import { resolveFunction } from "./util/resolve.js" export type CustomMacSignOptions = SignOptions export type CustomMacSign = (configuration: CustomMacSignOptions, packager: MacPackager) => Promise @@ -156,8 +159,10 @@ export class MacPackager extends PlatformPackager new DmgTarget(this, outDir)) + mapper(name, outDir => { + const { DmgTarget } = _require("dmg-builder") + return new DmgTarget(this, outDir) + }) break } diff --git a/packages/app-builder-lib/src/node-module-collector/bunNodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/bunNodeModulesCollector.ts index bbfb15404b6..21c3e42853f 100644 --- a/packages/app-builder-lib/src/node-module-collector/bunNodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/bunNodeModulesCollector.ts @@ -1,7 +1,7 @@ import { log } from "builder-util" -import { PM } from "./packageManager" -import { TraversedDependency } from "./types" -import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector" +import { PM } from "./packageManager.js" +import { TraversedDependency } from "./types.js" +import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector.js" export class BunNodeModulesCollector extends TraversalNodeModulesCollector { public readonly installOptions = { manager: PM.BUN, lockfile: "bun.lock" } diff --git a/packages/app-builder-lib/src/node-module-collector/index.ts b/packages/app-builder-lib/src/node-module-collector/index.ts index 43cfea4c6e2..b176598a75b 100644 --- a/packages/app-builder-lib/src/node-module-collector/index.ts +++ b/packages/app-builder-lib/src/node-module-collector/index.ts @@ -1,18 +1,18 @@ import { Nullish } from "builder-util-runtime" import { TmpDir } from "temp-file" -import { NpmNodeModulesCollector } from "./npmNodeModulesCollector" -import { detectPackageManager, getPackageManagerCommand, PM } from "./packageManager" -import { PnpmNodeModulesCollector } from "./pnpmNodeModulesCollector" -import { YarnBerryNodeModulesCollector } from "./yarnBerryNodeModulesCollector" -import { YarnNodeModulesCollector } from "./yarnNodeModulesCollector" -import { BunNodeModulesCollector } from "./bunNodeModulesCollector" +import { NpmNodeModulesCollector } from "./npmNodeModulesCollector.js" +import { detectPackageManager, getPackageManagerCommand, PM } from "./packageManager.js" +import { PnpmNodeModulesCollector } from "./pnpmNodeModulesCollector.js" +import { YarnBerryNodeModulesCollector } from "./yarnBerryNodeModulesCollector.js" +import { YarnNodeModulesCollector } from "./yarnNodeModulesCollector.js" +import { BunNodeModulesCollector } from "./bunNodeModulesCollector.js" import { Lazy } from "lazy-val" import { spawn, log, exists, isEmptyOrSpaces } from "builder-util" -import * as fs from "fs-extra" +import fs from "fs-extra" import * as path from "path" -import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector" +import { TraversalNodeModulesCollector } from "./traversalNodeModulesCollector.js" -export { getPackageManagerCommand, PM } +export { getPackageManagerCommand, PM, PnpmNodeModulesCollector, YarnNodeModulesCollector, YarnBerryNodeModulesCollector, BunNodeModulesCollector, TraversalNodeModulesCollector } export function getCollectorByPackageManager(pm: PM, rootDir: string, tempDirManager: TmpDir) { switch (pm) { diff --git a/packages/app-builder-lib/src/node-module-collector/moduleManager.ts b/packages/app-builder-lib/src/node-module-collector/moduleManager.ts index f6af5c255b8..72a48ff618b 100644 --- a/packages/app-builder-lib/src/node-module-collector/moduleManager.ts +++ b/packages/app-builder-lib/src/node-module-collector/moduleManager.ts @@ -1,6 +1,6 @@ import { exists, isEmptyOrSpaces, log, LogLevel } from "builder-util" -import { PackageJson } from "./types" -import * as fs from "fs-extra" +import { PackageJson } from "./types.js" +import fs from "fs-extra" import * as path from "path" import * as semver from "semver" diff --git a/packages/app-builder-lib/src/node-module-collector/nodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/nodeModulesCollector.ts index d14bd1affe7..5fb50798b5e 100644 --- a/packages/app-builder-lib/src/node-module-collector/nodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/nodeModulesCollector.ts @@ -1,13 +1,13 @@ import { exists, log, retry, stripSensitiveEnvVars, TmpDir } from "builder-util" import * as childProcess from "child_process" -import * as fs from "fs-extra" -import { createWriteStream } from "fs-extra" +import fs from "fs-extra" +import fsExtra from "fs-extra" import { Lazy } from "lazy-val" import * as path from "path" -import { hoist, type HoisterResult, type HoisterTree } from "./hoist" -import { LogMessageByKey, ModuleManager } from "./moduleManager" -import { getPackageManagerCommand, PM } from "./packageManager" -import type { Dependency, DependencyGraph, NodeModuleInfo, PackageJson } from "./types" +import { hoist, type HoisterResult, type HoisterTree } from "./hoist.js" +import { LogMessageByKey, ModuleManager } from "./moduleManager.js" +import { getPackageManagerCommand, PM } from "./packageManager.js" +import type { Dependency, DependencyGraph, NodeModuleInfo, PackageJson } from "./types.js" export abstract class NodeModulesCollector, OptionalDepType> { private readonly nodeModules: NodeModuleInfo[] = [] @@ -370,7 +370,7 @@ export abstract class NodeModulesCollector((resolve, reject) => { - const outStream = createWriteStream(tempOutputFile) + const outStream = fsExtra.createWriteStream(tempOutputFile) const child = childProcess.spawn(spawnCommand, spawnArgs, { cwd, diff --git a/packages/app-builder-lib/src/node-module-collector/packageManager.ts b/packages/app-builder-lib/src/node-module-collector/packageManager.ts index 5e8ba6f7082..d3d965b7b5d 100644 --- a/packages/app-builder-lib/src/node-module-collector/packageManager.ts +++ b/packages/app-builder-lib/src/node-module-collector/packageManager.ts @@ -1,5 +1,5 @@ import { exists, log } from "builder-util" -import * as fs from "fs-extra" +import fs from "fs-extra" import * as path from "path" import * as which from "which" diff --git a/packages/app-builder-lib/src/node-module-collector/pnpmNodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/pnpmNodeModulesCollector.ts index 5c92a31e79b..0e3926d8e3e 100644 --- a/packages/app-builder-lib/src/node-module-collector/pnpmNodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/pnpmNodeModulesCollector.ts @@ -1,8 +1,8 @@ import { Lazy } from "lazy-val" -import { LogMessageByKey, type Package } from "./moduleManager" -import { NodeModulesCollector } from "./nodeModulesCollector" -import { getPackageManagerCommand, PM } from "./packageManager" -import { PnpmDependency } from "./types" +import { LogMessageByKey, type Package } from "./moduleManager.js" +import { NodeModulesCollector } from "./nodeModulesCollector.js" +import { getPackageManagerCommand, PM } from "./packageManager.js" +import { PnpmDependency } from "./types.js" export class PnpmNodeModulesCollector extends NodeModulesCollector { public readonly installOptions = { diff --git a/packages/app-builder-lib/src/node-module-collector/traversalNodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/traversalNodeModulesCollector.ts index eef5dd98700..b375829d3d0 100644 --- a/packages/app-builder-lib/src/node-module-collector/traversalNodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/traversalNodeModulesCollector.ts @@ -1,7 +1,7 @@ import { log } from "builder-util" import * as path from "path" -import { LogMessageByKey } from "./moduleManager" -import { NodeModulesCollector } from "./nodeModulesCollector" +import { LogMessageByKey } from "./moduleManager.js" +import { NodeModulesCollector } from "./nodeModulesCollector.js" import { PM } from "./packageManager.js" import { TraversedDependency } from "./types.js" diff --git a/packages/app-builder-lib/src/node-module-collector/yarnBerryNodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/yarnBerryNodeModulesCollector.ts index d952c85501e..ba141f38f68 100644 --- a/packages/app-builder-lib/src/node-module-collector/yarnBerryNodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/yarnBerryNodeModulesCollector.ts @@ -1,8 +1,8 @@ import { log } from "builder-util" import { Lazy } from "lazy-val" -import { NpmNodeModulesCollector } from "./npmNodeModulesCollector" -import { PM } from "./packageManager" -import { NpmDependency } from "./types" +import { NpmNodeModulesCollector } from "./npmNodeModulesCollector.js" +import { PM } from "./packageManager.js" +import { NpmDependency } from "./types.js" type YarnSetupInfo = { yarnVersion: string | null diff --git a/packages/app-builder-lib/src/node-module-collector/yarnNodeModulesCollector.ts b/packages/app-builder-lib/src/node-module-collector/yarnNodeModulesCollector.ts index ed2cbdb4453..6054208553a 100644 --- a/packages/app-builder-lib/src/node-module-collector/yarnNodeModulesCollector.ts +++ b/packages/app-builder-lib/src/node-module-collector/yarnNodeModulesCollector.ts @@ -1,6 +1,6 @@ -import { NpmNodeModulesCollector } from "./npmNodeModulesCollector" -import { PM } from "./packageManager" -import { NpmDependency } from "./types" +import { NpmNodeModulesCollector } from "./npmNodeModulesCollector.js" +import { PM } from "./packageManager.js" +import { NpmDependency } from "./types.js" // Yarn Classic (v1) produces a hoisted node_modules structure similar to npm. // Instead of parsing Yarn's custom NDJSON output, we leverage npm's list command diff --git a/packages/app-builder-lib/src/options/AppXOptions.ts b/packages/app-builder-lib/src/options/AppXOptions.ts index 2908b030546..654f99a2c94 100644 --- a/packages/app-builder-lib/src/options/AppXOptions.ts +++ b/packages/app-builder-lib/src/options/AppXOptions.ts @@ -1,4 +1,4 @@ -import { TargetSpecificOptions } from "../core" +import { TargetSpecificOptions } from "../core.js" export interface AppXOptions extends TargetSpecificOptions { /** diff --git a/packages/app-builder-lib/src/options/CommonWindowsInstallerConfiguration.ts b/packages/app-builder-lib/src/options/CommonWindowsInstallerConfiguration.ts index af503c8ae0d..cc82cf100c6 100644 --- a/packages/app-builder-lib/src/options/CommonWindowsInstallerConfiguration.ts +++ b/packages/app-builder-lib/src/options/CommonWindowsInstallerConfiguration.ts @@ -1,6 +1,6 @@ import { InvalidConfigurationError, isEmptyOrSpaces } from "builder-util" -import { sanitizeFileName } from "builder-util/out/filename" -import { WinPackager } from "../winPackager" +import { sanitizeFileName } from "builder-util/internal" +import { WinPackager } from "../winPackager.js" export interface CommonWindowsInstallerConfiguration { readonly oneClick?: boolean diff --git a/packages/app-builder-lib/src/options/MsiOptions.ts b/packages/app-builder-lib/src/options/MsiOptions.ts index 3b905847941..1a18b784fdc 100644 --- a/packages/app-builder-lib/src/options/MsiOptions.ts +++ b/packages/app-builder-lib/src/options/MsiOptions.ts @@ -1,5 +1,5 @@ -import { TargetSpecificOptions } from "../core" -import { CommonWindowsInstallerConfiguration } from "./CommonWindowsInstallerConfiguration" +import { TargetSpecificOptions } from "../core.js" +import { CommonWindowsInstallerConfiguration } from "./CommonWindowsInstallerConfiguration.js" export interface MsiOptions extends CommonWindowsInstallerConfiguration, TargetSpecificOptions { /** diff --git a/packages/app-builder-lib/src/options/MsiWrappedOptions.ts b/packages/app-builder-lib/src/options/MsiWrappedOptions.ts index 282693f775b..e937333b53b 100644 --- a/packages/app-builder-lib/src/options/MsiWrappedOptions.ts +++ b/packages/app-builder-lib/src/options/MsiWrappedOptions.ts @@ -1,5 +1,5 @@ -import { TargetSpecificOptions } from "../core" -import { CommonWindowsInstallerConfiguration } from "./CommonWindowsInstallerConfiguration" +import { TargetSpecificOptions } from "../core.js" +import { CommonWindowsInstallerConfiguration } from "./CommonWindowsInstallerConfiguration.js" export interface MsiWrappedOptions extends CommonWindowsInstallerConfiguration, TargetSpecificOptions { /** diff --git a/packages/app-builder-lib/src/options/PlatformSpecificBuildOptions.ts b/packages/app-builder-lib/src/options/PlatformSpecificBuildOptions.ts index 98dea00fadb..102b7c8d93f 100644 --- a/packages/app-builder-lib/src/options/PlatformSpecificBuildOptions.ts +++ b/packages/app-builder-lib/src/options/PlatformSpecificBuildOptions.ts @@ -1,5 +1,5 @@ -import { CompressionLevel, Publish, TargetConfiguration, TargetSpecificOptions } from "../core" -import { FileAssociation } from "./FileAssociation" +import { CompressionLevel, Publish, TargetConfiguration, TargetSpecificOptions } from "../core.js" +import { FileAssociation } from "./FileAssociation.js" export interface FileSet { /** diff --git a/packages/app-builder-lib/src/options/SnapOptions.ts b/packages/app-builder-lib/src/options/SnapOptions.ts index 709851cdcc6..cd49dafb167 100644 --- a/packages/app-builder-lib/src/options/SnapOptions.ts +++ b/packages/app-builder-lib/src/options/SnapOptions.ts @@ -1,6 +1,6 @@ -import { TargetSpecificOptions } from "../core" -import { SnapcraftYAML } from "../targets/snap/snapcraft" -import { CommonLinuxOptions } from "./linuxOptions" +import { TargetSpecificOptions } from "../core.js" +import { SnapcraftYAML } from "../targets/snap/snapcraft.js" +import { CommonLinuxOptions } from "./linuxOptions.js" /** * New-style snap configuration. Use this via the `snapcraft` key in your build config. diff --git a/packages/app-builder-lib/src/options/SquirrelWindowsOptions.ts b/packages/app-builder-lib/src/options/SquirrelWindowsOptions.ts index 9bb97db6e3e..c9176c70e7f 100644 --- a/packages/app-builder-lib/src/options/SquirrelWindowsOptions.ts +++ b/packages/app-builder-lib/src/options/SquirrelWindowsOptions.ts @@ -1,7 +1,7 @@ /** * Squirrel.Windows options. */ -import { TargetSpecificOptions } from "../core" +import { TargetSpecificOptions } from "../core.js" export interface SquirrelWindowsOptions extends TargetSpecificOptions { /** diff --git a/packages/app-builder-lib/src/options/linuxOptions.ts b/packages/app-builder-lib/src/options/linuxOptions.ts index 7123afa05a0..866cb680425 100644 --- a/packages/app-builder-lib/src/options/linuxOptions.ts +++ b/packages/app-builder-lib/src/options/linuxOptions.ts @@ -1,4 +1,5 @@ -import { PlatformSpecificBuildOptions, TargetConfigType, TargetSpecificOptions } from "../index" +import { TargetConfigType, TargetSpecificOptions } from "../core.js" +import { PlatformSpecificBuildOptions } from "./PlatformSpecificBuildOptions.js" /** * Example Spec: https://specifications.freedesktop.org/desktop-entry-spec/latest/example.html diff --git a/packages/app-builder-lib/src/options/macOptions.ts b/packages/app-builder-lib/src/options/macOptions.ts index a29ff49f3c4..7afc584f92f 100644 --- a/packages/app-builder-lib/src/options/macOptions.ts +++ b/packages/app-builder-lib/src/options/macOptions.ts @@ -1,5 +1,6 @@ -import { PlatformSpecificBuildOptions, TargetConfiguration, TargetSpecificOptions } from "../index" -import { CustomMacSign } from "../macPackager" +import { TargetConfiguration, TargetSpecificOptions } from "../core.js" +import { PlatformSpecificBuildOptions } from "./PlatformSpecificBuildOptions.js" +import { CustomMacSign } from "../macPackager.js" export type MacOsTargetName = "default" | "dmg" | "mas" | "mas-dev" | "pkg" | "7z" | "zip" | "tar.xz" | "tar.lz" | "tar.gz" | "tar.bz2" | "dir" diff --git a/packages/app-builder-lib/src/options/metadata.ts b/packages/app-builder-lib/src/options/metadata.ts index 14735434a58..897c9378b4d 100644 --- a/packages/app-builder-lib/src/options/metadata.ts +++ b/packages/app-builder-lib/src/options/metadata.ts @@ -1,4 +1,4 @@ -import { Configuration } from "../configuration" +import { Configuration } from "../configuration.js" export interface Metadata { /** diff --git a/packages/app-builder-lib/src/options/pkgOptions.ts b/packages/app-builder-lib/src/options/pkgOptions.ts index 81192c86a67..ce23ee56df0 100644 --- a/packages/app-builder-lib/src/options/pkgOptions.ts +++ b/packages/app-builder-lib/src/options/pkgOptions.ts @@ -1,4 +1,4 @@ -import { TargetSpecificOptions } from "../core" +import { TargetSpecificOptions } from "../core.js" // noinspection SpellCheckingInspection export type BackgroundAlignment = "center" | "left" | "right" | "top" | "bottom" | "topleft" | "topright" | "bottomleft" | "bottomright" diff --git a/packages/app-builder-lib/src/options/winOptions.ts b/packages/app-builder-lib/src/options/winOptions.ts index 54f8d002142..2224e028d03 100644 --- a/packages/app-builder-lib/src/options/winOptions.ts +++ b/packages/app-builder-lib/src/options/winOptions.ts @@ -1,6 +1,7 @@ import { Nullish } from "builder-util-runtime" -import { CustomWindowsSign } from "../codeSign/windowsSignToolManager" -import { PlatformSpecificBuildOptions, TargetConfigType } from "../index" +import { CustomWindowsSign } from "../codeSign/windowsSignToolManager.js" +import { TargetConfigType } from "../core.js" +import { PlatformSpecificBuildOptions } from "./PlatformSpecificBuildOptions.js" export interface WindowsConfiguration extends PlatformSpecificBuildOptions { /** diff --git a/packages/app-builder-lib/src/packager.ts b/packages/app-builder-lib/src/packager.ts index eb88b555134..90ac891b5ed 100644 --- a/packages/app-builder-lib/src/packager.ts +++ b/packages/app-builder-lib/src/packager.ts @@ -16,33 +16,35 @@ import { TmpDir, } from "builder-util" import { CancellationToken, deepAssign, retry } from "builder-util-runtime" -import { chmod, mkdirs, outputFile } from "fs-extra" + import { isCI } from "ci-info" import { Lazy } from "lazy-val" import { release as getOsRelease } from "os" import * as path from "path" -import { AppInfo } from "./appInfo" -import { readAsarJson } from "./asar/asar" -import { AfterExtractContext, AfterPackContext, BeforePackContext, Configuration, Hook } from "./configuration" -import { Platform, SourceRepositoryInfo, Target } from "./core" -import { createElectronFrameworkSupport } from "./electron/ElectronFramework" -import { Framework } from "./Framework" -import { LibUiFramework } from "./frameworks/LibUiFramework" -import { Metadata } from "./options/metadata" -import { ArtifactBuildStarted, ArtifactCreated, PackagerOptions } from "./packagerApi" -import { PlatformPackager } from "./platformPackager" -import { ProtonFramework } from "./ProtonFramework" -import { computeArchToTargetNamesMap, createTargets, NoOpTarget } from "./targets/targetFactory" -import { computeDefaultAppDirectory, getConfig, validateConfiguration } from "./util/config/config" -import { expandMacro } from "./util/macroExpander" -import { checkMetadata, readPackageJson } from "./util/packageMetadata" -import { getRepositoryInfo } from "./util/repositoryInfo" -import { resolveFunction } from "./util/resolve" -import { installOrRebuild, nodeGypRebuild } from "./util/yarn" -import { PACKAGE_VERSION } from "./version" -import { AsyncEventEmitter, HandlerType } from "./util/asyncEventEmitter" +import { AppInfo } from "./appInfo.js" +import { readAsarJson } from "./asar/asar.js" +import { AfterExtractContext, AfterPackContext, BeforePackContext, Configuration, Hook } from "./configuration.js" +import { Platform, SourceRepositoryInfo, Target } from "./core.js" +import { createElectronFrameworkSupport } from "./electron/ElectronFramework.js" +import { Framework } from "./Framework.js" +import { LibUiFramework } from "./frameworks/LibUiFramework.js" +import { Metadata } from "./options/metadata.js" +import { ArtifactBuildStarted, ArtifactCreated, PackagerOptions } from "./packagerApi.js" +import { PlatformPackager } from "./platformPackager.js" +import { ProtonFramework } from "./ProtonFramework.js" +import { computeArchToTargetNamesMap, createTargets, NoOpTarget } from "./targets/targetFactory.js" +import { computeDefaultAppDirectory, getConfig, validateConfiguration } from "./util/config/config.js" +import { expandMacro } from "./util/macroExpander.js" +import { checkMetadata, readPackageJson } from "./util/packageMetadata.js" +import { getRepositoryInfo } from "./util/repositoryInfo.js" +import { resolveFunction } from "./util/resolve.js" +import { installOrRebuild, nodeGypRebuild } from "./util/yarn.js" +import { PACKAGE_VERSION } from "./version.js" +import { AsyncEventEmitter, HandlerType } from "./util/asyncEventEmitter.js" import asyncPool from "tiny-async-pool" -import { determinePackageManagerEnv, PM } from "./node-module-collector" +import { determinePackageManagerEnv, PM } from "./node-module-collector/index.js" +import _fsExtra from "fs-extra" +const { chmod, mkdirs, outputFile } = _fsExtra async function createFrameworkInfo(configuration: Configuration, packager: Packager): Promise { let framework = configuration.framework @@ -571,17 +573,17 @@ export class Packager { switch (platform) { case Platform.MAC: { - const helperClass = (await import("./macPackager")).MacPackager + const helperClass = (await import("./macPackager.js")).MacPackager return new helperClass(this) } case Platform.WINDOWS: { - const helperClass = (await import("./winPackager")).WinPackager + const helperClass = (await import("./winPackager.js")).WinPackager return new helperClass(this) } case Platform.LINUX: - return new (await import("./linuxPackager")).LinuxPackager(this) + return new (await import("./linuxPackager.js")).LinuxPackager(this) default: throw new Error(`Unknown platform: ${platform}`) diff --git a/packages/app-builder-lib/src/packagerApi.ts b/packages/app-builder-lib/src/packagerApi.ts index 28a490c146a..16c5a42a9ba 100644 --- a/packages/app-builder-lib/src/packagerApi.ts +++ b/packages/app-builder-lib/src/packagerApi.ts @@ -1,10 +1,10 @@ import { Arch } from "builder-util" import { PublishConfiguration } from "builder-util-runtime" import { UploadTask } from "electron-publish" -import { Configuration } from "./configuration" -import { Platform, Target } from "./core" -import { Packager } from "./packager" -import { PlatformPackager } from "./platformPackager" +import { Configuration } from "./configuration.js" +import { Platform, Target } from "./core.js" +import { Packager } from "./packager.js" +import { PlatformPackager } from "./platformPackager.js" export interface PackagerOptions { targets?: Map>> diff --git a/packages/app-builder-lib/src/platformPackager.ts b/packages/app-builder-lib/src/platformPackager.ts index cefb93166a5..89883a0c224 100644 --- a/packages/app-builder-lib/src/platformPackager.ts +++ b/packages/app-builder-lib/src/platformPackager.ts @@ -1,5 +1,5 @@ import type { FuseConfig, FuseV1Config } from "@electron/fuses" -import { dynamicImport } from "./util/dynamicImport" +import { dynamicImport } from "./util/dynamicImport.js" import { Arch, asArray, @@ -23,15 +23,18 @@ import { Minimatch } from "minimatch" import * as path from "path" import * as fs from "fs/promises" import * as os from "os" -import { AppInfo } from "./appInfo" -import { checkFileInArchive } from "./asar/asarFileChecker" -import { AsarPackager } from "./asar/asarUtil" -import { AsarIntegrity, computeData } from "./asar/integrity" -import { FuseOptionsV1 } from "./configuration" -import { copyFiles, FileMatcher, getFileMatchers, GetFileMatchersOptions, getMainFileMatchers, getNodeModuleFileMatcher } from "./fileMatcher" -import { createTransformer, isElectronCompileUsed } from "./fileTransformer" -import { Framework, isElectronBased } from "./Framework" -import { +import { AppInfo } from "./appInfo.js" +import { checkFileInArchive } from "./asar/asarFileChecker.js" +import { AsarPackager } from "./asar/asarUtil.js" +import { AsarIntegrity, computeData } from "./asar/integrity.js" +import { FuseOptionsV1 } from "./configuration.js" +import { copyFiles, FileMatcher, getFileMatchers, GetFileMatchersOptions, getMainFileMatchers, getNodeModuleFileMatcher } from "./fileMatcher.js" +import { createTransformer, isElectronCompileUsed } from "./fileTransformer.js" +import { Framework, isElectronBased } from "./Framework.js" +import { Platform } from "./core.js" +// Type-only barrel import: keeping these erased avoids a runtime cycle +// (index.ts → linuxPackager.ts → platformPackager.ts) that breaks ESM class init. +import type { AfterPackContext, AsarOptions, CompressionLevel, @@ -41,15 +44,14 @@ import { LinuxPackager, Packager, PackagerOptions, - Platform, PlatformSpecificBuildOptions, Target, TargetSpecificOptions, -} from "./index" -import { computeFileSets, computeNodeModuleFileSets, copyAppFiles, ELECTRON_COMPILE_SHIM_FILENAME, transformFiles } from "./util/appFileCopier" -import { convertIcon, IconFormat, IconInfo } from "./util/iconConverter" -import { expandMacro as doExpandMacro } from "./util/macroExpander" -import { AssetCatalogResult, generateAssetCatalogForIcon } from "./util/macosIconComposer" +} from "./index.js" +import { computeFileSets, computeNodeModuleFileSets, copyAppFiles, ELECTRON_COMPILE_SHIM_FILENAME, transformFiles } from "./util/appFileCopier.js" +import { convertIcon, IconFormat, IconInfo } from "./util/iconConverter.js" +import { expandMacro as doExpandMacro } from "./util/macroExpander.js" +import { AssetCatalogResult, generateAssetCatalogForIcon } from "./util/macosIconComposer.js" export type DoPackOptions = { outDir: string @@ -420,7 +422,9 @@ export abstract class PlatformPackager linux: "", }[electronPlatformName] - const executableName = this instanceof LinuxPackager ? this.executableName : this.appInfo.productFilename + // `"executableName" in this` instead of `instanceof LinuxPackager` keeps LinuxPackager a + // type-only import, avoiding the index.ts → linuxPackager.ts → platformPackager.ts runtime cycle. + const executableName = "executableName" in this ? (this as LinuxPackager).executableName : this.appInfo.productFilename const electronBinaryPath = path.join(appOutDir, `${executableName}${ext}`) log.info({ electronPath: log.filePath(electronBinaryPath) }, "executing @electron/fuses") diff --git a/packages/app-builder-lib/src/presets/rectCra.ts b/packages/app-builder-lib/src/presets/rectCra.ts index 5d610cf64e6..311a17f9076 100644 --- a/packages/app-builder-lib/src/presets/rectCra.ts +++ b/packages/app-builder-lib/src/presets/rectCra.ts @@ -1,6 +1,6 @@ import { log, statOrNull } from "builder-util" import * as path from "path" -import { Configuration } from "../configuration" +import { Configuration } from "../configuration.js" /** @internal */ export async function reactCra(projectDir: string): Promise { diff --git a/packages/app-builder-lib/src/publish/PublishManager.ts b/packages/app-builder-lib/src/publish/PublishManager.ts index 7c42d3ec08b..10aa781a82d 100644 --- a/packages/app-builder-lib/src/publish/PublishManager.ts +++ b/packages/app-builder-lib/src/publish/PublishManager.ts @@ -29,20 +29,24 @@ import { SpacesPublisher, UploadTask, } from "electron-publish" -import { MultiProgress } from "electron-publish/out/multiProgress" +import { MultiProgress } from "electron-publish/internal" import { readFile, writeFile } from "fs/promises" import { isCI } from "ci-info" import * as path from "path" import { WriteStream as TtyWriteStream } from "tty" import * as url from "url" -import { AppInfo, ArtifactCreated, Configuration, Platform, PlatformSpecificBuildOptions, Target, TargetSpecificOptions } from "../index" -import { Packager } from "../packager" -import { PlatformPackager } from "../platformPackager" -import { expandMacro } from "../util/macroExpander" -import { WinPackager } from "../winPackager" -import { createUpdateInfoTasks, UpdateInfoFileTask, writeUpdateInfoFiles } from "./updateInfoBuilder" -import { resolveModule } from "../util/resolve" -import { parseUrl } from "../util/pathManager" +import { AppInfo } from "../appInfo.js" +import { Configuration } from "../configuration.js" +import { Platform, Target, TargetSpecificOptions } from "../core.js" +import { ArtifactCreated } from "../packagerApi.js" +import { PlatformSpecificBuildOptions } from "../options/PlatformSpecificBuildOptions.js" +import { Packager } from "../packager.js" +import { PlatformPackager } from "../platformPackager.js" +import { expandMacro } from "../util/macroExpander.js" +import { WinPackager } from "../winPackager.js" +import { createUpdateInfoTasks, UpdateInfoFileTask, writeUpdateInfoFiles } from "./updateInfoBuilder.js" +import { resolveModule } from "../util/resolve.js" +import { parseUrl } from "../util/pathManager.js" const publishForPrWarning = "There are serious security concerns with PUBLISH_FOR_PULL_REQUEST=true (see the CircleCI documentation (https://circleci.com/docs/1.0/fork-pr-builds/) for details)" + diff --git a/packages/app-builder-lib/src/publish/updateInfoBuilder.ts b/packages/app-builder-lib/src/publish/updateInfoBuilder.ts index 0e0a832e7b9..611ab706c95 100644 --- a/packages/app-builder-lib/src/publish/updateInfoBuilder.ts +++ b/packages/app-builder-lib/src/publish/updateInfoBuilder.ts @@ -1,17 +1,17 @@ import asyncPool from "tiny-async-pool" import { Arch, log, safeStringifyJson, serializeToYaml } from "builder-util" import { GenericServerOptions, PublishConfiguration, UpdateInfo, WindowsUpdateInfo } from "builder-util-runtime" -import { outputFile, outputJson, readFile } from "fs-extra" +import fsExtra from "fs-extra" import { Lazy } from "lazy-val" import * as path from "path" import * as semver from "semver" -import { Platform } from "../core" -import { ReleaseInfo } from "../options/PlatformSpecificBuildOptions" -import { Packager } from "../packager" -import { ArtifactCreated } from "../packagerApi" -import { PlatformPackager } from "../platformPackager" -import { hashFile } from "../util/hash" -import { computeDownloadUrl, getPublishConfigsForUpdateInfo } from "./PublishManager" +import { Platform } from "../core.js" +import { ReleaseInfo } from "../options/PlatformSpecificBuildOptions.js" +import { Packager } from "../packager.js" +import { ArtifactCreated } from "../packagerApi.js" +import { PlatformPackager } from "../platformPackager.js" +import { hashFile } from "../util/hash.js" +import { computeDownloadUrl, getPublishConfigsForUpdateInfo } from "./PublishManager.js" async function getReleaseInfo(packager: PlatformPackager) { const releaseInfo: ReleaseInfo = { ...(packager.platformSpecificBuildOptions.releaseInfo || packager.config.releaseInfo) } @@ -23,7 +23,7 @@ async function getReleaseInfo(packager: PlatformPackager) { `release-notes-${packager.platform.nodeName}.md`, "release-notes.md" ) - const releaseNotes = releaseNotesFile == null ? null : await readFile(releaseNotesFile, "utf-8") + const releaseNotes = releaseNotesFile == null ? null : await fsExtra.readFile(releaseNotesFile, "utf-8") // to avoid undefined in the file, check for null if (releaseNotes != null) { releaseInfo.releaseNotes = releaseNotes @@ -238,7 +238,7 @@ export async function writeUpdateInfoFiles(updateInfoFileTasks: Array { diff --git a/packages/app-builder-lib/src/targets/FlatpakTarget.ts b/packages/app-builder-lib/src/targets/FlatpakTarget.ts index 7850654455e..5c2df457244 100644 --- a/packages/app-builder-lib/src/targets/FlatpakTarget.ts +++ b/packages/app-builder-lib/src/targets/FlatpakTarget.ts @@ -1,14 +1,16 @@ import { bundle as bundleFlatpak, FlatpakBundlerBuildOptions, FlatpakManifest } from "@malept/flatpak-bundler" import { Arch, copyFile, toLinuxArchString } from "builder-util" -import { chmod, outputFile } from "fs-extra" + import * as path from "path" -import { Target } from "../core" -import { LinuxPackager } from "../linuxPackager" -import { FlatpakOptions } from "../options/linuxOptions" -import { getNotLocalizedLicenseFile } from "../util/license" -import { LinuxTargetHelper } from "./LinuxTargetHelper" -import { createStageDir, StageDir } from "./targetUtil" +import { Target } from "../core.js" +import { LinuxPackager } from "../linuxPackager.js" +import { FlatpakOptions } from "../options/linuxOptions.js" +import { getNotLocalizedLicenseFile } from "../util/license.js" +import { LinuxTargetHelper } from "./LinuxTargetHelper.js" +import { createStageDir, StageDir } from "./targetUtil.js" import { deepAssign, Nullish } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { chmod, outputFile } = _fsExtra export default class FlatpakTarget extends Target { readonly options: FlatpakOptions = deepAssign({}, this.packager.platformSpecificBuildOptions, (this.packager.config as any)[this.name]) diff --git a/packages/app-builder-lib/src/targets/FpmTarget.ts b/packages/app-builder-lib/src/targets/FpmTarget.ts index a9ed853b3d1..7d878f46441 100644 --- a/packages/app-builder-lib/src/targets/FpmTarget.ts +++ b/packages/app-builder-lib/src/targets/FpmTarget.ts @@ -1,22 +1,24 @@ import { Arch, asArray, exec, getArchSuffix, log, serializeToYaml, stripSensitiveEnvVars, TmpDir, toLinuxArchString, unlinkIfExists, use } from "builder-util" import { deepAssign, Nullish } from "builder-util-runtime" -import { copyFile, outputFile, stat } from "fs-extra" + import { mkdir, readFile } from "fs/promises" import * as path from "path" -import { smarten } from "../appInfo" -import { Target } from "../core" -import * as errorMessages from "../errorMessages" -import { LinuxPackager } from "../linuxPackager" -import { DebOptions, LinuxTargetSpecificOptions } from "../options/linuxOptions" -import { ArtifactCreated } from "../packagerApi" -import { getAppUpdatePublishConfiguration } from "../publish/PublishManager" +import { smarten } from "../appInfo.js" +import { Target } from "../core.js" +import * as errorMessages from "../errorMessages.js" +import { LinuxPackager } from "../linuxPackager.js" +import { DebOptions, LinuxTargetSpecificOptions } from "../options/linuxOptions.js" +import { ArtifactCreated } from "../packagerApi.js" +import { getAppUpdatePublishConfiguration } from "../publish/PublishManager.js" import { objectToArgs } from "builder-util-runtime" -import { computeEnv } from "../util/bundledTool" -import { hashFile } from "../util/hash" -import { isMacOsSierra } from "../util/macosVersion" -import { getTemplatePath } from "../util/pathManager" -import { installPrefix, LinuxTargetHelper } from "./LinuxTargetHelper" -import { getFpmPath, getLinuxToolsPath } from "../toolsets/linux" +import { computeEnv } from "../util/bundledTool.js" +import { hashFile } from "../util/hash.js" +import { isMacOsSierra } from "../util/macosVersion.js" +import { getTemplatePath } from "../util/pathManager.js" +import { installPrefix, LinuxTargetHelper } from "./LinuxTargetHelper.js" +import { getFpmPath, getLinuxToolsPath } from "../toolsets/linux.js" +import _fsExtra from "fs-extra" +const { copyFile, outputFile, stat } = _fsExtra interface FpmOptions { name: string diff --git a/packages/app-builder-lib/src/targets/LinuxTargetHelper.ts b/packages/app-builder-lib/src/targets/LinuxTargetHelper.ts index 1e6fea6c74e..c2a986480b8 100644 --- a/packages/app-builder-lib/src/targets/LinuxTargetHelper.ts +++ b/packages/app-builder-lib/src/targets/LinuxTargetHelper.ts @@ -1,17 +1,19 @@ import { asArray, exists, InvalidConfigurationError, isEmptyOrSpaces, log } from "builder-util" import { deepAssign } from "builder-util-runtime" -import { outputFile } from "fs-extra" + import { Lazy } from "lazy-val" import { join } from "path" import * as semver from "semver" -import { CompressionLevel } from "../core" -import { LinuxPackager } from "../linuxPackager" -import { CommonLinuxOptions } from "../options/linuxOptions" -import { SnapCore } from "./snap/SnapTarget" -import { SnapCore24 } from "./snap/core24" -import { SnapCoreCustom } from "./snap/coreCustom" -import { SnapCoreLegacy } from "./snap/coreLegacy" -import { IconInfo } from "../util/iconConverter" +import { CompressionLevel } from "../core.js" +import { LinuxPackager } from "../linuxPackager.js" +import { CommonLinuxOptions } from "../options/linuxOptions.js" +import { SnapCore } from "./snap/SnapTarget.js" +import { SnapCore24 } from "./snap/core24.js" +import { SnapCoreCustom } from "./snap/coreCustom.js" +import { SnapCoreLegacy } from "./snap/coreLegacy.js" +import { IconInfo } from "../util/iconConverter.js" +import _fsExtra from "fs-extra" +const { outputFile } = _fsExtra /** * Escape a string value for use in a freedesktop .desktop file string field @@ -99,7 +101,6 @@ export class LinuxTargetHelper { return this.mimeTypeFilesPromise.value } - // eslint-disable-next-line @typescript-eslint/no-explicit-any getSnapCore(): SnapCore { const { snapcraft, snap: legacySnap } = this.packager.config if (snapcraft != null && legacySnap != null) { diff --git a/packages/app-builder-lib/src/targets/MsiTarget.ts b/packages/app-builder-lib/src/targets/MsiTarget.ts index c5d83b715da..d7c0595e6b9 100644 --- a/packages/app-builder-lib/src/targets/MsiTarget.ts +++ b/packages/app-builder-lib/src/targets/MsiTarget.ts @@ -5,17 +5,17 @@ import * as ejs from "ejs" import { readFile, writeFile } from "fs/promises" import { Lazy } from "lazy-val" import * as path from "path" -import { MsiOptions } from "../" -import { getBinFromUrl } from "../binDownload" -import { Target } from "../core" -import { DesktopShortcutCreationPolicy, FinalCommonWindowsInstallerOptions, getEffectiveOptions } from "../options/CommonWindowsInstallerConfiguration" -import { normalizeExt } from "../platformPackager" -import { getTemplatePath } from "../util/pathManager" -import { VmManager } from "../vm/vm" -import { WineVmManager } from "../vm/WineVm" -import { WinPackager } from "../winPackager" -import { withToolsetLock } from "../util/toolsetLock" -import { createStageDir, getWindowsInstallationDirName } from "./targetUtil" +import { MsiOptions } from "../index.js" +import { getBinFromUrl } from "../binDownload.js" +import { Target } from "../core.js" +import { DesktopShortcutCreationPolicy, FinalCommonWindowsInstallerOptions, getEffectiveOptions } from "../options/CommonWindowsInstallerConfiguration.js" +import { normalizeExt } from "../platformPackager.js" +import { getTemplatePath } from "../util/pathManager.js" +import { VmManager } from "../vm/vm.js" +import { WineVmManager } from "../vm/WineVm.js" +import { WinPackager } from "../winPackager.js" +import { withToolsetLock } from "../util/toolsetLock.js" +import { createStageDir, getWindowsInstallationDirName } from "./targetUtil.js" const ELECTRON_BUILDER_UPGRADE_CODE_NS_UUID = UUID.parse("d752fe43-5d44-44d5-9fc9-6dd1bf19d5cc") const ROOT_DIR_ID = "APPLICATIONFOLDER" diff --git a/packages/app-builder-lib/src/targets/MsiWrappedTarget.ts b/packages/app-builder-lib/src/targets/MsiWrappedTarget.ts index 8f63b945909..a3aab641902 100644 --- a/packages/app-builder-lib/src/targets/MsiWrappedTarget.ts +++ b/packages/app-builder-lib/src/targets/MsiWrappedTarget.ts @@ -1,11 +1,11 @@ import { Arch, exists, InvalidConfigurationError } from "builder-util" import { deepAssign, UUID } from "builder-util-runtime" import * as path from "path" -import { MsiWrappedOptions } from "../" -import { TargetConfiguration } from "../core" -import { FinalCommonWindowsInstallerOptions } from "../options/CommonWindowsInstallerConfiguration" -import { WinPackager } from "../winPackager" -import MsiTarget from "./MsiTarget" +import { MsiWrappedOptions } from "../options/MsiWrappedOptions.js" +import { TargetConfiguration } from "../core.js" +import { FinalCommonWindowsInstallerOptions } from "../options/CommonWindowsInstallerConfiguration.js" +import { WinPackager } from "../winPackager.js" +import MsiTarget from "./MsiTarget.js" const ELECTRON_MSI_WRAPPED_NS_UUID = UUID.parse("467f7bb2-a83c-442f-b776-394d316e8e53") diff --git a/packages/app-builder-lib/src/targets/appimage/AppImageTarget.ts b/packages/app-builder-lib/src/targets/appimage/AppImageTarget.ts index 754a27e4161..ebe022f8363 100644 --- a/packages/app-builder-lib/src/targets/appimage/AppImageTarget.ts +++ b/packages/app-builder-lib/src/targets/appimage/AppImageTarget.ts @@ -1,16 +1,18 @@ import { Arch, log, serializeToYaml } from "builder-util" -import { outputFile } from "fs-extra" + import { Lazy } from "lazy-val" import * as path from "path" -import { Target } from "../../core" -import { LinuxPackager } from "../../linuxPackager" -import { AppImageOptions } from "../../options/linuxOptions" -import { getAppUpdatePublishConfiguration } from "../../publish/PublishManager" -import { getNotLocalizedLicenseFile } from "../../util/license" -import { LinuxTargetHelper } from "../LinuxTargetHelper" -import { createStageDir } from "../targetUtil" -import { buildLegacyFuse2AppImage, buildStaticRuntimeAppImage } from "./appImageUtil" +import { Target } from "../../core.js" +import { LinuxPackager } from "../../linuxPackager.js" +import { AppImageOptions } from "../../options/linuxOptions.js" +import { getAppUpdatePublishConfiguration } from "../../publish/PublishManager.js" +import { getNotLocalizedLicenseFile } from "../../util/license.js" +import { LinuxTargetHelper } from "../LinuxTargetHelper.js" +import { createStageDir } from "../targetUtil.js" +import { buildLegacyFuse2AppImage, buildStaticRuntimeAppImage } from "./appImageUtil.js" import { BlockMapDataHolder, deepAssign } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { outputFile } = _fsExtra // https://unix.stackexchange.com/questions/375191/append-to-sub-directory-inside-squashfs-file diff --git a/packages/app-builder-lib/src/targets/appimage/appImageUtil.ts b/packages/app-builder-lib/src/targets/appimage/appImageUtil.ts index 1fdc44a79a7..e058647a6b1 100644 --- a/packages/app-builder-lib/src/targets/appimage/appImageUtil.ts +++ b/packages/app-builder-lib/src/targets/appimage/appImageUtil.ts @@ -1,14 +1,14 @@ import { Arch, copyDir, copyFile, exec, exists, InvalidConfigurationError, log } from "builder-util" -import * as fs from "fs-extra" +import fs from "fs-extra" import * as path from "path" -import { FileAssociation } from "../../options/FileAssociation" -import { getAppImageTools } from "../../toolsets/linux" -import { copyIcons, copyMimeTypes } from "./appLauncher" -import { appendBlockmap } from "../differentialUpdateInfoBuilder" +import { FileAssociation } from "../../options/FileAssociation.js" +import { getAppImageTools } from "../../toolsets/linux.js" +import { copyIcons, copyMimeTypes } from "./appLauncher.js" +import { appendBlockmap } from "../differentialUpdateInfoBuilder.js" import { BlockMapDataHolder } from "builder-util-runtime" -import { APP_RUN_ENTRYPOINT } from "./AppImageTarget" -import { ToolsetConfig } from "../../configuration" -import { IconInfo } from "../../util/iconConverter" +import { APP_RUN_ENTRYPOINT } from "./AppImageTarget.js" +import { ToolsetConfig } from "../../configuration.js" +import { IconInfo } from "../../util/iconConverter.js" interface Options { productName: string diff --git a/packages/app-builder-lib/src/targets/appimage/appLauncher.ts b/packages/app-builder-lib/src/targets/appimage/appLauncher.ts index 1d0b2289097..5a06708cc6d 100644 --- a/packages/app-builder-lib/src/targets/appimage/appLauncher.ts +++ b/packages/app-builder-lib/src/targets/appimage/appLauncher.ts @@ -1,7 +1,7 @@ import * as path from "path" -import * as fs from "fs-extra" +import fs from "fs-extra" import { copyOrLinkFile, log } from "builder-util" -import { AppImageBuilderOptions } from "./appImageUtil" +import { AppImageBuilderOptions } from "./appImageUtil.js" const ICON_DIR_RELATIVE_PATH = "usr/share/icons/hicolor" const MIME_TYPE_DIR_RELATIVE_PATH = "usr/share/mime/packages" diff --git a/packages/app-builder-lib/src/targets/archive.ts b/packages/app-builder-lib/src/targets/archive.ts index 45cf0924e1d..89c94c167fe 100644 --- a/packages/app-builder-lib/src/targets/archive.ts +++ b/packages/app-builder-lib/src/targets/archive.ts @@ -1,11 +1,13 @@ import { debug7z, exec, exists, getPath7za, log, statOrNull, unlinkIfExists } from "builder-util" -import { move } from "fs-extra" + import * as path from "path" import { create } from "tar" import { TmpDir } from "temp-file" -import { CompressionLevel } from "../core" -import { getLinuxToolsMacToolset } from "../toolsets/linux" -import { TarOptionsWithAliasesAsync } from "tar/dist/commonjs/options" +import { CompressionLevel } from "../core.js" +import { getLinuxToolsMacToolset } from "../toolsets/linux.js" +import type { TarOptionsWithAliasesAsync } from "tar" +import _fsExtra from "fs-extra" +const { move } = _fsExtra const ALLOWED_7Z_FILTERS = new Set(["BCJ", "BCJ2", "ARM", "ARMT", "IA64", "PPC", "SPARC", "DELTA"]) diff --git a/packages/app-builder-lib/src/targets/differentialUpdateInfoBuilder.ts b/packages/app-builder-lib/src/targets/differentialUpdateInfoBuilder.ts index 644e8c56e1f..0743e11d594 100644 --- a/packages/app-builder-lib/src/targets/differentialUpdateInfoBuilder.ts +++ b/packages/app-builder-lib/src/targets/differentialUpdateInfoBuilder.ts @@ -1,10 +1,10 @@ import { log } from "builder-util" import { BlockMapDataHolder, PackageFileInfo } from "builder-util-runtime" import * as path from "path" -import { Target } from "../core" -import { PlatformPackager } from "../platformPackager" -import { ArchiveOptions } from "./archive" -import { buildBlockMap } from "./blockmap/blockmap" +import { Target } from "../core.js" +import { PlatformPackager } from "../platformPackager.js" +import { ArchiveOptions } from "./archive.js" +import { buildBlockMap } from "./blockmap/blockmap.js" export const BLOCK_MAP_FILE_SUFFIX = ".blockmap" diff --git a/packages/app-builder-lib/src/targets/nsis/Defines.ts b/packages/app-builder-lib/src/targets/nsis/Defines.ts index 912f07993f7..fcad4e185ff 100644 --- a/packages/app-builder-lib/src/targets/nsis/Defines.ts +++ b/packages/app-builder-lib/src/targets/nsis/Defines.ts @@ -1,4 +1,4 @@ -import { PortableOptions } from "./nsisOptions" +import { PortableOptions } from "./nsisOptions.js" /** * Parameters declared as environment variables in NSIS scripts. * The documentation vaguely explains "All other electron-builder specific flags (e.g. ONE_CLICK) are still defined." diff --git a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts index 960822409f8..ba034f9407d 100644 --- a/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts +++ b/packages/app-builder-lib/src/targets/nsis/NsisTarget.ts @@ -18,28 +18,30 @@ import { import { CURRENT_APP_INSTALLER_FILE_NAME, CURRENT_APP_PACKAGE_FILE_NAME, deepAssign, PackageFileInfo, UUID } from "builder-util-runtime" import _debug from "debug" import * as fs from "fs" -import { readFile, stat, unlink } from "fs-extra" + import * as path from "path" -import { Target } from "../../core" -import { DesktopShortcutCreationPolicy, getEffectiveOptions } from "../../options/CommonWindowsInstallerConfiguration" -import { chooseNotNull, computeSafeArtifactNameIfNeeded, normalizeExt } from "../../platformPackager" -import { hashFile } from "../../util/hash" -import { isMacOsCatalina } from "../../util/macosVersion" -import { time } from "../../util/timer" -import { execWine } from "../../wine" -import { WinPackager } from "../../winPackager" -import { archive, ArchiveOptions } from "../archive" -import { appendBlockmap, configureDifferentialAwareArchiveOptions, createBlockmap, createNsisWebDifferentialUpdateInfo } from "../differentialUpdateInfoBuilder" -import { getWindowsInstallationAppPackageName, getWindowsInstallationDirName } from "../targetUtil" -import { Commands } from "./Commands" -import { Defines } from "./Defines" -import { addCustomMessageFileInclude, createAddLangsMacro, LangConfigurator } from "./nsisLang" -import { computeLicensePage } from "./nsisLicense" -import { NsisOptions, PortableOptions } from "./nsisOptions" -import { NsisScriptGenerator, nsisEscapeString } from "./nsisScriptGenerator" -import { getMakeNsisPath, getNsisPluginsPath } from "../../toolsets/windows" -import { AppPackageHelper, nsisTemplatesDir, UninstallerReader } from "./nsisUtil" -import { checkMakensisOutput, verifyInstallerSize } from "./nsisValidation" +import { Target } from "../../core.js" +import { DesktopShortcutCreationPolicy, getEffectiveOptions } from "../../options/CommonWindowsInstallerConfiguration.js" +import { chooseNotNull, computeSafeArtifactNameIfNeeded, normalizeExt } from "../../platformPackager.js" +import { hashFile } from "../../util/hash.js" +import { isMacOsCatalina } from "../../util/macosVersion.js" +import { time } from "../../util/timer.js" +import { execWine } from "../../wine.js" +import { WinPackager } from "../../winPackager.js" +import { archive, ArchiveOptions } from "../archive.js" +import { appendBlockmap, configureDifferentialAwareArchiveOptions, createBlockmap, createNsisWebDifferentialUpdateInfo } from "../differentialUpdateInfoBuilder.js" +import { getWindowsInstallationAppPackageName, getWindowsInstallationDirName } from "../targetUtil.js" +import { Commands } from "./Commands.js" +import { Defines } from "./Defines.js" +import { addCustomMessageFileInclude, createAddLangsMacro, LangConfigurator } from "./nsisLang.js" +import { computeLicensePage } from "./nsisLicense.js" +import { NsisOptions, PortableOptions } from "./nsisOptions.js" +import { NsisScriptGenerator, nsisEscapeString } from "./nsisScriptGenerator.js" +import { getMakeNsisPath, getNsisPluginsPath } from "../../toolsets/windows.js" +import { AppPackageHelper, nsisTemplatesDir, UninstallerReader } from "./nsisUtil.js" +import { checkMakensisOutput, verifyInstallerSize } from "./nsisValidation.js" +import _fsExtra from "fs-extra" +const { readFile, stat, unlink } = _fsExtra const debug = _debug("electron-builder:nsis") diff --git a/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts b/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts index e196779970d..531e8eee9f2 100644 --- a/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts +++ b/packages/app-builder-lib/src/targets/nsis/WebInstallerTarget.ts @@ -1,9 +1,9 @@ import { Arch, log } from "builder-util" -import { computeDownloadUrl, getPublishConfigs, getPublishConfigsForUpdateInfo } from "../../publish/PublishManager" -import { WinPackager } from "../../winPackager" -import { NsisWebOptions } from "./nsisOptions" -import { NsisTarget } from "./NsisTarget" -import { AppPackageHelper } from "./nsisUtil" +import { computeDownloadUrl, getPublishConfigs, getPublishConfigsForUpdateInfo } from "../../publish/PublishManager.js" +import { WinPackager } from "../../winPackager.js" +import { NsisWebOptions } from "./nsisOptions.js" +import { NsisTarget } from "./NsisTarget.js" +import { AppPackageHelper } from "./nsisUtil.js" /** @private */ export class WebInstallerTarget extends NsisTarget { diff --git a/packages/app-builder-lib/src/targets/nsis/nsisLang.ts b/packages/app-builder-lib/src/targets/nsis/nsisLang.ts index c93779eb350..0e2dc7a27dd 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisLang.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisLang.ts @@ -1,13 +1,13 @@ import { asArray } from "builder-util" import _debug from "debug" -import { outputFile, readFile } from "fs-extra" +import fsExtra from "fs-extra" import { load } from "js-yaml" import * as path from "path" -import { PlatformPackager } from "../../platformPackager" -import { bundledLanguages, langIdToName, lcid, toLangWithRegion } from "../../util/langs" -import { NsisOptions } from "./nsisOptions" -import { NsisScriptGenerator } from "./nsisScriptGenerator" -import { nsisTemplatesDir } from "./nsisUtil" +import { PlatformPackager } from "../../platformPackager.js" +import { bundledLanguages, langIdToName, lcid, toLangWithRegion } from "../../util/langs.js" +import { NsisOptions } from "./nsisOptions.js" +import { NsisScriptGenerator } from "./nsisScriptGenerator.js" +import { nsisTemplatesDir } from "./nsisUtil.js" const debug = _debug("electron-builder:nsis") @@ -63,12 +63,12 @@ export function createAddLangsMacro(scriptGenerator: NsisScriptGenerator, langCo async function writeCustomLangFile(data: string, packager: PlatformPackager) { const file = await packager.getTempFile("messages.nsh") - await outputFile(file, data) + await fsExtra.outputFile(file, data) return file } export async function addCustomMessageFileInclude(input: string, packager: PlatformPackager, scriptGenerator: NsisScriptGenerator, langConfigurator: LangConfigurator) { - const data = load(await readFile(path.join(nsisTemplatesDir, input), "utf-8")) + const data = load(await fsExtra.readFile(path.join(nsisTemplatesDir, input), "utf-8")) const instructions = computeCustomMessageTranslations(data, langConfigurator).join("\n") debug(instructions) scriptGenerator.include(await writeCustomLangFile(instructions, packager)) diff --git a/packages/app-builder-lib/src/targets/nsis/nsisLicense.ts b/packages/app-builder-lib/src/targets/nsis/nsisLicense.ts index a5cfaf799cd..436689606ef 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisLicense.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisLicense.ts @@ -1,12 +1,12 @@ import { log } from "builder-util" import * as fs from "fs" import * as path from "path" -import { lcid } from "../../util/langs" -import { getLicenseFiles, getNotLocalizedLicenseFile } from "../../util/license" -import { WinPackager } from "../../winPackager" -import { NsisOptions } from "./nsisOptions" -import { NsisScriptGenerator } from "./nsisScriptGenerator" -import { nsisTemplatesDir } from "./nsisUtil" +import { lcid } from "../../util/langs.js" +import { getLicenseFiles, getNotLocalizedLicenseFile } from "../../util/license.js" +import { WinPackager } from "../../winPackager.js" +import { NsisOptions } from "./nsisOptions.js" +import { NsisScriptGenerator } from "./nsisScriptGenerator.js" +import { nsisTemplatesDir } from "./nsisUtil.js" function convertFileToUtf8WithBOMSync(filePath: string): boolean { try { diff --git a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts index 823a69d64b1..37bdf583ef8 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisOptions.ts @@ -1,5 +1,5 @@ -import { CommonWindowsInstallerConfiguration } from "../.." -import { TargetSpecificOptions } from "../../core" +import { CommonWindowsInstallerConfiguration } from "../../options/CommonWindowsInstallerConfiguration.js" +import { TargetSpecificOptions } from "../../core.js" export interface CustomNsisBinary { /** diff --git a/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts b/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts index a4713a06348..28ba8984e28 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisUtil.ts @@ -3,9 +3,9 @@ import { PackageFileInfo } from "builder-util-runtime" import * as fs from "fs/promises" import * as path from "path" import * as zlib from "zlib" -import { getNsisElevatePath } from "../../toolsets/windows" -import { getTemplatePath } from "../../util/pathManager" -import { NsisTarget } from "./NsisTarget" +import { getNsisElevatePath } from "../../toolsets/windows.js" +import { getTemplatePath } from "../../util/pathManager.js" +import { NsisTarget } from "./NsisTarget.js" export const nsisTemplatesDir = getTemplatePath("nsis") diff --git a/packages/app-builder-lib/src/targets/nsis/nsisValidation.ts b/packages/app-builder-lib/src/targets/nsis/nsisValidation.ts index 9164f694a12..2758b1449ff 100644 --- a/packages/app-builder-lib/src/targets/nsis/nsisValidation.ts +++ b/packages/app-builder-lib/src/targets/nsis/nsisValidation.ts @@ -1,5 +1,5 @@ import { ExecError, statOrNull } from "builder-util" -import type { Defines } from "./Defines" +import type { Defines } from "./Defines.js" /** * Validates makensis stdout/stderr after a zero-exit run. diff --git a/packages/app-builder-lib/src/targets/pkg.ts b/packages/app-builder-lib/src/targets/pkg.ts index ad19e09b4b9..c7f08d5202e 100644 --- a/packages/app-builder-lib/src/targets/pkg.ts +++ b/packages/app-builder-lib/src/targets/pkg.ts @@ -3,13 +3,14 @@ import { Nullish } from "builder-util-runtime" import { readdirSync } from "fs" import { readFile, unlink, writeFile } from "fs/promises" import * as path from "path" -import { filterCFBundleIdentifier } from "../appInfo" -import { findIdentity, Identity } from "../codeSign/macCodeSign" -import { Target } from "../core" -import { MacPackager } from "../macPackager" -import { PkgOptions } from "../options/pkgOptions" -import { savePlistFile, parsePlistFile, PlistObject } from "../util/plist" -import { getNotLocalizedLicenseFile } from "../util/license" +import { filterCFBundleIdentifier } from "../appInfo.js" +import { findIdentity } from "../codeSign/macCodeSign.js" +import type { Identity } from "../codeSign/macCodeSign.js" +import { Target } from "../core.js" +import { MacPackager } from "../macPackager.js" +import { PkgOptions } from "../options/pkgOptions.js" +import { savePlistFile, parsePlistFile, PlistObject } from "../util/plist.js" +import { getNotLocalizedLicenseFile } from "../util/license.js" const certType = "Developer ID Installer" @@ -39,18 +40,19 @@ type ExtraPackages = { // productbuild --scripts doesn't work (because scripts in this case not added to our package) // https://github.com/electron-userland/@electron/osx-sign/issues/96#issuecomment-274986942 export class PkgTarget extends Target { - readonly options: PkgOptions = { - allowAnywhere: true, - allowCurrentUserHome: true, - allowRootDirectory: true, - ...this.packager.config.pkg, - } + readonly options: PkgOptions constructor( private readonly packager: MacPackager, readonly outDir: string ) { super("pkg") + this.options = { + allowAnywhere: true, + allowCurrentUserHome: true, + allowRootDirectory: true, + ...this.packager.config.pkg, + } } async build(appPath: string, arch: Arch): Promise { diff --git a/packages/app-builder-lib/src/targets/snap.ts b/packages/app-builder-lib/src/targets/snap.ts new file mode 100644 index 00000000000..265f979bc71 --- /dev/null +++ b/packages/app-builder-lib/src/targets/snap.ts @@ -0,0 +1,397 @@ +import { replaceDefault as _replaceDefault, Arch, deepAssign, executeAppBuilder, InvalidConfigurationError, log, serializeToYaml, toLinuxArchString } from "builder-util" +import { asArray, Nullish, SnapStoreOptions } from "builder-util-runtime" +import fsExtra from "fs-extra" +import { load } from "js-yaml" +import * as path from "path" +import * as semver from "semver" +import { Configuration } from "../configuration.js" +import { Publish, Target } from "../core.js" +import { LinuxPackager } from "../linuxPackager.js" +import { PlugDescriptor, SnapOptions } from "../options/SnapOptions.js" +import { getTemplatePath } from "../util/pathManager.js" +import { LinuxTargetHelper } from "./LinuxTargetHelper.js" +import { createStageDirPath } from "./targetUtil.js" + +const defaultPlugs = ["desktop", "desktop-legacy", "home", "x11", "wayland", "unity7", "browser-support", "network", "gsettings", "audio-playback", "pulseaudio", "opengl"] + +export default class SnapTarget extends Target { + readonly options: SnapOptions + + public isUseTemplateApp = false + + constructor( + name: string, + private readonly packager: LinuxPackager, + private readonly helper: LinuxTargetHelper, + readonly outDir: string + ) { + super(name) + this.options = { ...this.packager.platformSpecificBuildOptions, ...(this.packager.config as any)[this.name] } + } + + private replaceDefault(inList: Array | Nullish, defaultList: Array) { + const result = _replaceDefault(inList, defaultList) + if (result !== defaultList) { + this.isUseTemplateApp = false + } + return result + } + + private async createDescriptor(arch: Arch): Promise { + if (!this.isElectronVersionGreaterOrEqualThan("4.0.0")) { + if (!this.isElectronVersionGreaterOrEqualThan("2.0.0-beta.1")) { + throw new InvalidConfigurationError("Electron 2 and higher is required to build Snap") + } + + log.warn("Electron 4 and higher is highly recommended for Snap") + } + + const appInfo = this.packager.appInfo + const snapName = this.packager.executableName.toLowerCase() + const options = this.options + + const plugs = normalizePlugConfiguration(this.options.plugs) + + const plugNames = this.replaceDefault(plugs == null ? null : Object.getOwnPropertyNames(plugs), defaultPlugs) + + const slots = normalizePlugConfiguration(this.options.slots) + + const buildPackages = asArray(options.buildPackages) + const defaultStagePackages = getDefaultStagePackages() + const stagePackages = this.replaceDefault(options.stagePackages, defaultStagePackages) + + this.isUseTemplateApp = + this.options.useTemplateApp !== false && + (arch === Arch.x64 || arch === Arch.armv7l) && + buildPackages.length === 0 && + isArrayEqualRegardlessOfSort(stagePackages, defaultStagePackages) + + const appDescriptor: any = { + command: "command.sh", + plugs: plugNames, + adapter: "none", + } + + const snap: any = load(await fsExtra.readFile(path.join(getTemplatePath("snap"), "snapcraft.yaml"), "utf-8")) + if (this.isUseTemplateApp) { + delete appDescriptor.adapter + } + if (options.base != null) { + snap.base = options.base + // from core22 onwards adapter is legacy + if (Number(snap.base.split("core")[1]) >= 22) { + delete appDescriptor.adapter + } + } + if (options.grade != null) { + snap.grade = options.grade + } + if (options.confinement != null) { + snap.confinement = options.confinement + } + if (options.appPartStage != null) { + snap.parts.app.stage = options.appPartStage + } + if (options.layout != null) { + snap.layout = options.layout + } + if (slots != null) { + appDescriptor.slots = Object.getOwnPropertyNames(slots) + for (const slotName of appDescriptor.slots) { + const slotOptions = slots[slotName] + if (slotOptions == null) { + continue + } + if (!snap.slots) { + snap.slots = {} + } + snap.slots[slotName] = slotOptions + } + } + + deepAssign(snap, { + name: snapName, + version: appInfo.version, + title: options.title || appInfo.productName, + summary: options.summary || appInfo.productName, + compression: options.compression, + description: this.helper.getDescription(options), + architectures: [toLinuxArchString(arch, "snap")], + apps: { + [snapName]: appDescriptor, + }, + parts: { + app: { + "stage-packages": stagePackages, + }, + }, + }) + + if (options.autoStart) { + appDescriptor.autostart = `${snap.name}.desktop` + } + + if (options.confinement === "classic") { + delete appDescriptor.plugs + delete snap.plugs + } else { + const archTriplet = archNameToTriplet(arch) + const environment: Record = { + PATH: "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH", + SNAP_DESKTOP_RUNTIME: "$SNAP/gnome-platform", + LD_LIBRARY_PATH: [ + "$SNAP_LIBRARY_PATH", + "$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/" + archTriplet + ":$SNAP/usr/lib/" + archTriplet, + "$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib", + "$SNAP/lib/" + archTriplet + ":$SNAP/usr/lib/" + archTriplet, + ].join(":"), + ...options.environment, + } + // Determine whether Wayland should be disabled based on: + // - Electron version (<38 historically had Wayland disabled) + // - Explicit allowNativeWayland override. + // https://github.com/electron-userland/electron-builder/issues/9320 + const allow = options.allowNativeWayland + const isOldElectron = !this.isElectronVersionGreaterOrEqualThan("38.0.0") + if ( + (allow == null && isOldElectron) || // No explicit option -> use legacy behavior for old Electron + allow === false // Explicitly disallowed + ) { + environment.DISABLE_WAYLAND = "1" + } + + appDescriptor.environment = environment + + if (plugs != null) { + for (const plugName of plugNames) { + const plugOptions = plugs[plugName] + if (plugOptions == null) { + continue + } + + snap.plugs[plugName] = plugOptions + } + } + } + + if (buildPackages.length > 0) { + snap.parts.app["build-packages"] = buildPackages + } + if (options.after != null) { + snap.parts.app.after = options.after + } + + if (options.assumes != null) { + snap.assumes = asArray(options.assumes) + } + + return snap + } + + async build(appOutDir: string, arch: Arch): Promise { + const packager = this.packager + const options = this.options + // tslint:disable-next-line:no-invalid-template-strings + const artifactName = packager.expandArtifactNamePattern(this.options, "snap", arch, "${name}_${version}_${arch}.${ext}", false) + const artifactPath = path.join(this.outDir, artifactName) + await packager.info.emitArtifactBuildStarted({ + targetPresentableName: "snap", + file: artifactPath, + arch, + }) + + const snap = await this.createDescriptor(arch) + + const stageDir = await createStageDirPath(this, packager, arch) + const snapArch = toLinuxArchString(arch, "snap") + const args = ["snap", "--app", appOutDir, "--stage", stageDir, "--arch", snapArch, "--output", artifactPath, "--executable", this.packager.executableName] + + await this.helper.icons + if (this.helper.maxIconPath != null) { + if (!this.isUseTemplateApp) { + snap.icon = "snap/gui/icon.png" + } + args.push("--icon", this.helper.maxIconPath) + } + + // snapcraft.yaml inside a snap directory + const snapMetaDir = path.join(stageDir, this.isUseTemplateApp ? "meta" : "snap") + const desktopFile = path.join(snapMetaDir, "gui", `${snap.name}.desktop`) + await this.helper.writeDesktopEntry(this.options, packager.executableName + " %U", desktopFile, { + // tslint:disable:no-invalid-template-strings + Icon: "${SNAP}/meta/gui/icon.png", + }) + + const extraAppArgs: Array = options.executableArgs ?? [] + if (this.isElectronVersionGreaterOrEqualThan("5.0.0") && !isBrowserSandboxAllowed(snap)) { + const noSandboxArg = "--no-sandbox" + if (!extraAppArgs.includes(noSandboxArg)) { + extraAppArgs.push(noSandboxArg) + } + if (this.isUseTemplateApp) { + args.push("--exclude", "chrome-sandbox") + } + } + if (extraAppArgs.length > 0) { + args.push("--extraAppArgs=" + extraAppArgs.join(" ")) + } + + if (snap.compression != null) { + args.push("--compression", snap.compression) + } + + if (this.isUseTemplateApp) { + // remove fields that are valid in snapcraft.yaml, but not snap.yaml + const fieldsToStrip = ["compression", "contact", "donation", "issues", "parts", "source-code", "website"] + for (const field of fieldsToStrip) { + delete snap[field] + } + } + + if (packager.packagerOptions.effectiveOptionComputed != null && (await packager.packagerOptions.effectiveOptionComputed({ snap, desktopFile, args }))) { + return + } + + await fsExtra.outputFile(path.join(snapMetaDir, this.isUseTemplateApp ? "snap.yaml" : "snapcraft.yaml"), serializeToYaml(snap)) + + const hooksDir = await packager.getResource(options.hooks, "snap-hooks") + if (hooksDir != null) { + args.push("--hooks", hooksDir) + } + + if (this.isUseTemplateApp) { + args.push("--template-url", `electron4:${snapArch}`) + } + + await executeAppBuilder(args) + + const publishConfig = findSnapPublishConfig(this.packager.config) + + await packager.info.emitArtifactBuildCompleted({ + file: artifactPath, + safeArtifactName: packager.computeSafeArtifactName(artifactName, "snap", arch, false), + target: this, + arch, + packager, + publishConfig, + }) + } + + private isElectronVersionGreaterOrEqualThan(version: string) { + return semver.gte(this.packager.config.electronVersion || "7.0.0", version) + } +} + +function findSnapPublishConfig(config?: Configuration): SnapStoreOptions | null { + const fallback: SnapStoreOptions = { provider: "snapStore" } + + if (!config) { + return fallback + } + + if (config.snap?.publish) { + return findSnapPublishConfigInPublishNode(config.snap.publish) + } + + if (config.linux?.publish) { + const configCandidate = findSnapPublishConfigInPublishNode(config.linux.publish) + + if (configCandidate) { + return configCandidate + } + } + + if (config.publish) { + const configCandidate = findSnapPublishConfigInPublishNode(config.publish) + + if (configCandidate) { + return configCandidate + } + } + + return fallback +} + +function findSnapPublishConfigInPublishNode(configPublishNode: Publish): SnapStoreOptions | null { + if (!configPublishNode) { + return null + } + + if (Array.isArray(configPublishNode)) { + for (const configObj of configPublishNode) { + if (isSnapStoreOptions(configObj)) { + return configObj + } + } + } + + if (typeof configPublishNode === `object` && isSnapStoreOptions(configPublishNode)) { + return configPublishNode + } + + return null +} + +function isSnapStoreOptions(configPublishNode: Publish): configPublishNode is SnapStoreOptions { + const snapStoreOptionsCandidate = configPublishNode as SnapStoreOptions + return snapStoreOptionsCandidate?.provider === `snapStore` +} + +function archNameToTriplet(arch: Arch): string { + switch (arch) { + case Arch.x64: + return "x86_64-linux-gnu" + case Arch.ia32: + return "i386-linux-gnu" + case Arch.armv7l: + // noinspection SpellCheckingInspection + return "arm-linux-gnueabihf" + case Arch.arm64: + return "aarch64-linux-gnu" + + default: + throw new Error(`Unsupported arch ${arch}`) + } +} + +function isArrayEqualRegardlessOfSort(a: Array, b: Array) { + a = a.slice() + b = b.slice() + a.sort() + b.sort() + return a.length === b.length && a.every((value, index) => value === b[index]) +} + +function normalizePlugConfiguration(raw: Array | PlugDescriptor | Nullish): Record | null> | null { + if (raw == null) { + return null + } + + const result: any = {} + for (const item of Array.isArray(raw) ? raw : [raw]) { + if (typeof item === "string") { + result[item] = null + } else { + Object.assign(result, item) + } + } + return result +} + +function isBrowserSandboxAllowed(snap: any): boolean { + if (snap.plugs != null) { + for (const plugName of Object.keys(snap.plugs)) { + const plug = snap.plugs[plugName] + if (plug.interface === "browser-support" && plug["allow-sandbox"] === true) { + return true + } + } + } + return false +} + +function getDefaultStagePackages() { + // libxss1 - was "error while loading shared libraries: libXss.so.1" on Xubuntu 16.04 + // noinspection SpellCheckingInspection + return ["libnspr4", "libnss3", "libxss1", "libappindicator3-1", "libsecret-1-0"] +} diff --git a/packages/app-builder-lib/src/targets/snap/SnapTarget.ts b/packages/app-builder-lib/src/targets/snap/SnapTarget.ts index e860f36f3b6..465112786ac 100644 --- a/packages/app-builder-lib/src/targets/snap/SnapTarget.ts +++ b/packages/app-builder-lib/src/targets/snap/SnapTarget.ts @@ -1,13 +1,13 @@ import { Arch, log } from "builder-util" import { deepAssign, SnapStoreOptions } from "builder-util-runtime" import * as path from "path" -import { Configuration } from "../../configuration" -import { Publish, Target } from "../../core" -import { LinuxPackager } from "../../linuxPackager" -import { SnapcraftOptions, SnapOptions } from "../../options/SnapOptions" -import { LinuxTargetHelper } from "../LinuxTargetHelper" -import { createStageDirPath } from "../targetUtil" -import { SnapcraftYAML } from "./snapcraft" +import { Configuration } from "../../configuration.js" +import { Publish, Target } from "../../core.js" +import { LinuxPackager } from "../../linuxPackager.js" +import { SnapcraftOptions, SnapOptions } from "../../options/SnapOptions.js" +import { LinuxTargetHelper } from "../LinuxTargetHelper.js" +import { createStageDirPath } from "../targetUtil.js" +import { SnapcraftYAML } from "./snapcraft.js" /** Abstract base for all snap build strategies (core24, legacy core18/20/22, custom pass-through). */ export abstract class SnapCore { diff --git a/packages/app-builder-lib/src/targets/snap/core24.ts b/packages/app-builder-lib/src/targets/snap/core24.ts index 9bd19632891..d1056f1b478 100644 --- a/packages/app-builder-lib/src/targets/snap/core24.ts +++ b/packages/app-builder-lib/src/targets/snap/core24.ts @@ -1,12 +1,14 @@ import { Arch, archFromString, copyDir, InvalidConfigurationError, log, removeNullish, toLinuxArchString } from "builder-util" -import { copy, mkdir, readdir, writeFile } from "fs-extra" + import * as path from "path" -import { PlugDescriptor, SlotDescriptor, SnapOptions24, SnapcraftOptions } from "../../options/SnapOptions" -import { SnapCore } from "./SnapTarget" -import { App, Part, SnapcraftYAML } from "./snapcraft" -import { buildSnap, DEFAULT_STAGE_PACKAGES, SNAPCRAFT_YAML_OPTIONS } from "./snapcraftBuilder" +import { PlugDescriptor, SlotDescriptor, SnapOptions24 } from "../../options/SnapOptions.js" +import { SnapCore } from "./SnapTarget.js" +import { App, Part, SnapcraftYAML } from "./snapcraft.js" +import { buildSnap, DEFAULT_STAGE_PACKAGES, SNAPCRAFT_YAML_OPTIONS } from "./snapcraftBuilder.js" import * as yaml from "js-yaml" import { deepAssign, isValidKey, Nullish } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { copy, mkdir, readdir, writeFile } = _fsExtra /** Snap build strategy for core24 — generates a native snapcraft.yaml and invokes the snapcraft CLI. */ export class SnapCore24 extends SnapCore { @@ -110,7 +112,7 @@ export class SnapCore24 extends SnapCore { } } - const rootOptions = this.packager.config.snapcraft as SnapcraftOptions | null | undefined + const rootOptions = this.packager.config.snapcraft await buildSnap({ snapcraftConfig: snap, artifactPath, diff --git a/packages/app-builder-lib/src/targets/snap/coreCustom.ts b/packages/app-builder-lib/src/targets/snap/coreCustom.ts index 7a9576dfeeb..cbbf7642ecb 100644 --- a/packages/app-builder-lib/src/targets/snap/coreCustom.ts +++ b/packages/app-builder-lib/src/targets/snap/coreCustom.ts @@ -1,11 +1,13 @@ import { Arch, InvalidConfigurationError, log } from "builder-util" -import { outputFile, readFile } from "fs-extra" + import * as yaml from "js-yaml" import * as path from "path" -import { SnapOptionsCustom } from "../../options/SnapOptions" -import { SnapCore } from "./SnapTarget" -import { SnapcraftYAML } from "./snapcraft" -import { buildSnap, SNAPCRAFT_YAML_OPTIONS } from "./snapcraftBuilder" +import { SnapOptionsCustom } from "../../options/SnapOptions.js" +import { SnapCore } from "./SnapTarget.js" +import { SnapcraftYAML } from "./snapcraft.js" +import { buildSnap, SNAPCRAFT_YAML_OPTIONS } from "./snapcraftBuilder.js" +import _fsExtra from "fs-extra" +const { outputFile, readFile } = _fsExtra /** * Pass-through snap builder for `base: "custom"`. diff --git a/packages/app-builder-lib/src/targets/snap/coreLegacy.ts b/packages/app-builder-lib/src/targets/snap/coreLegacy.ts index 8eba3ed300f..90ea83f2af7 100644 --- a/packages/app-builder-lib/src/targets/snap/coreLegacy.ts +++ b/packages/app-builder-lib/src/targets/snap/coreLegacy.ts @@ -1,13 +1,15 @@ import { replaceDefault as _replaceDefault, Arch, executeAppBuilder, serializeToYaml, toLinuxArchString } from "builder-util" import { asArray, deepAssign, isValidKey, Nullish } from "builder-util-runtime" -import { outputFile, readFile } from "fs-extra" + import { load } from "js-yaml" import * as path from "path" -import { PlugDescriptor, SnapOptions } from "../../options/SnapOptions" -import { getTemplatePath } from "../../util/pathManager" -import { SnapCore } from "./SnapTarget" -import { SnapcraftYAML } from "./snapcraft" -import { DEFAULT_STAGE_PACKAGES } from "./snapcraftBuilder" +import { PlugDescriptor, SnapOptions } from "../../options/SnapOptions.js" +import { getTemplatePath } from "../../util/pathManager.js" +import { SnapCore } from "./SnapTarget.js" +import { SnapcraftYAML } from "./snapcraft.js" +import { DEFAULT_STAGE_PACKAGES } from "./snapcraftBuilder.js" +import _fsExtra from "fs-extra" +const { outputFile, readFile } = _fsExtra // Handles core18/core20/core22 snaps via the app-builder binary (not the snapcraft CLI). // See: https://github.com/develar/app-builder/blob/master/pkg/package-format/snap diff --git a/packages/app-builder-lib/src/targets/snap/snapcraftBuilder.ts b/packages/app-builder-lib/src/targets/snap/snapcraftBuilder.ts index edcfcf8eea9..012f1d57253 100644 --- a/packages/app-builder-lib/src/targets/snap/snapcraftBuilder.ts +++ b/packages/app-builder-lib/src/targets/snap/snapcraftBuilder.ts @@ -2,13 +2,15 @@ import { InvalidConfigurationError, isEmptyOrSpaces, log, spawn, stripSensitiveE import * as childProcess from "child_process" import { randomUUID } from "crypto" import { resolveSnapCredentials } from "electron-publish" -import { copyFile, ensureDir, pathExists, readdir, remove } from "fs-extra" + import * as path from "path" import * as util from "util" -import { LinuxPackager } from "../../linuxPackager" -import { RemoteBuildOptions } from "../../options/SnapOptions" -import { SnapcraftYAML } from "./snapcraft" +import { LinuxPackager } from "../../linuxPackager.js" +import { RemoteBuildOptions } from "../../options/SnapOptions.js" +import { SnapcraftYAML } from "./snapcraft.js" import { deepAssign } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { copyFile, ensureDir, pathExists, readdir, remove } = _fsExtra const execAsync = util.promisify(childProcess.exec) diff --git a/packages/app-builder-lib/src/targets/targetFactory.ts b/packages/app-builder-lib/src/targets/targetFactory.ts index 744d13a1f3a..8d1cf37b542 100644 --- a/packages/app-builder-lib/src/targets/targetFactory.ts +++ b/packages/app-builder-lib/src/targets/targetFactory.ts @@ -1,7 +1,7 @@ import { addValue, Arch, archFromString, ArchType, asArray } from "builder-util" -import { DEFAULT_TARGET, DIR_TARGET, Platform, Target, TargetConfiguration } from "../core" -import { PlatformPackager } from "../platformPackager" -import { ArchiveTarget } from "./ArchiveTarget" +import { DEFAULT_TARGET, DIR_TARGET, Platform, Target, TargetConfiguration } from "../core.js" +import { PlatformPackager } from "../platformPackager.js" +import { ArchiveTarget } from "./ArchiveTarget.js" const archiveTargets = new Set(["zip", "7z", "tar.xz", "tar.lz", "tar.gz", "tar.bz2"]) diff --git a/packages/app-builder-lib/src/targets/targetUtil.ts b/packages/app-builder-lib/src/targets/targetUtil.ts index cb7fb2a8cff..b07b29ef001 100644 --- a/packages/app-builder-lib/src/targets/targetUtil.ts +++ b/packages/app-builder-lib/src/targets/targetUtil.ts @@ -1,8 +1,9 @@ import { Arch, debug } from "builder-util" import * as fs from "fs/promises" import * as path from "path" -import { AppInfo, Target } from "../" -import { PlatformPackager } from "../platformPackager" +import { AppInfo } from "../appInfo.js" +import { Target } from "../core.js" +import { PlatformPackager } from "../platformPackager.js" export class StageDir { constructor(readonly dir: string) {} diff --git a/packages/app-builder-lib/src/targets/tools.ts b/packages/app-builder-lib/src/targets/tools.ts new file mode 100644 index 00000000000..089df14cf95 --- /dev/null +++ b/packages/app-builder-lib/src/targets/tools.ts @@ -0,0 +1,44 @@ +import * as path from "path" +import { getBinFromUrl } from "../binDownload.js" + +export function getLinuxToolsPath() { + return getBinFromUrl("linux-tools-mac-10.12.3", "linux-tools-mac-10.12.3.7z", "SQ8fqIRVXuQVWnVgaMTDWyf2TLAJjJYw3tRSqQJECmgF6qdM7Kogfa6KD49RbGzzMYIFca9Uw3MdsxzOPRWcYw==") +} + +export async function getFpmPath() { + // It's just easier to copy the map of checksums here rather then adding them to within each if-statement. Also, easy copy-paste from the releases page + const fpmChecksumMap = { + "fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z": "0n3BG/Xz1T5YIsoNNTG1bBege9E8A7rym5e3mfzHSHbiSiTS44v6GIHW4amDQk1Y5dtKtWXVq7FwjdmAf3kmMg==", + "fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z": "wPX3UheBznIlAXduM22W/d27i+DZVIB/MYnY5eh/qLeEEASZqHJWgN+pIckz3jT0dP37g1SQCikXXfsgxtMSPA==", + "fpm-1.17.0-ruby-3.4.3-linux-amd64.7z": "7miGWr6dfJSzXDD9ALqkwxvGACp7s7GR50NPcU0YwzbJL825H1SLwGJSGME+v57BxDI2xac47gFEkRZf5u9EtA==", + "fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z": "moRNjg6Q2iSXpkrm5sGNL2F6KilGNPagbefxhtr3VEqvAUSg2k2pMLr5xXUo0L4rZ4V+uETbwmbDCpeO3pmLyQ==", + "fpm-1.17.0-ruby-3.4.3-linux-i386.7z": "UPzsXhkW2T7+oHSKgFsZsFUxxmPC9lNZHsQbT+OeoTbIGsb6+qf3m7c6uP0XvRFnJiu3MM3lE1xAWQOctvajWA==", + } + + if (process.env.CUSTOM_FPM_PATH != null) { + return path.resolve(process.env.CUSTOM_FPM_PATH) + } + const exec = "fpm" + if (process.platform === "win32" || process.env.USE_SYSTEM_FPM === "true") { + return exec + } + const getKey = () => { + if (process.platform === "linux") { + if (process.arch == "x64") { + return "fpm-1.17.0-ruby-3.4.3-linux-amd64.7z" + } else if (process.arch === "arm64") { + return "fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z" + } + return "fpm-1.17.0-ruby-3.4.3-linux-i386.7z" + } + // darwin arm64 + if (process.arch === "arm64") { + return "fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z" + } + return "fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z" + } + + const filename = getKey() + const fpmPath = await getBinFromUrl("fpm@2.1.4", filename, fpmChecksumMap[filename]) + return path.join(fpmPath, exec) +} diff --git a/packages/app-builder-lib/src/toolsets/icons.ts b/packages/app-builder-lib/src/toolsets/icons.ts index c7955d6f536..dd25fc931c7 100644 --- a/packages/app-builder-lib/src/toolsets/icons.ts +++ b/packages/app-builder-lib/src/toolsets/icons.ts @@ -1,6 +1,6 @@ import { exec, exists, InvalidConfigurationError, resolveEnvToolsetPath, sanitizeDirPath } from "builder-util" import * as path from "path" -import { downloadBuilderToolset } from "../util/electronGet" +import { downloadBuilderToolset } from "../util/electronGet.js" const iconsToolsChecksums = { "icons-bundle.tar.gz": "a96b7322c2562dfa53e675c343b17326b79709b793fe8023314584a7891d2b44", diff --git a/packages/app-builder-lib/src/toolsets/linux.ts b/packages/app-builder-lib/src/toolsets/linux.ts index c5c98a29903..b48ec49d46a 100644 --- a/packages/app-builder-lib/src/toolsets/linux.ts +++ b/packages/app-builder-lib/src/toolsets/linux.ts @@ -1,8 +1,8 @@ import { Arch, exists, resolveEnvToolsetPath, use } from "builder-util" import * as path from "path" -import { getBinFromUrl } from "../binDownload" -import { ToolsetConfig } from "../configuration" -import { downloadBuilderToolset } from "../util/electronGet" +import { getBinFromUrl } from "../binDownload.js" +import { ToolsetConfig } from "../configuration.js" +import { downloadBuilderToolset } from "../util/electronGet.js" const fpmChecksums = { "fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z": "6cc6d4785875bc7d79bdf52ca146080a4c300e1d663376ae79615fb548030ede", diff --git a/packages/app-builder-lib/src/toolsets/windows.ts b/packages/app-builder-lib/src/toolsets/windows.ts index 477568b9a1c..58aeadc56c0 100644 --- a/packages/app-builder-lib/src/toolsets/windows.ts +++ b/packages/app-builder-lib/src/toolsets/windows.ts @@ -1,13 +1,15 @@ import { Arch, exists, resolveEnvToolsetPath } from "builder-util" import { Nullish } from "builder-util-runtime" -import { stat } from "fs-extra" + import * as os from "os" import * as path from "path" -import { getBinFromCustomLoc, getBinFromUrl } from "../binDownload" -import { ToolsetConfig } from "../configuration" -import { ToolInfo, computeToolEnv } from "../util/bundledTool" -import { downloadBuilderToolset } from "../util/electronGet" -import { isUseSystemSigncode } from "../util/flags" +import { getBinFromCustomLoc, getBinFromUrl } from "../binDownload.js" +import { ToolsetConfig } from "../configuration.js" +import { ToolInfo, computeToolEnv } from "../util/bundledTool.js" +import { downloadBuilderToolset } from "../util/electronGet.js" +import { isUseSystemSigncode } from "../util/flags.js" +import _fsExtra from "fs-extra" +const { stat } = _fsExtra function getLegacyWinCodeSignBin(): Promise { return downloadBuilderToolset({ diff --git a/packages/app-builder-lib/src/util/AppFileWalker.ts b/packages/app-builder-lib/src/util/AppFileWalker.ts index c0f5a4c7b2e..fb2ec796228 100644 --- a/packages/app-builder-lib/src/util/AppFileWalker.ts +++ b/packages/app-builder-lib/src/util/AppFileWalker.ts @@ -1,8 +1,8 @@ import { FileConsumer, Filter, FilterStats } from "builder-util" -import { readlink, stat, Stats } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" -import { FileMatcher } from "../fileMatcher" -import { Packager } from "../packager" +import { FileMatcher } from "../fileMatcher.js" +import { Packager } from "../packager.js" function addAllPatternIfNeed(matcher: FileMatcher) { if (!matcher.isSpecifiedAsEmptyArray && (matcher.isEmpty() || matcher.containsOnlyIgnore())) { @@ -12,7 +12,7 @@ function addAllPatternIfNeed(matcher: FileMatcher) { } export abstract class FileCopyHelper { - readonly metadata = new Map() + readonly metadata = new Map() protected constructor( protected readonly matcher: FileMatcher, @@ -20,23 +20,23 @@ export abstract class FileCopyHelper { protected readonly packager: Packager ) {} - protected handleFile(file: string, parent: string, fileStat: Stats): Promise | null { + protected handleFile(file: string, parent: string, fileStat: fsExtra.Stats): Promise | null { if (!fileStat.isSymbolicLink()) { return null } - return readlink(file).then((linkTarget): any => { + return fsExtra.readlink(file).then((linkTarget): any => { // http://unix.stackexchange.com/questions/105637/is-symlinks-target-relative-to-the-destinations-parent-directory-and-if-so-wh return this.handleSymlink(fileStat, file, parent, linkTarget) }) } - private handleSymlink(fileStat: Stats, file: string, parent: string, linkTarget: string): Promise | null { + private handleSymlink(fileStat: fsExtra.Stats, file: string, parent: string, linkTarget: string): Promise | null { const resolvedLinkTarget = path.resolve(parent, linkTarget) const link = path.relative(this.matcher.from, resolvedLinkTarget) if (link.startsWith("..")) { // outside of project, linked module (https://github.com/electron-userland/electron-builder/issues/675) - return stat(resolvedLinkTarget).then(targetFileStat => { + return fsExtra.stat(resolvedLinkTarget).then(targetFileStat => { this.metadata.set(file, targetFileStat) return targetFileStat }) @@ -66,7 +66,7 @@ export class AppFileWalker extends FileCopyHelper implements FileConsumer { // noinspection JSUnusedGlobalSymbols // eslint-disable-next-line @typescript-eslint/no-unused-vars - consume(file: string, fileStat: Stats, parent: string, siblingNames: Array): any { + consume(file: string, fileStat: fsExtra.Stats, parent: string, siblingNames: Array): any { if (fileStat.isDirectory()) { const matchesFilter = this.matcherFilter(file, fileStat) return !matchesFilter diff --git a/packages/app-builder-lib/src/util/NodeModuleCopyHelper.ts b/packages/app-builder-lib/src/util/NodeModuleCopyHelper.ts index 1460b848f9c..dd129521ef7 100644 --- a/packages/app-builder-lib/src/util/NodeModuleCopyHelper.ts +++ b/packages/app-builder-lib/src/util/NodeModuleCopyHelper.ts @@ -1,13 +1,13 @@ import { FilterStats, MAX_FILE_REQUESTS } from "builder-util" import { realpathSync } from "fs" -import { lstat, lstatSync, readdir } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" import asyncPool from "tiny-async-pool" -import { excludedNames, FileMatcher } from "../fileMatcher" -import { Packager } from "../packager" -import { FileCopyHelper } from "./AppFileWalker" -import { NodeModuleInfo } from "./packageDependencies" -import { resolveFunction } from "./resolve" +import { excludedNames, FileMatcher } from "../fileMatcher.js" +import { Packager } from "../packager.js" +import { FileCopyHelper } from "./AppFileWalker.js" +import { NodeModuleInfo } from "./packageDependencies.js" +import { resolveFunction } from "./resolve.js" const excludedFiles = new Set( [ @@ -69,7 +69,7 @@ export class NodeModuleCopyHelper extends FileCopyHelper { while (queue.length > 0) { const dirPath = queue.pop()! - const childNames = await readdir(dirPath) + const childNames = await fsExtra.readdir(dirPath) childNames.sort() const isTopLevel = dirPath === depPath @@ -85,7 +85,7 @@ export class NodeModuleCopyHelper extends FileCopyHelper { } // check if filematcher matches the files array as more important than the default excluded files. - const fileMatched = filter != null && filter(dirPath, lstatSync(dirPath)) + const fileMatched = filter != null && filter(dirPath, fsExtra.lstatSync(dirPath)) if (!fileMatched || !forceIncluded || !!this.packager.config.disableDefaultIgnoredFiles) { for (const ext of nodeModuleExcludedExts) { if (name.endsWith(ext)) { @@ -111,7 +111,7 @@ export class NodeModuleCopyHelper extends FileCopyHelper { } } - return lstat(filePath).then((stat: FilterStats) => { + return fsExtra.lstat(filePath).then((stat: FilterStats) => { stat.moduleName = moduleName stat.moduleRootPath = destination stat.moduleFullFilePath = path.join(destination, path.relative(depPath, filePath)) diff --git a/packages/app-builder-lib/src/util/appFileCopier.ts b/packages/app-builder-lib/src/util/appFileCopier.ts index 60806a6f7de..48d38f7d5be 100644 --- a/packages/app-builder-lib/src/util/appFileCopier.ts +++ b/packages/app-builder-lib/src/util/appFileCopier.ts @@ -1,20 +1,20 @@ import { AsyncTaskManager, FileCopier, FileTransformer, isEmptyOrSpaces, Link, log, MAX_FILE_REQUESTS, statOrNull, walk } from "builder-util" import { Stats } from "fs" -import { ensureSymlink } from "fs-extra" +import fsExtra from "fs-extra" import { mkdir, readlink } from "fs/promises" import * as path from "path" import asyncPool from "tiny-async-pool" -import { isLibOrExe } from "../asar/unpackDetector" -import { Platform } from "../core" -import { excludedExts, FileMatcher } from "../fileMatcher" -import { createElectronCompilerHost, NODE_MODULES_PATTERN } from "../fileTransformer" -import { getCollectorByPackageManager, PM } from "../node-module-collector" -import { LogMessageByKey, logMessageLevelByKey, ModuleManager } from "../node-module-collector/moduleManager" -import { Packager } from "../packager" -import { PlatformPackager } from "../platformPackager" -import { AppFileWalker } from "./AppFileWalker" -import { NodeModuleCopyHelper } from "./NodeModuleCopyHelper" -import { NodeModuleInfo } from "./packageDependencies" +import { isLibOrExe } from "../asar/unpackDetector.js" +import { Platform } from "../core.js" +import { excludedExts, FileMatcher } from "../fileMatcher.js" +import { createElectronCompilerHost, NODE_MODULES_PATTERN } from "../fileTransformer.js" +import { getCollectorByPackageManager, PM } from "../node-module-collector/index.js" +import { LogMessageByKey, logMessageLevelByKey, ModuleManager } from "../node-module-collector/moduleManager.js" +import { Packager } from "../packager.js" +import { PlatformPackager } from "../platformPackager.js" +import { AppFileWalker } from "./AppFileWalker.js" +import { NodeModuleCopyHelper } from "./NodeModuleCopyHelper.js" +import { NodeModuleInfo } from "./packageDependencies.js" const BOWER_COMPONENTS_PATTERN = `${path.sep}bower_components${path.sep}` /** @internal */ @@ -74,7 +74,7 @@ export async function copyAppFiles(fileSet: ResolvedFileSet, packager: Packager, await taskManager.awaitTasks() } - await asyncPool(MAX_FILE_REQUESTS, links, it => ensureSymlink(it.link, it.file)) + await asyncPool(MAX_FILE_REQUESTS, links, it => fsExtra.ensureSymlink(it.link, it.file)) } // os path separator is used @@ -295,7 +295,7 @@ async function compileUsingElectronCompile(mainFileSet: ResolvedFileSet, package mainFileSet.files.length - 1, ` 'use strict'; -require('electron-compile').init(__dirname, require('path').resolve(__dirname, '${packager.metadata.main || "index"}'), true); +require('electron-compile').init(import.meta.dirname, require('path').resolve(import.meta.dirname, '${packager.metadata.main || "index"}'), true); ` ) return { src: electronCompileCache, files: cacheFiles, metadata, destination: mainFileSet.destination } diff --git a/packages/app-builder-lib/src/util/cacheManager.ts b/packages/app-builder-lib/src/util/cacheManager.ts index 7d7b0c894b8..5ea787aac90 100644 --- a/packages/app-builder-lib/src/util/cacheManager.ts +++ b/packages/app-builder-lib/src/util/cacheManager.ts @@ -1,6 +1,6 @@ import { Arch, copyFile, log, orNullIfFileNotExist } from "builder-util" import { Hash } from "crypto" -import { readJson, writeJson } from "fs-extra" +import fsExtra from "fs-extra" import { mkdir, readFile } from "fs/promises" import * as path from "path" @@ -32,7 +32,7 @@ export class BuildCacheManager { async copyIfValid(digest: string): Promise { this.newDigest = digest - this.cacheInfo = await orNullIfFileNotExist(readJson(this.cacheInfoFile)) + this.cacheInfo = await orNullIfFileNotExist(fsExtra.readJson(this.cacheInfoFile)) const oldDigest = this.cacheInfo == null ? null : this.cacheInfo.executableDigest if (oldDigest !== digest) { log.debug({ oldDigest, newDigest: digest }, "no valid cached executable found") @@ -66,7 +66,7 @@ export class BuildCacheManager { try { await mkdir(this.cacheDir, { recursive: true }) - await Promise.all([writeJson(this.cacheInfoFile, this.cacheInfo), copyFile(this.executableFile, this.cacheFile, false)]) + await Promise.all([fsExtra.writeJson(this.cacheInfoFile, this.cacheInfo), copyFile(this.executableFile, this.cacheFile, false)]) } catch (e: any) { log.warn({ error: e.stack || e }, `cannot save build cache`) } diff --git a/packages/app-builder-lib/src/util/config/config.ts b/packages/app-builder-lib/src/util/config/config.ts index 51ddfdc880b..0df1b9eccff 100644 --- a/packages/app-builder-lib/src/util/config/config.ts +++ b/packages/app-builder-lib/src/util/config/config.ts @@ -1,14 +1,19 @@ +import { createRequire } from "node:module" import { DebugLogger, InvalidConfigurationError, log, safeStringifyJson, statOrNull } from "builder-util" + +const _requireResolve = createRequire(import.meta.url).resolve import { deepAssign, Nullish } from "builder-util-runtime" -import { readJson } from "fs-extra" + import { Lazy } from "lazy-val" import * as path from "path" -import { Configuration } from "../../configuration" -import { FileSet } from "../../options/PlatformSpecificBuildOptions" -import { reactCra } from "../../presets/rectCra" -import { PACKAGE_VERSION } from "../../version" -import { getConfig as _getConfig, loadParentConfig, orNullIfFileNotExist, ReadConfigRequest } from "./load" -import { validateSchema } from "./schemaValidator" +import { Configuration } from "../../configuration.js" +import { FileSet } from "../../options/PlatformSpecificBuildOptions.js" +import { reactCra } from "../../presets/rectCra.js" +import { PACKAGE_VERSION } from "../../version.js" +import { getConfig as _getConfig, loadParentConfig, orNullIfFileNotExist, ReadConfigRequest } from "./load.js" +import { validateSchema } from "./schemaValidator.js" +import _fsExtra from "fs-extra" +const { readJson } = _fsExtra // https://github.com/electron-userland/electron-builder/issues/1847 function mergePublish(config: Configuration, configFromOptions: Configuration) { @@ -59,9 +64,9 @@ export async function getConfig( } else if (devDependencies != null && "electron-webpack" in devDependencies) { let file = "electron-webpack/out/electron-builder.js" try { - file = require.resolve(file) + file = _requireResolve(file) } catch (_ignore) { - file = require.resolve("electron-webpack/electron-builder.yml") + file = _requireResolve("electron-webpack/electron-builder.yml") } config.extends = `file:${file}` } @@ -214,7 +219,7 @@ function getDefaultConfig(): Configuration { } } -const schemeDataPromise = new Lazy(() => readJson(path.join(__dirname, "..", "..", "..", "scheme.json"))) +const schemeDataPromise = new Lazy(() => readJson(path.join(import.meta.dirname, "..", "..", "..", "scheme.json"))) export async function validateConfiguration(config: Configuration, debugLogger: DebugLogger) { const extraMetadata = config.extraMetadata diff --git a/packages/app-builder-lib/src/util/config/load.ts b/packages/app-builder-lib/src/util/config/load.ts index 2c398084dd4..ecbfa7ed1d6 100644 --- a/packages/app-builder-lib/src/util/config/load.ts +++ b/packages/app-builder-lib/src/util/config/load.ts @@ -1,4 +1,7 @@ +import { createRequire } from "node:module" import { log } from "builder-util" + +const require = createRequire(import.meta.url) import { parse as parseEnv } from "dotenv" import { DotenvParseInput, expand } from "dotenv-expand" import { promises as fs } from "fs" @@ -6,9 +9,9 @@ import { createJiti } from "jiti" import { load } from "js-yaml" import { Lazy } from "lazy-val" import * as path from "path" -import { resolveModule } from "../resolve" +import { resolveModule } from "../resolve.js" -const jiti = createJiti(__filename) +const jiti = createJiti(import.meta.filename) export interface ReadConfigResult { readonly result: T diff --git a/packages/app-builder-lib/src/util/dynamicImport.ts b/packages/app-builder-lib/src/util/dynamicImport.ts index 86d726a5708..9c37292aa79 100644 --- a/packages/app-builder-lib/src/util/dynamicImport.ts +++ b/packages/app-builder-lib/src/util/dynamicImport.ts @@ -1,11 +1,15 @@ -// TypeScript's "module": "CommonJS" compiles `await import(x)` to -// `await Promise.resolve().then(() => require(x))`, which fails for ESM-only -// packages. helpers/dynamic-import.js is plain JS so TypeScript never -// transforms its native import() call — route through it instead. -// eslint-disable-next-line @typescript-eslint/no-require-imports -const _helper = require("../../helpers/dynamic-import") as { dynamicImport(path: string): Promise } +// helpers/dynamic-import.cjs uses CJS require.resolve so it can follow pnpm +// symlinks — load it via createRequire so TypeScript does not statically +// include the out-of-rootDir file in the compilation. +import { createRequire } from "node:module" + +type DynamicImportHelper = { + dynamicImport(modulePath: string): Promise + dynamicImportMaybe(modulePath: string): Promise +} + +const _helper = createRequire(import.meta.url)("../../helpers/dynamic-import.cjs") as DynamicImportHelper -// eslint-disable-next-line @typescript-eslint/no-explicit-any export function dynamicImport(modulePath: string): Promise { - return _helper.dynamicImport(modulePath) + return _helper.dynamicImport(modulePath) as Promise } diff --git a/packages/app-builder-lib/src/util/electronGet.ts b/packages/app-builder-lib/src/util/electronGet.ts index f4c5887b153..a943f3a6e89 100644 --- a/packages/app-builder-lib/src/util/electronGet.ts +++ b/packages/app-builder-lib/src/util/electronGet.ts @@ -8,7 +8,7 @@ import { MirrorOptions, } from "@electron/get" import { buildGotProxyAgent, exec, exists, getPath7za, log, PADDING, parseValidEnvVarUrl, sanitizeDirPath, to7zaOutputSwitch } from "builder-util" -import { MultiProgress } from "electron-publish/out/multiProgress" +import { MultiProgress } from "electron-publish" import { createReadStream, createWriteStream } from "fs" import * as fs from "fs/promises" import * as crypto from "crypto" @@ -19,8 +19,8 @@ import { pipeline } from "stream/promises" import * as tar from "tar" import * as unzipper from "unzipper" import { HttpError, retry } from "builder-util-runtime" -import { ElectronPlatformName } from "../electron/ElectronFramework" -import { CacheState, cleanupCacheDirectory, computeCacheMetadata, readCacheStateFile, validateCacheDirectory, writeCacheState } from "./cacheState" +import { ElectronPlatformName } from "../electron/ElectronFramework.js" +import { CacheState, cleanupCacheDirectory, computeCacheMetadata, readCacheStateFile, validateCacheDirectory, writeCacheState } from "./cacheState.js" import type { ProgressBar } from "electron-publish" export type ElectronGetOptions = Omit< diff --git a/packages/app-builder-lib/src/util/iconConverter.ts b/packages/app-builder-lib/src/util/iconConverter.ts index 189f026f2a6..c53c4a6ee14 100644 --- a/packages/app-builder-lib/src/util/iconConverter.ts +++ b/packages/app-builder-lib/src/util/iconConverter.ts @@ -1,6 +1,6 @@ import { mkdir, readFile, readdir, rename, stat } from "fs/promises" import * as path from "path" -import { runIconsTool } from "../toolsets/icons" +import { runIconsTool } from "../toolsets/icons.js" class IconConversionError extends Error { constructor( diff --git a/packages/app-builder-lib/src/util/license.ts b/packages/app-builder-lib/src/util/license.ts index 7b9f06eeee6..da20e4dd392 100644 --- a/packages/app-builder-lib/src/util/license.ts +++ b/packages/app-builder-lib/src/util/license.ts @@ -1,7 +1,7 @@ import { Nullish } from "builder-util-runtime" import * as path from "path" -import { PlatformPackager } from "../platformPackager" -import { langIdToName, toLangWithRegion } from "./langs" +import { PlatformPackager } from "../platformPackager.js" +import { langIdToName, toLangWithRegion } from "./langs.js" export function getLicenseAssets(fileNames: Array, packager: PlatformPackager) { return fileNames diff --git a/packages/app-builder-lib/src/util/macosVersion.ts b/packages/app-builder-lib/src/util/macosVersion.ts index 62156f9e70d..c10ba42f597 100644 --- a/packages/app-builder-lib/src/util/macosVersion.ts +++ b/packages/app-builder-lib/src/util/macosVersion.ts @@ -1,11 +1,11 @@ import { log } from "builder-util" -import { readFile } from "fs-extra" +import fsExtra from "fs-extra" import { Lazy } from "lazy-val" import { release as osRelease } from "os" import * as semver from "semver" const macOsVersion = new Lazy(async () => { - const file = await readFile("/System/Library/CoreServices/SystemVersion.plist", "utf8") + const file = await fsExtra.readFile("/System/Library/CoreServices/SystemVersion.plist", "utf8") const matches = /ProductVersion<\/key>[\s\S]*([\d.]+)<\/string>/.exec(file) if (!matches) { throw new Error("Couldn't find the macOS version") diff --git a/packages/app-builder-lib/src/util/macroExpander.ts b/packages/app-builder-lib/src/util/macroExpander.ts index e0e85b09db7..d7067331141 100644 --- a/packages/app-builder-lib/src/util/macroExpander.ts +++ b/packages/app-builder-lib/src/util/macroExpander.ts @@ -1,6 +1,6 @@ import { InvalidConfigurationError, log } from "builder-util" import { Nullish } from "builder-util-runtime" -import { AppInfo } from "../appInfo" +import { AppInfo } from "../appInfo.js" export function expandMacro(pattern: string, arch: string | Nullish, appInfo: AppInfo, extra: any = {}, isProductNameSanitized = true): string { if (arch == null) { diff --git a/packages/app-builder-lib/src/util/normalizePackageData.ts b/packages/app-builder-lib/src/util/normalizePackageData.ts index 43e56ab711f..d58b81a16ff 100644 --- a/packages/app-builder-lib/src/util/normalizePackageData.ts +++ b/packages/app-builder-lib/src/util/normalizePackageData.ts @@ -1,6 +1,6 @@ import { fromUrl } from "hosted-git-info" import * as semver from "semver" -import { parseUrl } from "./pathManager" +import { parseUrl } from "./pathManager.js" export function normalizePackageData(data: any) { for (const it of check) { diff --git a/packages/app-builder-lib/src/util/packageMetadata.ts b/packages/app-builder-lib/src/util/packageMetadata.ts index abef9283810..fe86036c826 100644 --- a/packages/app-builder-lib/src/util/packageMetadata.ts +++ b/packages/app-builder-lib/src/util/packageMetadata.ts @@ -1,14 +1,14 @@ import { InvalidConfigurationError, isEmptyOrSpaces, log } from "builder-util" import { Nullish } from "builder-util-runtime" -import { readFile, readJson, readJsonSync } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" import * as semver from "semver" -import { Metadata } from "../options/metadata" -import { normalizePackageData } from "./normalizePackageData" +import { Metadata } from "../options/metadata.js" +import { normalizePackageData } from "./normalizePackageData.js" /** @internal */ export async function readPackageJson(file: string): Promise { - const data = await readJson(file) + const data = await fsExtra.readJson(file) await authors(file, data) // remove not required fields because can be used for remote build delete data.scripts @@ -24,7 +24,7 @@ async function authors(file: string, data: any) { let authorData try { - authorData = await readFile(path.resolve(path.dirname(file), "AUTHORS"), "utf8") + authorData = await fsExtra.readFile(path.resolve(path.dirname(file), "AUTHORS"), "utf8") } catch (_ignored) { return } @@ -115,8 +115,8 @@ function checkDependencies(dependencies: Record | Nullish, error for (const prefix of prefixes) { if (updaterVersion.startsWith(prefix)) { const normalized = path.normalize(updaterVersion.substring(prefix.length)) - const packageJsonPath = path.isAbsolute(normalized) ? normalized : path.resolve(__dirname, normalized) - const json = readJsonSync(path.join(packageJsonPath, "package.json")) + const packageJsonPath = path.isAbsolute(normalized) ? normalized : path.resolve(process.cwd(), normalized) + const json = fsExtra.readJsonSync(path.join(packageJsonPath, "package.json")) updaterVersion = json.version break } diff --git a/packages/app-builder-lib/src/util/pathManager.ts b/packages/app-builder-lib/src/util/pathManager.ts index a80c0cdeee8..8f7ca31f0d0 100644 --- a/packages/app-builder-lib/src/util/pathManager.ts +++ b/packages/app-builder-lib/src/util/pathManager.ts @@ -1,6 +1,6 @@ import * as path from "path" -const root = path.join(__dirname, "..", "..") +const root = path.join(import.meta.dirname, "..", "..") export function getTemplatePath(file: string) { return path.join(root, "templates", file) diff --git a/packages/app-builder-lib/src/util/plist.ts b/packages/app-builder-lib/src/util/plist.ts index 2f2e31aecbf..ae4dd82ba1c 100644 --- a/packages/app-builder-lib/src/util/plist.ts +++ b/packages/app-builder-lib/src/util/plist.ts @@ -1,4 +1,4 @@ -import { build, parse } from "plist" +import * as plist_1 from "plist" import * as fs from "fs/promises" type PlistValue = string | number | boolean | Date | PlistObject | PlistValue[] @@ -27,13 +27,13 @@ function sortObjectKeys(obj: PlistValue): PlistValue { export async function savePlistFile(path: string, data: PlistValue): Promise { const sortedData = sortObjectKeys(data) - const plist = build(sortedData) + const plist = plist_1.build(sortedData) await fs.writeFile(path, plist) } export async function parsePlistFile(file: string): Promise { const data = await fs.readFile(file, "utf8") - return parse(data) as T + return plist_1.parse(data) as T } export type { PlistValue, PlistObject } diff --git a/packages/app-builder-lib/src/util/rebuild.ts b/packages/app-builder-lib/src/util/rebuild.ts index 39595c02413..eedc88ad847 100644 --- a/packages/app-builder-lib/src/util/rebuild.ts +++ b/packages/app-builder-lib/src/util/rebuild.ts @@ -7,7 +7,7 @@ export const rebuild = async (options: RebuildOptions): Promise => { const { arch } = options log.info({ arch }, `installing native dependencies`) - const child = cp.fork(path.resolve(__dirname, "../../helpers/remote-rebuild.js"), [JSON.stringify(options)], { + const child = cp.fork(path.resolve(import.meta.dirname, "../../helpers/remote-rebuild.js"), [JSON.stringify(options)], { stdio: ["pipe", "pipe", "pipe", "ipc"], }) diff --git a/packages/app-builder-lib/src/util/repositoryInfo.ts b/packages/app-builder-lib/src/util/repositoryInfo.ts index 2a24592f259..61f1365d77f 100644 --- a/packages/app-builder-lib/src/util/repositoryInfo.ts +++ b/packages/app-builder-lib/src/util/repositoryInfo.ts @@ -1,16 +1,16 @@ import { orNullIfFileNotExist } from "builder-util" -import { readFile } from "fs-extra" +import fsExtra from "fs-extra" import GitHost, { fromUrl } from "hosted-git-info" import * as path from "path" -import { SourceRepositoryInfo } from "../core" -import { Metadata, RepositoryInfo } from "../options/metadata" +import { SourceRepositoryInfo } from "../core.js" +import { Metadata, RepositoryInfo } from "../options/metadata.js" export function getRepositoryInfo(projectDir: string, metadata?: Metadata, devMetadata?: Metadata | null): Promise { return _getInfo(projectDir, (devMetadata == null ? null : devMetadata.repository) || (metadata == null ? null : metadata.repository)) } async function getGitUrlFromGitConfig(projectDir: string): Promise { - const data = await orNullIfFileNotExist(readFile(path.join(projectDir, ".git", "config"), "utf8")) + const data = await orNullIfFileNotExist(fsExtra.readFile(path.join(projectDir, ".git", "config"), "utf8")) if (data == null) { return null } diff --git a/packages/app-builder-lib/src/util/resEdit.ts b/packages/app-builder-lib/src/util/resEdit.ts index e67c5cbed3b..4e5646b79be 100644 --- a/packages/app-builder-lib/src/util/resEdit.ts +++ b/packages/app-builder-lib/src/util/resEdit.ts @@ -1,7 +1,7 @@ import { log } from "builder-util" import { readFile, writeFile } from "fs/promises" import { Data, NtExecutable, NtExecutableResource, Resource } from "resedit" -import { RequestedExecutionLevel } from "../options/winOptions" +import { RequestedExecutionLevel } from "../options/winOptions.js" export interface ResourceEditOptions { file: string diff --git a/packages/app-builder-lib/src/util/resolve.ts b/packages/app-builder-lib/src/util/resolve.ts index 2fa6896d78a..df70f93bc5f 100644 --- a/packages/app-builder-lib/src/util/resolve.ts +++ b/packages/app-builder-lib/src/util/resolve.ts @@ -1,13 +1,16 @@ -import { InvalidConfigurationError } from "builder-util" -import { log } from "builder-util/out/log" +import { InvalidConfigurationError, log } from "builder-util" import debug from "debug" import { realpath } from "fs/promises" +import { createRequire } from "node:module" import * as path from "path" -import * as requireMaybe from "../../helpers/dynamic-import" + +const _require = createRequire(import.meta.url) +const _requireResolve = _require.resolve +const _dynamicImportMaybe: (modulePath: string) => Promise = _require("../../helpers/dynamic-import.cjs").dynamicImportMaybe export async function resolveModule(type: string | undefined, name: string): Promise { try { - return requireMaybe.dynamicImportMaybe(name) + return _dynamicImportMaybe(name) } catch (error: any) { log.error({ moduleName: name, message: error.message ?? error.stack }, "Unable to dynamically `import` or `require`") throw error @@ -38,7 +41,7 @@ export async function resolveFunction(type: string | undefined, executor: T | } try { - p = require.resolve(p) + p = _requireResolve(p) } catch (e: any) { debug(e) p = path.resolve(p) diff --git a/packages/app-builder-lib/src/util/yarn.ts b/packages/app-builder-lib/src/util/yarn.ts index df9f89299c2..825f9667ba3 100644 --- a/packages/app-builder-lib/src/util/yarn.ts +++ b/packages/app-builder-lib/src/util/yarn.ts @@ -1,14 +1,16 @@ import { asArray, log, spawn, stripSensitiveEnvVars } from "builder-util" -import { pathExists } from "fs-extra" + import { homedir } from "os" import * as path from "path" -import { Configuration } from "../configuration" -import { PM, getPackageManagerCommand } from "../node-module-collector" -import { detectPackageManager } from "../node-module-collector/packageManager" -import { rebuild as remoteRebuild } from "./rebuild" +import { Configuration } from "../configuration.js" +import { PM, getPackageManagerCommand } from "../node-module-collector/index.js" +import { detectPackageManager } from "../node-module-collector/packageManager.js" +import { rebuild as remoteRebuild } from "./rebuild.js" import * as which from "which" import type { RebuildOptions as ElectronRebuildOptions } from "@electron/rebuild" import { Nullish } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { pathExists } = _fsExtra export async function installOrRebuild( config: Configuration, diff --git a/packages/app-builder-lib/src/vm/MonoVm.ts b/packages/app-builder-lib/src/vm/MonoVm.ts index fc97d8361fb..ad354bfb3a9 100644 --- a/packages/app-builder-lib/src/vm/MonoVm.ts +++ b/packages/app-builder-lib/src/vm/MonoVm.ts @@ -1,6 +1,6 @@ import { exec, ExtraSpawnOptions, spawn } from "builder-util" import { ExecFileOptions, SpawnOptions } from "child_process" -import { VmManager } from "./vm" +import { VmManager } from "./vm.js" export class MonoVmManager extends VmManager { constructor() { diff --git a/packages/app-builder-lib/src/vm/ParallelsVm.ts b/packages/app-builder-lib/src/vm/ParallelsVm.ts index de9aabdaf1c..fe406de8fc8 100644 --- a/packages/app-builder-lib/src/vm/ParallelsVm.ts +++ b/packages/app-builder-lib/src/vm/ParallelsVm.ts @@ -1,6 +1,9 @@ +import { createRequire } from "node:module" import { DebugLogger, ExtraSpawnOptions, exec, log, spawn } from "builder-util" + +const require = createRequire(import.meta.url) import { ExecFileOptions, SpawnOptions, execFileSync } from "child_process" -import { VmManager } from "./vm" +import { VmManager } from "./vm.js" /** @internal */ export async function parseVmList(debugLogger: DebugLogger) { diff --git a/packages/app-builder-lib/src/vm/PwshVm.ts b/packages/app-builder-lib/src/vm/PwshVm.ts index 17a73e774ed..2f8df53f949 100644 --- a/packages/app-builder-lib/src/vm/PwshVm.ts +++ b/packages/app-builder-lib/src/vm/PwshVm.ts @@ -1,6 +1,6 @@ import { log } from "builder-util" import { Lazy } from "lazy-val" -import { isPwshAvailable, VmManager } from "./vm" +import { isPwshAvailable, VmManager } from "./vm.js" export class PwshVmManager extends VmManager { constructor() { diff --git a/packages/app-builder-lib/src/vm/WineVm.ts b/packages/app-builder-lib/src/vm/WineVm.ts index 2158ba865bd..f0a6a974948 100644 --- a/packages/app-builder-lib/src/vm/WineVm.ts +++ b/packages/app-builder-lib/src/vm/WineVm.ts @@ -1,8 +1,8 @@ import { ExtraSpawnOptions } from "builder-util" import { ExecFileOptions, SpawnOptions } from "child_process" import * as path from "path" -import { execWine } from "../wine" -import { VmManager } from "./vm" +import { execWine } from "../wine.js" +import { VmManager } from "./vm.js" export class WineVmManager extends VmManager { constructor() { diff --git a/packages/app-builder-lib/src/vm/vm.ts b/packages/app-builder-lib/src/vm/vm.ts index 756982a29df..39df09d3304 100644 --- a/packages/app-builder-lib/src/vm/vm.ts +++ b/packages/app-builder-lib/src/vm/vm.ts @@ -2,7 +2,7 @@ import { DebugLogger, exec, ExtraSpawnOptions, InvalidConfigurationError, log, s import { ExecFileOptions, SpawnOptions } from "child_process" import { Lazy } from "lazy-val" import * as path from "path" -import { ParallelsVm } from "./ParallelsVm" +import { ParallelsVm } from "./ParallelsVm.js" export class VmManager { get pathSep(): string { return path.sep @@ -34,13 +34,13 @@ export class VmManager { } export async function getWindowsVm(debugLogger: DebugLogger): Promise { - const parallelsVmModule = await import("./ParallelsVm") + const parallelsVmModule = await import("./ParallelsVm.js") let vmList: ParallelsVm[] = [] try { vmList = (await parallelsVmModule.parseVmList(debugLogger)).filter(it => ["win-10", "win-11"].includes(it.os)) } catch (_error) { if ((await isPwshAvailable.value) && (await isWineAvailable.value)) { - const vmModule = await import("./PwshVm") + const vmModule = await import("./PwshVm.js") return new vmModule.PwshVmManager() } } @@ -57,13 +57,13 @@ export async function getLinuxVm(debugLogger: DebugLogger): Promise it.os === "ubuntu") if (vmList.length === 0) { return undefined } const vm = vmList.find(it => it.state === "running") || vmList.find(it => it.state === "suspended") || vmList[0] - return new parallelsVmModule.ParallelsVmManager(vm!) + return new parallelsVmModule.ParallelsVmManager(vm) } catch { return undefined } diff --git a/packages/app-builder-lib/src/winPackager.ts b/packages/app-builder-lib/src/winPackager.ts index 8ca32fe9542..b4f17308826 100644 --- a/packages/app-builder-lib/src/winPackager.ts +++ b/packages/app-builder-lib/src/winPackager.ts @@ -1,32 +1,35 @@ import { Arch, CopyFileTransformer, exists, FileTransformer, InvalidConfigurationError, log, walk } from "builder-util" +import { createRequire } from "node:module" import { Nullish } from "builder-util-runtime" import { isCI } from "ci-info" import { createHash } from "crypto" import { readdir } from "fs/promises" import { Lazy } from "lazy-val" import * as path from "path" -import { readAsarHeader } from "./asar/asar" -import { SignManager } from "./codeSign/signManager" -import { signWindows, WindowsSignOptions } from "./codeSign/windowsCodeSign" -import { WindowsSignAzureManager } from "./codeSign/windowsSignAzureManager" -import { FileCodeSigningInfo, WindowsSignToolManager } from "./codeSign/windowsSignToolManager" -import { AfterPackContext } from "./configuration" -import { DIR_TARGET, Platform, Target } from "./core" -import { RequestedExecutionLevel, WindowsConfiguration } from "./options/winOptions" -import { Packager } from "./packager" -import { chooseNotNull, PlatformPackager } from "./platformPackager" -import AppXTarget from "./targets/AppxTarget" -import MsiTarget from "./targets/MsiTarget" -import MsiWrappedTarget from "./targets/MsiWrappedTarget" -import { NsisTarget } from "./targets/nsis/NsisTarget" -import { AppPackageHelper, CopyElevateHelper } from "./targets/nsis/nsisUtil" -import { WebInstallerTarget } from "./targets/nsis/WebInstallerTarget" -import { createCommonTarget } from "./targets/targetFactory" -import { BuildCacheManager, digest } from "./util/cacheManager" -import { isBuildCacheEnabled } from "./util/flags" -import { editWindowsResources, ResourceEditOptions } from "./util/resEdit" -import { time } from "./util/timer" -import { getWindowsVm, VmManager } from "./vm/vm" +import { readAsarHeader } from "./asar/asar.js" +import { SignManager } from "./codeSign/signManager.js" +import { signWindows, WindowsSignOptions } from "./codeSign/windowsCodeSign.js" +import { WindowsSignAzureManager } from "./codeSign/windowsSignAzureManager.js" +import { FileCodeSigningInfo, WindowsSignToolManager } from "./codeSign/windowsSignToolManager.js" +import { AfterPackContext } from "./configuration.js" +import { DIR_TARGET, Platform, Target } from "./core.js" +import { RequestedExecutionLevel, WindowsConfiguration } from "./options/winOptions.js" +import { Packager } from "./packager.js" +import { chooseNotNull, PlatformPackager } from "./platformPackager.js" +import AppXTarget from "./targets/AppxTarget.js" +import MsiTarget from "./targets/MsiTarget.js" +import MsiWrappedTarget from "./targets/MsiWrappedTarget.js" +import { NsisTarget } from "./targets/nsis/NsisTarget.js" +import { AppPackageHelper, CopyElevateHelper } from "./targets/nsis/nsisUtil.js" +import { WebInstallerTarget } from "./targets/nsis/WebInstallerTarget.js" +import { createCommonTarget } from "./targets/targetFactory.js" +import { BuildCacheManager, digest } from "./util/cacheManager.js" +import { isBuildCacheEnabled } from "./util/flags.js" +import { editWindowsResources, ResourceEditOptions } from "./util/resEdit.js" +import { time } from "./util/timer.js" +import { getWindowsVm, VmManager } from "./vm/vm.js" + +const _require = createRequire(import.meta.url) export class WinPackager extends PlatformPackager { _iconPath = new Lazy(() => this.getOrConvertIcon("ico")) @@ -89,19 +92,19 @@ export class WinPackager extends PlatformPackager { switch (name) { case "squirrel": try { - return require("electron-builder-squirrel-windows").default + return _require("electron-builder-squirrel-windows").default } catch (e: any) { throw new InvalidConfigurationError(`Module electron-builder-squirrel-windows must be installed in addition to build Squirrel.Windows: ${e.stack || e}`) } case "appx": - return require("./targets/AppxTarget").default + return AppXTarget case "msi": - return require("./targets/MsiTarget").default + return MsiTarget case "msiwrapped": - return require("./targets/MsiWrappedTarget").default + return MsiWrappedTarget default: return null diff --git a/packages/app-builder-lib/tsconfig-scheme.json b/packages/app-builder-lib/tsconfig-scheme.json index 7c1ea20d7aa..e6f1af42b9f 100644 --- a/packages/app-builder-lib/tsconfig-scheme.json +++ b/packages/app-builder-lib/tsconfig-scheme.json @@ -8,6 +8,4 @@ "src/**/*.ts", "../../typings/*.d.ts" ], - "exclude": [ - ] } \ No newline at end of file diff --git a/packages/app-builder-lib/tsconfig.build.json b/packages/app-builder-lib/tsconfig.build.json new file mode 100644 index 00000000000..a7e8002eb6d --- /dev/null +++ b/packages/app-builder-lib/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts", "../../typings/*.d.ts"] +} diff --git a/packages/app-builder-lib/tsconfig.json b/packages/app-builder-lib/tsconfig.json index 9c8c13598e0..162e4b06d22 100644 --- a/packages/app-builder-lib/tsconfig.json +++ b/packages/app-builder-lib/tsconfig.json @@ -1,10 +1,5 @@ { "extends": "./tsconfig-scheme.json", - "jsdoc": { - "out": "../../scripts/jsdoc/out/builder-lib", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, "compilerOptions": { "outDir": "out", "rootDir": "src", @@ -13,8 +8,6 @@ "src/**/*.ts", "../../typings/*.d.ts" ], - "exclude": [ - ], "references": [ { "path": "../builder-util" diff --git a/packages/builder-util-runtime/package.json b/packages/builder-util-runtime/package.json index b3294ad23c2..bffc796f9a4 100644 --- a/packages/builder-util-runtime/package.json +++ b/packages/builder-util-runtime/package.json @@ -1,7 +1,21 @@ { "name": "builder-util-runtime", "version": "9.6.3", - "main": "out/index.js", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { @@ -12,10 +26,14 @@ "bugs": "https://github.com/electron-userland/electron-builder/issues", "homepage": "https://github.com/electron-userland/electron-builder", "files": [ - "out" + "dist" ], + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, "engines": { - "node": ">=12.0.0" + "node": ">=22.12.0" }, "dependencies": { "debug": "^4.3.4", @@ -25,5 +43,5 @@ "@types/debug": "4.1.7", "@types/sax": "1.2.3" }, - "types": "./out/index.d.ts" + "types": "./dist/index.d.ts" } diff --git a/packages/builder-util-runtime/src/ProgressCallbackTransform.ts b/packages/builder-util-runtime/src/ProgressCallbackTransform.ts index 39fd25ea75a..1e9e8562232 100644 --- a/packages/builder-util-runtime/src/ProgressCallbackTransform.ts +++ b/packages/builder-util-runtime/src/ProgressCallbackTransform.ts @@ -1,5 +1,5 @@ import { Transform } from "stream" -import { CancellationToken } from "./CancellationToken" +import { CancellationToken } from "./CancellationToken.js" export interface ProgressInfo { total: number diff --git a/packages/builder-util-runtime/src/httpExecutor.ts b/packages/builder-util-runtime/src/httpExecutor.ts index 1b10ecc5710..dc2ab1c59fb 100644 --- a/packages/builder-util-runtime/src/httpExecutor.ts +++ b/packages/builder-util-runtime/src/httpExecutor.ts @@ -5,10 +5,10 @@ import { IncomingMessage, OutgoingHttpHeader, OutgoingHttpHeaders, RequestOption import { Socket } from "net" import { Transform } from "stream" import { URL } from "url" -import { Nullish } from "." -import { CancellationToken } from "./CancellationToken" -import { newError } from "./error" -import { ProgressCallbackTransform, ProgressInfo } from "./ProgressCallbackTransform" +import { Nullish } from "./index.js" +import { CancellationToken } from "./CancellationToken.js" +import { newError } from "./error.js" +import { ProgressCallbackTransform, ProgressInfo } from "./ProgressCallbackTransform.js" const debug = _debug("electron-builder") diff --git a/packages/builder-util-runtime/src/index.ts b/packages/builder-util-runtime/src/index.ts index 92f16bc975e..62d0972778a 100644 --- a/packages/builder-util-runtime/src/index.ts +++ b/packages/builder-util-runtime/src/index.ts @@ -1,6 +1,6 @@ -export { BlockMap } from "./blockMapApi" -export { CancellationError, CancellationToken } from "./CancellationToken" -export { newError } from "./error" +export { BlockMap } from "./blockMapApi.js" +export { CancellationError, CancellationToken } from "./CancellationToken.js" +export { newError } from "./error.js" export { configureRequestOptions, configureRequestOptionsFromUrl, @@ -14,9 +14,9 @@ export { RequestHeaders, safeGetHeader, safeStringifyJson, -} from "./httpExecutor" -export { MemoLazy } from "./MemoLazy" -export { ProgressCallbackTransform, ProgressInfo } from "./ProgressCallbackTransform" +} from "./httpExecutor.js" +export { MemoLazy } from "./MemoLazy.js" +export { ProgressCallbackTransform, ProgressInfo } from "./ProgressCallbackTransform.js" export { AllPublishOptions, BaseS3Options, @@ -36,13 +36,13 @@ export { SpacesOptions, GitlabReleaseInfo, GitlabReleaseAsset, -} from "./publishOptions" -export { retry } from "./retry" -export { parseDn } from "./rfc2253Parser" -export { BlockMapDataHolder, PackageFileInfo, ReleaseNoteInfo, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from "./updateInfo" -export { UUID } from "./uuid" -export { parseXml, XElement } from "./xml" -export { isValidKey, mapToObject, asArray, Nullish, deepAssign, objectToArgs } from "./objects" +} from "./publishOptions.js" +export { retry } from "./retry.js" +export { parseDn } from "./rfc2253Parser.js" +export { BlockMapDataHolder, PackageFileInfo, ReleaseNoteInfo, UpdateFileInfo, UpdateInfo, WindowsUpdateInfo } from "./updateInfo.js" +export { UUID } from "./uuid.js" +export { parseXml, XElement } from "./xml.js" +export { isValidKey, mapToObject, asArray, Nullish, deepAssign, objectToArgs } from "./objects.js" // nsis export const CURRENT_APP_INSTALLER_FILE_NAME = "installer.exe" diff --git a/packages/builder-util-runtime/src/indexInternal.ts b/packages/builder-util-runtime/src/indexInternal.ts new file mode 100644 index 00000000000..7a09717e60b --- /dev/null +++ b/packages/builder-util-runtime/src/indexInternal.ts @@ -0,0 +1 @@ +export { BlockMapFile } from "./blockMapApi.js" diff --git a/packages/builder-util-runtime/src/publishOptions.ts b/packages/builder-util-runtime/src/publishOptions.ts index 8c39ec44b2e..4ade39be1bd 100644 --- a/packages/builder-util-runtime/src/publishOptions.ts +++ b/packages/builder-util-runtime/src/publishOptions.ts @@ -1,5 +1,5 @@ import { OutgoingHttpHeaders } from "http" -import { Nullish } from "." +import { Nullish } from "./index.js" export type PublishProvider = "github" | "gitlab" | "s3" | "spaces" | "generic" | "custom" | "snapStore" | "keygen" | "bitbucket" diff --git a/packages/builder-util-runtime/src/retry.ts b/packages/builder-util-runtime/src/retry.ts index d55dc5fa986..041262eaf9f 100644 --- a/packages/builder-util-runtime/src/retry.ts +++ b/packages/builder-util-runtime/src/retry.ts @@ -1,4 +1,4 @@ -import { CancellationToken } from "./CancellationToken" +import { CancellationToken } from "./CancellationToken.js" export async function retry( task: () => Promise, diff --git a/packages/builder-util-runtime/src/uuid.ts b/packages/builder-util-runtime/src/uuid.ts index 74d5f6f1ca2..224ce9fe6aa 100644 --- a/packages/builder-util-runtime/src/uuid.ts +++ b/packages/builder-util-runtime/src/uuid.ts @@ -1,5 +1,5 @@ import { createHash, randomBytes } from "crypto" -import { newError } from "./error" +import { newError } from "./error.js" const invalidName = "options.name must be either a string or a Buffer" diff --git a/packages/builder-util-runtime/src/xml.ts b/packages/builder-util-runtime/src/xml.ts index d172124e0f4..6985419c24e 100644 --- a/packages/builder-util-runtime/src/xml.ts +++ b/packages/builder-util-runtime/src/xml.ts @@ -1,5 +1,5 @@ import * as sax from "sax" -import { newError } from "./error" +import { newError } from "./error.js" export class XElement { value = "" diff --git a/packages/builder-util-runtime/tsconfig.build.json b/packages/builder-util-runtime/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/builder-util-runtime/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/builder-util-runtime/tsconfig.json b/packages/builder-util-runtime/tsconfig.json index ccba996ab8d..71504d14a7b 100644 --- a/packages/builder-util-runtime/tsconfig.json +++ b/packages/builder-util-runtime/tsconfig.json @@ -5,11 +5,6 @@ "outDir": "out", "rootDir": "src" }, - "jsdoc": { - "out": "../../scripts/jsdoc/out/builder-util-runtime", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, "include": [ "src/**/*.ts" ] diff --git a/packages/builder-util/package.json b/packages/builder-util/package.json index 95241611b64..5cf7c28c484 100644 --- a/packages/builder-util/package.json +++ b/packages/builder-util/package.json @@ -1,7 +1,21 @@ { "name": "builder-util", "version": "26.14.0", - "main": "out/util.js", + "type": "module", + "main": "./dist/util.js", + "exports": { + ".": { + "types": "./dist/util.d.ts", + "import": "./dist/util.js", + "require": "./dist/util.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { @@ -12,8 +26,12 @@ "bugs": "https://github.com/electron-userland/electron-builder/issues", "homepage": "https://github.com/electron-userland/electron-builder", "files": [ - "out" + "dist" ], + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, "dependencies": { "7zip-bin": "~5.2.0", "@types/debug": "^4.1.6", @@ -22,7 +40,7 @@ "chalk": "^4.1.2", "cross-spawn": "^7.0.6", "debug": "^4.3.4", - "fs-extra": "^10.1.0", + "fs-extra": "^11.3.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", "js-yaml": "^4.1.0", @@ -32,7 +50,7 @@ "temp-file": "^3.4.0", "tiny-async-pool": "1.3.0" }, - "typings": "./out/util.d.ts", + "types": "./dist/util.d.ts", "devDependencies": { "@types/cross-spawn": "6.0.6", "@types/fs-extra": "^9.0.11", @@ -41,6 +59,6 @@ "@types/tiny-async-pool": "^1.0.5" }, "engines": { - "node": ">=14.0.0" + "node": ">=22.12.0" } } diff --git a/packages/builder-util/src/7za.ts b/packages/builder-util/src/7za.ts index c3323a49ac0..ef0582909bd 100644 --- a/packages/builder-util/src/7za.ts +++ b/packages/builder-util/src/7za.ts @@ -1,15 +1,15 @@ import { path7x, path7za } from "7zip-bin" import * as fs from "fs" -import { chmod } from "fs-extra" +import fsExtra from "fs-extra" export async function getPath7za(): Promise { if (fs.existsSync(path7za)) { - await chmod(path7za, 0o755) + await fsExtra.chmod(path7za, 0o755) } return path7za } export async function getPath7x(): Promise { - await chmod(path7x, 0o755) + await fsExtra.chmod(path7x, 0o755) return path7x } diff --git a/packages/builder-util/src/DebugLogger.ts b/packages/builder-util/src/DebugLogger.ts index 2ee55f8311e..0072912213f 100644 --- a/packages/builder-util/src/DebugLogger.ts +++ b/packages/builder-util/src/DebugLogger.ts @@ -1,6 +1,7 @@ -import { outputFile } from "fs-extra" -import { serializeToYaml } from "./util" +import { serializeToYaml } from "./util.js" import { mapToObject } from "builder-util-runtime" +import _fsExtra from "fs-extra" +const { outputFile } = _fsExtra export class DebugLogger { readonly data = new Map() diff --git a/packages/builder-util/src/asyncTaskManager.ts b/packages/builder-util/src/asyncTaskManager.ts index f27ca28b8d7..b02467c3b45 100644 --- a/packages/builder-util/src/asyncTaskManager.ts +++ b/packages/builder-util/src/asyncTaskManager.ts @@ -1,6 +1,6 @@ import { CancellationToken } from "builder-util-runtime" -import { log } from "./log" -import { NestedError } from "./promise" +import { log } from "./log.js" +import { NestedError } from "./promise.js" export class AsyncTaskManager { readonly tasks: Array> = [] diff --git a/packages/builder-util/src/cscLink.ts b/packages/builder-util/src/cscLink.ts index c5859143e22..3c2c79e9ea9 100644 --- a/packages/builder-util/src/cscLink.ts +++ b/packages/builder-util/src/cscLink.ts @@ -1,7 +1,7 @@ import { readFile } from "fs/promises" import { homedir } from "os" import * as path from "path" -import { statOrNull } from "./fs" +import { statOrNull } from "./fs.js" /** Decodes a base64 CSC link to a Buffer, or returns null if the value is not base64. */ export function decodeCscLinkBase64(link: string): Buffer | null { diff --git a/packages/builder-util/src/deepAssign.ts b/packages/builder-util/src/deepAssign.ts new file mode 100644 index 00000000000..1760c9b4fc9 --- /dev/null +++ b/packages/builder-util/src/deepAssign.ts @@ -0,0 +1,50 @@ +import { isValidKey } from "builder-util-runtime" + +function isObject(x: any) { + if (Array.isArray(x)) { + return false + } + + const type = typeof x + return type === "object" || type === "function" +} + +function assignKey(target: any, from: any, key: string) { + const value = from[key] + // https://github.com/electron-userland/electron-builder/pull/562 + if (value === undefined) { + return + } + + const prevValue = target[key] + if (prevValue == null || value == null || !isObject(prevValue) || !isObject(value)) { + // Merge arrays. + if (Array.isArray(prevValue) && Array.isArray(value)) { + target[key] = Array.from(new Set(prevValue.concat(value))) + } else { + target[key] = value + } + } else { + target[key] = assign(prevValue, value) + } +} + +function assign(to: any, from: any) { + if (to !== from) { + for (const key of Object.getOwnPropertyNames(from)) { + if (isValidKey(key)) { + assignKey(to, from, key) + } + } + } + return to +} + +export function deepAssign(target: T, ...objects: Array): T { + for (const o of objects) { + if (o != null) { + assign(target, o) + } + } + return target +} diff --git a/packages/builder-util/src/envUtil.ts b/packages/builder-util/src/envUtil.ts index 6a5b5827daa..d6cca8c64a5 100644 --- a/packages/builder-util/src/envUtil.ts +++ b/packages/builder-util/src/envUtil.ts @@ -1,7 +1,7 @@ import * as path from "path" -import { isEmptyOrSpaces } from "./stringUtil" -import { log } from "./log" -import { exists } from "./fs" +import { isEmptyOrSpaces } from "./stringUtil.js" +import { log } from "./log.js" +import { exists } from "./fs.js" import { stat } from "fs/promises" export function resolveEnvShellValue(envVarName: string): string | null { diff --git a/packages/builder-util/src/filename.ts b/packages/builder-util/src/filename.ts index 623a0e1c34a..3144af6046c 100644 --- a/packages/builder-util/src/filename.ts +++ b/packages/builder-util/src/filename.ts @@ -1,6 +1,5 @@ import * as path from "path" -// @ts-ignore -import * as _sanitizeFileName from "sanitize-filename" +import _sanitizeFileName from "sanitize-filename" export function sanitizeFileName(s: string, normalizeNfd = false): string { const sanitized = _sanitizeFileName(s) diff --git a/packages/builder-util/src/fs.ts b/packages/builder-util/src/fs.ts index 40c4498fe2f..aac7f52a0b6 100644 --- a/packages/builder-util/src/fs.ts +++ b/packages/builder-util/src/fs.ts @@ -1,13 +1,13 @@ import { Nullish } from "builder-util-runtime" import { Stats } from "fs" -import { copyFile as _nodeCopyFile } from "fs-extra" +import fsExtra from "fs-extra" import { access, chmod, link, lstat, mkdir, readdir, readlink, stat, symlink, unlink, writeFile } from "fs/promises" import { platform } from "os" import * as path from "path" -import { Mode } from "stat-mode" +import statMode from "stat-mode" import asyncPool from "tiny-async-pool" -import { log } from "./log" -import { orIfFileNotExist, orNullIfFileNotExist } from "./promise" +import { log } from "./log.js" +import { orIfFileNotExist, orNullIfFileNotExist } from "./promise.js" export const MAX_FILE_REQUESTS = 8 @@ -170,7 +170,7 @@ export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, if (stats != null) { const originalModeNumber = stats.mode - const mode = new Mode(stats) + const mode = new statMode.Mode(stats) if (mode.owner.execute) { mode.group.execute = true mode.others.execute = true @@ -184,7 +184,7 @@ export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, if (originalModeNumber !== stats.mode) { if (log.isDebugEnabled) { - const oldMode = new Mode({ mode: originalModeNumber }) + const oldMode = new statMode.Mode({ mode: originalModeNumber }) log.debug({ file: dest, oldMode, mode }, "permissions fixed from") } @@ -215,7 +215,7 @@ export function copyOrLinkFile(src: string, dest: string, stats?: Stats | null, } function doCopyFile(src: string, dest: string, stats: Stats | Nullish): Promise { - const promise = _nodeCopyFile(src, dest) + const promise = fsExtra.copyFile(src, dest) if (stats == null) { return promise } diff --git a/packages/builder-util/src/indexInternal.ts b/packages/builder-util/src/indexInternal.ts new file mode 100644 index 00000000000..e51ad83abed --- /dev/null +++ b/packages/builder-util/src/indexInternal.ts @@ -0,0 +1 @@ +export { getCompleteExtname, sanitizeFileName } from "./filename.js" diff --git a/packages/builder-util/src/log.ts b/packages/builder-util/src/log.ts index b53d69f35af..b8083e9358f 100644 --- a/packages/builder-util/src/log.ts +++ b/packages/builder-util/src/log.ts @@ -1,7 +1,7 @@ -import * as chalk from "chalk" +import chalk from "chalk" import { Chalk } from "chalk" import _debug from "debug" -import WritableStream = NodeJS.WritableStream +type WritableStream = NodeJS.WritableStream let printer: ((message: string) => void) | null = null diff --git a/packages/builder-util/src/nodeHttpExecutor.ts b/packages/builder-util/src/nodeHttpExecutor.ts index 3cb77c69614..bcd68909dd0 100644 --- a/packages/builder-util/src/nodeHttpExecutor.ts +++ b/packages/builder-util/src/nodeHttpExecutor.ts @@ -3,7 +3,7 @@ import { ClientRequest, request as httpRequest } from "http" import { HttpProxyAgent } from "http-proxy-agent" import * as https from "https" import { HttpsProxyAgent } from "https-proxy-agent" -import { isEmptyOrSpaces } from "./stringUtil" +import { isEmptyOrSpaces } from "./stringUtil.js" export class NodeHttpExecutor extends HttpExecutor { // noinspection JSMethodCanBeStatic diff --git a/packages/builder-util/src/promise.ts b/packages/builder-util/src/promise.ts index 24e737df262..7e38a024ba1 100644 --- a/packages/builder-util/src/promise.ts +++ b/packages/builder-util/src/promise.ts @@ -1,4 +1,4 @@ -import * as chalk from "chalk" +import chalk from "chalk" export function printErrorAndExit(error: Error) { console.error(chalk.red((error.stack || error).toString())) diff --git a/packages/builder-util/src/util.ts b/packages/builder-util/src/util.ts index fb0a9f34007..2ff019e3d59 100644 --- a/packages/builder-util/src/util.ts +++ b/packages/builder-util/src/util.ts @@ -8,36 +8,38 @@ import _debug from "debug" import { dump } from "js-yaml" import * as path from "path" import { install as installSourceMap } from "source-map-support" -import { getPath7za } from "./7za" -import { debug, log } from "./log" -import { exists } from "./fs" -import { mkdir } from "fs-extra" -import { isEmptyOrSpaces } from "./stringUtil" +import { getPath7za } from "./7za.js" +import { debug, log } from "./log.js" +import { exists } from "./fs.js" + +import { isEmptyOrSpaces } from "./stringUtil.js" +import _fsExtra from "fs-extra" +const { mkdir } = _fsExtra if (process.env.JEST_WORKER_ID == null) { installSourceMap() } -export { isEmptyOrSpaces } from "./stringUtil" +export { isEmptyOrSpaces } from "./stringUtil.js" export { safeStringifyJson, retry } from "builder-util-runtime" export { TmpDir } from "temp-file" -export * from "./arch" -export { Arch, archFromString, ArchType, defaultArchFromString, getArchCliNames, getArchSuffix, toLinuxArchString } from "./arch" -export { AsyncTaskManager } from "./asyncTaskManager" -export { DebugLogger } from "./DebugLogger" -export * from "./log" -export { buildGotProxyAgent, httpExecutor, NodeHttpExecutor } from "./nodeHttpExecutor" -export * from "./promise" -export * from "./envUtil" -export { parseValidEnvVarUrl } from "./envUtil" +export * from "./arch.js" +export { Arch, archFromString, ArchType, defaultArchFromString, getArchCliNames, getArchSuffix, toLinuxArchString } from "./arch.js" +export { AsyncTaskManager } from "./asyncTaskManager.js" +export { DebugLogger } from "./DebugLogger.js" +export * from "./log.js" +export { buildGotProxyAgent, httpExecutor, NodeHttpExecutor } from "./nodeHttpExecutor.js" +export * from "./promise.js" +export * from "./envUtil.js" +export { parseValidEnvVarUrl } from "./envUtil.js" export { asArray, deepAssign, isValidKey } from "builder-util-runtime" -export * from "./fs" +export * from "./fs.js" -export { generateKsuid } from "./ksuid" -export { loadCscLink, decodeCscLinkBase64, resolveCscLinkPath } from "./cscLink" +export { generateKsuid } from "./ksuid.js" +export { loadCscLink, decodeCscLinkBase64, resolveCscLinkPath } from "./cscLink.js" -export { getPath7x, getPath7za } from "./7za" +export { getPath7x, getPath7za } from "./7za.js" export const debug7z = _debug("electron-builder:7z") diff --git a/packages/builder-util/tsconfig.build.json b/packages/builder-util/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/builder-util/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/builder-util/tsconfig.json b/packages/builder-util/tsconfig.json index 0b6f6190a3b..8e94f1ec546 100644 --- a/packages/builder-util/tsconfig.json +++ b/packages/builder-util/tsconfig.json @@ -11,9 +11,5 @@ { "path": "../builder-util-runtime" } - ], - "jsdoc": { - "out": "../../scripts/jsdoc/out/util", - "access": "public" - } + ] } \ No newline at end of file diff --git a/packages/dmg-builder/package.json b/packages/dmg-builder/package.json index a0eb20c6788..da8b21ea2b9 100644 --- a/packages/dmg-builder/package.json +++ b/packages/dmg-builder/package.json @@ -1,30 +1,46 @@ { - "name": "dmg-builder", - "version": "26.14.0", - "main": "out/dmgUtil.js", - "author": "Vladimir Krivosheev", - "license": "MIT", - "repository": { - "type": "git", - "url": "git+https://github.com/electron-userland/electron-builder.git", - "directory": "packages/dmg-builder" - }, - "bugs": "https://github.com/electron-userland/electron-builder/issues", - "homepage": "https://github.com/electron-userland/electron-builder", - "files": [ - "out", - "templates" - ], - "dependencies": { - "app-builder-lib": "workspace:*", - "builder-util": "workspace:*", - "fs-extra": "^10.1.0", - "js-yaml": "^4.1.0" - }, - "devDependencies": { - "@types/fs-extra": "9.0.13", - "@types/js-yaml": "4.0.3", - "temp-file": "3.4.0" - }, - "typings": "./out/dmg.d.ts" + "name": "dmg-builder", + "version": "26.14.0", + "type": "module", + "main": "./dist/dmgUtil.js", + "exports": { + ".": { + "types": "./dist/dmgUtil.d.ts", + "import": "./dist/dmgUtil.js", + "require": "./dist/dmgUtil.js" + }, + "./src/*": "./src/*.ts" + }, + "author": "Vladimir Krivosheev", + "license": "MIT", + "repository": { + "type": "git", + "url": "git+https://github.com/electron-userland/electron-builder.git", + "directory": "packages/dmg-builder" + }, + "bugs": "https://github.com/electron-userland/electron-builder/issues", + "homepage": "https://github.com/electron-userland/electron-builder", + "files": [ + "dist", + "templates" + ], + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, + "dependencies": { + "app-builder-lib": "workspace:*", + "builder-util": "workspace:*", + "fs-extra": "^11.3.0", + "js-yaml": "^4.1.0" + }, + "devDependencies": { + "@types/fs-extra": "9.0.13", + "@types/js-yaml": "4.0.3", + "temp-file": "3.4.0" + }, + "types": "./dist/dmgUtil.d.ts" } diff --git a/packages/dmg-builder/src/dmg.ts b/packages/dmg-builder/src/dmg.ts index 8ad32100b15..b5da0dd991f 100644 --- a/packages/dmg-builder/src/dmg.ts +++ b/packages/dmg-builder/src/dmg.ts @@ -1,15 +1,13 @@ -import { DmgOptions, Target } from "app-builder-lib" -import { findIdentity, isSignAllowed } from "app-builder-lib/out/codeSign/macCodeSign" -import { MacPackager } from "app-builder-lib/out/macPackager" -import { createBlockmap } from "app-builder-lib/out/targets/differentialUpdateInfoBuilder" +import { DmgOptions, MacPackager, Target } from "app-builder-lib" +import { createBlockmap, findIdentity, isSignAllowed } from "app-builder-lib/internal" import { Arch, exec, getArchSuffix, InvalidConfigurationError, isEmptyOrSpaces } from "builder-util" -import { sanitizeFileName } from "builder-util/out/filename" +import { sanitizeFileName } from "builder-util/internal" import { release as getOsRelease } from "os" import * as path from "path" -import type { DmgBuildLicenseConfig } from "./dmgLicense" -import { addLicenseToDmg } from "./dmgLicense" -import { computeBackground, customizeDmg } from "./dmgUtil" -import { hdiUtil } from "./hdiuil" +import type { DmgBuildLicenseConfig } from "./dmgLicense.js" +import { addLicenseToDmg } from "./dmgLicense.js" +import { computeBackground, customizeDmg } from "./dmgUtil.js" +import { hdiUtil } from "./hdiuil.js" export interface DmgBuildConfig { title: string diff --git a/packages/dmg-builder/src/dmgLicense.ts b/packages/dmg-builder/src/dmgLicense.ts index 9a07e5ca920..b5f50a5151d 100644 --- a/packages/dmg-builder/src/dmgLicense.ts +++ b/packages/dmg-builder/src/dmgLicense.ts @@ -1,9 +1,11 @@ import { PlatformPackager } from "app-builder-lib" -import { getLicenseFiles } from "app-builder-lib/out/util/license" +import { getLicenseFiles } from "app-builder-lib/internal" import { InvalidConfigurationError } from "builder-util" -import { readFile, readJson } from "fs-extra" + import { CORE_SCHEMA, load } from "js-yaml" -import { getLicenseButtonsFile } from "./licenseButtons" +import { getLicenseButtonsFile } from "./licenseButtons.js" +import _fsExtra from "fs-extra" +const { readFile, readJson } = _fsExtra export type DmgBuildLicenseConfig = { "default-language": string diff --git a/packages/dmg-builder/src/dmgUtil.ts b/packages/dmg-builder/src/dmgUtil.ts index d4f69126ebb..bcf37ee5fff 100644 --- a/packages/dmg-builder/src/dmgUtil.ts +++ b/packages/dmg-builder/src/dmgUtil.ts @@ -1,17 +1,18 @@ -import { DmgOptions, MacPackager, PlatformPackager } from "app-builder-lib" -import { downloadBuilderToolset } from "app-builder-lib/out/util/electronGet" -import { withToolsetLock } from "app-builder-lib/out/util/toolsetLock" +import { DmgContent, DmgOptions, MacPackager, PlatformPackager } from "app-builder-lib" +import { downloadBuilderToolset, withToolsetLock } from "app-builder-lib/internal" import { exec, executeFinally, exists, InvalidConfigurationError, isEmptyOrSpaces, log, TmpDir } from "builder-util" import { stat } from "fs/promises" -import { writeFile } from "fs-extra" + import * as path from "path" -import { DmgBuildConfig } from "./dmg" -import type { DmgBuildLicenseConfig } from "./dmgLicense" -import { hdiUtil, hdiUtilWithStdin, hdiutilTransientExitCodes } from "./hdiuil" +import { DmgBuildConfig } from "./dmg.js" +import type { DmgBuildLicenseConfig } from "./dmgLicense.js" +import { hdiUtil, hdiUtilWithStdin, hdiutilTransientExitCodes } from "./hdiuil.js" +import _fsExtra from "fs-extra" +const { writeFile } = _fsExtra -export { DmgTarget } from "./dmg" +export { DmgTarget } from "./dmg.js" -const root = path.join(__dirname, "..") +const root = path.join(import.meta.dirname, "..") export function getDmgTemplatePath() { return path.join(root, "templates") @@ -146,7 +147,7 @@ export async function customizeDmg({ appPath, artifactPath, volumeName, specific size: specification.size, shrink: specification.shrink, contents: - specification.contents?.map(c => ({ + specification.contents?.map((c: DmgContent) => ({ path: c.path || appPath, // path is required, when ommitted, appPath is used (backward compatibility x: c.x, y: c.y, diff --git a/packages/dmg-builder/src/hdiuil.ts b/packages/dmg-builder/src/hdiuil.ts index 5985bdb7f93..630b2a8200e 100644 --- a/packages/dmg-builder/src/hdiuil.ts +++ b/packages/dmg-builder/src/hdiuil.ts @@ -52,7 +52,7 @@ const shouldRetry = (args: string[]) => (error: any) => { } export async function hdiUtil(args: string[]): Promise { - return retry(() => exec("hdiutil", args), { + return await retry(() => exec("hdiutil", args), { retries: 5, interval: 5000, backoff: 2000, diff --git a/packages/dmg-builder/src/licenseButtons.ts b/packages/dmg-builder/src/licenseButtons.ts index 0f0075b9872..0db60f78a18 100644 --- a/packages/dmg-builder/src/licenseButtons.ts +++ b/packages/dmg-builder/src/licenseButtons.ts @@ -1,5 +1,5 @@ import { PlatformPackager } from "app-builder-lib" -import { getLicenseAssets } from "app-builder-lib/out/util/license" +import { getLicenseAssets } from "app-builder-lib/internal" export interface LicenseButtonsFile { file: string diff --git a/packages/dmg-builder/tsconfig.build.json b/packages/dmg-builder/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/dmg-builder/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/dmg-builder/tsconfig.json b/packages/dmg-builder/tsconfig.json index b78528697b3..467818ca969 100644 --- a/packages/dmg-builder/tsconfig.json +++ b/packages/dmg-builder/tsconfig.json @@ -4,11 +4,6 @@ "outDir": "out", "rootDir": "src" }, - "jsdoc": { - "out": "../../scripts/jsdoc/out/dmg-builder", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, "references": [ { "path": "../app-builder-lib" diff --git a/packages/electron-builder-squirrel-windows/package.json b/packages/electron-builder-squirrel-windows/package.json index 5f019e4eba5..ae9e141bfcb 100644 --- a/packages/electron-builder-squirrel-windows/package.json +++ b/packages/electron-builder-squirrel-windows/package.json @@ -1,7 +1,16 @@ { "name": "electron-builder-squirrel-windows", "version": "26.14.0", - "main": "out/SquirrelWindowsTarget.js", + "type": "module", + "main": "./dist/SquirrelWindowsTarget.js", + "exports": { + ".": { + "types": "./dist/SquirrelWindowsTarget.d.ts", + "import": "./dist/SquirrelWindowsTarget.js", + "require": "./dist/SquirrelWindowsTarget.js" + }, + "./src/*": "./src/*.ts" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { @@ -12,9 +21,16 @@ "bugs": "https://github.com/electron-userland/electron-builder/issues", "homepage": "https://github.com/electron-userland/electron-builder", "files": [ - "out", + "dist", "template.nuspectemplate" ], + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, "dependencies": { "app-builder-lib": "workspace:*", "builder-util": "workspace:*", @@ -24,5 +40,5 @@ "@types/archiver": "5.3.1", "@types/fs-extra": "9.0.13" }, - "types": "./out/SquirrelWindowsTarget.d.ts" + "types": "./dist/SquirrelWindowsTarget.d.ts" } diff --git a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts index 64364c2e1cc..c9f687d1db6 100644 --- a/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts +++ b/packages/electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts @@ -1,9 +1,10 @@ +import { createRequire } from "node:module" import { InvalidConfigurationError, log, isEmptyOrSpaces, exists } from "builder-util" -import { execWine } from "app-builder-lib/out/wine" -import { getBinFromUrl } from "app-builder-lib/out/binDownload" -import { sanitizeFileName } from "builder-util/out/filename" + +const _requireResolve = createRequire(import.meta.url).resolve +import { execWine, getBinFromUrl, withToolsetLock } from "app-builder-lib/internal" +import { sanitizeFileName } from "builder-util/internal" import { Arch, getArchSuffix, SquirrelWindowsOptions, Target, WinPackager } from "app-builder-lib" -import { withToolsetLock } from "app-builder-lib/out/util/toolsetLock" import * as path from "path" import * as fs from "fs" import * as os from "os" @@ -33,7 +34,7 @@ export default class SquirrelWindowsTarget extends Target { log.warn({ customSquirrelVendorDirectory }, "unable to access custom Squirrel.Windows vendor directory, falling back to default vendor") } - const windowInstallerPackage = require.resolve("electron-winstaller/package.json") + const windowInstallerPackage = _requireResolve("electron-winstaller/package.json") const [squirrelBin] = await Promise.all([ getBinFromUrl("squirrel.windows@1.0.0", "squirrel.windows-2.0.1-patched.7z", "76851f0c192eaf9bc6f8f3eecdfe325857ebe70d7833ec62ed846a1acd50c846"), fs.promises.cp(path.join(path.dirname(windowInstallerPackage), "vendor"), tmpVendorDirectory, { recursive: true }), @@ -217,7 +218,7 @@ export default class SquirrelWindowsTarget extends Target { } private async createNuspecTemplateWithProjectUrl() { - const templatePath = path.resolve(__dirname, "..", "template.nuspectemplate") + const templatePath = path.resolve(import.meta.dirname, "..", "template.nuspectemplate") const projectUrl = await this.packager.appInfo.computePackageUrl() if (projectUrl != null) { const nuspecTemplate = await this.packager.info.tempDirManager.getTempFile({ prefix: "template", suffix: ".nuspectemplate" }) diff --git a/packages/electron-builder-squirrel-windows/tsconfig.build.json b/packages/electron-builder-squirrel-windows/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/electron-builder-squirrel-windows/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/electron-builder-squirrel-windows/tsconfig.json b/packages/electron-builder-squirrel-windows/tsconfig.json index c09a92f11c5..e569ae0df14 100644 --- a/packages/electron-builder-squirrel-windows/tsconfig.json +++ b/packages/electron-builder-squirrel-windows/tsconfig.json @@ -1,10 +1,5 @@ { "extends": "../tsconfig-base.json", - "jsdoc": { - "out": "../../scripts/jsdoc/out/builder-lib", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, "compilerOptions": { "outDir": "out", "rootDir": "src" diff --git a/packages/electron-builder/cli.js b/packages/electron-builder/cli.js index 90282b0ce4c..6a23f8bb683 100755 --- a/packages/electron-builder/cli.js +++ b/packages/electron-builder/cli.js @@ -1,4 +1,3 @@ #!/usr/bin/env node -// https://github.com/pnpm/pnpm/issues/1801 -require("./out/cli/cli") +import("./dist/cli/cli") diff --git a/packages/electron-builder/install-app-deps.js b/packages/electron-builder/install-app-deps.js index 65a838b4e18..567f2f84caf 100755 --- a/packages/electron-builder/install-app-deps.js +++ b/packages/electron-builder/install-app-deps.js @@ -1,4 +1,3 @@ #!/usr/bin/env node -// https://github.com/pnpm/pnpm/issues/1801 -require("./out/cli/install-app-deps") +import("./dist/cli/install-app-deps") diff --git a/packages/electron-builder/package.json b/packages/electron-builder/package.json index 730a7542958..a6261814c42 100644 --- a/packages/electron-builder/package.json +++ b/packages/electron-builder/package.json @@ -2,10 +2,30 @@ "name": "electron-builder", "description": "A complete solution to package and build a ready for distribution Electron app for MacOS, Windows and Linux with “auto update” support out of the box", "version": "26.14.0", - "main": "out/index.js", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "files": [ - "out" + "dist", + "cli.js", + "install-app-deps.js" ], + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, "bin": { "electron-builder": "./cli.js", "install-app-deps": "./install-app-deps.js" @@ -16,7 +36,7 @@ "directory": "packages/electron-builder" }, "engines": { - "node": ">=14.0.0" + "node": ">=22.12.0" }, "keywords": [ "electron", @@ -57,7 +77,7 @@ "chalk": "^4.1.2", "ci-info": "^4.2.0", "dmg-builder": "workspace:*", - "fs-extra": "^10.1.0", + "fs-extra": "^11.3.0", "lazy-val": "^1.0.5", "simple-update-notifier": "2.0.0", "yargs": "^17.6.2" @@ -66,7 +86,7 @@ "@types/fs-extra": "9.0.13", "@types/yargs": "^17.0.16" }, - "typings": "./out/index.d.ts", + "types": "./dist/index.d.ts", "publishConfig": { "tag": "next" } diff --git a/packages/electron-builder/src/builder.ts b/packages/electron-builder/src/builder.ts index 90ece28a86e..87b972e5f6b 100644 --- a/packages/electron-builder/src/builder.ts +++ b/packages/electron-builder/src/builder.ts @@ -3,10 +3,15 @@ import { addValue, Arch, archFromString } from "builder-util" import { deepAssign } from "builder-util-runtime" import * as chalk from "chalk" import { PublishOptions } from "electron-publish" +import { hideBin } from "yargs/helpers" import * as yargs from "yargs" export function createYargs(): yargs.Argv { - return yargs.parserConfiguration({ + // In ESM, yargs.default is the factory function; call it to create an instance. + // In CJS, yargs.default is already an Argv singleton. + const factory = (yargs as any).default ?? yargs + const instance = typeof factory?.parserConfiguration === "function" ? factory : factory(hideBin(process.argv)) + return (instance as unknown as yargs.Argv).parserConfiguration({ "camel-case-expansion": false, }) } diff --git a/packages/electron-builder/src/cli/clear-cache.ts b/packages/electron-builder/src/cli/clear-cache.ts index 854b9303de1..e19251913e3 100644 --- a/packages/electron-builder/src/cli/clear-cache.ts +++ b/packages/electron-builder/src/cli/clear-cache.ts @@ -1,7 +1,7 @@ -import { getCacheDirectory } from "app-builder-lib/out/util/electronGet" +import { getCacheDirectory } from "app-builder-lib/internal" import { log } from "builder-util" import { access, constants, rm } from "fs/promises" -import { createInterface } from "readline/promises" +import { createInterface } from "node:readline/promises" import * as path from "path" export async function clearCache(): Promise { diff --git a/packages/electron-builder/src/cli/cli-util.ts b/packages/electron-builder/src/cli/cli-util.ts index e155077ee4b..caf424bfff2 100644 --- a/packages/electron-builder/src/cli/cli-util.ts +++ b/packages/electron-builder/src/cli/cli-util.ts @@ -1,18 +1,20 @@ -import { loadEnv } from "app-builder-lib/out/util/config/load" +import { loadEnv } from "app-builder-lib/internal" import { ExecError, InvalidConfigurationError, log } from "builder-util" import { isCI } from "ci-info" -import { readJson } from "fs-extra" + import * as path from "path" +import _fsExtra from "fs-extra" +const { readJson } = _fsExtra export async function checkIsOutdated(): Promise { if (isCI || process.env.NO_UPDATE_NOTIFIER != null) { return } - const pkg = await readJson(path.join(__dirname, "..", "..", "package.json")) + const pkg = await readJson(path.join(import.meta.dirname, "..", "..", "package.json")) if (pkg.version === "0.0.0-semantic-release") { return } - const UpdateNotifier = require("simple-update-notifier") + const { default: UpdateNotifier } = await import("simple-update-notifier") await UpdateNotifier({ pkg }) } diff --git a/packages/electron-builder/src/cli/cli.ts b/packages/electron-builder/src/cli/cli.ts index d9a4af622aa..3cb9df7c2e3 100644 --- a/packages/electron-builder/src/cli/cli.ts +++ b/packages/electron-builder/src/cli/cli.ts @@ -1,15 +1,14 @@ #! /usr/bin/env node -import { getElectronVersion } from "app-builder-lib/out/electron/electronVersion" -import { nodeGypRebuild } from "app-builder-lib/out/util/yarn" -import * as chalk from "chalk" -import { build, configureBuildCommand, createYargs } from "../builder" -import { configurePublishCommand, publish } from "../publish" -import { clearCache } from "./clear-cache" -import { wrap } from "./cli-util" -import { createSelfSignedCert } from "./create-self-signed-cert" -import { configureInstallAppDepsCommand, installAppDeps } from "./install-app-deps" -import { start } from "./start" +import { getElectronVersion, nodeGypRebuild } from "app-builder-lib/internal" +import chalk from "chalk" +import { build, configureBuildCommand, createYargs } from "../builder.js" +import { configurePublishCommand, publish } from "../publish.js" +import { clearCache } from "./clear-cache.js" +import { wrap } from "./cli-util.js" +import { createSelfSignedCert } from "./create-self-signed-cert.js" +import { configureInstallAppDepsCommand, installAppDeps } from "./install-app-deps.js" +import { start } from "./start.js" // tslint:disable:no-unused-expression void createYargs() diff --git a/packages/electron-builder/src/cli/create-self-signed-cert.ts b/packages/electron-builder/src/cli/create-self-signed-cert.ts index 74c73e27971..6669871e184 100644 --- a/packages/electron-builder/src/cli/create-self-signed-cert.ts +++ b/packages/electron-builder/src/cli/create-self-signed-cert.ts @@ -1,7 +1,7 @@ -import { getWindowsKitsBundle } from "app-builder-lib/out/toolsets/windows" +import { getWindowsKitsBundle } from "app-builder-lib/internal" import { archFromString, exec, log, spawn, TmpDir, unlinkIfExists } from "builder-util" -import { sanitizeFileName } from "builder-util/out/filename" -import * as chalk from "chalk" +import { sanitizeFileName } from "builder-util/internal" +import chalk from "chalk" import { mkdir } from "fs/promises" import * as path from "path" diff --git a/packages/electron-builder/src/cli/install-app-deps.ts b/packages/electron-builder/src/cli/install-app-deps.ts index 507ea22c9a6..6d30cfb18b0 100644 --- a/packages/electron-builder/src/cli/install-app-deps.ts +++ b/packages/electron-builder/src/cli/install-app-deps.ts @@ -1,16 +1,23 @@ #! /usr/bin/env node -import { getElectronVersion } from "app-builder-lib/out/electron/electronVersion" -import { computeDefaultAppDirectory, getConfig } from "app-builder-lib/out/util/config/config" -import { orNullIfFileNotExist } from "app-builder-lib/out/util/config/load" -import { installOrRebuild } from "app-builder-lib/out/util/yarn" -import { PACKAGE_VERSION } from "app-builder-lib/out/version" -import { determinePackageManagerEnv } from "app-builder-lib/out/node-module-collector" +import { + computeDefaultAppDirectory, + determinePackageManagerEnv, + getConfig, + getElectronVersion, + installOrRebuild, + orNullIfFileNotExist, + PACKAGE_VERSION, +} from "app-builder-lib/internal" import { getArchCliNames, log, printErrorAndExit } from "builder-util" -import { readJson } from "fs-extra" + import { Lazy } from "lazy-val" import * as path from "path" +import { fileURLToPath } from "node:url" +import { hideBin } from "yargs/helpers" import * as yargs from "yargs" +import _fsExtra from "fs-extra" +const { readJson } = _fsExtra /** @internal */ export function configureInstallAppDepsCommand(yargs: yargs.Argv): yargs.Argv { @@ -69,10 +76,12 @@ export async function installAppDeps(args: any) { } function main() { - return installAppDeps(configureInstallAppDepsCommand(yargs).argv) + const factory = (yargs as any).default ?? yargs + const instance = typeof factory?.parserConfiguration === "function" ? factory : factory(hideBin(process.argv)) + return installAppDeps(configureInstallAppDepsCommand(instance as unknown as yargs.Argv).argv) } -if (require.main === module) { +if (process.argv[1] === fileURLToPath(import.meta.url)) { log.warn("please use as subcommand: electron-builder install-app-deps") main().catch(printErrorAndExit) } diff --git a/packages/electron-builder/src/cli/start.ts b/packages/electron-builder/src/cli/start.ts index b54d293f388..40a1cd7cd5f 100644 --- a/packages/electron-builder/src/cli/start.ts +++ b/packages/electron-builder/src/cli/start.ts @@ -1,3 +1,7 @@ +import { createRequire } from "node:module" + +const require = createRequire(import.meta.url) + /** @internal */ export function start() { require("electron-webpack/dev-runner") diff --git a/packages/electron-builder/src/index.ts b/packages/electron-builder/src/index.ts index a50a67e4613..f7812eaa48e 100644 --- a/packages/electron-builder/src/index.ts +++ b/packages/electron-builder/src/index.ts @@ -1,6 +1,6 @@ export { getArchSuffix, Arch, archFromString, log } from "builder-util" -export { build, CliOptions, createTargets } from "./builder" -export { publish, publishArtifactsWithOptions } from "./publish" +export { build, CliOptions, createTargets } from "./builder.js" +export { publish, publishArtifactsWithOptions } from "./publish.js" export { TargetConfiguration, Platform, diff --git a/packages/electron-builder/src/indexInternal.ts b/packages/electron-builder/src/indexInternal.ts new file mode 100644 index 00000000000..d440c7daf38 --- /dev/null +++ b/packages/electron-builder/src/indexInternal.ts @@ -0,0 +1 @@ +export { configureBuildCommand, createYargs, normalizeOptions, coerceTypes } from "./builder.js" diff --git a/packages/electron-builder/src/publish.ts b/packages/electron-builder/src/publish.ts index 626ed6247be..2478ddde130 100644 --- a/packages/electron-builder/src/publish.ts +++ b/packages/electron-builder/src/publish.ts @@ -1,18 +1,17 @@ #! /usr/bin/env node +import { fileURLToPath } from "node:url" import { AppInfo, CancellationToken, Packager, PackagerOptions, PublishManager, PublishOptions, UploadTask, checkBuildRequestOptions } from "app-builder-lib" -import { Publish } from "app-builder-lib/out/core" -import { computeSafeArtifactNameIfNeeded } from "app-builder-lib/out/platformPackager" -import { getConfig } from "app-builder-lib/out/util/config/config" +import { Publish, computeSafeArtifactNameIfNeeded, getConfig } from "app-builder-lib/internal" import { InvalidConfigurationError, archFromString, log, printErrorAndExit } from "builder-util" import { PublishPolicy } from "electron-publish" -import * as chalk from "chalk" +import chalk from "chalk" import * as path from "path" -import * as yargs from "yargs" -import { BuildOptions, normalizeOptions } from "./builder" +import { Argv } from "yargs" +import { BuildOptions, createYargs, normalizeOptions } from "./builder.js" /** @internal */ -export function configurePublishCommand(yargs: yargs.Argv): yargs.Argv { +export function configurePublishCommand(yargs: Argv): Argv { // https://github.com/yargs/yargs/issues/760 // demandOption is required to be set return yargs @@ -121,10 +120,10 @@ async function publishPackageWithTasks( } function main() { - return publish(configurePublishCommand(yargs).argv as any) + return publish(configurePublishCommand(createYargs()).argv as any) } -if (require.main === module) { +if (process.argv[1] === fileURLToPath(import.meta.url)) { log.warn("please use as subcommand: electron-builder publish") main().catch(printErrorAndExit) } diff --git a/packages/electron-builder/tsconfig.build.json b/packages/electron-builder/tsconfig.build.json new file mode 100644 index 00000000000..a7e8002eb6d --- /dev/null +++ b/packages/electron-builder/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts", "../../typings/*.d.ts"] +} diff --git a/packages/electron-builder/tsconfig.json b/packages/electron-builder/tsconfig.json index 8a55ef2a447..488b8196b73 100644 --- a/packages/electron-builder/tsconfig.json +++ b/packages/electron-builder/tsconfig.json @@ -18,11 +18,6 @@ "path": "../dmg-builder" } ], - "jsdoc": { - "out": "../../scripts/jsdoc/out/builder", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, "include": [ "src/**/*.ts", "../../typings/*.d.ts" diff --git a/packages/electron-forge-maker-appimage/package.json b/packages/electron-forge-maker-appimage/package.json index b0483b2c47a..03d0573d4f4 100644 --- a/packages/electron-forge-maker-appimage/package.json +++ b/packages/electron-forge-maker-appimage/package.json @@ -2,6 +2,9 @@ "name": "electron-forge-maker-appimage", "version": "26.14.0", "main": "main.js", + "engines": { + "node": ">=22.12.0" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { diff --git a/packages/electron-forge-maker-nsis-web/package.json b/packages/electron-forge-maker-nsis-web/package.json index e9864fa2def..b5297e6ed28 100644 --- a/packages/electron-forge-maker-nsis-web/package.json +++ b/packages/electron-forge-maker-nsis-web/package.json @@ -2,6 +2,9 @@ "name": "electron-forge-maker-nsis-web", "version": "26.14.0", "main": "main.js", + "engines": { + "node": ">=22.12.0" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { diff --git a/packages/electron-forge-maker-nsis/package.json b/packages/electron-forge-maker-nsis/package.json index b83d61abdfe..54df6dad35a 100644 --- a/packages/electron-forge-maker-nsis/package.json +++ b/packages/electron-forge-maker-nsis/package.json @@ -2,6 +2,9 @@ "name": "electron-forge-maker-nsis", "version": "26.14.0", "main": "main.js", + "engines": { + "node": ">=22.12.0" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { diff --git a/packages/electron-forge-maker-snap/package.json b/packages/electron-forge-maker-snap/package.json index 341a5716f26..6e0976c8523 100644 --- a/packages/electron-forge-maker-snap/package.json +++ b/packages/electron-forge-maker-snap/package.json @@ -2,6 +2,9 @@ "name": "electron-forge-maker-snap", "version": "26.14.0", "main": "main.js", + "engines": { + "node": ">=22.12.0" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { diff --git a/packages/electron-publish/package.json b/packages/electron-publish/package.json index fcf1194e776..4e5d04a4d24 100644 --- a/packages/electron-publish/package.json +++ b/packages/electron-publish/package.json @@ -1,7 +1,21 @@ { "name": "electron-publish", "version": "26.14.0", - "main": "out/index.js", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { @@ -12,8 +26,15 @@ "bugs": "https://github.com/electron-userland/electron-builder/issues", "homepage": "https://github.com/electron-userland/electron-builder", "files": [ - "out" + "dist" ], + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" + }, "dependencies": { "@types/fs-extra": "^9.0.11", "aws4": "^1.13.2", @@ -21,11 +42,11 @@ "builder-util-runtime": "workspace:*", "chalk": "^4.1.2", "form-data": "^4.0.5", - "fs-extra": "^10.1.0", + "fs-extra": "^11.3.0", "lazy-val": "^1.0.5", "mime": "^2.5.2" }, - "typings": "./out/index.d.ts", + "types": "./dist/index.d.ts", "devDependencies": { "@types/aws4": "^1.11.6", "@types/mime": "2.0.3" diff --git a/packages/electron-publish/src/bitbucketPublisher.ts b/packages/electron-publish/src/bitbucketPublisher.ts index 5fc1397b234..cb45b36d901 100644 --- a/packages/electron-publish/src/bitbucketPublisher.ts +++ b/packages/electron-publish/src/bitbucketPublisher.ts @@ -1,11 +1,11 @@ import { Arch, httpExecutor, InvalidConfigurationError, isEmptyOrSpaces, log } from "builder-util" import { configureRequestOptions, HttpExecutor } from "builder-util-runtime" -import { BitbucketOptions } from "builder-util-runtime/out/publishOptions" -import * as FormData from "form-data" -import { readFile } from "fs-extra" +import { BitbucketOptions } from "builder-util-runtime" +import FormData from "form-data" +import fsExtra from "fs-extra" import { ClientRequest, RequestOptions } from "http" -import { PublishContext } from "./" -import { HttpPublisher } from "./httpPublisher" +import { PublishContext } from "./index.js" +import { HttpPublisher } from "./httpPublisher.js" export class BitbucketPublisher extends HttpPublisher { readonly providerName = "bitbucket" @@ -42,7 +42,7 @@ export class BitbucketPublisher extends HttpPublisher { file: string ): Promise { return HttpExecutor.retryOnServerError(async () => { - const fileContent = await readFile(file) + const fileContent = await fsExtra.readFile(file) const form = new FormData() form.append("files", fileContent, fileName) const upload: RequestOptions = { diff --git a/packages/electron-publish/src/gitHubPublisher.ts b/packages/electron-publish/src/gitHubPublisher.ts index ea525cb49f8..13ad01f28d5 100644 --- a/packages/electron-publish/src/gitHubPublisher.ts +++ b/packages/electron-publish/src/gitHubPublisher.ts @@ -4,10 +4,10 @@ import { ClientRequest } from "http" import { Lazy } from "lazy-val" import * as mime from "mime" import { parse as parseUrl, UrlWithStringQuery } from "url" -import { HttpPublisher } from "./httpPublisher" -import { PublishContext, PublishOptions } from "./index" -import { getCiTag } from "./publisher" -import { trimStringWithWarn } from "./util" +import { HttpPublisher } from "./httpPublisher.js" +import { PublishContext, PublishOptions } from "./index.js" +import { getCiTag } from "./publisher.js" +import { trimStringWithWarn } from "./util.js" export interface Release { id: number diff --git a/packages/electron-publish/src/gitlabPublisher.ts b/packages/electron-publish/src/gitlabPublisher.ts index ce210a99acf..b42ebf538b4 100644 --- a/packages/electron-publish/src/gitlabPublisher.ts +++ b/packages/electron-publish/src/gitlabPublisher.ts @@ -6,11 +6,11 @@ import { configureRequestOptions, GitlabOptions, GitlabReleaseInfo, parseJson, H import { ClientRequest } from "http" import { Lazy } from "lazy-val" import * as mime from "mime" -import * as FormData from "form-data" +import FormData from "form-data" import { URL } from "url" -import { HttpPublisher } from "./httpPublisher" -import { PublishContext } from "./index" -import { trimStringWithWarn } from "./util" +import { HttpPublisher } from "./httpPublisher.js" +import { PublishContext } from "./index.js" +import { trimStringWithWarn } from "./util.js" type RequestProcessor = (request: ClientRequest, reject: (error: Error) => void) => void diff --git a/packages/electron-publish/src/httpPublisher.ts b/packages/electron-publish/src/httpPublisher.ts index 8c19d036575..549132ee2f1 100644 --- a/packages/electron-publish/src/httpPublisher.ts +++ b/packages/electron-publish/src/httpPublisher.ts @@ -1,9 +1,9 @@ import { Arch } from "builder-util" -import { stat } from "fs-extra" +import fsExtra from "fs-extra" import { ClientRequest } from "http" import { basename } from "path" -import { PublishContext, UploadTask } from "." -import { Publisher } from "./publisher" +import { PublishContext, UploadTask } from "./index.js" +import { Publisher } from "./publisher.js" export abstract class HttpPublisher extends Publisher { protected constructor( @@ -35,7 +35,7 @@ export abstract class HttpPublisher extends Publisher { return } - const fileStat = await stat(task.file) + const fileStat = await fsExtra.stat(task.file) const progressBar = this.createProgressBar(fileName, fileStat.size) return this.doUpload( diff --git a/packages/electron-publish/src/index.ts b/packages/electron-publish/src/index.ts index c88fe813977..f5826c5fa52 100644 --- a/packages/electron-publish/src/index.ts +++ b/packages/electron-publish/src/index.ts @@ -1,28 +1,28 @@ import { Arch } from "builder-util" import { CancellationToken } from "builder-util-runtime" -import { MultiProgress } from "./multiProgress" +import { MultiProgress } from "./multiProgress.js" export { MultiProgress } -export { ProgressBar } from "./progress" +export { ProgressBar } from "./progress.js" -export { BitbucketPublisher } from "./bitbucketPublisher" -export { GitHubPublisher } from "./gitHubPublisher" -export { GitlabPublisher } from "./gitlabPublisher" -export { KeygenPublisher } from "./keygenPublisher" -export { S3Publisher } from "./s3/s3Publisher" -export { SpacesPublisher } from "./s3/spacesPublisher" -export { SnapStorePublisher, resolveSnapCredentials } from "./snapStorePublisher" +export { BitbucketPublisher } from "./bitbucketPublisher.js" +export { GitHubPublisher } from "./gitHubPublisher.js" +export { GitlabPublisher } from "./gitlabPublisher.js" +export { KeygenPublisher } from "./keygenPublisher.js" +export { S3Publisher } from "./s3/s3Publisher.js" +export { SpacesPublisher } from "./s3/spacesPublisher.js" +export { SnapStorePublisher, resolveSnapCredentials } from "./snapStorePublisher.js" export type PublishPolicy = "onTag" | "onTagOrDraft" | "always" | "never" -export { ProgressCallback } from "./progress" +export { ProgressCallback } from "./progress.js" export interface PublishOptions { publish?: PublishPolicy | null } -export { HttpPublisher } from "./httpPublisher" -export { getCiTag, Publisher } from "./publisher" +export { HttpPublisher } from "./httpPublisher.js" +export { getCiTag, Publisher } from "./publisher.js" export interface PublishContext { readonly cancellationToken: CancellationToken diff --git a/packages/electron-publish/src/indexInternal.ts b/packages/electron-publish/src/indexInternal.ts new file mode 100644 index 00000000000..c3ffd454e98 --- /dev/null +++ b/packages/electron-publish/src/indexInternal.ts @@ -0,0 +1 @@ +export { MultiProgress } from "./multiProgress.js" diff --git a/packages/electron-publish/src/keygenPublisher.ts b/packages/electron-publish/src/keygenPublisher.ts index 9e5a709de53..990e1721de4 100644 --- a/packages/electron-publish/src/keygenPublisher.ts +++ b/packages/electron-publish/src/keygenPublisher.ts @@ -1,10 +1,10 @@ import { Arch, httpExecutor, InvalidConfigurationError, isEmptyOrSpaces, log } from "builder-util" import { configureRequestOptions, HttpExecutor, parseJson } from "builder-util-runtime" -import { KeygenOptions } from "builder-util-runtime/out/publishOptions" -import { getCompleteExtname } from "builder-util/out/filename" +import { KeygenOptions } from "builder-util-runtime" +import { getCompleteExtname } from "builder-util/internal" import { ClientRequest, RequestOptions } from "http" -import { PublishContext } from "./" -import { HttpPublisher } from "./httpPublisher" +import { PublishContext } from "./index.js" +import { HttpPublisher } from "./httpPublisher.js" type RecursivePartial = { [P in keyof T]?: RecursivePartial diff --git a/packages/electron-publish/src/multiProgress.ts b/packages/electron-publish/src/multiProgress.ts index 6321d51141d..7da359a9965 100644 --- a/packages/electron-publish/src/multiProgress.ts +++ b/packages/electron-publish/src/multiProgress.ts @@ -1,5 +1,5 @@ import { setPrinter } from "builder-util" -import { ProgressBar } from "./progress" +import { ProgressBar } from "./progress.js" export class MultiProgress { private readonly stream = process.stdout as any diff --git a/packages/electron-publish/src/publisher.ts b/packages/electron-publish/src/publisher.ts index 57fbd51c3ea..23d0c4390b2 100644 --- a/packages/electron-publish/src/publisher.ts +++ b/packages/electron-publish/src/publisher.ts @@ -1,9 +1,9 @@ import { log, PADDING } from "builder-util" import { ProgressCallbackTransform, PublishProvider } from "builder-util-runtime" -import * as chalk from "chalk" -import { createReadStream, Stats } from "fs-extra" -import { PublishContext, UploadTask } from "." -import { ProgressBar } from "./progress" +import chalk from "chalk" +import fsExtra from "fs-extra" +import { PublishContext, UploadTask } from "./index.js" +import { ProgressBar } from "./progress.js" const progressBarOptions = { incomplete: " ", @@ -28,8 +28,8 @@ export abstract class Publisher { }) } - protected createReadStreamAndProgressBar(file: string, fileStat: Stats, progressBar: ProgressBar | null, reject: (error: Error) => void): NodeJS.ReadableStream { - const fileInputStream = createReadStream(file) + protected createReadStreamAndProgressBar(file: string, fileStat: fsExtra.Stats, progressBar: ProgressBar | null, reject: (error: Error) => void): NodeJS.ReadableStream { + const fileInputStream = fsExtra.createReadStream(file) fileInputStream.on("error", reject) if (progressBar == null) { diff --git a/packages/electron-publish/src/s3/awsCredentials.ts b/packages/electron-publish/src/s3/awsCredentials.ts index 7d051897a46..5a67c7f7dea 100644 --- a/packages/electron-publish/src/s3/awsCredentials.ts +++ b/packages/electron-publish/src/s3/awsCredentials.ts @@ -18,7 +18,9 @@ function parseIniSection(content: string, sectionName: string): Record 0) { diff --git a/packages/electron-publish/src/s3/baseS3Publisher.ts b/packages/electron-publish/src/s3/baseS3Publisher.ts index 20c84cb20ab..662d8f2783f 100644 --- a/packages/electron-publish/src/s3/baseS3Publisher.ts +++ b/packages/electron-publish/src/s3/baseS3Publisher.ts @@ -2,10 +2,10 @@ import { log } from "builder-util" import { BaseS3Options } from "builder-util-runtime" import { mkdir, symlink } from "fs/promises" import * as path from "path" -import { PublishContext, UploadTask } from ".." -import { Publisher } from "../publisher" -import type { AwsCredentials } from "./awsCredentials" -import { getS3ContentType, startS3PutObject } from "./s3UploadHelper" +import { PublishContext, UploadTask } from "../index.js" +import { Publisher } from "../publisher.js" +import type { AwsCredentials } from "./awsCredentials.js" +import { getS3ContentType, startS3PutObject } from "./s3UploadHelper.js" export interface S3UploadConfig { region: string diff --git a/packages/electron-publish/src/s3/bucketLocation.ts b/packages/electron-publish/src/s3/bucketLocation.ts index bee21257ef1..3b8b8a91c94 100644 --- a/packages/electron-publish/src/s3/bucketLocation.ts +++ b/packages/electron-publish/src/s3/bucketLocation.ts @@ -1,6 +1,7 @@ -import { sign } from "aws4" +import _aws4 from "aws4" +const { sign } = _aws4 import { request } from "https" -import { resolveAwsCredentials } from "./awsCredentials" +import { resolveAwsCredentials } from "./awsCredentials.js" /** * Resolves the AWS region for a bucket via the S3 GetBucketLocation API (SigV4-signed). diff --git a/packages/electron-publish/src/s3/s3Publisher.ts b/packages/electron-publish/src/s3/s3Publisher.ts index 9780635bf71..f21832db78a 100644 --- a/packages/electron-publish/src/s3/s3Publisher.ts +++ b/packages/electron-publish/src/s3/s3Publisher.ts @@ -1,9 +1,9 @@ import { InvalidConfigurationError, log } from "builder-util" import { S3Options } from "builder-util-runtime" -import { PublishContext } from ".." -import { resolveAwsCredentials } from "./awsCredentials" -import { BaseS3Publisher, S3UploadConfig, S3UploadExtraParams } from "./baseS3Publisher" -import { getBucketLocation } from "./bucketLocation" +import { PublishContext } from "../index.js" +import { resolveAwsCredentials } from "./awsCredentials.js" +import { BaseS3Publisher, S3UploadConfig, S3UploadExtraParams } from "./baseS3Publisher.js" +import { getBucketLocation } from "./bucketLocation.js" export class S3Publisher extends BaseS3Publisher { readonly providerName = "s3" diff --git a/packages/electron-publish/src/s3/s3UploadHelper.ts b/packages/electron-publish/src/s3/s3UploadHelper.ts index f98e78ea5d9..2d6c37a235e 100644 --- a/packages/electron-publish/src/s3/s3UploadHelper.ts +++ b/packages/electron-publish/src/s3/s3UploadHelper.ts @@ -1,10 +1,11 @@ -import { sign } from "aws4" +import _aws4 from "aws4" +const { sign } = _aws4 import * as fs from "fs" import * as http from "http" import * as https from "https" import * as mime from "mime" import * as path from "path" -import type { AwsCredentials } from "./awsCredentials" +import type { AwsCredentials } from "./awsCredentials.js" export interface S3PutObjectParams { bucket: string @@ -55,9 +56,15 @@ export function startS3PutObject(params: S3PutObjectParams): { req: http.ClientR "Content-Type": params.contentType, "Content-Length": String(stat.size), } - if (params.acl != null) headers["x-amz-acl"] = params.acl - if (params.storageClass != null) headers["x-amz-storage-class"] = params.storageClass - if (params.serverSideEncryption != null) headers["x-amz-server-side-encryption"] = params.serverSideEncryption + if (params.acl != null) { + headers["x-amz-acl"] = params.acl + } + if (params.storageClass != null) { + headers["x-amz-storage-class"] = params.storageClass + } + if (params.serverSideEncryption != null) { + headers["x-amz-server-side-encryption"] = params.serverSideEncryption + } const signed = sign( { diff --git a/packages/electron-publish/src/s3/spacesPublisher.ts b/packages/electron-publish/src/s3/spacesPublisher.ts index b63ae407b89..7d54a51769a 100644 --- a/packages/electron-publish/src/s3/spacesPublisher.ts +++ b/packages/electron-publish/src/s3/spacesPublisher.ts @@ -1,7 +1,7 @@ import { InvalidConfigurationError, isEmptyOrSpaces } from "builder-util" import { SpacesOptions } from "builder-util-runtime" -import { PublishContext } from "../" -import { BaseS3Publisher, S3UploadConfig } from "./baseS3Publisher" +import { PublishContext } from "../index.js" +import { BaseS3Publisher, S3UploadConfig } from "./baseS3Publisher.js" export class SpacesPublisher extends BaseS3Publisher { readonly providerName = "spaces" @@ -44,7 +44,7 @@ export class SpacesPublisher extends BaseS3Publisher { return { region: this.info.region, endpoint: `https://${this.info.region}.digitaloceanspaces.com`, - credentials: { accessKeyId: accessKey!, secretAccessKey: secretKey! }, + credentials: { accessKeyId: accessKey, secretAccessKey: secretKey }, } } } diff --git a/packages/electron-publish/src/snapStorePublisher.ts b/packages/electron-publish/src/snapStorePublisher.ts index 5508c1480f3..0e2abedc4af 100644 --- a/packages/electron-publish/src/snapStorePublisher.ts +++ b/packages/electron-publish/src/snapStorePublisher.ts @@ -1,8 +1,8 @@ import { exec, loadCscLink, spawn } from "builder-util" -import { SnapStoreOptions } from "builder-util-runtime/out/publishOptions" +import { SnapStoreOptions } from "builder-util-runtime" import * as path from "path" -import { PublishContext, UploadTask } from "." -import { Publisher } from "./publisher" +import { PublishContext, UploadTask } from "./index.js" +import { Publisher } from "./publisher.js" export class SnapStorePublisher extends Publisher { readonly providerName = "snapStore" diff --git a/packages/electron-publish/tsconfig.build.json b/packages/electron-publish/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/electron-publish/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/electron-publish/tsconfig.json b/packages/electron-publish/tsconfig.json index 1d0ee3793fa..d76d5d6e7b5 100644 --- a/packages/electron-publish/tsconfig.json +++ b/packages/electron-publish/tsconfig.json @@ -12,12 +12,7 @@ "path": "../builder-util-runtime" } ], - "jsdoc": { - "out": "../../scripts/jsdoc/out/index", - "access": "public" - }, "include": [ - "src/**/*.ts", - "../../typings/mime.d.ts" + "src/**/*.ts" ] } \ No newline at end of file diff --git a/packages/electron-updater/package.json b/packages/electron-updater/package.json index e4add6443c4..8e1b8615fa4 100644 --- a/packages/electron-updater/package.json +++ b/packages/electron-updater/package.json @@ -2,7 +2,21 @@ "name": "electron-updater", "version": "6.8.8", "description": "Cross platform updater for electron applications", - "main": "out/main.js", + "type": "module", + "main": "./dist/index.js", + "exports": { + ".": { + "types": "./dist/index.d.ts", + "import": "./dist/index.js", + "require": "./dist/index.js" + }, + "./internal": { + "types": "./dist/indexInternal.d.ts", + "import": "./dist/indexInternal.js", + "require": "./dist/indexInternal.js" + }, + "./src/*": "./src/*.ts" + }, "author": "Vladimir Krivosheev", "license": "MIT", "repository": { @@ -13,11 +27,11 @@ "bugs": "https://github.com/electron-userland/electron-builder/issues", "homepage": "https://github.com/electron-userland/electron-builder", "files": [ - "out" + "dist" ], "dependencies": { "builder-util-runtime": "workspace:*", - "fs-extra": "^10.1.0", + "fs-extra": "^11.3.4", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", "lodash.escaperegexp": "^4.1.2", @@ -33,8 +47,15 @@ "@types/semver": "7.7.1", "electron": "39.8.5" }, - "typings": "./out/main.d.ts", + "types": "./dist/index.d.ts", "publishConfig": { "tag": "next" + }, + "engines": { + "node": ">=22.12.0" + }, + "scripts": { + "build": "node -e \"require('fs').rmSync('dist',{recursive:true,force:true})\" && tsc -p tsconfig.build.json", + "watch": "tsc -p tsconfig.build.json --watch" } } diff --git a/packages/electron-updater/src/AppImageUpdater.ts b/packages/electron-updater/src/AppImageUpdater.ts index 816a16a0324..5a2be23c067 100644 --- a/packages/electron-updater/src/AppImageUpdater.ts +++ b/packages/electron-updater/src/AppImageUpdater.ts @@ -1,14 +1,14 @@ import { AllPublishOptions, newError } from "builder-util-runtime" import { execFileSync } from "child_process" -import { chmod } from "fs-extra" +import fsExtra from "fs-extra" import { unlinkSync } from "fs" import * as path from "path" -import { DownloadUpdateOptions } from "./AppUpdater" -import { BaseUpdater, InstallOptions } from "./BaseUpdater" -import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader" -import { FileWithEmbeddedBlockMapDifferentialDownloader } from "./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader" -import { findFile, Provider } from "./providers/Provider" -import { DOWNLOAD_PROGRESS, ResolvedUpdateFileInfo } from "./types" +import { DownloadUpdateOptions } from "./AppUpdater.js" +import { BaseUpdater, InstallOptions } from "./BaseUpdater.js" +import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader.js" +import { FileWithEmbeddedBlockMapDifferentialDownloader } from "./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js" +import { findFile, Provider } from "./providers/Provider.js" +import { DOWNLOAD_PROGRESS, ResolvedUpdateFileInfo } from "./types.js" export class AppImageUpdater extends BaseUpdater { constructor(options?: AllPublishOptions | null, app?: any) { @@ -45,7 +45,7 @@ export class AppImageUpdater extends BaseUpdater { await this.httpExecutor.download(fileInfo.url, updateFile, downloadOptions) } - await chmod(updateFile, 0o755) + await fsExtra.chmod(updateFile, 0o755) }, }) } diff --git a/packages/electron-updater/src/AppUpdater.ts b/packages/electron-updater/src/AppUpdater.ts index c7b06af4c7d..a3ee28895f6 100644 --- a/packages/electron-updater/src/AppUpdater.ts +++ b/packages/electron-updater/src/AppUpdater.ts @@ -1,3 +1,4 @@ +import { createRequire } from "node:module" import { AllPublishOptions, asArray, @@ -15,27 +16,29 @@ import { import { randomBytes } from "crypto" import { release } from "os" import { EventEmitter } from "events" -import { mkdir, outputFile, readFile, rename, unlink, copyFile, pathExists } from "fs-extra" +import fsExtra from "fs-extra" import { OutgoingHttpHeaders } from "http" import { load } from "js-yaml" import { Lazy } from "lazy-val" import * as path from "path" import { eq as isVersionsEqual, gt as isVersionGreaterThan, lt as isVersionLessThan, parse as parseVersion, prerelease as getVersionPreleaseComponents, SemVer } from "semver" -import { AppAdapter } from "./AppAdapter" -import { createTempUpdateFile, DownloadedUpdateHelper } from "./DownloadedUpdateHelper" -import { ElectronAppAdapter } from "./ElectronAppAdapter" -import { ElectronHttpExecutor, getNetSession, LoginCallback } from "./electronHttpExecutor" -import { GenericProvider } from "./providers/GenericProvider" -import { createClient, isUrlProbablySupportMultiRangeRequests } from "./providerFactory" -import { Provider, ProviderPlatform } from "./providers/Provider" +import { AppAdapter } from "./AppAdapter.js" +import { createTempUpdateFile, DownloadedUpdateHelper } from "./DownloadedUpdateHelper.js" +import { ElectronAppAdapter } from "./ElectronAppAdapter.js" +import { ElectronHttpExecutor, getNetSession, LoginCallback } from "./electronHttpExecutor.js" +import { GenericProvider } from "./providers/GenericProvider.js" +import { createClient, isUrlProbablySupportMultiRangeRequests } from "./providerFactory.js" +import { Provider, ProviderPlatform } from "./providers/Provider.js" import type { TypedEmitter } from "tiny-typed-emitter" -import Session = Electron.Session +type Session = Electron.Session import type { AuthInfo } from "electron" import { gunzipSync, gzipSync } from "zlib" -import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader" -import { GenericDifferentialDownloader } from "./differentialDownloader/GenericDifferentialDownloader" -import { DOWNLOAD_PROGRESS, Logger, ResolvedUpdateFileInfo, UPDATE_DOWNLOADED, UpdateCheckResult, UpdateDownloadedEvent, UpdaterSignal } from "./types" -import { VerifyUpdateSupport } from "./main" +import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader.js" +import { GenericDifferentialDownloader } from "./differentialDownloader/GenericDifferentialDownloader.js" +import { DOWNLOAD_PROGRESS, Logger, ResolvedUpdateFileInfo, UPDATE_DOWNLOADED, UpdateCheckResult, UpdateDownloadedEvent, UpdaterSignal } from "./types.js" +import { VerifyUpdateSupport } from "./index.js" + +const require = createRequire(import.meta.url) export type AppUpdaterEvents = { error: (error: Error, message?: string) => void @@ -622,7 +625,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter if (this._appUpdateConfigPath == null) { this._appUpdateConfigPath = this.app.appUpdateConfigPath } - return load(await readFile(this._appUpdateConfigPath, "utf-8")) + return load(await fsExtra.readFile(this._appUpdateConfigPath, "utf-8")) } private computeRequestHeaders(provider: Provider): OutgoingHttpHeaders { @@ -642,7 +645,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter private async getOrCreateStagingUserId(): Promise { const file = path.join(this.app.userDataPath, ".updaterId") try { - const id = await readFile(file, "utf-8") + const id = await fsExtra.readFile(file, "utf-8") if (UUID.check(id)) { return id } else { @@ -657,7 +660,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter const id = UUID.v5(randomBytes(4096), UUID.OID) this._logger.info(`Generated new staging user ID: ${id}`) try { - await outputFile(file, id) + await fsExtra.outputFile(file, id) } catch (e: any) { this._logger.warn(`Couldn't write out staging user ID: ${e}`) } @@ -737,7 +740,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter const downloadedUpdateHelper = await this.getOrCreateDownloadHelper() const cacheDir = downloadedUpdateHelper.cacheDirForPendingUpdate - await mkdir(cacheDir, { recursive: true }) + await fsExtra.mkdir(cacheDir, { recursive: true }) const updateFileName = getCacheUpdateFileName() let updateFile = path.join(cacheDir, updateFileName) const packageFile = packageInfo == null ? null : path.join(cacheDir, `package-${version}${path.extname(packageInfo.path) || ".7z"}`) @@ -749,8 +752,8 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter downloadedFile: updateFile, }) const currentBlockMapFile = path.join(cacheDir, "current.blockmap") - if (await pathExists(currentBlockMapFile)) { - await copyFile(currentBlockMapFile, path.join(downloadedUpdateHelper.cacheDir, "current.blockmap")) + if (await fsExtra.pathExists(currentBlockMapFile)) { + await fsExtra.copyFile(currentBlockMapFile, path.join(downloadedUpdateHelper.cacheDir, "current.blockmap")) } return packageFile == null ? [updateFile] : [updateFile, packageFile] } @@ -766,7 +769,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter await downloadedUpdateHelper.clear().catch(() => { // ignore }) - return await unlink(updateFile).catch(() => { + return await fsExtra.unlink(updateFile).catch(() => { // ignore }) } @@ -774,7 +777,7 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter const tempUpdateFile = await createTempUpdateFile(`temp-${updateFileName}`, cacheDir, log) try { await taskOptions.task(tempUpdateFile, downloadOptions, packageFile, removeFileIfAny) - await retry(() => rename(tempUpdateFile, updateFile), { + await retry(() => fsExtra.rename(tempUpdateFile, updateFile), { retries: 60, interval: 500, shouldRetry: (error: Error) => { @@ -851,14 +854,14 @@ export abstract class AppUpdater extends (EventEmitter as new () => TypedEmitter const saveBlockMapToCacheDir = async (blockMapData: BlockMap, cacheDir: string) => { const blockMapFile = path.join(cacheDir, "current.blockmap") - await outputFile(blockMapFile, gzipSync(JSON.stringify(blockMapData))) + await fsExtra.outputFile(blockMapFile, gzipSync(JSON.stringify(blockMapData))) } const getBlockMapFromCacheDir = async (cacheDir: string) => { const blockMapFile = path.join(cacheDir, "current.blockmap") try { - if (await pathExists(blockMapFile)) { - return JSON.parse(gunzipSync(await readFile(blockMapFile)).toString()) + if (await fsExtra.pathExists(blockMapFile)) { + return JSON.parse(gunzipSync(await fsExtra.readFile(blockMapFile)).toString()) } } catch (e: any) { this._logger.warn(`Cannot parse blockmap "${blockMapFile}", error: ${e}`) diff --git a/packages/electron-updater/src/BaseUpdater.ts b/packages/electron-updater/src/BaseUpdater.ts index c5ad445093a..98cf4184d03 100644 --- a/packages/electron-updater/src/BaseUpdater.ts +++ b/packages/electron-updater/src/BaseUpdater.ts @@ -1,8 +1,11 @@ +import { createRequire } from "node:module" import { AllPublishOptions } from "builder-util-runtime" import { spawn, SpawnOptions, spawnSync, StdioOptions } from "child_process" import * as path from "path" -import { AppAdapter } from "./AppAdapter" -import { AppUpdater, DownloadExecutorTask } from "./AppUpdater" +import { AppAdapter } from "./AppAdapter.js" +import { AppUpdater, DownloadExecutorTask } from "./AppUpdater.js" + +const require = createRequire(import.meta.url) export abstract class BaseUpdater extends AppUpdater { protected quitAndInstallCalled = false diff --git a/packages/electron-updater/src/DebUpdater.ts b/packages/electron-updater/src/DebUpdater.ts index c3512c8f72e..9c0d537af3b 100644 --- a/packages/electron-updater/src/DebUpdater.ts +++ b/packages/electron-updater/src/DebUpdater.ts @@ -1,10 +1,10 @@ import { AllPublishOptions } from "builder-util-runtime" -import { AppAdapter } from "./AppAdapter" -import { DownloadUpdateOptions } from "./AppUpdater" -import { InstallOptions } from "./BaseUpdater" -import { findFile } from "./providers/Provider" -import { DOWNLOAD_PROGRESS, Logger } from "./types" -import { LinuxUpdater } from "./LinuxUpdater" +import { AppAdapter } from "./AppAdapter.js" +import { DownloadUpdateOptions } from "./AppUpdater.js" +import { InstallOptions } from "./BaseUpdater.js" +import { findFile } from "./providers/Provider.js" +import { DOWNLOAD_PROGRESS, Logger } from "./types.js" +import { LinuxUpdater } from "./LinuxUpdater.js" export class DebUpdater extends LinuxUpdater { constructor(options?: AllPublishOptions | null, app?: AppAdapter) { diff --git a/packages/electron-updater/src/DownloadedUpdateHelper.ts b/packages/electron-updater/src/DownloadedUpdateHelper.ts index c032d790892..414a0ac7d20 100644 --- a/packages/electron-updater/src/DownloadedUpdateHelper.ts +++ b/packages/electron-updater/src/DownloadedUpdateHelper.ts @@ -1,11 +1,10 @@ import { UpdateInfo } from "builder-util-runtime" import { createHash } from "crypto" import { createReadStream } from "fs" -// @ts-ignore -import * as isEqual from "lodash.isequal" -import { ResolvedUpdateFileInfo } from "./types" -import { Logger } from "./types" -import { pathExists, readJson, emptyDir, outputJson, unlink } from "fs-extra" +import isEqual from "lodash.isequal" +import { ResolvedUpdateFileInfo } from "./types.js" +import { Logger } from "./types.js" +import fsExtra from "fs-extra" import * as path from "path" /** @private **/ @@ -39,7 +38,7 @@ export class DownloadedUpdateHelper { if (this.versionInfo != null && this.file === updateFile && this.fileInfo != null) { // update has already been downloaded from this running instance // check here only existence, not checksum - if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await pathExists(updateFile))) { + if (isEqual(this.versionInfo, updateInfo) && isEqual(this.fileInfo.info, fileInfo.info) && (await fsExtra.pathExists(updateFile))) { return updateFile } else { return null @@ -75,7 +74,7 @@ export class DownloadedUpdateHelper { } if (isSaveCache) { - await outputJson(this.getUpdateInfoFile(), this._downloadedFileInfo) + await fsExtra.outputJson(this.getUpdateInfoFile(), this._downloadedFileInfo) } } @@ -90,7 +89,7 @@ export class DownloadedUpdateHelper { private async cleanCacheDirForPendingUpdate(): Promise { try { // remove stale data - await emptyDir(this.cacheDirForPendingUpdate) + await fsExtra.emptyDir(this.cacheDirForPendingUpdate) } catch (_ignore) { // ignore } @@ -104,14 +103,14 @@ export class DownloadedUpdateHelper { private async getValidCachedUpdateFile(fileInfo: ResolvedUpdateFileInfo, logger: Logger): Promise { const updateInfoFilePath: string = this.getUpdateInfoFile() - const doesUpdateInfoFileExist = await pathExists(updateInfoFilePath) + const doesUpdateInfoFileExist = await fsExtra.pathExists(updateInfoFilePath) if (!doesUpdateInfoFileExist) { return null } let cachedInfo: CachedUpdateInfo try { - cachedInfo = await readJson(updateInfoFilePath) + cachedInfo = await fsExtra.readJson(updateInfoFilePath) } catch (error: any) { let message = `No cached update info available` if (error.code !== "ENOENT") { @@ -138,7 +137,7 @@ export class DownloadedUpdateHelper { } const updateFile = path.join(this.cacheDirForPendingUpdate, cachedInfo.fileName) - if (!(await pathExists(updateFile))) { + if (!(await fsExtra.pathExists(updateFile))) { logger.info("Cached update file doesn't exist") return null } @@ -185,7 +184,7 @@ export async function createTempUpdateFile(name: string, cacheDir: string, log: let result = path.join(cacheDir, name) for (let i = 0; i < 3; i++) { try { - await unlink(result) + await fsExtra.unlink(result) return result } catch (e: any) { if (e.code === "ENOENT") { diff --git a/packages/electron-updater/src/ElectronAppAdapter.ts b/packages/electron-updater/src/ElectronAppAdapter.ts index a4480f8624f..4a4c0136971 100644 --- a/packages/electron-updater/src/ElectronAppAdapter.ts +++ b/packages/electron-updater/src/ElectronAppAdapter.ts @@ -1,5 +1,8 @@ +import { createRequire } from "node:module" import * as path from "path" -import { AppAdapter, getAppCacheDir } from "./AppAdapter" + +const require = createRequire(import.meta.url) +import { AppAdapter, getAppCacheDir } from "./AppAdapter.js" export class ElectronAppAdapter implements AppAdapter { constructor(private readonly app = require("electron").app) {} diff --git a/packages/electron-updater/src/LinuxUpdater.ts b/packages/electron-updater/src/LinuxUpdater.ts index 92fab97a90f..cd444b86c70 100644 --- a/packages/electron-updater/src/LinuxUpdater.ts +++ b/packages/electron-updater/src/LinuxUpdater.ts @@ -1,6 +1,6 @@ import { AllPublishOptions } from "builder-util-runtime" -import { AppAdapter } from "./AppAdapter" -import { BaseUpdater } from "./BaseUpdater" +import { AppAdapter } from "./AppAdapter.js" +import { BaseUpdater } from "./BaseUpdater.js" // Matches safe package manager names: alphanumeric, hyphens, underscores only. // Rejects names with shell metacharacters that could cause command injection. diff --git a/packages/electron-updater/src/MacUpdater.ts b/packages/electron-updater/src/MacUpdater.ts index eb2f40e2883..977fbe8bcb8 100644 --- a/packages/electron-updater/src/MacUpdater.ts +++ b/packages/electron-updater/src/MacUpdater.ts @@ -1,14 +1,17 @@ +import { createRequire } from "node:module" import { AllPublishOptions, newError, safeStringifyJson } from "builder-util-runtime" -import { pathExistsSync, stat, copyFile } from "fs-extra" + +const require = createRequire(import.meta.url) +import fsExtra from "fs-extra" import { createReadStream } from "fs" import * as path from "path" import { createServer, IncomingMessage, Server, ServerResponse } from "http" -import { AppAdapter } from "./AppAdapter" -import { AppUpdater, DownloadUpdateOptions } from "./AppUpdater" -import { ResolvedUpdateFileInfo } from "./main" -import { UpdateDownloadedEvent } from "./types" -import { findFile } from "./providers/Provider" -import AutoUpdater = Electron.AutoUpdater +import { AppAdapter } from "./AppAdapter.js" +import { AppUpdater, DownloadUpdateOptions } from "./AppUpdater.js" +import { ResolvedUpdateFileInfo } from "./types.js" +import { UpdateDownloadedEvent } from "./types.js" +import { findFile } from "./providers/Provider.js" +type AutoUpdater = Electron.AutoUpdater import { execFileSync } from "child_process" import { randomBytes } from "crypto" @@ -109,7 +112,7 @@ export class MacUpdater extends AppUpdater { task: async (destinationFile, downloadOptions) => { const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME) const canDifferentialDownload = () => { - if (!pathExistsSync(cachedUpdateFilePath)) { + if (!fsExtra.pathExistsSync(cachedUpdateFilePath)) { log.info("Unable to locate previous update.zip for differential download (is this first install?), falling back to full download") return false } @@ -128,7 +131,7 @@ export class MacUpdater extends AppUpdater { if (!downloadUpdateOptions.disableDifferentialDownload) { try { const cachedUpdateFilePath = path.join(this.downloadedUpdateHelper!.cacheDir, CURRENT_MAC_APP_ZIP_FILE_NAME) - await copyFile(event.downloadedFile, cachedUpdateFilePath) + await fsExtra.copyFile(event.downloadedFile, cachedUpdateFilePath) } catch (error: any) { this._logger.warn(`Unable to copy file for caching for future differential downloads: ${error.message}`) } @@ -140,7 +143,7 @@ export class MacUpdater extends AppUpdater { private async updateDownloaded(zipFileInfo: ResolvedUpdateFileInfo, event: UpdateDownloadedEvent): Promise> { const downloadedFile = event.downloadedFile - const updateFileSize = zipFileInfo.info.size ?? (await stat(downloadedFile)).size + const updateFileSize = zipFileInfo.info.size ?? (await fsExtra.stat(downloadedFile)).size const log = this._logger const logContext = `fileToProxy=${zipFileInfo.url.href}` diff --git a/packages/electron-updater/src/NsisUpdater.ts b/packages/electron-updater/src/NsisUpdater.ts index ada9e9ed7ba..1b64e702ddb 100644 --- a/packages/electron-updater/src/NsisUpdater.ts +++ b/packages/electron-updater/src/NsisUpdater.ts @@ -1,17 +1,20 @@ +import { createRequire } from "node:module" import { AllPublishOptions, newError, PackageFileInfo, CURRENT_APP_INSTALLER_FILE_NAME, CURRENT_APP_PACKAGE_FILE_NAME } from "builder-util-runtime" import * as path from "path" -import { AppAdapter } from "./AppAdapter" -import { DownloadUpdateOptions } from "./AppUpdater" -import { BaseUpdater, InstallOptions } from "./BaseUpdater" -import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader" -import { FileWithEmbeddedBlockMapDifferentialDownloader } from "./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader" -import { DOWNLOAD_PROGRESS } from "./types" -import { VerifyUpdateCodeSignature } from "./main" -import { findFile, Provider } from "./providers/Provider" -import { unlink } from "fs-extra" -import { verifySignature } from "./windowsExecutableCodeSignatureVerifier" +import { AppAdapter } from "./AppAdapter.js" +import { DownloadUpdateOptions } from "./AppUpdater.js" +import { BaseUpdater, InstallOptions } from "./BaseUpdater.js" +import { DifferentialDownloaderOptions } from "./differentialDownloader/DifferentialDownloader.js" +import { FileWithEmbeddedBlockMapDifferentialDownloader } from "./differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.js" +import { DOWNLOAD_PROGRESS } from "./types.js" +import { VerifyUpdateCodeSignature } from "./index.js" +import { findFile, Provider } from "./providers/Provider.js" +import fsExtra from "fs-extra" +import { verifySignature } from "./windowsExecutableCodeSignatureVerifier.js" import { URL } from "url" +const require = createRequire(import.meta.url) + export class NsisUpdater extends BaseUpdater { /** * Specify custom install directory path @@ -90,7 +93,7 @@ export class NsisUpdater extends BaseUpdater { }) } catch (e: any) { try { - await unlink(packageFile) + await fsExtra.unlink(packageFile) } catch (_ignored) { // ignore } diff --git a/packages/electron-updater/src/PacmanUpdater.ts b/packages/electron-updater/src/PacmanUpdater.ts index c329c8a9e86..8c3b5b6f1b1 100644 --- a/packages/electron-updater/src/PacmanUpdater.ts +++ b/packages/electron-updater/src/PacmanUpdater.ts @@ -1,10 +1,10 @@ import { AllPublishOptions } from "builder-util-runtime" -import { AppAdapter } from "./AppAdapter" -import { DownloadUpdateOptions } from "./AppUpdater" -import { InstallOptions } from "./BaseUpdater" -import { DOWNLOAD_PROGRESS, Logger } from "./types" -import { findFile } from "./providers/Provider" -import { LinuxUpdater } from "./LinuxUpdater" +import { AppAdapter } from "./AppAdapter.js" +import { DownloadUpdateOptions } from "./AppUpdater.js" +import { InstallOptions } from "./BaseUpdater.js" +import { DOWNLOAD_PROGRESS, Logger } from "./types.js" +import { findFile } from "./providers/Provider.js" +import { LinuxUpdater } from "./LinuxUpdater.js" export class PacmanUpdater extends LinuxUpdater { constructor(options?: AllPublishOptions | null, app?: AppAdapter) { diff --git a/packages/electron-updater/src/RpmUpdater.ts b/packages/electron-updater/src/RpmUpdater.ts index eb2b360ed5e..3df356a8a71 100644 --- a/packages/electron-updater/src/RpmUpdater.ts +++ b/packages/electron-updater/src/RpmUpdater.ts @@ -1,10 +1,10 @@ import { AllPublishOptions } from "builder-util-runtime" -import { AppAdapter } from "./AppAdapter" -import { DownloadUpdateOptions } from "./AppUpdater" -import { InstallOptions } from "./BaseUpdater" -import { DOWNLOAD_PROGRESS, Logger } from "./types" -import { findFile } from "./providers/Provider" -import { LinuxUpdater } from "./LinuxUpdater" +import { AppAdapter } from "./AppAdapter.js" +import { DownloadUpdateOptions } from "./AppUpdater.js" +import { InstallOptions } from "./BaseUpdater.js" +import { DOWNLOAD_PROGRESS, Logger } from "./types.js" +import { findFile } from "./providers/Provider.js" +import { LinuxUpdater } from "./LinuxUpdater.js" export class RpmUpdater extends LinuxUpdater { constructor(options?: AllPublishOptions | null, app?: AppAdapter) { diff --git a/packages/electron-updater/src/differentialDownloader/DataSplitter.ts b/packages/electron-updater/src/differentialDownloader/DataSplitter.ts index 326c9ea0ed9..23faabb90bc 100644 --- a/packages/electron-updater/src/differentialDownloader/DataSplitter.ts +++ b/packages/electron-updater/src/differentialDownloader/DataSplitter.ts @@ -1,8 +1,8 @@ import { newError } from "builder-util-runtime" import { createReadStream } from "fs" import { Writable } from "stream" -import { Operation, OperationKind } from "./downloadPlanBuilder" -import { ProgressInfo } from "./ProgressDifferentialDownloadCallbackTransform" +import { Operation, OperationKind } from "./downloadPlanBuilder.js" +import { ProgressInfo } from "./ProgressDifferentialDownloadCallbackTransform.js" const DOUBLE_CRLF = Buffer.from("\r\n\r\n") diff --git a/packages/electron-updater/src/differentialDownloader/DifferentialDownloader.ts b/packages/electron-updater/src/differentialDownloader/DifferentialDownloader.ts index d62c0ddf73c..15b9d20e168 100644 --- a/packages/electron-updater/src/differentialDownloader/DifferentialDownloader.ts +++ b/packages/electron-updater/src/differentialDownloader/DifferentialDownloader.ts @@ -1,15 +1,15 @@ import { BlockMapDataHolder, createHttpError, DigestTransform, HttpExecutor, configureRequestUrl, configureRequestOptions } from "builder-util-runtime" -import { BlockMap } from "builder-util-runtime/out/blockMapApi" -import { close, open } from "fs-extra" +import { BlockMap } from "builder-util-runtime" +import fsExtra from "fs-extra" import { createWriteStream } from "fs" import { OutgoingHttpHeaders, RequestOptions } from "http" import { ProgressInfo, CancellationToken } from "builder-util-runtime" -import { Logger } from "../types" -import { copyData } from "./DataSplitter" +import { Logger } from "../types.js" +import { copyData } from "./DataSplitter.js" import { URL } from "url" -import { computeOperations, Operation, OperationKind } from "./downloadPlanBuilder" -import { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from "./multipleRangeDownloader" -import { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from "./ProgressDifferentialDownloadCallbackTransform" +import { computeOperations, Operation, OperationKind } from "./downloadPlanBuilder.js" +import { checkIsRangesSupported, executeTasksUsingMultipleRangeRequests } from "./multipleRangeDownloader.js" +import { ProgressDifferentialDownloadCallbackTransform, ProgressDifferentialDownloadInfo } from "./ProgressDifferentialDownloadCallbackTransform.js" export interface DifferentialDownloaderOptions { readonly oldFile: string @@ -90,7 +90,7 @@ export abstract class DifferentialDownloader { const closeFiles = (): Promise> => { return Promise.all( fdList.map(openedFile => { - return close(openedFile.descriptor).catch((e: any) => { + return fsExtra.close(openedFile.descriptor).catch((e: any) => { this.logger.error(`cannot close file "${openedFile.path}": ${e}`) }) }) @@ -121,9 +121,9 @@ export abstract class DifferentialDownloader { } private async doDownloadFile(tasks: Array, fdList: Array): Promise { - const oldFileFd = await open(this.options.oldFile, "r") + const oldFileFd = await fsExtra.open(this.options.oldFile, "r") fdList.push({ descriptor: oldFileFd, path: this.options.oldFile }) - const newFileFd = await open(this.options.newFile, "w") + const newFileFd = await fsExtra.open(this.options.newFile, "w") fdList.push({ descriptor: newFileFd, path: this.options.newFile }) const fileOut = createWriteStream(this.options.newFile, { fd: newFileFd }) await new Promise((resolve, reject) => { diff --git a/packages/electron-updater/src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts b/packages/electron-updater/src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts index d4446db1d7a..e842403c7c1 100644 --- a/packages/electron-updater/src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts +++ b/packages/electron-updater/src/differentialDownloader/FileWithEmbeddedBlockMapDifferentialDownloader.ts @@ -1,6 +1,6 @@ -import { BlockMap } from "builder-util-runtime/out/blockMapApi" -import { close, fstat, open, read } from "fs-extra" -import { DifferentialDownloader } from "./DifferentialDownloader" +import { BlockMap } from "builder-util-runtime" +import fsExtra from "fs-extra" +import { DifferentialDownloader } from "./DifferentialDownloader.js" import { inflateRawSync } from "zlib" export class FileWithEmbeddedBlockMapDifferentialDownloader extends DifferentialDownloader { @@ -19,19 +19,19 @@ function readBlockMap(data: Buffer): BlockMap { } async function readEmbeddedBlockMapData(file: string): Promise { - const fd = await open(file, "r") + const fd = await fsExtra.open(file, "r") try { - const fileSize = (await fstat(fd)).size + const fileSize = (await fsExtra.fstat(fd)).size const sizeBuffer = Buffer.allocUnsafe(4) - await read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length) + await fsExtra.read(fd, sizeBuffer, 0, sizeBuffer.length, fileSize - sizeBuffer.length) const dataBuffer = Buffer.allocUnsafe(sizeBuffer.readUInt32BE(0)) - await read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length) - await close(fd) + await fsExtra.read(fd, dataBuffer, 0, dataBuffer.length, fileSize - sizeBuffer.length - dataBuffer.length) + await fsExtra.close(fd) return readBlockMap(dataBuffer) } catch (e: any) { - await close(fd) + await fsExtra.close(fd) throw e } } diff --git a/packages/electron-updater/src/differentialDownloader/GenericDifferentialDownloader.ts b/packages/electron-updater/src/differentialDownloader/GenericDifferentialDownloader.ts index b7727d6c564..fc4f73c613a 100644 --- a/packages/electron-updater/src/differentialDownloader/GenericDifferentialDownloader.ts +++ b/packages/electron-updater/src/differentialDownloader/GenericDifferentialDownloader.ts @@ -1,5 +1,5 @@ -import { BlockMap } from "builder-util-runtime/out/blockMapApi" -import { DifferentialDownloader } from "./DifferentialDownloader" +import { BlockMap } from "builder-util-runtime" +import { DifferentialDownloader } from "./DifferentialDownloader.js" export class GenericDifferentialDownloader extends DifferentialDownloader { download(oldBlockMap: BlockMap, newBlockMap: BlockMap): Promise { diff --git a/packages/electron-updater/src/differentialDownloader/downloadPlanBuilder.ts b/packages/electron-updater/src/differentialDownloader/downloadPlanBuilder.ts index 7a7c1612c0a..76c74c36566 100644 --- a/packages/electron-updater/src/differentialDownloader/downloadPlanBuilder.ts +++ b/packages/electron-updater/src/differentialDownloader/downloadPlanBuilder.ts @@ -1,5 +1,6 @@ -import { BlockMap, BlockMapFile } from "builder-util-runtime/out/blockMapApi" -import { Logger } from "../types" +import { BlockMap } from "builder-util-runtime" +import { BlockMapFile } from "builder-util-runtime/internal" +import { Logger } from "../types.js" export enum OperationKind { COPY, diff --git a/packages/electron-updater/src/differentialDownloader/multipleRangeDownloader.ts b/packages/electron-updater/src/differentialDownloader/multipleRangeDownloader.ts index fe72f15dcfe..cad44191223 100644 --- a/packages/electron-updater/src/differentialDownloader/multipleRangeDownloader.ts +++ b/packages/electron-updater/src/differentialDownloader/multipleRangeDownloader.ts @@ -1,9 +1,9 @@ import { createHttpError, safeGetHeader } from "builder-util-runtime" import { IncomingMessage } from "http" import { Writable } from "stream" -import { copyData, DataSplitter, PartListDataTask } from "./DataSplitter" -import { DifferentialDownloader } from "./DifferentialDownloader" -import { Operation, OperationKind } from "./downloadPlanBuilder" +import { copyData, DataSplitter, PartListDataTask } from "./DataSplitter.js" +import { DifferentialDownloader } from "./DifferentialDownloader.js" +import { Operation, OperationKind } from "./downloadPlanBuilder.js" export function executeTasksUsingMultipleRangeRequests( differentialDownloader: DifferentialDownloader, diff --git a/packages/electron-updater/src/electronHttpExecutor.ts b/packages/electron-updater/src/electronHttpExecutor.ts index 298db362a62..f3fc6dbeb62 100644 --- a/packages/electron-updater/src/electronHttpExecutor.ts +++ b/packages/electron-updater/src/electronHttpExecutor.ts @@ -1,8 +1,11 @@ +import { createRequire } from "node:module" import { DownloadOptions, HttpExecutor, configureRequestOptions, configureRequestUrl } from "builder-util-runtime" + +const require = createRequire(import.meta.url) import type { AuthInfo } from "electron" import { RequestOptions } from "http" -import Session = Electron.Session -import ClientRequest = Electron.ClientRequest +type Session = Electron.Session +type ClientRequest = Electron.ClientRequest export type LoginCallback = (username: string, password: string) => void export const NET_SESSION_NAME = "electron-updater" diff --git a/packages/electron-updater/src/index.ts b/packages/electron-updater/src/index.ts new file mode 100644 index 00000000000..a0663b6719f --- /dev/null +++ b/packages/electron-updater/src/index.ts @@ -0,0 +1,91 @@ +import fsExtra from "fs-extra" +import { createRequire } from "node:module" +import * as path from "path" +import { AppUpdater } from "./AppUpdater.js" + +const require = createRequire(import.meta.url) + +import { UpdateInfo } from "builder-util-runtime" + +export { AppImageUpdater } from "./AppImageUpdater.js" +export { BaseUpdater } from "./BaseUpdater.js" +export { DebUpdater } from "./DebUpdater.js" +export { MacUpdater } from "./MacUpdater.js" +export { NsisUpdater } from "./NsisUpdater.js" +export { PacmanUpdater } from "./PacmanUpdater.js" +export { BitbucketProvider } from "./providers/BitbucketProvider.js" +export { GitHubProvider } from "./providers/GitHubProvider.js" +export { GitLabProvider } from "./providers/GitLabProvider.js" +export { KeygenProvider } from "./providers/KeygenProvider.js" +export { PrivateGitHubProvider } from "./providers/PrivateGitHubProvider.js" +export { ProviderRuntimeOptions } from "./providers/Provider.js" +export { RpmUpdater } from "./RpmUpdater.js" +export { AppUpdater } + +export { Provider } from "./providers/Provider.js" + +export * from "./types.js" + +function doLoadAutoUpdater(): AppUpdater { + let updater: any + if (process.platform === "win32") { + updater = new (require("./NsisUpdater.js").NsisUpdater)() + } else if (process.platform === "darwin") { + updater = new (require("./MacUpdater.js").MacUpdater)() + } else { + updater = new (require("./AppImageUpdater.js").AppImageUpdater)() + try { + const identity = path.join(process.resourcesPath, "package-type") + if (!fsExtra.existsSync(identity)) { + return updater + } + const fileType = fsExtra.readFileSync(identity).toString().trim() + switch (fileType) { + case "deb": + updater = new (require("./DebUpdater.js").DebUpdater)() + break + case "rpm": + updater = new (require("./RpmUpdater.js").RpmUpdater)() + break + case "pacman": + updater = new (require("./PacmanUpdater.js").PacmanUpdater)() + break + default: + break + } + } catch (error: any) { + console.warn( + "Unable to detect 'package-type' for autoUpdater (rpm/deb/pacman support). If you'd like to expand support, please consider contributing to electron-builder", + error.message + ) + } + } + return updater +} + +let _autoUpdater: AppUpdater | undefined + +export const autoUpdater: AppUpdater = new Proxy({} as AppUpdater, { + get(_target, prop) { + if (_autoUpdater === undefined) { + _autoUpdater = doLoadAutoUpdater() + } + const value = (_autoUpdater as any)[prop] + return typeof value === "function" ? value.bind(_autoUpdater) : value + }, + set(_target, prop, value) { + if (_autoUpdater === undefined) { + _autoUpdater = doLoadAutoUpdater() + } + ;(_autoUpdater as any)[prop] = value + return true + }, +}) + +/** + * return null if verify signature succeed + * return error message if verify signature failed + */ +export type VerifyUpdateCodeSignature = (publisherName: string[], path: string) => Promise + +export type VerifyUpdateSupport = (updateInfo: UpdateInfo) => boolean | Promise diff --git a/packages/electron-updater/src/indexInternal.ts b/packages/electron-updater/src/indexInternal.ts new file mode 100644 index 00000000000..89dced1c39d --- /dev/null +++ b/packages/electron-updater/src/indexInternal.ts @@ -0,0 +1,5 @@ +export { ElectronAppAdapter } from "./ElectronAppAdapter.js" +export { TestOnlyUpdaterOptions } from "./AppUpdater.js" +export { NoOpLogger } from "./AppUpdater.js" + +export * as utils from "./util.js" diff --git a/packages/electron-updater/src/main.ts b/packages/electron-updater/src/main.ts deleted file mode 100644 index 49f850f69bc..00000000000 --- a/packages/electron-updater/src/main.ts +++ /dev/null @@ -1,74 +0,0 @@ -import { existsSync, readFileSync } from "fs-extra" -import * as path from "path" -import { AppUpdater } from "./AppUpdater" -import { UpdateInfo } from "builder-util-runtime" - -export { BaseUpdater } from "./BaseUpdater" -export { AppUpdater, NoOpLogger } from "./AppUpdater" -export { Provider } from "./providers/Provider" -export { AppImageUpdater } from "./AppImageUpdater" -export { DebUpdater } from "./DebUpdater" -export { PacmanUpdater } from "./PacmanUpdater" -export { RpmUpdater } from "./RpmUpdater" -export { MacUpdater } from "./MacUpdater" -export { NsisUpdater } from "./NsisUpdater" - -export * from "./types" - -// autoUpdater to mimic electron bundled autoUpdater -let _autoUpdater: any - -// required for jsdoc -export declare const autoUpdater: AppUpdater - -function doLoadAutoUpdater(): AppUpdater { - // tslint:disable:prefer-conditional-expression - if (process.platform === "win32") { - _autoUpdater = new (require("./NsisUpdater").NsisUpdater)() - } else if (process.platform === "darwin") { - _autoUpdater = new (require("./MacUpdater").MacUpdater)() - } else { - _autoUpdater = new (require("./AppImageUpdater").AppImageUpdater)() - try { - const identity = path.join(process.resourcesPath, "package-type") - if (!existsSync(identity)) { - return _autoUpdater - } - const fileType = readFileSync(identity).toString().trim() - switch (fileType) { - case "deb": - _autoUpdater = new (require("./DebUpdater").DebUpdater)() - break - case "rpm": - _autoUpdater = new (require("./RpmUpdater").RpmUpdater)() - break - case "pacman": - _autoUpdater = new (require("./PacmanUpdater").PacmanUpdater)() - break - default: - break - } - } catch (error: any) { - console.warn( - "Unable to detect 'package-type' for autoUpdater (rpm/deb/pacman support). If you'd like to expand support, please consider contributing to electron-builder", - error.message - ) - } - } - return _autoUpdater -} - -Object.defineProperty(exports, "autoUpdater", { - enumerable: true, - get: () => { - return _autoUpdater || doLoadAutoUpdater() - }, -}) - -/** - * return null if verify signature succeed - * return error message if verify signature failed - */ -export type VerifyUpdateCodeSignature = (publisherName: string[], path: string) => Promise - -export type VerifyUpdateSupport = (updateInfo: UpdateInfo) => boolean | Promise diff --git a/packages/electron-updater/src/providerFactory.ts b/packages/electron-updater/src/providerFactory.ts index 8f1e35a4c4d..91f13e17b75 100644 --- a/packages/electron-updater/src/providerFactory.ts +++ b/packages/electron-updater/src/providerFactory.ts @@ -11,14 +11,14 @@ import { newError, PublishConfiguration, } from "builder-util-runtime" -import { AppUpdater } from "./AppUpdater" -import { BitbucketProvider } from "./providers/BitbucketProvider" -import { GenericProvider } from "./providers/GenericProvider" -import { GitHubProvider } from "./providers/GitHubProvider" -import { GitLabProvider } from "./providers/GitLabProvider" -import { KeygenProvider } from "./providers/KeygenProvider" -import { PrivateGitHubProvider } from "./providers/PrivateGitHubProvider" -import { Provider, ProviderRuntimeOptions } from "./providers/Provider" +import { AppUpdater } from "./AppUpdater.js" +import { BitbucketProvider } from "./providers/BitbucketProvider.js" +import { GenericProvider } from "./providers/GenericProvider.js" +import { GitHubProvider } from "./providers/GitHubProvider.js" +import { GitLabProvider } from "./providers/GitLabProvider.js" +import { KeygenProvider } from "./providers/KeygenProvider.js" +import { PrivateGitHubProvider } from "./providers/PrivateGitHubProvider.js" +import { Provider, ProviderRuntimeOptions } from "./providers/Provider.js" export function isUrlProbablySupportMultiRangeRequests(url: string): boolean { return !url.includes("s3.amazonaws.com") diff --git a/packages/electron-updater/src/providers/BitbucketProvider.ts b/packages/electron-updater/src/providers/BitbucketProvider.ts index 824a5fca77f..d36e7d797de 100644 --- a/packages/electron-updater/src/providers/BitbucketProvider.ts +++ b/packages/electron-updater/src/providers/BitbucketProvider.ts @@ -1,8 +1,8 @@ import { CancellationToken, BitbucketOptions, newError, UpdateInfo } from "builder-util-runtime" -import { AppUpdater } from "../AppUpdater" -import { ResolvedUpdateFileInfo } from "../types" -import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util" -import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider" +import { AppUpdater } from "../AppUpdater.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util.js" +import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider.js" export class BitbucketProvider extends Provider { private readonly baseUrl: URL diff --git a/packages/electron-updater/src/providers/GenericProvider.ts b/packages/electron-updater/src/providers/GenericProvider.ts index b5a23d0013c..1e32ccba297 100644 --- a/packages/electron-updater/src/providers/GenericProvider.ts +++ b/packages/electron-updater/src/providers/GenericProvider.ts @@ -1,11 +1,11 @@ import { GenericServerOptions, HttpError, newError, UpdateInfo } from "builder-util-runtime" -import { AppUpdater } from "../AppUpdater" -import { ResolvedUpdateFileInfo } from "../types" -import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util" -import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider" +import { AppUpdater } from "../AppUpdater.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util.js" +import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider.js" export class GenericProvider extends Provider { - private readonly baseUrl = newBaseUrl(this.configuration.url) + private readonly baseUrl: URL constructor( private readonly configuration: GenericServerOptions, @@ -13,6 +13,7 @@ export class GenericProvider extends Provider { runtimeOptions: ProviderRuntimeOptions ) { super(runtimeOptions) + this.baseUrl = newBaseUrl(this.configuration.url) } private get channel(): string { diff --git a/packages/electron-updater/src/providers/GitHubProvider.ts b/packages/electron-updater/src/providers/GitHubProvider.ts index f6b3804bd8a..8d17e7cdd91 100644 --- a/packages/electron-updater/src/providers/GitHubProvider.ts +++ b/packages/electron-updater/src/providers/GitHubProvider.ts @@ -1,10 +1,10 @@ import { CancellationToken, GithubOptions, githubUrl, HttpError, newError, parseXml, ReleaseNoteInfo, UpdateInfo, XElement } from "builder-util-runtime" import * as semver from "semver" import { URL } from "url" -import { AppUpdater } from "../AppUpdater" -import { ResolvedUpdateFileInfo } from "../types" -import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util" -import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider" +import { AppUpdater } from "../AppUpdater.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util.js" +import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider.js" const hrefRegExp = /\/tag\/(v?[^/]+)$/ diff --git a/packages/electron-updater/src/providers/GitLabProvider.ts b/packages/electron-updater/src/providers/GitLabProvider.ts index 016248ce307..f001b43aff4 100644 --- a/packages/electron-updater/src/providers/GitLabProvider.ts +++ b/packages/electron-updater/src/providers/GitLabProvider.ts @@ -1,11 +1,10 @@ import { CancellationToken, GitlabOptions, HttpError, newError, UpdateFileInfo, UpdateInfo, GitlabReleaseInfo, GitlabReleaseAsset } from "builder-util-runtime" import { URL } from "url" -// @ts-ignore -import * as escapeRegExp from "lodash.escaperegexp" -import { AppUpdater } from "../AppUpdater" -import { ResolvedUpdateFileInfo } from "../types" -import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util" -import { getFileList, parseUpdateInfo, Provider, ProviderRuntimeOptions } from "./Provider" +import escapeRegExp from "lodash.escaperegexp" +import { AppUpdater } from "../AppUpdater.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util.js" +import { getFileList, parseUpdateInfo, Provider, ProviderRuntimeOptions } from "./Provider.js" interface GitlabUpdateInfo extends UpdateInfo { tag: string diff --git a/packages/electron-updater/src/providers/KeygenProvider.ts b/packages/electron-updater/src/providers/KeygenProvider.ts index 6842628a030..5007598e9a8 100644 --- a/packages/electron-updater/src/providers/KeygenProvider.ts +++ b/packages/electron-updater/src/providers/KeygenProvider.ts @@ -1,8 +1,8 @@ import { CancellationToken, KeygenOptions, newError, UpdateInfo } from "builder-util-runtime" -import { AppUpdater } from "../AppUpdater" -import { ResolvedUpdateFileInfo } from "../types" -import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util" -import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider" +import { AppUpdater } from "../AppUpdater.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getChannelFilename, newBaseUrl, newUrlFromBase } from "../util.js" +import { parseUpdateInfo, Provider, ProviderRuntimeOptions, resolveFiles } from "./Provider.js" export class KeygenProvider extends Provider { private readonly defaultHostname = "api.keygen.sh" diff --git a/packages/electron-updater/src/providers/PrivateGitHubProvider.ts b/packages/electron-updater/src/providers/PrivateGitHubProvider.ts index f6c787f62ce..81316046d09 100644 --- a/packages/electron-updater/src/providers/PrivateGitHubProvider.ts +++ b/packages/electron-updater/src/providers/PrivateGitHubProvider.ts @@ -2,12 +2,12 @@ import { CancellationToken, GithubOptions, HttpError, newError, UpdateInfo } fro import { OutgoingHttpHeaders, RequestOptions } from "http" import { load } from "js-yaml" import * as path from "path" -import { AppUpdater } from "../AppUpdater" +import { AppUpdater } from "../AppUpdater.js" import { URL } from "url" -import { getChannelFilename, newUrlFromBase } from "../util" -import { BaseGitHubProvider } from "./GitHubProvider" -import { ResolvedUpdateFileInfo } from "../types" -import { getFileList, ProviderRuntimeOptions } from "./Provider" +import { getChannelFilename, newUrlFromBase } from "../util.js" +import { BaseGitHubProvider } from "./GitHubProvider.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { getFileList, ProviderRuntimeOptions } from "./Provider.js" export interface PrivateGitHubUpdateInfo extends UpdateInfo { assets: Array diff --git a/packages/electron-updater/src/providers/Provider.ts b/packages/electron-updater/src/providers/Provider.ts index 4d247325b33..23b073fd1fe 100644 --- a/packages/electron-updater/src/providers/Provider.ts +++ b/packages/electron-updater/src/providers/Provider.ts @@ -2,11 +2,10 @@ import { CancellationToken, configureRequestUrl, newError, safeStringifyJson, Up import { OutgoingHttpHeaders, RequestOptions } from "http" import { load } from "js-yaml" import { URL } from "url" -import { ElectronHttpExecutor } from "../electronHttpExecutor" -import { ResolvedUpdateFileInfo } from "../types" -import { newUrlFromBase } from "../util" -// @ts-ignore -import * as escapeRegExp from "lodash.escaperegexp" +import { ElectronHttpExecutor } from "../electronHttpExecutor.js" +import { ResolvedUpdateFileInfo } from "../types.js" +import { newUrlFromBase } from "../util.js" +import escapeRegExp from "lodash.escaperegexp" export type ProviderPlatform = "darwin" | "linux" | "win32" diff --git a/packages/electron-updater/src/types.ts b/packages/electron-updater/src/types.ts index d4e92de3c24..94a394c9827 100644 --- a/packages/electron-updater/src/types.ts +++ b/packages/electron-updater/src/types.ts @@ -1,7 +1,7 @@ import { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo } from "builder-util-runtime" import { EventEmitter } from "events" import { URL } from "url" -import { LoginCallback } from "./electronHttpExecutor" +import { LoginCallback } from "./electronHttpExecutor.js" export { CancellationToken, PackageFileInfo, ProgressInfo, UpdateFileInfo, UpdateInfo } diff --git a/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts b/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts index f35f2aa88d3..e7f23c8f612 100644 --- a/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts +++ b/packages/electron-updater/src/windowsExecutableCodeSignatureVerifier.ts @@ -1,7 +1,7 @@ import { parseDn } from "builder-util-runtime" import { execFile, execFileSync, ExecFileOptions } from "child_process" import * as os from "os" -import { Logger } from "./types" +import { Logger } from "./types.js" import * as path from "path" function preparePowerShellExec(command: string, timeout?: number) { diff --git a/packages/electron-updater/tsconfig.build.json b/packages/electron-updater/tsconfig.build.json new file mode 100644 index 00000000000..43ec572d771 --- /dev/null +++ b/packages/electron-updater/tsconfig.build.json @@ -0,0 +1,8 @@ +{ + "extends": "../tsconfig-build.json", + "compilerOptions": { + "outDir": "dist", + "rootDir": "src" + }, + "include": ["src/**/*.ts"] +} diff --git a/packages/electron-updater/tsconfig.json b/packages/electron-updater/tsconfig.json index c92cd864271..e569ae0df14 100644 --- a/packages/electron-updater/tsconfig.json +++ b/packages/electron-updater/tsconfig.json @@ -4,13 +4,6 @@ "outDir": "out", "rootDir": "src" }, - "jsdoc": { - "out": "../../scripts/jsdoc/out/updater", - "examples": "../../scripts/jsdoc/examples", - "access": "public" - }, - "files": [ - ], "include": [ "src/**/*.ts" ] diff --git a/packages/tsconfig-build.json b/packages/tsconfig-build.json new file mode 100644 index 00000000000..6b169cb99a3 --- /dev/null +++ b/packages/tsconfig-build.json @@ -0,0 +1,11 @@ +{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "module": "ESNext", + "moduleResolution": "bundler", + "declaration": true, + "declarationMap": true, + "composite": false, + "incremental": false + } +} diff --git a/packages/tsconfig-tsup.json b/packages/tsconfig-tsup.json new file mode 100644 index 00000000000..7230c3f045f --- /dev/null +++ b/packages/tsconfig-tsup.json @@ -0,0 +1,9 @@ +{ + "extends": "./tsconfig-base.json", + "compilerOptions": { + "composite": false, + "incremental": false, + "declaration": true + }, + "include": ["../typings/*.d.ts"] +} diff --git a/patches/estree-walker@3.0.3.patch b/patches/estree-walker@3.0.3.patch new file mode 100644 index 00000000000..527f36a5f82 --- /dev/null +++ b/patches/estree-walker@3.0.3.patch @@ -0,0 +1,14 @@ +diff --git a/package.json b/package.json +index c9f54edd9f394c267429a4b1393d67df42fbbe45..e35588d8883ef95741ae2c1daab72c1b654bb655 100644 +--- a/package.json ++++ b/package.json +@@ -15,7 +15,8 @@ + "./package.json": "./package.json", + ".": { + "types": "./types/index.d.ts", +- "import": "./src/index.js" ++ "import": "./src/index.js", ++ "require": "./src/index.js" + } + }, + "types": "types/index.d.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 261f3e2315e..f0f38811fdc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -11,6 +11,7 @@ overrides: patchedDependencies: '@changesets/assemble-release-plan@6.0.9': ef56f57067dfcc594f40d9afc7278abe38cecf1c04230936e447a60e0d58a46e '@changesets/cli@2.29.7': 4ef9ea77709c09dd51d013cff58b6b8d9004f0c22208e12942cbf4161351d590 + estree-walker@3.0.3: 591af4f8bfba56a5da5f4340b1501bbcb00ca5a5a63d1e1d55c4aacd9a165f75 importers: @@ -35,6 +36,9 @@ importers: '@stylistic/eslint-plugin': specifier: ^2.8.0 version: 2.13.0(eslint@9.39.2(jiti@2.4.2))(typescript@5.8.2) + '@tsconfig/node22': + specifier: ^22.0.5 + version: 22.0.5 '@types/node': specifier: ^22.7.4 version: 22.13.17 @@ -65,15 +69,18 @@ importers: eslint-plugin-prettier: specifier: ^5.2.1 version: 5.5.4(@types/eslint@9.6.1)(eslint-config-prettier@9.1.2(eslint@9.39.2(jiti@2.4.2)))(eslint@9.39.2(jiti@2.4.2))(prettier@3.7.4) + fs-extra: + specifier: ^10.1.0 + version: 10.1.0 is-ci: specifier: ^4.1.0 version: 4.1.0 prettier: specifier: 3.7.4 version: 3.7.4 - ts-node: - specifier: ^10.9.2 - version: 10.9.2(@swc/core@1.15.33)(@types/node@22.13.17)(typescript@5.8.2) + tsx: + specifier: ^4.0.0 + version: 4.22.3 typedoc: specifier: ^0.28.19 version: 0.28.19(typescript@5.8.2) @@ -85,7 +92,7 @@ importers: version: 0.64.0(@swc/core@1.15.33) vitest: specifier: ^3.2.2 - version: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) + version: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) packages/app-builder-lib: dependencies: @@ -159,8 +166,8 @@ importers: specifier: workspace:* version: link:../electron-publish fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.0 + version: 11.3.0 hosted-git-info: specifier: ^4.1.0 version: 4.1.0 @@ -310,6 +317,8 @@ importers: specifier: ^3.0.0 version: 3.0.0 + packages/app-builder-lib/helpers: {} + packages/builder-util: dependencies: 7zip-bin: @@ -334,8 +343,8 @@ importers: specifier: ^4.3.4 version: 4.4.3 fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.0 + version: 11.3.0 http-proxy-agent: specifier: ^7.0.0 version: 7.0.2 @@ -402,8 +411,8 @@ importers: specifier: workspace:* version: link:../builder-util fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.0 + version: 11.3.0 js-yaml: specifier: ^4.1.0 version: 4.1.1 @@ -439,8 +448,8 @@ importers: specifier: workspace:* version: link:../dmg-builder fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.0 + version: 11.3.0 lazy-val: specifier: ^1.0.5 version: 1.0.5 @@ -522,8 +531,8 @@ importers: specifier: ^4.0.5 version: 4.0.5 fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.0 + version: 11.3.0 lazy-val: specifier: ^1.0.5 version: 1.0.5 @@ -544,8 +553,8 @@ importers: specifier: workspace:* version: link:../builder-util-runtime fs-extra: - specifier: ^10.1.0 - version: 10.1.0 + specifier: ^11.3.4 + version: 11.3.5 js-yaml: specifier: ^4.1.0 version: 4.1.1 @@ -685,6 +694,9 @@ importers: lazy-val: specifier: ^1.0.5 version: 1.0.5 + minimatch: + specifier: ^10.2.5 + version: 10.2.5 path-sort: specifier: ^0.1.0 version: 0.1.0 @@ -708,7 +720,7 @@ importers: version: 0.12.3 vitest: specifier: ^3.2.4 - version: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) + version: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) vitest-mock-commonjs: specifier: ^1.0.2 version: 1.0.2 @@ -2846,150 +2858,306 @@ packages: cpu: [ppc64] os: [aix] + '@esbuild/aix-ppc64@0.28.0': + resolution: {integrity: sha512-lhRUCeuOyJQURhTxl4WkpFTjIsbDayJHih5kZC1giwE+MhIzAb7mEsQMqMf18rHLsrb5qI1tafG20mLxEWcWlA==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [aix] + '@esbuild/android-arm64@0.25.2': resolution: {integrity: sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w==} engines: {node: '>=18'} cpu: [arm64] os: [android] + '@esbuild/android-arm64@0.28.0': + resolution: {integrity: sha512-+WzIXQOSaGs33tLEgYPYe/yQHf0WTU0X42Jca3y8NWMbUVhp7rUnw+vAsRC/QiDrdD31IszMrZy+qwPOPjd+rw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [android] + '@esbuild/android-arm@0.25.2': resolution: {integrity: sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA==} engines: {node: '>=18'} cpu: [arm] os: [android] + '@esbuild/android-arm@0.28.0': + resolution: {integrity: sha512-wqh0ByljabXLKHeWXYLqoJ5jKC4XBaw6Hk08OfMrCRd2nP2ZQ5eleDZC41XHyCNgktBGYMbqnrJKq/K/lzPMSQ==} + engines: {node: '>=18'} + cpu: [arm] + os: [android] + '@esbuild/android-x64@0.25.2': resolution: {integrity: sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg==} engines: {node: '>=18'} cpu: [x64] os: [android] + '@esbuild/android-x64@0.28.0': + resolution: {integrity: sha512-+VJggoaKhk2VNNqVL7f6S189UzShHC/mR9EE8rDdSkdpN0KflSwWY/gWjDrNxxisg8Fp1ZCD9jLMo4m0OUfeUA==} + engines: {node: '>=18'} + cpu: [x64] + os: [android] + '@esbuild/darwin-arm64@0.25.2': resolution: {integrity: sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA==} engines: {node: '>=18'} cpu: [arm64] os: [darwin] + '@esbuild/darwin-arm64@0.28.0': + resolution: {integrity: sha512-0T+A9WZm+bZ84nZBtk1ckYsOvyA3x7e2Acj1KdVfV4/2tdG4fzUp91YHx+GArWLtwqp77pBXVCPn2We7Letr0Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [darwin] + '@esbuild/darwin-x64@0.25.2': resolution: {integrity: sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA==} engines: {node: '>=18'} cpu: [x64] os: [darwin] + '@esbuild/darwin-x64@0.28.0': + resolution: {integrity: sha512-fyzLm/DLDl/84OCfp2f/XQ4flmORsjU7VKt8HLjvIXChJoFFOIL6pLJPH4Yhd1n1gGFF9mPwtlN5Wf82DZs+LQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [darwin] + '@esbuild/freebsd-arm64@0.25.2': resolution: {integrity: sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w==} engines: {node: '>=18'} cpu: [arm64] os: [freebsd] + '@esbuild/freebsd-arm64@0.28.0': + resolution: {integrity: sha512-l9GeW5UZBT9k9brBYI+0WDffcRxgHQD8ShN2Ur4xWq/NFzUKm3k5lsH4PdaRgb2w7mI9u61nr2gI2mLI27Nh3Q==} + engines: {node: '>=18'} + cpu: [arm64] + os: [freebsd] + '@esbuild/freebsd-x64@0.25.2': resolution: {integrity: sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ==} engines: {node: '>=18'} cpu: [x64] os: [freebsd] + '@esbuild/freebsd-x64@0.28.0': + resolution: {integrity: sha512-BXoQai/A0wPO6Es3yFJ7APCiKGc1tdAEOgeTNy3SsB491S3aHn4S4r3e976eUnPdU+NbdtmBuLncYir2tMU9Nw==} + engines: {node: '>=18'} + cpu: [x64] + os: [freebsd] + '@esbuild/linux-arm64@0.25.2': resolution: {integrity: sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g==} engines: {node: '>=18'} cpu: [arm64] os: [linux] + '@esbuild/linux-arm64@0.28.0': + resolution: {integrity: sha512-RVyzfb3FWsGA55n6WY0MEIEPURL1FcbhFE6BffZEMEekfCzCIMtB5yyDcFnVbTnwk+CLAgTujmV/Lgvih56W+A==} + engines: {node: '>=18'} + cpu: [arm64] + os: [linux] + '@esbuild/linux-arm@0.25.2': resolution: {integrity: sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g==} engines: {node: '>=18'} cpu: [arm] os: [linux] + '@esbuild/linux-arm@0.28.0': + resolution: {integrity: sha512-CjaaREJagqJp7iTaNQjjidaNbCKYcd4IDkzbwwxtSvjI7NZm79qiHc8HqciMddQ6CKvJT6aBd8lO9kN/ZudLlw==} + engines: {node: '>=18'} + cpu: [arm] + os: [linux] + '@esbuild/linux-ia32@0.25.2': resolution: {integrity: sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ==} engines: {node: '>=18'} cpu: [ia32] os: [linux] + '@esbuild/linux-ia32@0.28.0': + resolution: {integrity: sha512-KBnSTt1kxl9x70q+ydterVdl+Cn0H18ngRMRCEQfrbqdUuntQQ0LoMZv47uB97NljZFzY6HcfqEZ2SAyIUTQBQ==} + engines: {node: '>=18'} + cpu: [ia32] + os: [linux] + '@esbuild/linux-loong64@0.25.2': resolution: {integrity: sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w==} engines: {node: '>=18'} cpu: [loong64] os: [linux] + '@esbuild/linux-loong64@0.28.0': + resolution: {integrity: sha512-zpSlUce1mnxzgBADvxKXX5sl8aYQHo2ezvMNI8I0lbblJtp8V4odlm3Yzlj7gPyt3T8ReksE6bK+pT3WD+aJRg==} + engines: {node: '>=18'} + cpu: [loong64] + os: [linux] + '@esbuild/linux-mips64el@0.25.2': resolution: {integrity: sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q==} engines: {node: '>=18'} cpu: [mips64el] os: [linux] + '@esbuild/linux-mips64el@0.28.0': + resolution: {integrity: sha512-2jIfP6mmjkdmeTlsX/9vmdmhBmKADrWqN7zcdtHIeNSCH1SqIoNI63cYsjQR8J+wGa4Y5izRcSHSm8K3QWmk3w==} + engines: {node: '>=18'} + cpu: [mips64el] + os: [linux] + '@esbuild/linux-ppc64@0.25.2': resolution: {integrity: sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g==} engines: {node: '>=18'} cpu: [ppc64] os: [linux] + '@esbuild/linux-ppc64@0.28.0': + resolution: {integrity: sha512-bc0FE9wWeC0WBm49IQMPSPILRocGTQt3j5KPCA8os6VprfuJ7KD+5PzESSrJ6GmPIPJK965ZJHTUlSA6GNYEhg==} + engines: {node: '>=18'} + cpu: [ppc64] + os: [linux] + '@esbuild/linux-riscv64@0.25.2': resolution: {integrity: sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw==} engines: {node: '>=18'} cpu: [riscv64] os: [linux] + '@esbuild/linux-riscv64@0.28.0': + resolution: {integrity: sha512-SQPZOwoTTT/HXFXQJG/vBX8sOFagGqvZyXcgLA3NhIqcBv1BJU1d46c0rGcrij2B56Z2rNiSLaZOYW5cUk7yLQ==} + engines: {node: '>=18'} + cpu: [riscv64] + os: [linux] + '@esbuild/linux-s390x@0.25.2': resolution: {integrity: sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q==} engines: {node: '>=18'} cpu: [s390x] os: [linux] + '@esbuild/linux-s390x@0.28.0': + resolution: {integrity: sha512-SCfR0HN8CEEjnYnySJTd2cw0k9OHB/YFzt5zgJEwa+wL/T/raGWYMBqwDNAC6dqFKmJYZoQBRfHjgwLHGSrn3Q==} + engines: {node: '>=18'} + cpu: [s390x] + os: [linux] + '@esbuild/linux-x64@0.25.2': resolution: {integrity: sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg==} engines: {node: '>=18'} cpu: [x64] os: [linux] + '@esbuild/linux-x64@0.28.0': + resolution: {integrity: sha512-us0dSb9iFxIi8srnpl931Nvs65it/Jd2a2K3qs7fz2WfGPHqzfzZTfec7oxZJRNPXPnNYZtanmRc4AL/JwVzHQ==} + engines: {node: '>=18'} + cpu: [x64] + os: [linux] + '@esbuild/netbsd-arm64@0.25.2': resolution: {integrity: sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw==} engines: {node: '>=18'} cpu: [arm64] os: [netbsd] + '@esbuild/netbsd-arm64@0.28.0': + resolution: {integrity: sha512-CR/RYotgtCKwtftMwJlUU7xCVNg3lMYZ0RzTmAHSfLCXw3NtZtNpswLEj/Kkf6kEL3Gw+BpOekRX0BYCtklhUw==} + engines: {node: '>=18'} + cpu: [arm64] + os: [netbsd] + '@esbuild/netbsd-x64@0.25.2': resolution: {integrity: sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg==} engines: {node: '>=18'} cpu: [x64] os: [netbsd] + '@esbuild/netbsd-x64@0.28.0': + resolution: {integrity: sha512-nU1yhmYutL+fQ71Kxnhg8uEOdC0pwEW9entHykTgEbna2pw2dkbFSMeqjjyHZoCmt8SBkOSvV+yNmm94aUrrqw==} + engines: {node: '>=18'} + cpu: [x64] + os: [netbsd] + '@esbuild/openbsd-arm64@0.25.2': resolution: {integrity: sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg==} engines: {node: '>=18'} cpu: [arm64] os: [openbsd] + '@esbuild/openbsd-arm64@0.28.0': + resolution: {integrity: sha512-cXb5vApOsRsxsEl4mcZ1XY3D4DzcoMxR/nnc4IyqYs0rTI8ZKmW6kyyg+11Z8yvgMfAEldKzP7AdP64HnSC/6g==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openbsd] + '@esbuild/openbsd-x64@0.25.2': resolution: {integrity: sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw==} engines: {node: '>=18'} cpu: [x64] os: [openbsd] + '@esbuild/openbsd-x64@0.28.0': + resolution: {integrity: sha512-8wZM2qqtv9UP3mzy7HiGYNH/zjTA355mpeuA+859TyR+e+Tc08IHYpLJuMsfpDJwoLo1ikIJI8jC3GFjnRClzA==} + engines: {node: '>=18'} + cpu: [x64] + os: [openbsd] + + '@esbuild/openharmony-arm64@0.28.0': + resolution: {integrity: sha512-FLGfyizszcef5C3YtoyQDACyg95+dndv79i2EekILBofh5wpCa1KuBqOWKrEHZg3zrL3t5ouE5jgr94vA+Wb2w==} + engines: {node: '>=18'} + cpu: [arm64] + os: [openharmony] + '@esbuild/sunos-x64@0.25.2': resolution: {integrity: sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA==} engines: {node: '>=18'} cpu: [x64] os: [sunos] + '@esbuild/sunos-x64@0.28.0': + resolution: {integrity: sha512-1ZgjUoEdHZZl/YlV76TSCz9Hqj9h9YmMGAgAPYd+q4SicWNX3G5GCyx9uhQWSLcbvPW8Ni7lj4gDa1T40akdlw==} + engines: {node: '>=18'} + cpu: [x64] + os: [sunos] + '@esbuild/win32-arm64@0.25.2': resolution: {integrity: sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q==} engines: {node: '>=18'} cpu: [arm64] os: [win32] + '@esbuild/win32-arm64@0.28.0': + resolution: {integrity: sha512-Q9StnDmQ/enxnpxCCLSg0oo4+34B9TdXpuyPeTedN/6+iXBJ4J+zwfQI28u/Jl40nOYAxGoNi7mFP40RUtkmUA==} + engines: {node: '>=18'} + cpu: [arm64] + os: [win32] + '@esbuild/win32-ia32@0.25.2': resolution: {integrity: sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg==} engines: {node: '>=18'} cpu: [ia32] os: [win32] + '@esbuild/win32-ia32@0.28.0': + resolution: {integrity: sha512-zF3ag/gfiCe6U2iczcRzSYJKH1DCI+ByzSENHlM2FcDbEeo5Zd2C86Aq0tKUYAJJ1obRP84ymxIAksZUcdztHA==} + engines: {node: '>=18'} + cpu: [ia32] + os: [win32] + '@esbuild/win32-x64@0.25.2': resolution: {integrity: sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA==} engines: {node: '>=18'} cpu: [x64] os: [win32] + '@esbuild/win32-x64@0.28.0': + resolution: {integrity: sha512-pEl1bO9mfAmIC+tW5btTmrKaujg3zGtUmWNdCw/xs70FBjwAL3o9OEKNHvNmnyylD6ubxUERiEhdsL0xBQ9efw==} + engines: {node: '>=18'} + cpu: [x64] + os: [win32] + '@eslint-community/eslint-utils@4.9.0': resolution: {integrity: sha512-ayVFHdtZ+hsq1t2Dy24wCmGXGe4q9Gu3smhLYALJrr473ZH27MsnSL+LKUlimp4BWJqMDMLmPpx/Q9R3OAlL4g==} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} @@ -4046,6 +4214,9 @@ packages: '@tsconfig/node16@1.0.4': resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + '@tsconfig/node22@22.0.5': + resolution: {integrity: sha512-hLf2ld+sYN/BtOJjHUWOk568dvjFQkHnLNa6zce25GIH+vxKfvTgm3qpaH6ToF5tu/NN0IH66s+Bb5wElHrLcw==} + '@tybys/wasm-util@0.10.2': resolution: {integrity: sha512-RoBvJ2X0wuKlWFIjrwffGw1IqZHKQqzIchKaadZZfnNpsAYp2mM0h36JtPCjNDAHGgYez/15uMBpfGwchhiMgg==} @@ -6012,6 +6183,11 @@ packages: engines: {node: '>=18'} hasBin: true + esbuild@0.28.0: + resolution: {integrity: sha512-sNR9MHpXSUV/XB4zmsFKN+QgVG82Cc7+/aaxJ8Adi8hyOac+EXptIp45QBPaVyX3N70664wRbTcLTOemCAnyqw==} + engines: {node: '>=18'} + hasBin: true + escalade@3.2.0: resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} @@ -6352,6 +6528,10 @@ packages: resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==} engines: {node: '>=14.14'} + fs-extra@11.3.5: + resolution: {integrity: sha512-eKpRKAovdpZtR1WopLHxlBWvAgPny3c4gX1G5Jhwmmw4XJj0ifSD5qB5TOo8hmA0wlRKDAOAhEE1yVPgs6Fgcg==} + engines: {node: '>=14.14'} + fs-extra@7.0.1: resolution: {integrity: sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==} engines: {node: '>=6 <7 || >=8'} @@ -9497,6 +9677,11 @@ packages: tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} + tsx@4.22.3: + resolution: {integrity: sha512-mdoNxBC/cSQObGGVQ5Bpn5i+yv7j68gk3Nfm3wFjcJg3Z0Mix9jzAFfP12prmm5eVGmDKtp0yyArrs0Q+8gZHg==} + engines: {node: '>=18.0.0'} + hasBin: true + tsyringe@4.10.0: resolution: {integrity: sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==} engines: {node: '>= 6.0.0'} @@ -13818,78 +14003,156 @@ snapshots: '@esbuild/aix-ppc64@0.25.2': optional: true + '@esbuild/aix-ppc64@0.28.0': + optional: true + '@esbuild/android-arm64@0.25.2': optional: true + '@esbuild/android-arm64@0.28.0': + optional: true + '@esbuild/android-arm@0.25.2': optional: true + '@esbuild/android-arm@0.28.0': + optional: true + '@esbuild/android-x64@0.25.2': optional: true + '@esbuild/android-x64@0.28.0': + optional: true + '@esbuild/darwin-arm64@0.25.2': optional: true + '@esbuild/darwin-arm64@0.28.0': + optional: true + '@esbuild/darwin-x64@0.25.2': optional: true + '@esbuild/darwin-x64@0.28.0': + optional: true + '@esbuild/freebsd-arm64@0.25.2': optional: true + '@esbuild/freebsd-arm64@0.28.0': + optional: true + '@esbuild/freebsd-x64@0.25.2': optional: true + '@esbuild/freebsd-x64@0.28.0': + optional: true + '@esbuild/linux-arm64@0.25.2': optional: true + '@esbuild/linux-arm64@0.28.0': + optional: true + '@esbuild/linux-arm@0.25.2': optional: true + '@esbuild/linux-arm@0.28.0': + optional: true + '@esbuild/linux-ia32@0.25.2': optional: true + '@esbuild/linux-ia32@0.28.0': + optional: true + '@esbuild/linux-loong64@0.25.2': optional: true + '@esbuild/linux-loong64@0.28.0': + optional: true + '@esbuild/linux-mips64el@0.25.2': optional: true + '@esbuild/linux-mips64el@0.28.0': + optional: true + '@esbuild/linux-ppc64@0.25.2': optional: true + '@esbuild/linux-ppc64@0.28.0': + optional: true + '@esbuild/linux-riscv64@0.25.2': optional: true + '@esbuild/linux-riscv64@0.28.0': + optional: true + '@esbuild/linux-s390x@0.25.2': optional: true + '@esbuild/linux-s390x@0.28.0': + optional: true + '@esbuild/linux-x64@0.25.2': optional: true + '@esbuild/linux-x64@0.28.0': + optional: true + '@esbuild/netbsd-arm64@0.25.2': optional: true + '@esbuild/netbsd-arm64@0.28.0': + optional: true + '@esbuild/netbsd-x64@0.25.2': optional: true + '@esbuild/netbsd-x64@0.28.0': + optional: true + '@esbuild/openbsd-arm64@0.25.2': optional: true + '@esbuild/openbsd-arm64@0.28.0': + optional: true + '@esbuild/openbsd-x64@0.25.2': optional: true + '@esbuild/openbsd-x64@0.28.0': + optional: true + + '@esbuild/openharmony-arm64@0.28.0': + optional: true + '@esbuild/sunos-x64@0.25.2': optional: true + '@esbuild/sunos-x64@0.28.0': + optional: true + '@esbuild/win32-arm64@0.25.2': optional: true + '@esbuild/win32-arm64@0.28.0': + optional: true + '@esbuild/win32-ia32@0.25.2': optional: true + '@esbuild/win32-ia32@0.28.0': + optional: true + '@esbuild/win32-x64@0.25.2': optional: true + '@esbuild/win32-x64@0.28.0': + optional: true + '@eslint-community/eslint-utils@4.9.0(eslint@9.39.2(jiti@2.4.2))': dependencies: eslint: 9.39.2(jiti@2.4.2) @@ -14270,7 +14533,7 @@ snapshots: devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 estree-util-scope: 1.0.0 - estree-walker: 3.0.3 + estree-walker: 3.0.3(patch_hash=591af4f8bfba56a5da5f4340b1501bbcb00ca5a5a63d1e1d55c4aacd9a165f75) hast-util-to-jsx-runtime: 2.3.6 markdown-extensions: 2.0.0 recma-build-jsx: 1.0.0 @@ -14975,6 +15238,8 @@ snapshots: '@tsconfig/node16@1.0.4': {} + '@tsconfig/node22@22.0.5': {} + '@tybys/wasm-util@0.10.2': dependencies: tslib: 2.8.1 @@ -15538,13 +15803,13 @@ snapshots: chai: 5.2.0 tinyrainbow: 2.0.0 - '@vitest/mocker@3.2.4(vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4))': + '@vitest/mocker@3.2.4(vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4))': dependencies: '@vitest/spy': 3.2.4 - estree-walker: 3.0.3 + estree-walker: 3.0.3(patch_hash=591af4f8bfba56a5da5f4340b1501bbcb00ca5a5a63d1e1d55c4aacd9a165f75) magic-string: 0.30.17 optionalDependencies: - vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) + vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) '@vitest/pretty-format@3.2.4': dependencies: @@ -17264,6 +17529,35 @@ snapshots: '@esbuild/win32-ia32': 0.25.2 '@esbuild/win32-x64': 0.25.2 + esbuild@0.28.0: + optionalDependencies: + '@esbuild/aix-ppc64': 0.28.0 + '@esbuild/android-arm': 0.28.0 + '@esbuild/android-arm64': 0.28.0 + '@esbuild/android-x64': 0.28.0 + '@esbuild/darwin-arm64': 0.28.0 + '@esbuild/darwin-x64': 0.28.0 + '@esbuild/freebsd-arm64': 0.28.0 + '@esbuild/freebsd-x64': 0.28.0 + '@esbuild/linux-arm': 0.28.0 + '@esbuild/linux-arm64': 0.28.0 + '@esbuild/linux-ia32': 0.28.0 + '@esbuild/linux-loong64': 0.28.0 + '@esbuild/linux-mips64el': 0.28.0 + '@esbuild/linux-ppc64': 0.28.0 + '@esbuild/linux-riscv64': 0.28.0 + '@esbuild/linux-s390x': 0.28.0 + '@esbuild/linux-x64': 0.28.0 + '@esbuild/netbsd-arm64': 0.28.0 + '@esbuild/netbsd-x64': 0.28.0 + '@esbuild/openbsd-arm64': 0.28.0 + '@esbuild/openbsd-x64': 0.28.0 + '@esbuild/openharmony-arm64': 0.28.0 + '@esbuild/sunos-x64': 0.28.0 + '@esbuild/win32-arm64': 0.28.0 + '@esbuild/win32-ia32': 0.28.0 + '@esbuild/win32-x64': 0.28.0 + escalade@3.2.0: {} escape-goat@4.0.0: {} @@ -17374,7 +17668,7 @@ snapshots: '@types/estree-jsx': 1.0.5 devlop: 1.1.0 estree-util-is-identifier-name: 3.0.0 - estree-walker: 3.0.3 + estree-walker: 3.0.3(patch_hash=591af4f8bfba56a5da5f4340b1501bbcb00ca5a5a63d1e1d55c4aacd9a165f75) estree-util-is-identifier-name@3.0.0: {} @@ -17400,7 +17694,7 @@ snapshots: estree-walker@2.0.2: {} - estree-walker@3.0.3: + estree-walker@3.0.3(patch_hash=591af4f8bfba56a5da5f4340b1501bbcb00ca5a5a63d1e1d55c4aacd9a165f75): dependencies: '@types/estree': 1.0.8 @@ -17672,6 +17966,12 @@ snapshots: jsonfile: 6.1.0 universalify: 2.0.1 + fs-extra@11.3.5: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + fs-extra@7.0.1: dependencies: graceful-fs: 4.2.11 @@ -21387,30 +21687,16 @@ snapshots: optionalDependencies: '@swc/core': 1.15.33 - ts-node@10.9.2(@swc/core@1.15.33)(@types/node@22.13.17)(typescript@5.8.2): - dependencies: - '@cspotcode/source-map-support': 0.8.1 - '@tsconfig/node10': 1.0.11 - '@tsconfig/node12': 1.0.11 - '@tsconfig/node14': 1.0.3 - '@tsconfig/node16': 1.0.4 - '@types/node': 22.13.17 - acorn: 8.15.0 - acorn-walk: 8.3.4 - arg: 4.1.3 - create-require: 1.1.1 - diff: 4.0.2 - make-error: 1.3.6 - typescript: 5.8.2 - v8-compile-cache-lib: 3.0.1 - yn: 3.1.1 - optionalDependencies: - '@swc/core': 1.15.33 - tslib@1.14.1: {} tslib@2.8.1: {} + tsx@4.22.3: + dependencies: + esbuild: 0.28.0 + optionalDependencies: + fsevents: 2.3.3 + tsyringe@4.10.0: dependencies: tslib: 1.14.1 @@ -21644,13 +21930,13 @@ snapshots: '@types/unist': 3.0.3 vfile-message: 4.0.2 - vite-node@3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4): + vite-node@3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4): dependencies: cac: 6.7.14 debug: 4.4.3 es-module-lexer: 1.7.0 pathe: 2.0.3 - vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) + vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) transitivePeerDependencies: - '@types/node' - jiti @@ -21665,7 +21951,7 @@ snapshots: - tsx - yaml - vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4): + vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4): dependencies: esbuild: 0.25.2 postcss: 8.5.3 @@ -21677,15 +21963,16 @@ snapshots: lightningcss: 1.32.0 sass: 1.86.1 terser: 5.47.1 + tsx: 4.22.3 yaml: 2.8.4 vitest-mock-commonjs@1.0.2: {} - vitest@3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4): + vitest@3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4): dependencies: '@types/chai': 5.2.2 '@vitest/expect': 3.2.4 - '@vitest/mocker': 3.2.4(vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4)) + '@vitest/mocker': 3.2.4(vite@6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4)) '@vitest/pretty-format': 3.2.4 '@vitest/runner': 3.2.4 '@vitest/snapshot': 3.2.4 @@ -21703,8 +21990,8 @@ snapshots: tinyglobby: 0.2.14 tinypool: 1.1.1 tinyrainbow: 2.0.0 - vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) - vite-node: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(yaml@2.8.4) + vite: 6.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) + vite-node: 3.2.4(@types/node@22.13.17)(jiti@2.4.2)(lightningcss@1.32.0)(sass@1.86.1)(terser@5.47.1)(tsx@4.22.3)(yaml@2.8.4) why-is-node-running: 2.3.0 optionalDependencies: '@types/node': 22.13.17 diff --git a/pnpm-workspace.yaml b/pnpm-workspace.yaml index b9740632a89..9a50ff4a226 100644 --- a/pnpm-workspace.yaml +++ b/pnpm-workspace.yaml @@ -16,6 +16,7 @@ minimumReleaseAge: 10080 patchedDependencies: '@changesets/cli@2.29.7': patches/@changesets__cli@2.29.7.patch '@changesets/assemble-release-plan@6.0.9': patches/@changesets__assemble-release-plan@6.0.9.patch + estree-walker@3.0.3: patches/estree-walker@3.0.3.patch overrides: flatted: '>=3.4.2' handlebars: '>=4.7.9' diff --git a/scripts/checkDeps.js b/scripts/checkDeps.js index 1d90577944d..423e56565a2 100644 --- a/scripts/checkDeps.js +++ b/scripts/checkDeps.js @@ -15,6 +15,11 @@ const knownUnusedDevDependencies = new Set([ "eslint-config-prettier", "eslint-plugin-prettier", "@rollup/plugin-typescript", + // Used in test/vitest-scripts/ (test dir is ignored by depcheck) or via pnpm workspace scripts + "is-ci", + "tsup", + "vitest", + "tsx", ]) const knownMissedDependencies = new Set(["babel-core", "babel-preset-env", "babel-preset-stage-0", "babel-preset-react"]) @@ -26,7 +31,7 @@ async function check(projectDir, devPackageData) { // console.log(`Checking ${projectDir}`) const result = await new Promise(resolve => { - depCheck(projectDir, { ignoreDirs: ["out", "test", "pages", "typings", "docker", "certs", "templates", "vendor"] }, resolve) + depCheck(projectDir, { ignoreDirs: ["out", "dist", "test", "pages", "typings", "docker", "certs", "templates", "vendor"] }, resolve) }) let unusedDependencies = result.dependencies @@ -34,6 +39,10 @@ async function check(projectDir, devPackageData) { if (packageName === "electron-builder") { unusedDependencies = unusedDependencies.filter(it => it !== "dmg-builder") } + if (packageName === "app-builder-lib") { + // @electron/universal is used via dynamic string import which depcheck cannot detect statically + unusedDependencies = unusedDependencies.filter(it => it !== "@electron/universal") + } if (unusedDependencies.length > 0) { console.error(`${chalk.bold(packageName)} Unused dependencies: ${JSON.stringify(unusedDependencies, null, 2)}`) return false @@ -50,6 +59,8 @@ async function check(projectDir, devPackageData) { } delete result.missing.electron + // tsup is a root devDependency accessed via pnpm hoisting; each package uses it in tsup.config.ts + delete result.missing.tsup const toml = result.missing.toml if (toml != null && toml.length === 1 && toml[0].endsWith("config.js")) { delete result.missing.toml diff --git a/scripts/generate-schema.ts b/scripts/generate-schema.ts index e19a289ea7d..9fa97720530 100644 --- a/scripts/generate-schema.ts +++ b/scripts/generate-schema.ts @@ -12,12 +12,13 @@ const compilerOptions: TJS.CompilerOptions = { baseUrl: rootDir, esModuleInterop: false, forceConsistentCasingInFileNames: true, - moduleResolution: TypeScript.ModuleResolutionKind.Node10, + moduleResolution: TypeScript.ModuleResolutionKind.Node10 as any, skipLibCheck: true, - strict: true, - noUnusedLocals: true, + // strict: true, + // noUnusedLocals: true, noFallthroughCasesInSwitch: true, - noImplicitReturns: true, + // noImplicitReturns: true, + noEmit: true, inlineSources: true, sourceMap: true, @@ -33,18 +34,22 @@ const compilerOptions: TJS.CompilerOptions = { "../typings", "../../typings", // - "../node_module/@types", - "node_module/@types" - ], + "../node_modules/@types", + "app-builder-lib/typings", + "node_modules/@types" + ].map(it => path.resolve(rootDir, it)), } // schema generator args const settings: TJS.PartialArgs = { required: true, + // ref: false, + // aliasRef: true, noExtraProps: true, typeOfKeyword: true, strictNullChecks: true, skipLibCheck: true, + ignoreErrors: true, } const definitionFile = path.resolve(rootDir, "app-builder-lib/src/configuration.ts") @@ -53,7 +58,7 @@ const generator = TJS.buildGenerator(program, settings) const schema = TJS.generateSchema(program, "Configuration", settings, [], generator!) const PlugDescriptor: any = schema!.definitions!.PlugDescriptor -PlugDescriptor.additionalProperties!.anyOf![0] = { +PlugDescriptor.additionalProperties = { type: "object", } @@ -73,7 +78,7 @@ OutgoingHttpHeaders.additionalProperties = { } const SnapOptions: any = schema!.definitions!.SnapOptions -SnapOptions.properties.environment!.anyOf![0] = { +SnapOptions.properties.environment = { additionalProperties: { type: "string" }, type: "object", } diff --git a/scripts/renderer/src/typedoc2html.ts b/scripts/renderer/src/typedoc2html.ts new file mode 100644 index 00000000000..31e405f6e67 --- /dev/null +++ b/scripts/renderer/src/typedoc2html.ts @@ -0,0 +1,42 @@ +import fsExtra from "fs-extra" +import { rm } from "fs/promises" +import * as path from "path" +import * as process from "process" +import * as typedoc from "typedoc" + +async function main() { + const outputDir = "docs" + const dest = path.resolve(process.cwd(), outputDir) + + const origin = path.resolve(process.cwd(), "pages") + console.log("copying from", origin, dest) + const siteDir = path.resolve(process.cwd(), "site") + + if (await fsExtra.exists(siteDir)) { + await rm(siteDir, { recursive: true }) + } + if (await fsExtra.exists(dest)) { + await rm(dest, { recursive: true }) + } + await fsExtra.copy(origin, dest) + await fsExtra.copy(path.resolve(process.cwd(), "./README.md"), path.resolve(dest, "README.md")) + + const typedocConfig: Partial = { + options: "typedoc.config.js", + } + + const config = { + ...typedocConfig, + flattenOutputFiles: true, + } + const app = await typedoc.Application.bootstrapWithPlugins(config) + + const project = await app.convert() + + await app.generateDocs(project!, outputDir) +} + +main().catch(e => { + console.error(e) + process.exit(1) +}) diff --git a/scripts/tsconfig.json b/scripts/tsconfig.json index 6f4fe18f1c3..a3a0b41bd67 100644 --- a/scripts/tsconfig.json +++ b/scripts/tsconfig.json @@ -3,9 +3,9 @@ "compilerOptions": { "outDir": "out", "noUnusedLocals": false, - "skipLibCheck": true + "skipLibCheck": true, + "declaration": false }, - "declaration": false, "include": [ "**/*.ts", ], diff --git a/test/fixtures/test-app-yarn-several-workspace/pnpm-lock.yaml b/test/fixtures/test-app-yarn-several-workspace/pnpm-lock.yaml index e69de29bb2d..0e461196e44 100644 --- a/test/fixtures/test-app-yarn-several-workspace/pnpm-lock.yaml +++ b/test/fixtures/test-app-yarn-several-workspace/pnpm-lock.yaml @@ -0,0 +1,583 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: {} + + packages/foo: + dependencies: + ms: + specifier: 2.0.0 + version: 2.0.0 + + packages/test-app: + dependencies: + debug: + specifier: 4.4.3 + version: 4.4.3 + devDependencies: + electron: + specifier: 39.8.5 + version: 39.8.5 + +packages: + + '@electron/get@2.0.3': + resolution: {integrity: sha512-Qkzpg2s9GnVV2I2BjRksUi43U5e6+zaQMcjoJy0C+C5oxaKl+fmckGDQFtRpZpZV0NQekuZZ+tGz7EA9TVnQtQ==} + engines: {node: '>=12'} + + '@sindresorhus/is@4.6.0': + resolution: {integrity: sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==} + engines: {node: '>=10'} + + '@szmarczak/http-timer@4.0.6': + resolution: {integrity: sha512-4BAffykYOgO+5nzBWYwE3W90sBgLJoUPRWWcL8wlyiM8IB8ipJz3UMJ9KXQd1RKQXpKp8Tutn80HZtWsu2u76w==} + engines: {node: '>=10'} + + '@types/cacheable-request@6.0.3': + resolution: {integrity: sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==} + + '@types/http-cache-semantics@4.2.0': + resolution: {integrity: sha512-L3LgimLHXtGkWikKnsPg0/VFx9OGZaC+eN1u4r+OB1XRqH3meBIAVC2zr1WdMH+RHmnRkqliQAOHNJ/E0j/e0Q==} + + '@types/keyv@3.1.4': + resolution: {integrity: sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==} + + '@types/node@22.19.19': + resolution: {integrity: sha512-dyh/xO2Fh5bYrfWaaqGrRQQGkNdmYw6AmaAUvYeUMNTWQtvb796ikLdmTchRmOlOiIJ1TDXfWgVx1QkUlQ6Hew==} + + '@types/responselike@1.0.3': + resolution: {integrity: sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==} + + '@types/yauzl@2.10.3': + resolution: {integrity: sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==} + + boolean@3.2.0: + resolution: {integrity: sha512-d0II/GO9uf9lfUHH2BQsjxzRJZBdsjgsBiW4BvhWk/3qoKwQFjIDVN19PfX8F2D/r9PCMTtLWjYVCFrpeYUzsw==} + deprecated: Package no longer supported. Contact Support at https://www.npmjs.com/support for more info. + + buffer-crc32@0.2.13: + resolution: {integrity: sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==} + + cacheable-lookup@5.0.4: + resolution: {integrity: sha512-2/kNscPhpcxrOigMZzbiWF7dz8ilhb/nIHU3EyZiXWXpeq/au8qJ8VhdftMkty3n7Gj6HIGalQG8oiBNB3AJgA==} + engines: {node: '>=10.6.0'} + + cacheable-request@7.0.4: + resolution: {integrity: sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==} + engines: {node: '>=8'} + + clone-response@1.0.3: + resolution: {integrity: sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==} + + debug@4.4.3: + resolution: {integrity: sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + + decompress-response@6.0.0: + resolution: {integrity: sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==} + engines: {node: '>=10'} + + defer-to-connect@2.0.1: + resolution: {integrity: sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==} + engines: {node: '>=10'} + + define-data-property@1.1.4: + resolution: {integrity: sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==} + engines: {node: '>= 0.4'} + + define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + + detect-node@2.1.0: + resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} + + electron@39.8.5: + resolution: {integrity: sha512-q6+LiQIcTadSyvtPgLDQkCtVA9jQJXQVMrQcctfOJILh6OFMN+UJJLRkuUTy8CZDYeCIBn1ZycqsL1dAXugxZA==} + engines: {node: '>= 12.20.55'} + hasBin: true + + end-of-stream@1.4.5: + resolution: {integrity: sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==} + + env-paths@2.2.1: + resolution: {integrity: sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==} + engines: {node: '>=6'} + + es-define-property@1.0.1: + resolution: {integrity: sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==} + engines: {node: '>= 0.4'} + + es-errors@1.3.0: + resolution: {integrity: sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==} + engines: {node: '>= 0.4'} + + es6-error@4.1.1: + resolution: {integrity: sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg==} + + escape-string-regexp@4.0.0: + resolution: {integrity: sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==} + engines: {node: '>=10'} + + extract-zip@2.0.1: + resolution: {integrity: sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==} + engines: {node: '>= 10.17.0'} + hasBin: true + + fd-slicer@1.1.0: + resolution: {integrity: sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==} + + fs-extra@8.1.0: + resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==} + engines: {node: '>=6 <7 || >=8'} + + get-stream@5.2.0: + resolution: {integrity: sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==} + engines: {node: '>=8'} + + global-agent@3.0.0: + resolution: {integrity: sha512-PT6XReJ+D07JvGoxQMkT6qji/jVNfX/h364XHZOWeRzy64sSFr+xJ5OX7LI3b4MPQzdL4H8Y8M0xzPpsVMwA8Q==} + engines: {node: '>=10.0'} + + globalthis@1.0.4: + resolution: {integrity: sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==} + engines: {node: '>= 0.4'} + + gopd@1.2.0: + resolution: {integrity: sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==} + engines: {node: '>= 0.4'} + + got@11.8.6: + resolution: {integrity: sha512-6tfZ91bOr7bOXnK7PRDCGBLa1H4U080YHNaAQ2KsMGlLEzRbk44nsZF2E1IeRc3vtJHPVbKCYgdFbaGO2ljd8g==} + engines: {node: '>=10.19.0'} + + graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + + has-property-descriptors@1.0.2: + resolution: {integrity: sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==} + + http-cache-semantics@4.2.0: + resolution: {integrity: sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==} + + http2-wrapper@1.0.3: + resolution: {integrity: sha512-V+23sDMr12Wnz7iTcDeJr3O6AIxlnvT/bmaAAAP/Xda35C90p9599p0F1eHR/N1KILWSoWVAiOMFjBBXaXSMxg==} + engines: {node: '>=10.19.0'} + + json-buffer@3.0.1: + resolution: {integrity: sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==} + + json-stringify-safe@5.0.1: + resolution: {integrity: sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==} + + jsonfile@4.0.0: + resolution: {integrity: sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==} + + keyv@4.5.4: + resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + + lowercase-keys@2.0.0: + resolution: {integrity: sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==} + engines: {node: '>=8'} + + matcher@3.0.0: + resolution: {integrity: sha512-OkeDaAZ/bQCxeFAozM55PKcKU0yJMPGifLwV4Qgjitu+5MoAfSQN4lsLJeXZ1b8w0x+/Emda6MZgXS1jvsapng==} + engines: {node: '>=10'} + + mimic-response@1.0.1: + resolution: {integrity: sha512-j5EctnkH7amfV/q5Hgmoal1g2QHFJRraOtmx0JpIqkxhBhI/lJSl1nMpQ45hVarwNETOoWEimndZ4QK0RHxuxQ==} + engines: {node: '>=4'} + + mimic-response@3.1.0: + resolution: {integrity: sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==} + engines: {node: '>=10'} + + ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + + ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + + normalize-url@6.1.0: + resolution: {integrity: sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==} + engines: {node: '>=10'} + + object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + + once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + + p-cancelable@2.1.1: + resolution: {integrity: sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==} + engines: {node: '>=8'} + + pend@1.2.0: + resolution: {integrity: sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==} + + progress@2.0.3: + resolution: {integrity: sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==} + engines: {node: '>=0.4.0'} + + pump@3.0.4: + resolution: {integrity: sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==} + + quick-lru@5.1.1: + resolution: {integrity: sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==} + engines: {node: '>=10'} + + resolve-alpn@1.2.1: + resolution: {integrity: sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==} + + responselike@2.0.1: + resolution: {integrity: sha512-4gl03wn3hj1HP3yzgdI7d3lCkF95F21Pz4BPGvKHinyQzALR5CapwC8yIi0Rh58DEMQ/SguC03wFj2k0M/mHhw==} + + roarr@2.15.4: + resolution: {integrity: sha512-CHhPh+UNHD2GTXNYhPWLnU8ONHdI+5DI+4EYIAOaiD63rHeYlZvyh8P+in5999TTSFgUYuKUAjzRI4mdh/p+2A==} + engines: {node: '>=8.0'} + + semver-compare@1.0.0: + resolution: {integrity: sha512-YM3/ITh2MJ5MtzaM429anh+x2jiLVjqILF4m4oyQB18W7Ggea7BfqdH/wGMK7dDiMghv/6WG7znWMwUDzJiXow==} + + semver@6.3.1: + resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} + hasBin: true + + semver@7.8.0: + resolution: {integrity: sha512-AcM7dV/5ul4EekoQ29Agm5vri8JNqRyj39o0qpX6vDF2GZrtutZl5RwgD1XnZjiTAfncsJhMI48QQH3sN87YNA==} + engines: {node: '>=10'} + hasBin: true + + serialize-error@7.0.1: + resolution: {integrity: sha512-8I8TjW5KMOKsZQTvoxjuSIa7foAwPWGOts+6o7sgjz41/qMD9VQHEDxi6PBvK2l0MXUmqZyNpUK+T2tQaaElvw==} + engines: {node: '>=10'} + + sprintf-js@1.1.3: + resolution: {integrity: sha512-Oo+0REFV59/rz3gfJNKQiBlwfHaSESl1pcGyABQsnnIfWOFt6JNj5gCog2U6MLZ//IGYD+nA8nI+mTShREReaA==} + + sumchecker@3.0.1: + resolution: {integrity: sha512-MvjXzkz/BOfyVDkG0oFOtBxHX2u3gKbMHIF/dXblZsgD3BWOFLmHovIpZY7BykJdAjcqRCBi1WYBNdEC9yI7vg==} + engines: {node: '>= 8.0'} + + type-fest@0.13.1: + resolution: {integrity: sha512-34R7HTnG0XIJcBSn5XhDd7nNFPRcXYRZrBB2O2jdKqYODldSzBAqzsWoZYYvduky73toYS/ESqxPvkDf/F0XMg==} + engines: {node: '>=10'} + + undici-types@6.21.0: + resolution: {integrity: sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ==} + + universalify@0.1.2: + resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} + engines: {node: '>= 4.0.0'} + + wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + + yauzl@2.10.0: + resolution: {integrity: sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==} + +snapshots: + + '@electron/get@2.0.3': + dependencies: + debug: 4.4.3 + env-paths: 2.2.1 + fs-extra: 8.1.0 + got: 11.8.6 + progress: 2.0.3 + semver: 6.3.1 + sumchecker: 3.0.1 + optionalDependencies: + global-agent: 3.0.0 + transitivePeerDependencies: + - supports-color + + '@sindresorhus/is@4.6.0': {} + + '@szmarczak/http-timer@4.0.6': + dependencies: + defer-to-connect: 2.0.1 + + '@types/cacheable-request@6.0.3': + dependencies: + '@types/http-cache-semantics': 4.2.0 + '@types/keyv': 3.1.4 + '@types/node': 22.19.19 + '@types/responselike': 1.0.3 + + '@types/http-cache-semantics@4.2.0': {} + + '@types/keyv@3.1.4': + dependencies: + '@types/node': 22.19.19 + + '@types/node@22.19.19': + dependencies: + undici-types: 6.21.0 + + '@types/responselike@1.0.3': + dependencies: + '@types/node': 22.19.19 + + '@types/yauzl@2.10.3': + dependencies: + '@types/node': 22.19.19 + optional: true + + boolean@3.2.0: + optional: true + + buffer-crc32@0.2.13: {} + + cacheable-lookup@5.0.4: {} + + cacheable-request@7.0.4: + dependencies: + clone-response: 1.0.3 + get-stream: 5.2.0 + http-cache-semantics: 4.2.0 + keyv: 4.5.4 + lowercase-keys: 2.0.0 + normalize-url: 6.1.0 + responselike: 2.0.1 + + clone-response@1.0.3: + dependencies: + mimic-response: 1.0.1 + + debug@4.4.3: + dependencies: + ms: 2.1.3 + + decompress-response@6.0.0: + dependencies: + mimic-response: 3.1.0 + + defer-to-connect@2.0.1: {} + + define-data-property@1.1.4: + dependencies: + es-define-property: 1.0.1 + es-errors: 1.3.0 + gopd: 1.2.0 + optional: true + + define-properties@1.2.1: + dependencies: + define-data-property: 1.1.4 + has-property-descriptors: 1.0.2 + object-keys: 1.1.1 + optional: true + + detect-node@2.1.0: + optional: true + + electron@39.8.5: + dependencies: + '@electron/get': 2.0.3 + '@types/node': 22.19.19 + extract-zip: 2.0.1 + transitivePeerDependencies: + - supports-color + + end-of-stream@1.4.5: + dependencies: + once: 1.4.0 + + env-paths@2.2.1: {} + + es-define-property@1.0.1: + optional: true + + es-errors@1.3.0: + optional: true + + es6-error@4.1.1: + optional: true + + escape-string-regexp@4.0.0: + optional: true + + extract-zip@2.0.1: + dependencies: + debug: 4.4.3 + get-stream: 5.2.0 + yauzl: 2.10.0 + optionalDependencies: + '@types/yauzl': 2.10.3 + transitivePeerDependencies: + - supports-color + + fd-slicer@1.1.0: + dependencies: + pend: 1.2.0 + + fs-extra@8.1.0: + dependencies: + graceful-fs: 4.2.11 + jsonfile: 4.0.0 + universalify: 0.1.2 + + get-stream@5.2.0: + dependencies: + pump: 3.0.4 + + global-agent@3.0.0: + dependencies: + boolean: 3.2.0 + es6-error: 4.1.1 + matcher: 3.0.0 + roarr: 2.15.4 + semver: 7.8.0 + serialize-error: 7.0.1 + optional: true + + globalthis@1.0.4: + dependencies: + define-properties: 1.2.1 + gopd: 1.2.0 + optional: true + + gopd@1.2.0: + optional: true + + got@11.8.6: + dependencies: + '@sindresorhus/is': 4.6.0 + '@szmarczak/http-timer': 4.0.6 + '@types/cacheable-request': 6.0.3 + '@types/responselike': 1.0.3 + cacheable-lookup: 5.0.4 + cacheable-request: 7.0.4 + decompress-response: 6.0.0 + http2-wrapper: 1.0.3 + lowercase-keys: 2.0.0 + p-cancelable: 2.1.1 + responselike: 2.0.1 + + graceful-fs@4.2.11: {} + + has-property-descriptors@1.0.2: + dependencies: + es-define-property: 1.0.1 + optional: true + + http-cache-semantics@4.2.0: {} + + http2-wrapper@1.0.3: + dependencies: + quick-lru: 5.1.1 + resolve-alpn: 1.2.1 + + json-buffer@3.0.1: {} + + json-stringify-safe@5.0.1: + optional: true + + jsonfile@4.0.0: + optionalDependencies: + graceful-fs: 4.2.11 + + keyv@4.5.4: + dependencies: + json-buffer: 3.0.1 + + lowercase-keys@2.0.0: {} + + matcher@3.0.0: + dependencies: + escape-string-regexp: 4.0.0 + optional: true + + mimic-response@1.0.1: {} + + mimic-response@3.1.0: {} + + ms@2.0.0: {} + + ms@2.1.3: {} + + normalize-url@6.1.0: {} + + object-keys@1.1.1: + optional: true + + once@1.4.0: + dependencies: + wrappy: 1.0.2 + + p-cancelable@2.1.1: {} + + pend@1.2.0: {} + + progress@2.0.3: {} + + pump@3.0.4: + dependencies: + end-of-stream: 1.4.5 + once: 1.4.0 + + quick-lru@5.1.1: {} + + resolve-alpn@1.2.1: {} + + responselike@2.0.1: + dependencies: + lowercase-keys: 2.0.0 + + roarr@2.15.4: + dependencies: + boolean: 3.2.0 + detect-node: 2.1.0 + globalthis: 1.0.4 + json-stringify-safe: 5.0.1 + semver-compare: 1.0.0 + sprintf-js: 1.1.3 + optional: true + + semver-compare@1.0.0: + optional: true + + semver@6.3.1: {} + + semver@7.8.0: + optional: true + + serialize-error@7.0.1: + dependencies: + type-fest: 0.13.1 + optional: true + + sprintf-js@1.1.3: + optional: true + + sumchecker@3.0.1: + dependencies: + debug: 4.4.3 + transitivePeerDependencies: + - supports-color + + type-fest@0.13.1: + optional: true + + undici-types@6.21.0: {} + + universalify@0.1.2: {} + + wrappy@1.0.2: {} + + yauzl@2.10.0: + dependencies: + buffer-crc32: 0.2.13 + fd-slicer: 1.1.0 diff --git a/test/package.json b/test/package.json index 4148c450b92..02cf3ccf758 100644 --- a/test/package.json +++ b/test/package.json @@ -36,6 +36,7 @@ "fs-extra": "^10.1.0", "js-yaml": "^4.1.0", "lazy-val": "^1.0.5", + "minimatch": "^10.2.5", "path-sort": "^0.1.0", "resedit": "1.7.0", "sanitize-filename": "^1.6.3", diff --git a/test/snapshots/linux/snapHeavyTest.js.snap b/test/snapshots/linux/snapHeavyTest.js.snap index c097251ff4d..680c9a744ae 100644 --- a/test/snapshots/linux/snapHeavyTest.js.snap +++ b/test/snapshots/linux/snapHeavyTest.js.snap @@ -321,6 +321,79 @@ exports[`snap heavy > snap full (core18 armhf) 2`] = ` } `; +exports[`snap heavy > snap full (core18) 1`] = ` +{ + "apps": { + "se-wo-template": { + "command": "command.sh", + "environment": { + "LD_LIBRARY_PATH": "$SNAP_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu", + "PATH": "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH", + "SNAP_DESKTOP_RUNTIME": "$SNAP/gnome-platform", + }, + "plugs": [ + "desktop", + "desktop-legacy", + "home", + "x11", + "wayland", + "unity7", + "browser-support", + "network", + "gsettings", + "audio-playback", + "pulseaudio", + "opengl", + ], + }, + }, + "architectures": [ + "amd64", + ], + "base": "core18", + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "name": "se-wo-template", + "plugs": { + "gnome-3-28-1804": { + "default-provider": "gnome-3-28-1804", + "interface": "content", + "target": "$SNAP/gnome-platform", + }, + "gtk-3-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/themes", + }, + "icon-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/icons", + }, + "sound-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/sounds", + }, + }, + "summary": "Snap Electron App (full build)", + "title": "Snap Electron App (full build)", + "version": "1.1.0", +} +`; + +exports[`snap heavy > snap full (core18) 2`] = ` +{ + "linux": [ + { + "arch": "x64", + "file": "se-wo-template_1.1.0_amd64.snap", + }, + ], +} +`; + exports[`snap heavy > snap full (core20 armhf) 1`] = ` { "apps": { @@ -394,6 +467,79 @@ exports[`snap heavy > snap full (core20 armhf) 2`] = ` } `; +exports[`snap heavy > snap full (core20) 1`] = ` +{ + "apps": { + "se-wo-template": { + "command": "command.sh", + "environment": { + "LD_LIBRARY_PATH": "$SNAP_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu", + "PATH": "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH", + "SNAP_DESKTOP_RUNTIME": "$SNAP/gnome-platform", + }, + "plugs": [ + "desktop", + "desktop-legacy", + "home", + "x11", + "wayland", + "unity7", + "browser-support", + "network", + "gsettings", + "audio-playback", + "pulseaudio", + "opengl", + ], + }, + }, + "architectures": [ + "amd64", + ], + "base": "core20", + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "name": "se-wo-template", + "plugs": { + "gnome-3-28-1804": { + "default-provider": "gnome-3-28-1804", + "interface": "content", + "target": "$SNAP/gnome-platform", + }, + "gtk-3-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/themes", + }, + "icon-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/icons", + }, + "sound-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/sounds", + }, + }, + "summary": "Snap Electron App (full build)", + "title": "Snap Electron App (full build)", + "version": "1.1.0", +} +`; + +exports[`snap heavy > snap full (core20) 2`] = ` +{ + "linux": [ + { + "arch": "x64", + "file": "se-wo-template_1.1.0_amd64.snap", + }, + ], +} +`; + exports[`snap heavy > snap full (core22 armhf) 1`] = ` { "apps": { @@ -467,6 +613,79 @@ exports[`snap heavy > snap full (core22 armhf) 2`] = ` } `; +exports[`snap heavy > snap full (core22) 1`] = ` +{ + "apps": { + "se-wo-template": { + "command": "command.sh", + "environment": { + "LD_LIBRARY_PATH": "$SNAP_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu:$LD_LIBRARY_PATH:$SNAP/lib:$SNAP/usr/lib:$SNAP/lib/x86_64-linux-gnu:$SNAP/usr/lib/x86_64-linux-gnu", + "PATH": "$SNAP/usr/sbin:$SNAP/usr/bin:$SNAP/sbin:$SNAP/bin:$PATH", + "SNAP_DESKTOP_RUNTIME": "$SNAP/gnome-platform", + }, + "plugs": [ + "desktop", + "desktop-legacy", + "home", + "x11", + "wayland", + "unity7", + "browser-support", + "network", + "gsettings", + "audio-playback", + "pulseaudio", + "opengl", + ], + }, + }, + "architectures": [ + "amd64", + ], + "base": "core22", + "confinement": "strict", + "description": "Test Application (test quite “ #378)", + "grade": "stable", + "name": "se-wo-template", + "plugs": { + "gnome-3-28-1804": { + "default-provider": "gnome-3-28-1804", + "interface": "content", + "target": "$SNAP/gnome-platform", + }, + "gtk-3-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/themes", + }, + "icon-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/icons", + }, + "sound-themes": { + "default-provider": "gtk-common-themes", + "interface": "content", + "target": "$SNAP/data-dir/sounds", + }, + }, + "summary": "Snap Electron App (full build)", + "title": "Snap Electron App (full build)", + "version": "1.1.0", +} +`; + +exports[`snap heavy > snap full (core22) 2`] = ` +{ + "linux": [ + { + "arch": "x64", + "file": "se-wo-template_1.1.0_amd64.snap", + }, + ], +} +`; + exports[`snap heavy > snap full (core24) 1`] = ` { "apps": { diff --git a/test/snapshots/windows/winPackagerTest.js.snap b/test/snapshots/windows/winPackagerTest.js.snap new file mode 100644 index 00000000000..c19b104a511 --- /dev/null +++ b/test/snapshots/windows/winPackagerTest.js.snap @@ -0,0 +1,553 @@ +// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html + +exports[`winCodeSign: 0.0.0 > beta version 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW Setup 3.0.0-beta.2.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "arch": "arm64", + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + ], +} +`; + +exports[`winCodeSign: 0.0.0 > icon < 256 1`] = `"ERR_ICON_TOO_SMALL"`; + +exports[`winCodeSign: 0.0.0 > icon not an image 1`] = `"ERR_ICON_UNKNOWN_FORMAT"`; + +exports[`winCodeSign: 0.0.0 > legacy win-codesign 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 0.0.0 > win zip 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + { + "arch": "arm64", + "file": "Test App ßW-1.1.0-arm64-win.zip", + "safeArtifactName": "TestApp-1.1.0-arm64-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 0.0.0 > win zip 2`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 0.0.0 > win zip 3`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 0.0.0 > win zip 4`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 0.0.0 > win zip 5`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 0.0.0 > zip artifactName 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win-x64.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.0.0 > beta version 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW Setup 3.0.0-beta.2.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "arch": "arm64", + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + ], +} +`; + +exports[`winCodeSign: 1.0.0 > icon < 256 1`] = `"ERR_ICON_TOO_SMALL"`; + +exports[`winCodeSign: 1.0.0 > icon not an image 1`] = `"ERR_ICON_UNKNOWN_FORMAT"`; + +exports[`winCodeSign: 1.0.0 > legacy win-codesign 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.0.0 > win zip 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + { + "arch": "arm64", + "file": "Test App ßW-1.1.0-arm64-win.zip", + "safeArtifactName": "TestApp-1.1.0-arm64-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.0.0 > win zip 2`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 1.0.0 > win zip 3`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 1.0.0 > win zip 4`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 1.0.0 > win zip 5`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 1.0.0 > zip artifactName 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win-x64.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.1.0 > beta version 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW Setup 3.0.0-beta.2.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "arch": "arm64", + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2-arm64.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2-arm64.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + { + "file": "Test App ßW Setup 3.0.0-beta.2.exe.blockmap", + "safeArtifactName": "TestApp-Setup-3.0.0-beta.2.exe.blockmap", + "updateInfo": { + "sha512": "@sha512", + "size": "@size", + }, + }, + ], +} +`; + +exports[`winCodeSign: 1.1.0 > icon < 256 1`] = `"ERR_ICON_TOO_SMALL"`; + +exports[`winCodeSign: 1.1.0 > icon not an image 1`] = `"ERR_ICON_UNKNOWN_FORMAT"`; + +exports[`winCodeSign: 1.1.0 > legacy win-codesign 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.1.0 > win zip 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + { + "arch": "arm64", + "file": "Test App ßW-1.1.0-arm64-win.zip", + "safeArtifactName": "TestApp-1.1.0-arm64-win.zip", + }, + ], +} +`; + +exports[`winCodeSign: 1.1.0 > win zip 2`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 1.1.0 > win zip 3`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 1.1.0 > win zip 4`] = ` +[ + "chrome_100_percent.pak", + "chrome_200_percent.pak", + "d3dcompiler_47.dll", + "dxcompiler.dll", + "dxil.dll", + "ffmpeg.dll", + "icudtl.dat", + "libEGL.dll", + "libGLESv2.dll", + "LICENSE.electron.txt", + "LICENSES.chromium.html", + "locales/", + "resources/", + "resources/app.asar", + "resources/extraAsar.asar", + "resources/subdir/", + "resources/subdir/extraAsar2.asar", + "resources.pak", + "snapshot_blob.bin", + "Test App ßW.exe", + "v8_context_snapshot.bin", + "vk_swiftshader.dll", + "vk_swiftshader_icd.json", + "vulkan-1.dll", +] +`; + +exports[`winCodeSign: 1.1.0 > win zip 5`] = ` +[ + { + "alg": "SHA256", + "file": "resources\\app.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\extraAsar.asar", + "value": "hash", + }, + { + "alg": "SHA256", + "file": "resources\\subdir\\extraAsar2.asar", + "value": "hash", + }, +] +`; + +exports[`winCodeSign: 1.1.0 > zip artifactName 1`] = ` +{ + "win": [ + { + "arch": "x64", + "file": "Test App ßW-1.1.0-win-x64.zip", + "safeArtifactName": "TestApp-1.1.0-win.zip", + }, + ], +} +`; diff --git a/test/src/ArtifactPublisherTest.ts b/test/src/ArtifactPublisherTest.ts index a68a9993163..362be571f38 100644 --- a/test/src/ArtifactPublisherTest.ts +++ b/test/src/ArtifactPublisherTest.ts @@ -1,5 +1,5 @@ import { Platform } from "app-builder-lib" -import { createPublisher } from "app-builder-lib/out/publish/PublishManager" +import { createPublisher } from "app-builder-lib/internal" import { Arch } from "builder-util" import { BitbucketOptions, CancellationToken, HttpError, KeygenOptions, S3Options, SpacesOptions } from "builder-util-runtime" import { publishArtifactsWithOptions } from "electron-builder" @@ -17,8 +17,8 @@ function versionNumber() { //noinspection SpellCheckingInspection const token = Buffer.from("Y2Y5NDdhZDJhYzJlMzg1OGNiNzQzYzcwOWZhNGI0OTk2NWQ4ZDg3Yg==", "base64").toString() -const iconPath = path.join(__dirname, "..", "fixtures", "test-app", "build", "icon.icns") -const icoPath = path.join(__dirname, "..", "fixtures", "test-app", "build", "icon.ico") +const iconPath = path.join(import.meta.dirname, "..", "fixtures", "test-app", "build", "icon.icns") +const icoPath = path.join(import.meta.dirname, "..", "fixtures", "test-app", "build", "icon.ico") const publishContext: PublishContext = { cancellationToken: new CancellationToken(), diff --git a/test/src/BuildTest.ts b/test/src/BuildTest.ts index 0600a458a8d..ab91e443ea4 100644 --- a/test/src/BuildTest.ts +++ b/test/src/BuildTest.ts @@ -1,18 +1,21 @@ +import { createRequire } from "node:module" import { checkBuildRequestOptions } from "app-builder-lib" -import { doMergeConfigs } from "app-builder-lib/out/util/config/config" +import { doMergeConfigs } from "app-builder-lib/internal" import { Arch, createTargets, DIR_TARGET, Platform } from "electron-builder" -import { createYargs } from "electron-builder/out/builder" +import { createYargs } from "electron-builder/internal" import { promises as fs } from "fs" -import { outputFile, outputJson } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" -import { app, appTwo, appTwoThrows, assertPack, getFixtureDir, linuxDirTarget, modifyPackageJson, packageJson, toSystemIndependentPath } from "./helpers/packTester" -import { ELECTRON_VERSION } from "./helpers/testConfig" -import { verifySmartUnpack } from "./helpers/verifySmartUnpack" -import { PM } from "app-builder-lib/out/node-module-collector/packageManager" +import { app, appTwo, appTwoThrows, assertPack, getFixtureDir, linuxDirTarget, modifyPackageJson, packageJson, toSystemIndependentPath } from "./helpers/packTester.js" +import { ELECTRON_VERSION } from "./helpers/testConfig.js" +import { verifySmartUnpack } from "./helpers/verifySmartUnpack.js" +import { PM } from "app-builder-lib/internal" + +const require = createRequire(import.meta.url) test.ifLinux("cli", ({ expect }) => { // because these methods are internal - const { configureBuildCommand, normalizeOptions } = require("electron-builder/out/builder") + const { configureBuildCommand, normalizeOptions } = require("electron-builder/internal") const yargs = createYargs() configureBuildCommand(yargs) @@ -161,7 +164,7 @@ it.ifNotWindows("electron version from electron-prebuilt dependency", ({ expect data.devDependencies = {} }) return () => - outputJson(path.join(projectDir, "node_modules", "electron-prebuilt", "package.json"), { + fsExtra.outputJson(path.join(projectDir, "node_modules", "electron-prebuilt", "package.json"), { version: ELECTRON_VERSION, }) }, @@ -182,7 +185,7 @@ test.ifNotWindows("electron version from electron dependency", ({ expect }) => data.devDependencies = {} }) return () => - outputJson(path.join(projectDir, "node_modules", "electron", "package.json"), { + fsExtra.outputJson(path.join(projectDir, "node_modules", "electron", "package.json"), { version: ELECTRON_VERSION, }) }, @@ -399,8 +402,8 @@ test("smart unpack local module with dll file", ({ expect }) => { projectDirCreated: async (projectDir, tmpDir) => { const tmpPath = await tmpDir.getTempDir() const localPath = path.join(tmpPath, "foo") - await outputFile(path.join(localPath, "package.json"), `{"name":"foo","version":"9.0.0","main":"index.js","license":"MIT"}`) - await outputFile(path.join(localPath, "test.dll"), `test`) + await fsExtra.outputFile(path.join(localPath, "package.json"), `{"name":"foo","version":"9.0.0","main":"index.js","license":"MIT"}`) + await fsExtra.outputFile(path.join(localPath, "test.dll"), `test`) await modifyPackageJson(projectDir, data => { data.dependencies = { debug: "3.1.0", diff --git a/test/src/HoistTest.ts b/test/src/HoistTest.ts index 92199e56756..dd8c6b942ba 100644 --- a/test/src/HoistTest.ts +++ b/test/src/HoistTest.ts @@ -1,5 +1,5 @@ // copy from https://github.com/yarnpkg/berry/blob/master/packages/yarnpkg-nm/tests/hoist.test.ts -import { hoist, HoisterTree, HoisterResult, HoisterDependencyKind } from "app-builder-lib/out/node-module-collector/hoist" +import { hoist, HoisterTree, HoisterResult, HoisterDependencyKind } from "app-builder-lib/internal" import { expect } from "vitest" const toTree = (obj: any, key: string = `.`, nodes = new Map()): HoisterTree => { diff --git a/test/src/HoistedNodeModuleTest.ts b/test/src/HoistedNodeModuleTest.ts index df24b5d90aa..0fc3ce94733 100644 --- a/test/src/HoistedNodeModuleTest.ts +++ b/test/src/HoistedNodeModuleTest.ts @@ -1,5 +1,5 @@ -import { PM } from "app-builder-lib/out/node-module-collector" -import { spawn } from "builder-util/out/util" +import { PM } from "app-builder-lib/internal" +import { spawn } from "builder-util/src/util" import { Arch, DIR_TARGET, Platform } from "electron-builder" import * as path from "path" import { appTwoThrows, assertPack, linuxDirTarget, modifyPackageJson, verifyAsarFileTree } from "./helpers/packTester" diff --git a/test/src/PublishManagerTest.ts b/test/src/PublishManagerTest.ts index 7cf1bdd9d1e..45197fd040f 100644 --- a/test/src/PublishManagerTest.ts +++ b/test/src/PublishManagerTest.ts @@ -1,9 +1,9 @@ import { GenericServerOptions, GithubOptions, KeygenOptions, SpacesOptions } from "builder-util-runtime" import { Arch, createTargets, Platform } from "electron-builder" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "./helpers/fileAssert" -import { app, checkDirContents } from "./helpers/packTester" +import { assertThat } from "./helpers/fileAssert.js" +import { app, checkDirContents } from "./helpers/packTester.js" function spacesPublisher(publishAutoUpdate = true): SpacesOptions { return { @@ -149,7 +149,7 @@ test.ifNotWindows("custom provider", ({ expect }) => { publish: "never", projectDirCreated: projectDir => - outputFile( + fsExtra.outputFile( path.join(projectDir, "build/electron-publisher-custom.js"), `class Publisher { async upload(task) { diff --git a/test/src/RepoSlugTest.ts b/test/src/RepoSlugTest.ts index 2bc245fd339..605cb031120 100644 --- a/test/src/RepoSlugTest.ts +++ b/test/src/RepoSlugTest.ts @@ -1,4 +1,4 @@ -import { getRepositoryInfo } from "app-builder-lib/out/util/repositoryInfo" +import { getRepositoryInfo } from "app-builder-lib/internal" import { ExpectStatic } from "vitest" function checkInfo(expect: ExpectStatic, info: any) { diff --git a/test/src/blockmapTest.ts b/test/src/blockmapTest.ts index c4a700cefa2..8ad1f879844 100644 --- a/test/src/blockmapTest.ts +++ b/test/src/blockmapTest.ts @@ -6,7 +6,7 @@ import * as os from "os" import * as path from "path" import * as zlib from "zlib" import { afterEach, beforeEach, describe, expect, it } from "vitest" -import { buildBlockMap } from "app-builder-lib/out/targets/blockmap/blockmap" +import { buildBlockMap } from "app-builder-lib/internal" import { appBuilderPath } from "app-builder-bin" // True when the app-builder-bin binary is actually present on disk. @@ -173,7 +173,7 @@ describe("buildBlockMap", () => { it("chunk checksums match BLAKE2b-18 of chunk content", async () => { const blake2bPath = require.resolve("@noble/hashes/blake2.js", { - paths: [require.resolve("app-builder-lib/out/targets/blockmap/blockmap")], + paths: [require.resolve("app-builder-lib/src/targets/blockmap/blockmap")], }) const { blake2b } = require(blake2bPath) as typeof import("@noble/hashes/blake2") const data = makeTestData(50_000) diff --git a/test/src/builder-util/nodeHttpExecutorTest.ts b/test/src/builder-util/nodeHttpExecutorTest.ts index b59f3522bcb..135cd3bfb07 100644 --- a/test/src/builder-util/nodeHttpExecutorTest.ts +++ b/test/src/builder-util/nodeHttpExecutorTest.ts @@ -1,11 +1,13 @@ -import { buildGotProxyAgent, NodeHttpExecutor } from "builder-util/out/nodeHttpExecutor" +import { buildGotProxyAgent, NodeHttpExecutor } from "builder-util/src/nodeHttpExecutor" import { afterEach, beforeEach, vi } from "vitest" const PROXY_VARS = ["HTTPS_PROXY", "https_proxy", "HTTP_PROXY", "http_proxy"] as const describe("buildGotProxyAgent", () => { beforeEach(() => { - for (const key of PROXY_VARS) delete process.env[key] + for (const key of PROXY_VARS) { + delete process.env[key] + } }) afterEach(() => { vi.unstubAllEnvs() @@ -128,7 +130,9 @@ describe("NodeHttpExecutor.createRequest", () => { beforeEach(() => { executor = new NodeHttpExecutor() - for (const key of PROXY_VARS) delete process.env[key] + for (const key of PROXY_VARS) { + delete process.env[key] + } }) afterEach(() => { vi.unstubAllEnvs() diff --git a/test/src/builder-util/utilTest.ts b/test/src/builder-util/utilTest.ts index cb5c2bf3869..419996513c7 100644 --- a/test/src/builder-util/utilTest.ts +++ b/test/src/builder-util/utilTest.ts @@ -1,4 +1,4 @@ -import { parseValidEnvVarUrl, resolveEnvShellValue } from "builder-util/out/envUtil" +import { parseValidEnvVarUrl, resolveEnvShellValue } from "builder-util/src/envUtil" import { removePassword, filterSensitiveEnv, spawnAndWriteWithOutput, ExecError } from "builder-util" import { afterEach, vi } from "vitest" diff --git a/test/src/certInfoTest.ts b/test/src/certInfoTest.ts index 78968bba2f5..06c8c06308f 100644 --- a/test/src/certInfoTest.ts +++ b/test/src/certInfoTest.ts @@ -5,7 +5,7 @@ import { writeFileSync } from "fs" import { mkdtemp } from "fs/promises" import { afterAll, beforeAll, describe, it, expect } from "vitest" import { writeFile, remove } from "fs-extra" -import { readCertInfo, _testingOnly } from "app-builder-lib/src/codeSign/certInfo" +import { readCertInfo, _testingOnly } from "app-builder-lib/internal" const { pkcs12PbeDeriveKey, pkcs12PasswordToUtf16, rc2CbcDecrypt, MAX_PKCS12_PBE_ITERATIONS } = _testingOnly import { executeAppBuilder } from "builder-util" diff --git a/test/src/cliTest.ts b/test/src/cliTest.ts index 48716133c57..a410b562fdc 100644 --- a/test/src/cliTest.ts +++ b/test/src/cliTest.ts @@ -3,8 +3,12 @@ import yargs from "yargs" // ─── Module mocks (hoisted by vitest above all imports) ─────────────────────── -vi.mock("app-builder-lib/out/util/electronGet", () => ({ +// getCacheDirectory (clear-cache) and loadEnv (cli-util) are the only `app-builder-lib/internal` +// exports exercised here. Stub just those — a full mock keeps the heavy app-builder-lib module +// graph (and its circular class hierarchy) from loading for these isolated CLI unit tests. +vi.mock("app-builder-lib/internal", () => ({ getCacheDirectory: vi.fn().mockReturnValue("/home/user/.cache/electron-builder"), + loadEnv: vi.fn().mockResolvedValue(undefined), })) vi.mock("fs/promises", async () => { @@ -16,7 +20,7 @@ vi.mock("fs/promises", async () => { } }) -vi.mock("readline/promises", () => ({ +vi.mock("node:readline/promises", () => ({ createInterface: vi.fn(() => ({ question: vi.fn().mockResolvedValue("y"), close: vi.fn(), @@ -32,15 +36,11 @@ vi.mock("builder-util", async () => { } }) -vi.mock("app-builder-lib/out/util/config/load", () => ({ - loadEnv: vi.fn().mockResolvedValue(undefined), -})) - // ─── Imports ────────────────────────────────────────────────────────────────── import { access, rm } from "fs/promises" -import { createInterface } from "readline/promises" -import { getCacheDirectory } from "app-builder-lib/out/util/electronGet" +import { createInterface } from "node:readline/promises" +import { getCacheDirectory } from "app-builder-lib/internal" import { ExecError, InvalidConfigurationError, log } from "builder-util" // Relative imports bypass project-reference declaration files, which strip @internal exports import { clearCache } from "../../packages/electron-builder/src/cli/clear-cache" diff --git a/test/src/concurrentBuildsTest.ts b/test/src/concurrentBuildsTest.ts index db4c5b5338f..a11ddd0155d 100644 --- a/test/src/concurrentBuildsTest.ts +++ b/test/src/concurrentBuildsTest.ts @@ -1,7 +1,7 @@ import { Arch, Configuration, DIR_TARGET, Platform } from "app-builder-lib" import { deepAssign } from "builder-util-runtime" import { TmpDir } from "temp-file" -import { assertPack, modifyPackageJson } from "./helpers/packTester" +import { assertPack, modifyPackageJson } from "./helpers/packTester.js" const options = { timeout: 30 * 60 * 1000 } diff --git a/test/src/configurationValidationTest.ts b/test/src/configurationValidationTest.ts index e49fe5d3c89..8b9a27050d3 100644 --- a/test/src/configurationValidationTest.ts +++ b/test/src/configurationValidationTest.ts @@ -1,8 +1,8 @@ -import { validateConfiguration } from "app-builder-lib/out/util/config/config" +import { validateConfiguration } from "app-builder-lib/internal" import { Arch, DebugLogger } from "builder-util" -import { Configuration, Platform } from "electron-builder" -import { CliOptions, configureBuildCommand, createYargs, normalizeOptions } from "electron-builder/out/builder" -import { app, appThrows, linuxDirTarget } from "./helpers/packTester" +import { CliOptions, Configuration, Platform } from "electron-builder" +import { configureBuildCommand, createYargs, normalizeOptions } from "electron-builder/internal" +import { app, appThrows, linuxDirTarget } from "./helpers/packTester.js" test.ifNotWindows("validation", ({ expect }) => appThrows( diff --git a/test/src/dynamicImportTest.ts b/test/src/dynamicImportTest.ts index c509455c44f..b64c681f0de 100644 --- a/test/src/dynamicImportTest.ts +++ b/test/src/dynamicImportTest.ts @@ -4,8 +4,7 @@ import { expect } from "vitest" const WORKSPACE_ROOT = path.resolve(__dirname, "../../") -// eslint-disable-next-line @typescript-eslint/no-require-imports -const helper = require("../../packages/app-builder-lib/helpers/dynamic-import") as { +const helper = require("../../packages/app-builder-lib/helpers/dynamic-import.cjs") as { dynamicImport(modulePath: string): Promise dynamicImportMaybe(modulePath: string): Promise } diff --git a/test/src/electronGetTest.ts b/test/src/electronGetTest.ts index 737f00ca080..4d63560deed 100644 --- a/test/src/electronGetTest.ts +++ b/test/src/electronGetTest.ts @@ -7,14 +7,14 @@ import * as path from "path" import { afterAll, afterEach, beforeAll, vi } from "vitest" import { ArtifactDownloadOptions, + CacheState, ElectronDownloadOptions, ElectronGetOptions, downloadBuilderToolset, downloadElectronArtifact, getCacheDirectory, getBinariesMirrorUrl, -} from "app-builder-lib/out/util/electronGet" -import { CacheState } from "app-builder-lib/out/util/cacheState" +} from "app-builder-lib/internal" import { ELECTRON_VERSION } from "./helpers/testConfig" // ─── getCacheDirectory ──────────────────────────────────────────────────────── diff --git a/test/src/electronVersionTest.ts b/test/src/electronVersionTest.ts index 534f2d08776..a8b51594286 100644 --- a/test/src/electronVersionTest.ts +++ b/test/src/electronVersionTest.ts @@ -6,7 +6,7 @@ import { log } from "builder-util" // getElectronVersion is the public entry point; passing an explicit config with no // electronVersion bypasses getConfig and falls through to computeElectronVersion. -import { getElectronVersion } from "app-builder-lib/out/electron/electronVersion" +import { getElectronVersion } from "app-builder-lib/internal" function rangeLogMessage(version: string): string { return ( diff --git a/test/src/extraMetadataTest.ts b/test/src/extraMetadataTest.ts index 04d8ebdff69..1aa349aeff7 100644 --- a/test/src/extraMetadataTest.ts +++ b/test/src/extraMetadataTest.ts @@ -1,12 +1,15 @@ -import { readAsarJson } from "app-builder-lib/out/asar/asar" +import { createRequire } from "node:module" +import { readAsarJson } from "app-builder-lib/internal" import { Platform } from "electron-builder" -import { coerceTypes } from "electron-builder/out/builder" -import { readJson } from "fs-extra" +import { coerceTypes } from "electron-builder/internal" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "./helpers/fileAssert" -import { app, linuxDirTarget, modifyPackageJson } from "./helpers/packTester" +import { assertThat } from "./helpers/fileAssert.js" +import { app, linuxDirTarget, modifyPackageJson } from "./helpers/packTester.js" import { ExpectStatic } from "vitest" +const require = createRequire(import.meta.url) + function createExtraMetadataTest(expect: ExpectStatic, asar: boolean) { return app( expect, @@ -44,7 +47,7 @@ function createExtraMetadataTest(expect: ExpectStatic, asar: boolean) { if (asar) { expect(await readAsarJson(path.join(context.getResources(Platform.LINUX), "app.asar"), "package.json")).toMatchSnapshot() } else { - expect(await readJson(path.join(context.getResources(Platform.LINUX), "app", "package.json"))).toMatchSnapshot() + expect(await fsExtra.readJson(path.join(context.getResources(Platform.LINUX), "app", "package.json"))).toMatchSnapshot() } }, } @@ -56,7 +59,7 @@ test("extra metadata (no asar)", ({ expect }) => createExtraMetadataTest(expect, test("cli", ({ expect }) => { // because these methods are internal - const { configureBuildCommand, normalizeOptions } = require("electron-builder/out/builder") + const { configureBuildCommand, normalizeOptions } = require("electron-builder/internal") const yargs = require("yargs") .strict() .fail((message: string, error: Error | null) => { diff --git a/test/src/filenameUtilTest.ts b/test/src/filenameUtilTest.ts index f9ba2726789..577df87f61c 100644 --- a/test/src/filenameUtilTest.ts +++ b/test/src/filenameUtilTest.ts @@ -1,4 +1,4 @@ -import { getCompleteExtname } from "builder-util/out/filename" +import { getCompleteExtname } from "builder-util/internal" // [inputFilename, expectedExtname] const tests = [ diff --git a/test/src/filesTest.ts b/test/src/filesTest.ts index 736c322bde2..db4b5305d65 100644 --- a/test/src/filesTest.ts +++ b/test/src/filesTest.ts @@ -1,11 +1,11 @@ import { TmpDir, archFromString, copyDir } from "builder-util" import { DIR_TARGET, Platform } from "electron-builder" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import * as fs from "fs/promises" import * as path from "path" -import { Mode, RWX } from "stat-mode" -import { assertThat } from "./helpers/fileAssert" -import { app, appThrows, assertPack, checkDirContents, linuxDirTarget, modifyPackageJson } from "./helpers/packTester" +import statMode from "stat-mode" +import { assertThat } from "./helpers/fileAssert.js" +import { app, appThrows, assertPack, checkDirContents, linuxDirTarget, modifyPackageJson } from "./helpers/packTester.js" import { ExpectStatic } from "vitest" test.ifNotWindows("expand not defined env", ({ expect }) => @@ -35,10 +35,10 @@ test.ifNotWindows("files", ({ expect }) => { projectDirCreated: projectDir => Promise.all([ - outputFile(path.join(projectDir, "ignoreMe", "foo"), "data"), - outputFile(path.join(projectDir, "ignoreEmptyDir", "bar"), "data"), - outputFile(path.join(projectDir, "test.h"), "test that"), - outputFile(path.join(projectDir, "dist/electron/foo.js"), "data"), + fsExtra.outputFile(path.join(projectDir, "ignoreMe", "foo"), "data"), + fsExtra.outputFile(path.join(projectDir, "ignoreEmptyDir", "bar"), "data"), + fsExtra.outputFile(path.join(projectDir, "test.h"), "test that"), + fsExtra.outputFile(path.join(projectDir, "dist/electron/foo.js"), "data"), ]), packed: context => { const resources = path.join(context.getResources(Platform.LINUX), "app") @@ -100,7 +100,8 @@ test.ifNotWindows("map resources", ({ expect }) => }, }, { - projectDirCreated: projectDir => Promise.all([outputFile(path.join(projectDir, "foo", "old"), "data"), outputFile(path.join(projectDir, "license.txt"), "data")]), + projectDirCreated: projectDir => + Promise.all([fsExtra.outputFile(path.join(projectDir, "foo", "old"), "data"), fsExtra.outputFile(path.join(projectDir, "license.txt"), "data")]), packed: context => { const resources = context.getResources(Platform.LINUX) return Promise.all([ @@ -132,13 +133,13 @@ async function doExtraResourcesTest(expect: ExpectStatic, platform: Platform) { { projectDirCreated: async projectDir => { return Promise.all([ - outputFile(path.resolve(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"), - outputFile(path.resolve(projectDir, "bar/hello.txt"), "data"), - outputFile(path.resolve(projectDir, "dir-relative/f.txt"), "data"), - outputFile(path.resolve(projectDir, `bar/${process.arch}.txt`), "data"), - outputFile(path.resolve(projectDir, `${osName}/${process.arch}.txt`), "data"), - outputFile(path.resolve(projectDir, "platformSpecificR"), "platformSpecificR"), - outputFile(path.resolve(projectDir, "ignoreMe.txt"), "ignoreMe"), + fsExtra.outputFile(path.resolve(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"), + fsExtra.outputFile(path.resolve(projectDir, "bar/hello.txt"), "data"), + fsExtra.outputFile(path.resolve(projectDir, "dir-relative/f.txt"), "data"), + fsExtra.outputFile(path.resolve(projectDir, `bar/${process.arch}.txt`), "data"), + fsExtra.outputFile(path.resolve(projectDir, `${osName}/${process.arch}.txt`), "data"), + fsExtra.outputFile(path.resolve(projectDir, "platformSpecificR"), "platformSpecificR"), + fsExtra.outputFile(path.resolve(projectDir, "ignoreMe.txt"), "ignoreMe"), ]) }, packed: async context => { @@ -188,14 +189,14 @@ test.ifNotWindows("extraResources - two-package", ({ expect }) => { { projectDirCreated: projectDir => { return Promise.all([ - outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"), - outputFile(path.join(projectDir, "bar/hello.txt"), "data", { mode: 0o400 }), - outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"), - outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"), - outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"), - outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"), - outputFile(path.join(projectDir, "executable"), "executable", { mode: 0o755 }), - outputFile(path.join(projectDir, "executableOnlyOwner"), "executable", { mode: 0o740 }), + fsExtra.outputFile(path.join(projectDir, "foo/nameWithoutDot"), "nameWithoutDot"), + fsExtra.outputFile(path.join(projectDir, "bar/hello.txt"), "data", { mode: 0o400 }), + fsExtra.outputFile(path.join(projectDir, `bar/${process.arch}.txt`), "data"), + fsExtra.outputFile(path.join(projectDir, `${osName}/${process.arch}.txt`), "data"), + fsExtra.outputFile(path.join(projectDir, "platformSpecificR"), "platformSpecificR"), + fsExtra.outputFile(path.join(projectDir, "ignoreMe.txt"), "ignoreMe"), + fsExtra.outputFile(path.join(projectDir, "executable"), "executable", { mode: 0o755 }), + fsExtra.outputFile(path.join(projectDir, "executableOnlyOwner"), "executable", { mode: 0o740 }), ]) }, packed: async context => { @@ -236,7 +237,7 @@ test.ifNotWindows("postpone symlink", async () => { const source = await tmpDir.getTempDir() const aSourceFile = path.join(source, "z", "Z") const bSourceFileLink = path.join(source, "B") - await outputFile(aSourceFile, "test") + await fsExtra.outputFile(aSourceFile, "test") await fs.symlink(aSourceFile, bSourceFileLink) const dest = await tmpDir.getTempDir() @@ -246,15 +247,15 @@ test.ifNotWindows("postpone symlink", async () => { }) async function allCan(file: string, execute: boolean) { - const mode = new Mode(await fs.stat(file)) + const mode = new statMode.Mode(await fs.stat(file)) - function checkExecute(value: RWX) { + function checkExecute(value: statMode.RWX) { if (value.execute !== execute) { throw new Error(`${file} is ${execute ? "not " : ""}executable`) } } - function checkRead(value: RWX) { + function checkRead(value: statMode.RWX) { if (!value.read) { throw new Error(`${file} is not readable`) } diff --git a/test/src/filterTest.ts b/test/src/filterTest.ts index ee2e03a5b4b..7edc442c20a 100644 --- a/test/src/filterTest.ts +++ b/test/src/filterTest.ts @@ -1,5 +1,5 @@ import { FilterStats } from "builder-util" -import { FileMatcher, getFileMatchers, GetFileMatchersOptions } from "app-builder-lib/out/fileMatcher" +import { FileMatcher, getFileMatchers, GetFileMatchersOptions } from "app-builder-lib/internal" import * as path from "path" // --------------------------------------------------------------------------- @@ -241,7 +241,7 @@ describe("FileMatcher – computeParsedPatterns: auto-expand bare directory name describe("FileMatcher – createFilter with excludePatterns", () => { test("excludePatterns exclude matched files but not directories", ({ expect }) => { - const { Minimatch } = require("app-builder-lib/node_modules/minimatch") + const { Minimatch } = require("minimatch") const m = new FileMatcher("/app", "/out", noMacro, ["**/*"]) m.excludePatterns = [new Minimatch("**/*.map", { dot: true })] const filter = m.createFilter() diff --git a/test/src/globTest.ts b/test/src/globTest.ts index dea45f3ad0a..1dc75dc52e8 100644 --- a/test/src/globTest.ts +++ b/test/src/globTest.ts @@ -1,21 +1,21 @@ import { Platform } from "app-builder-lib" -import { readAsar } from "app-builder-lib/out/asar/asar" -import { PM } from "app-builder-lib/out/node-module-collector/packageManager" -import { outputFile } from "fs-extra" +import { readAsar } from "app-builder-lib/internal" +import { PM } from "app-builder-lib/internal" +import fsExtra from "fs-extra" import * as fs from "fs/promises" import * as path from "path" import { ExpectStatic } from "vitest" -import { assertThat } from "./helpers/fileAssert" -import { app, appThrows, assertPack, linuxDirTarget, modifyPackageJson, PackedContext, removeUnstableProperties, verifyAsarFileTree } from "./helpers/packTester" -import { verifySmartUnpack } from "./helpers/verifySmartUnpack" +import { assertThat } from "./helpers/fileAssert.js" +import { app, appThrows, assertPack, linuxDirTarget, modifyPackageJson, PackedContext, removeUnstableProperties, verifyAsarFileTree } from "./helpers/packTester.js" +import { verifySmartUnpack } from "./helpers/verifySmartUnpack.js" async function createFiles(appDir: string) { await Promise.all([ - outputFile(path.join(appDir, "assets", "file1"), "data"), - outputFile(path.join(appDir, "assets", "file2"), "data"), - outputFile(path.join(appDir, "assets", "subdir", "file3"), "data"), - outputFile(path.join(appDir, "b2", "file"), "data"), - outputFile(path.join(appDir, "do-not-unpack-dir", "file.json"), "{}").then(() => fs.writeFile(path.join(appDir, "do-not-unpack-dir", "must-be-not-unpacked"), "{}")), + fsExtra.outputFile(path.join(appDir, "assets", "file1"), "data"), + fsExtra.outputFile(path.join(appDir, "assets", "file2"), "data"), + fsExtra.outputFile(path.join(appDir, "assets", "subdir", "file3"), "data"), + fsExtra.outputFile(path.join(appDir, "b2", "file"), "data"), + fsExtra.outputFile(path.join(appDir, "do-not-unpack-dir", "file.json"), "{}").then(() => fs.writeFile(path.join(appDir, "do-not-unpack-dir", "must-be-not-unpacked"), "{}")), ]) const dir = path.join(appDir, "do-not-unpack-dir", "dir-2", "dir-3", "dir-3") @@ -84,7 +84,7 @@ test.ifNotWindows("asarUnpack and files ignore", ({ expect }) => { }, }, { - projectDirCreated: projectDir => outputFile(path.join(projectDir, "test/ffprobe-static/bin/darwin/x64/ffprobe"), "data"), + projectDirCreated: projectDir => fsExtra.outputFile(path.join(projectDir, "test/ffprobe-static/bin/darwin/x64/ffprobe"), "data"), packed: async context => { const resourceDir = context.getResources(Platform.LINUX) await Promise.all([assertThat(expect, path.join(resourceDir, "app.asar.unpacked", "test/ffprobe-static/bin/darwin/x64/ffprobe")).doesNotExist()]) @@ -123,7 +123,7 @@ test.skip("outside link", ({ expect }) => { projectDirCreated: async (projectDir, tmpDir) => { const tempDir = await tmpDir.getTempDir() - await outputFile(path.join(tempDir, "foo"), "data") + await fsExtra.outputFile(path.join(tempDir, "foo"), "data") await fs.symlink(tempDir, path.join(projectDir, "o-dir")) }, }, diff --git a/test/src/helpers/CheckingPackager.ts b/test/src/helpers/CheckingPackager.ts index 2852e2ab842..9c70e9b3a31 100644 --- a/test/src/helpers/CheckingPackager.ts +++ b/test/src/helpers/CheckingPackager.ts @@ -1,11 +1,9 @@ -import { SignOptions as MacSignOptions } from "@electron/osx-sign/dist/cjs/types" -import { Identity } from "app-builder-lib/out/codeSign/macCodeSign" -import { DoPackOptions } from "app-builder-lib/out/platformPackager" +import { SignOptions as MacSignOptions } from "@electron/osx-sign/dist/esm/types.js" +import { Identity, DoPackOptions } from "app-builder-lib/internal" import { WinPackager, getArchSuffix, MacPackager } from "app-builder-lib" import { AsyncTaskManager } from "builder-util" import { DmgTarget } from "dmg-builder" import { Arch, MacConfiguration, Packager, Target } from "electron-builder" -import SquirrelWindowsTarget from "electron-builder-squirrel-windows" import * as path from "path" export class CheckingWinPackager extends WinPackager { @@ -15,18 +13,17 @@ export class CheckingWinPackager extends WinPackager { super(info) } - //noinspection JSUnusedLocalSymbols async pack(outDir: string, arch: Arch, targets: Array, taskManager: AsyncTaskManager): Promise { + const pkgName = "electron-builder-squirrel-windows" // skip pack - const helperClass: typeof SquirrelWindowsTarget = (await import("electron-builder-squirrel-windows")).default - const newClass = new helperClass(this, outDir) + const helperClass = (await import(pkgName)).default + const newClass = new (helperClass as any)(this, outDir) const setupFile = this.expandArtifactNamePattern(newClass.options, "exe", arch, "${productName} Setup ${version}.${ext}") const installerOutDir = path.join(outDir, `squirrel-windows${getArchSuffix(arch)}`) this.effectiveDistOptions = await newClass.computeEffectiveDistOptions(installerOutDir, outDir, setupFile) await this.signIf(this.computeAppOutDir(outDir, arch)) } - //noinspection JSUnusedLocalSymbols packageInDistributableFormat(appOutDir: string, arch: Arch, targets: Array, taskManager: AsyncTaskManager): void { // skip } diff --git a/test/src/helpers/TestAppAdapter.ts b/test/src/helpers/TestAppAdapter.ts index 25947245605..af63c678c51 100644 --- a/test/src/helpers/TestAppAdapter.ts +++ b/test/src/helpers/TestAppAdapter.ts @@ -1,4 +1,4 @@ -import { ElectronAppAdapter } from "electron-updater/out/ElectronAppAdapter" +import { ElectronAppAdapter } from "electron-updater/internal" // do not implement AppAdapter directly, test that our ElectronAppAdapter implementation is correct export class TestAppAdapter extends ElectronAppAdapter { diff --git a/test/src/helpers/asarVerifier.ts b/test/src/helpers/asarVerifier.ts index fb2842f22f1..fd2f7fa96cd 100644 --- a/test/src/helpers/asarVerifier.ts +++ b/test/src/helpers/asarVerifier.ts @@ -1,4 +1,4 @@ -import { readAsar } from "app-builder-lib/src/asar/asar" +import { readAsar } from "app-builder-lib/internal" import path from "path" import { expect, ExpectStatic } from "vitest" diff --git a/test/src/helpers/downloadElectron.ts b/test/src/helpers/downloadElectron.ts new file mode 100644 index 00000000000..0c3a9e497c6 --- /dev/null +++ b/test/src/helpers/downloadElectron.ts @@ -0,0 +1,76 @@ +import { createRequire } from "node:module" +import { fileURLToPath } from "node:url" +import { isCI as isCi } from "ci-info" +import * as fs from "fs/promises" +import * as path from "path" +import { gte } from "semver" +import { ELECTRON_VERSION, getElectronCacheDir } from "./testConfig.js" + +const require = createRequire(import.meta.url) + +const executeAppBuilder: (options: any) => Promise = require(path.join(import.meta.dirname, "../../..", "packages/builder-util")).executeAppBuilder + +export async function deleteOldElectronVersion(): Promise { + // on CircleCi no need to clean manually + if (process.env.CIRCLECI || !isCi) { + return + } + + const cacheDir = getElectronCacheDir() + let files: Array + try { + files = await fs.readdir(cacheDir) + } catch (e: any) { + if (e.code === "ENOENT") { + return + } else { + throw e + } + } + return await Promise.all( + files.map(file => { + if (file.endsWith(".zip") && !file.includes(ELECTRON_VERSION)) { + console.log(`Remove old electron ${file}`) + return fs.unlink(path.join(cacheDir, file)) + } + return Promise.resolve(null) + }) + ) +} + +export function downloadAllRequiredElectronVersions(): Promise { + const platforms = process.platform === "win32" ? ["win32"] : ["darwin", "linux", "win32"] + if (process.platform === "darwin") { + platforms.push("mas") + } + + const versions: Array = [] + for (const platform of platforms) { + const archs: string[] = + platform === "mas" || platform === "darwin" + ? ["x64"] + : platform === "win32" + ? ["ia32", "x64"] + : require(`${path.join(import.meta.dirname, "../../..")}/packages/builder-util/dist/util.js`).getArchCliNames() + for (const arch of archs) { + if (gte(ELECTRON_VERSION, "19.0.0") && platform === "linux" && arch === "ia32") { + // Chromium dropped support for ia32 linux binaries in 102.0.4999.0 + // https://www.electronjs.org/docs/latest/breaking-changes#removed-ia32-linux-binaries + continue + } + versions.push({ + version: ELECTRON_VERSION, + arch, + platform, + }) + } + } + return executeAppBuilder(["download-electron", "--configuration", JSON.stringify(versions)]) +} + +if (process.argv[1] === fileURLToPath(import.meta.url)) { + downloadAllRequiredElectronVersions().catch(error => { + console.error((error.stack || error).toString()) + process.exitCode = -1 + }) +} diff --git a/test/src/helpers/fileAssert.ts b/test/src/helpers/fileAssert.ts index 97a7469262e..ea33535da24 100644 --- a/test/src/helpers/fileAssert.ts +++ b/test/src/helpers/fileAssert.ts @@ -2,14 +2,13 @@ import { exists, statOrNull } from "builder-util" import * as fs from "fs/promises" import * as path from "path" import { ExpectStatic } from "vitest" +import { PACKAGE_VERSION as appVersion } from "app-builder-lib/internal" // http://joel-costigliola.github.io/assertj/ export function assertThat(expect: ExpectStatic, actual: any): Assertions { return new Assertions(expect, actual) } -const appVersion = require(path.join(__dirname, "../../../packages/app-builder-lib/package.json")).version - class Assertions { constructor( private readonly expect: ExpectStatic, diff --git a/test/src/helpers/launchAppCrossPlatform.ts b/test/src/helpers/launchAppCrossPlatform.ts index 32d8880bd63..7f95be9718a 100644 --- a/test/src/helpers/launchAppCrossPlatform.ts +++ b/test/src/helpers/launchAppCrossPlatform.ts @@ -1,4 +1,4 @@ -import type { VmManager } from "app-builder-lib/out/vm/vm" +import type { VmManager } from "app-builder-lib/internal" import { ChildProcess, execSync, spawn, StdioOptions } from "child_process" import { createHash, randomUUID } from "crypto" import * as fs from "fs" diff --git a/test/src/helpers/packTester.ts b/test/src/helpers/packTester.ts index 005b68b7b1d..4d4300adacf 100644 --- a/test/src/helpers/packTester.ts +++ b/test/src/helpers/packTester.ts @@ -1,9 +1,6 @@ import { PublishManager } from "app-builder-lib" import { verifyAsarFileTree as _verifyAsarFileTree } from "./asarVerifier" -import { computeArchToTargetNamesMap } from "app-builder-lib/out/targets/targetFactory" -import { getLinuxToolsMacToolset } from "app-builder-lib/out/toolsets/linux" -import { parsePlistFile, PlistObject } from "app-builder-lib/out/util/plist" -import { AsarIntegrity } from "app-builder-lib/out/asar/integrity" +import { AsarIntegrity, computeArchToTargetNamesMap, getLinuxToolsMacToolset, parsePlistFile, PlistObject } from "app-builder-lib/internal" import { addValue, copyDir, exec, executeFinally, exists, FileCopier, log, USE_HARD_LINKS, walk } from "builder-util" import { CancellationToken, deepAssign, UpdateFileInfo } from "builder-util-runtime" import { Arch, ArtifactCreated, Configuration, DIR_TARGET, getArchSuffix, MacOsTargetName, Packager, PackagerOptions, Platform, Target } from "electron-builder" @@ -17,7 +14,7 @@ import * as path from "path" import pathSorter from "path-sort" import { NtExecutable, NtExecutableResource } from "resedit" import { TmpDir } from "temp-file" -import { getCollectorByPackageManager, PM } from "app-builder-lib/out/node-module-collector" +import { getCollectorByPackageManager, PM } from "app-builder-lib/internal" import { promisify } from "util" import { MAC_CSC_LINK, WIN_CSC_LINK } from "./codeSignData" import { assertThat } from "./fileAssert" @@ -25,11 +22,10 @@ import AdmZip from "adm-zip" // @ts-ignore import sanitizeFileName from "sanitize-filename" import type { ExpectStatic } from "vitest" -import { computeDefaultAppDirectory } from "app-builder-lib/out/util/config/config" -import { installDependencies } from "app-builder-lib/out/util/yarn" +import { computeDefaultAppDirectory, installDependencies } from "app-builder-lib/internal" import { ELECTRON_VERSION } from "./testConfig" import { execSync } from "child_process" -import { detectPackageManager } from "app-builder-lib/out/node-module-collector/packageManager" +import { detectPackageManager } from "app-builder-lib/internal" const PACKAGE_MANAGER_VERSION_MAP = { [PM.NPM]: { cli: "npm", version: "9.8.1" }, diff --git a/test/src/helpers/updaterTestUtil.ts b/test/src/helpers/updaterTestUtil.ts index 4355290114d..29696cdc241 100644 --- a/test/src/helpers/updaterTestUtil.ts +++ b/test/src/helpers/updaterTestUtil.ts @@ -1,11 +1,11 @@ import { NodeHttpExecutor, serializeToYaml, TmpDir } from "builder-util" import { AllPublishOptions, DownloadOptions } from "builder-util-runtime" import { AppUpdater, MacUpdater, NsisUpdater } from "electron-updater" -import { NoOpLogger, TestOnlyUpdaterOptions } from "electron-updater/out/AppUpdater" -import { outputFile, writeFile } from "fs-extra" +import { NoOpLogger, TestOnlyUpdaterOptions } from "electron-updater/internal" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "./fileAssert" -import { TestAppAdapter } from "./TestAppAdapter" +import { assertThat } from "./fileAssert.js" +import { TestAppAdapter } from "./TestAppAdapter.js" import { ExpectStatic, vi } from "vitest" const tmpDir = new TmpDir("updater-test-util") @@ -24,7 +24,7 @@ export async function createNsisUpdater(version = "0.0.1") { // to reduce difference in test mode, setFeedURL is not used to set (NsisUpdater also read configOnDisk to load original publisherName) export async function writeUpdateConfig(data: T): Promise { const updateConfigPath = path.join(await tmpDir.getTempDir({ prefix: "test-update-config" }), "app-update.yml") - await outputFile(updateConfigPath, serializeToYaml(data)) + await fsExtra.outputFile(updateConfigPath, serializeToYaml(data)) return updateConfigPath } @@ -62,7 +62,7 @@ export class TestNodeHttpExecutor extends NodeHttpExecutor { async download(url: string, destination: string, options: DownloadOptions): Promise { const obj = new URL(url) const buffer = await this.downloadToBuffer(obj, options) - await writeFile(destination, buffer) + await fsExtra.writeFile(destination, buffer) return buffer.toString() } } diff --git a/test/src/helpers/verifySmartUnpack.ts b/test/src/helpers/verifySmartUnpack.ts index 4f846e36f5d..09d0cb102dd 100644 --- a/test/src/helpers/verifySmartUnpack.ts +++ b/test/src/helpers/verifySmartUnpack.ts @@ -1,8 +1,8 @@ -import { AsarFilesystem, readAsar } from "app-builder-lib/out/asar/asar" +import { AsarFilesystem, readAsar } from "app-builder-lib/internal" import { walk } from "builder-util" import { readFileSync } from "fs" import * as path from "path" -import { toSystemIndependentPath } from "./packTester" +import { toSystemIndependentPath } from "./packTester.js" import { ExpectStatic } from "vitest" export function removeUnstableProperties(data: any) { diff --git a/test/src/helpers/winHelper.ts b/test/src/helpers/winHelper.ts index e1f38cbaa37..952a9af7a70 100644 --- a/test/src/helpers/winHelper.ts +++ b/test/src/helpers/winHelper.ts @@ -1,13 +1,13 @@ -import { readAsarJson } from "app-builder-lib/out/asar/asar" +import { readAsarJson } from "app-builder-lib/internal" import { walk } from "builder-util" import { Arch, Platform } from "electron-builder" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import * as fs from "fs/promises" import { load } from "js-yaml" import * as path from "path" -import { assertThat } from "./fileAssert" -import { PackedContext } from "./packTester" -import { diff, WineManager } from "./wine" +import { assertThat } from "./fileAssert.js" +import { PackedContext } from "./packTester.js" +import { diff, WineManager } from "./wine.js" import { ExpectStatic } from "vitest" export async function expectUpdateMetadata(expect: ExpectStatic, context: PackedContext, arch: Arch = Arch.ia32, requireCodeSign: boolean = false): Promise { @@ -91,7 +91,7 @@ export async function doTest( // run installer again to test uninstall const appDataFile = path.join(wine.userDir!, "Application Data", name, "doNotDeleteMe") - await outputFile(appDataFile, "app data must be not removed") + await fsExtra.outputFile(appDataFile, "app data must be not removed") fsBefore = await listFiles() await wine.exec(path.join(outDir, `${productFilename} Setup 1.1.0.exe`), "/S") fsAfter = await listFiles() diff --git a/test/src/helpers/wine.ts b/test/src/helpers/wine.ts index 82c2d118a6e..5296f4ee879 100644 --- a/test/src/helpers/wine.ts +++ b/test/src/helpers/wine.ts @@ -1,5 +1,5 @@ import { exec, safeStringifyJson, unlinkIfExists } from "builder-util" -import { emptyDir } from "fs-extra" +import fsExtra from "fs-extra" import * as fs from "fs/promises" import { homedir } from "os" import * as path from "path" @@ -37,7 +37,7 @@ export class WineManager { } async prepareWine(wineDir: string) { - await emptyDir(wineDir) + await fsExtra.emptyDir(wineDir) //noinspection SpellCheckingInspection const env = { ...process.env, diff --git a/test/src/httpExecutorTest.ts b/test/src/httpExecutorTest.ts index 40614f82877..be95fdf0408 100644 --- a/test/src/httpExecutorTest.ts +++ b/test/src/httpExecutorTest.ts @@ -1,5 +1,5 @@ import { expect, test, describe } from "vitest" -import { HttpExecutor } from "builder-util-runtime/src/httpExecutor" +import { HttpExecutor } from "builder-util-runtime" import { RequestOptions } from "http" describe("HttpExecutor.prepareRedirectUrlOptions", () => { @@ -506,7 +506,6 @@ describe("HttpExecutor.prepareRedirectUrlOptions", () => { }) }) -// @ts-ignore describe("HttpExecutor.isCrossOriginRedirect", () => { const testCases: Array<{ name: string; url1: string; url2: string; expected: boolean }> = [ { diff --git a/test/src/iconConverterTest.ts b/test/src/iconConverterTest.ts index b2632d63414..7e54cfbf8be 100644 --- a/test/src/iconConverterTest.ts +++ b/test/src/iconConverterTest.ts @@ -3,7 +3,7 @@ import { mkdir, mkdtemp, readFile, rm, writeFile } from "fs/promises" import * as os from "os" import * as path from "path" import { afterEach, beforeEach, describe, expect, it } from "vitest" -import { buildSourceCandidates, convertIcon, getPngSize } from "app-builder-lib/out/util/iconConverter" +import { buildSourceCandidates, convertIcon, getPngSize } from "app-builder-lib/internal" const FIXTURES = path.join(__dirname, "../fixtures") const TEST_APP_ICONS = path.join(FIXTURES, "test-app-one/build") @@ -33,7 +33,7 @@ const CRC_TABLE = (() => { function crc32(buf: Buffer): number { let crc = 0xffffffff for (const byte of buf) { - crc = CRC_TABLE[(crc ^ byte) & 0xff]! ^ (crc >>> 8) + crc = CRC_TABLE[(crc ^ byte) & 0xff] ^ (crc >>> 8) } return (crc ^ 0xffffffff) >>> 0 } @@ -80,14 +80,20 @@ async function writePng(size: number, filePath: string): Promise { function parseIcns(data: Buffer): Map { const magic = data.toString("ascii", 0, 4) - if (magic !== "icns") throw new Error(`Not an ICNS file (got ${magic})`) + if (magic !== "icns") { + throw new Error(`Not an ICNS file (got ${magic})`) + } const entries = new Map() let offset = 8 while (offset < data.length) { - if (offset + 8 > data.length) break + if (offset + 8 > data.length) { + break + } const ostype = data.toString("ascii", offset, offset + 4) const len = data.readUInt32BE(offset + 4) - if (len < 8) break + if (len < 8) { + break + } entries.set(ostype, data.subarray(offset + 8, offset + len)) offset += len } diff --git a/test/src/ignoreTest.ts b/test/src/ignoreTest.ts index efe4153009c..49aa86580ea 100644 --- a/test/src/ignoreTest.ts +++ b/test/src/ignoreTest.ts @@ -1,9 +1,9 @@ import { DIR_TARGET, Platform, archFromString } from "electron-builder" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "./helpers/fileAssert" -import { app, checkDirContents, linuxDirTarget, modifyPackageJson } from "./helpers/packTester" -import { PM } from "app-builder-lib/out/node-module-collector/packageManager" +import { assertThat } from "./helpers/fileAssert.js" +import { app, checkDirContents, linuxDirTarget, modifyPackageJson } from "./helpers/packTester.js" +import { PM } from "app-builder-lib/internal" const currentProcessTarget = Platform.LINUX.createTarget(DIR_TARGET, archFromString(process.arch)) @@ -18,7 +18,7 @@ test.ifNotWindows("ignore build resources", ({ expect }) => }, { projectDirCreated: projectDir => { - return outputFile(path.join(projectDir, "one/build/foo.txt"), "data") + return fsExtra.outputFile(path.join(projectDir, "one/build/foo.txt"), "data") }, packed: context => { return assertThat(expect, path.join(context.getResources(Platform.LINUX), "app", "one", "build", "foo.txt")).isFile() @@ -47,7 +47,7 @@ test.ifNotWindows("2 ignore", ({ expect }) => }, { projectDirCreated: projectDir => { - return outputFile(path.join(projectDir, "electron/foo.txt"), "data") + return fsExtra.outputFile(path.join(projectDir, "electron/foo.txt"), "data") }, packed: context => { return assertThat(expect, path.join(context.getResources(Platform.LINUX), "app", "electron", "foo.txt")).doesNotExist() @@ -68,10 +68,10 @@ test.ifNotWindows("ignore known ignored files", ({ expect }) => { projectDirCreated: projectDir => Promise.all([ - outputFile(path.join(projectDir, ".svn", "foo"), "data"), - outputFile(path.join(projectDir, ".git", "foo"), "data"), - outputFile(path.join(projectDir, "node_modules", ".bin", "f.txt"), "data"), - outputFile(path.join(projectDir, "node_modules", ".bin2", "f.txt"), "data"), + fsExtra.outputFile(path.join(projectDir, ".svn", "foo"), "data"), + fsExtra.outputFile(path.join(projectDir, ".git", "foo"), "data"), + fsExtra.outputFile(path.join(projectDir, "node_modules", ".bin", "f.txt"), "data"), + fsExtra.outputFile(path.join(projectDir, "node_modules", ".bin2", "f.txt"), "data"), ]), packed: context => checkDirContents(expect, path.join(context.getResources(Platform.LINUX), "app")), } @@ -128,8 +128,8 @@ test.ifNotWindows("copied sub node_modules of the rootDir/node_modules", ({ expe ...data.dependencies, } }), - outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), - outputFile(path.join(projectDir, "others", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "others", "node_modules", "package.json"), "{}"), ]) }, packed: context => { @@ -164,10 +164,10 @@ test.ifNotWindows("Don't copy sub node_modules of the other dir instead of rootD ...data.dependencies, } }), - outputFile(path.join(projectDir, "others", "node_modules", "package.json"), "{}"), - outputFile(path.join(projectDir, "others", "test1", "package.json"), "{}"), - outputFile(path.join(projectDir, "others", "submodule-2-test", "node_modules", "package.json"), "{}"), - outputFile(path.join(projectDir, "others", "submodule-2-test", "test2", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "others", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "others", "test1", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "others", "submodule-2-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "others", "submodule-2-test", "test2", "package.json"), "{}"), ]) }, packed: context => { @@ -205,8 +205,8 @@ test.ifNotWindows("copied select submodule node_modules", ({ expect }) => ...data.dependencies, } }), - outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), - outputFile(path.join(projectDir, "submodule-2-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "submodule-2-test", "node_modules", "package.json"), "{}"), ]) }, packed: context => { @@ -238,7 +238,7 @@ test.ifNotWindows("cannot copied select submodule node_modules by */", ({ expect ...data.dependencies, } }), - outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), ]) }, packed: context => { @@ -268,7 +268,7 @@ test.ifNotWindows("cannot copied select submodule node_modules by **/submodule-1 ...data.dependencies, } }), - outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), + fsExtra.outputFile(path.join(projectDir, "submodule-1-test", "node_modules", "package.json"), "{}"), ]) }, packed: context => { diff --git a/test/src/linux/appImageTest.ts b/test/src/linux/appImageTest.ts index 25378c2229d..e4bfcaeb4af 100644 --- a/test/src/linux/appImageTest.ts +++ b/test/src/linux/appImageTest.ts @@ -1,6 +1,5 @@ import { Platform } from "app-builder-lib/src" -import { validateCriticalPathString } from "app-builder-lib/src/targets/appimage/appImageUtil" -import { copyMimeTypes } from "app-builder-lib/src/targets/appimage/appLauncher" +import { copyMimeTypes, validateCriticalPathString } from "app-builder-lib/internal" import { Arch, InvalidConfigurationError, TmpDir } from "builder-util" import { execSync, spawnSync } from "child_process" import * as fs from "fs-extra" @@ -68,7 +67,7 @@ describe("copyMimeTypes - invalid extension handling", () => { executableName: "testapp", }) expect(result).not.toBeNull() - const xml = await fs.readFile(path.join(dir, result!), "utf8") + const xml = await fs.readFile(path.join(dir, result), "utf8") expect(xml).not.toContain('') }) @@ -80,7 +79,7 @@ describe("copyMimeTypes - invalid extension handling", () => { executableName: "testapp", }) expect(result).not.toBeNull() - const xml = await fs.readFile(path.join(dir, result!), "utf8") + const xml = await fs.readFile(path.join(dir, result), "utf8") expect(xml).toContain('') }) }) diff --git a/test/src/linux/flatpakTest.ts b/test/src/linux/flatpakTest.ts index 7eb8719bf72..8af24b97bb2 100644 --- a/test/src/linux/flatpakTest.ts +++ b/test/src/linux/flatpakTest.ts @@ -1,5 +1,5 @@ import { Platform } from "electron-builder" -import { app } from "../helpers/packTester" +import { app } from "../helpers/packTester.js" import * as which from "which" describe.heavy.ifEnv(which.sync("flatpak", { nothrow: true }) != null)("Linux Flatpak Test", () => { diff --git a/test/src/linux/fpmTest.ts b/test/src/linux/fpmTest.ts index 5ed8b74353b..182c1d9590b 100644 --- a/test/src/linux/fpmTest.ts +++ b/test/src/linux/fpmTest.ts @@ -1,5 +1,5 @@ import { Arch, Platform } from "electron-builder" -import { app, EXTENDED_TIMEOUT } from "../helpers/packTester" +import { app, EXTENDED_TIMEOUT } from "../helpers/packTester.js" // "apk" is very slow, don't test for now describe.heavy.ifNotWindows("fpm", () => { diff --git a/test/src/linux/linuxArchiveTest.ts b/test/src/linux/linuxArchiveTest.ts index d46f84dd55c..ac4bb5808f2 100644 --- a/test/src/linux/linuxArchiveTest.ts +++ b/test/src/linux/linuxArchiveTest.ts @@ -1,5 +1,5 @@ import { Arch, Platform } from "electron-builder" -import { app, EXTENDED_TIMEOUT } from "../helpers/packTester" +import { app, EXTENDED_TIMEOUT } from "../helpers/packTester.js" test.ifNotWindows("tar", { timeout: EXTENDED_TIMEOUT }, ({ expect }) => app(expect, { diff --git a/test/src/linux/linuxPackagerTest.ts b/test/src/linux/linuxPackagerTest.ts new file mode 100644 index 00000000000..c1ea5318e5b --- /dev/null +++ b/test/src/linux/linuxPackagerTest.ts @@ -0,0 +1,351 @@ +import { GenericServerOptions } from "builder-util-runtime" +import { Arch, build, Platform } from "electron-builder" +import fsExtra from "fs-extra" +import * as fs from "fs/promises" +import * as path from "path" +import { assertThat } from "../helpers/fileAssert.js" +import { app, appThrows, copyTestAsset, modifyPackageJson } from "../helpers/packTester.js" +import { ELECTRON_VERSION } from "../helpers/testConfig.js" +import { ToolsetConfig } from "app-builder-lib" + +const appImageTarget = Platform.LINUX.createTarget("appimage", Arch.x64) + +// test update info file name +const testPublishConfig: GenericServerOptions = { + provider: "generic", + url: "https://example.com/download", +} + +const appImageToolset: ToolsetConfig["appimage"][] = ["0.0.0", "1.0.2", "1.0.3"] +describe.ifNotWindows("LinuxPackager", () => { + for (const appimage of appImageToolset) { + const toolsets: ToolsetConfig = { + appimage, + } + describe(`AppImage toolset ${appimage}`, () => { + test("AppImage", ({ expect }) => + app(expect, { + targets: appImageTarget, + config: { + toolsets, + directories: { + output: "dist/${os}", + }, + downloadAlternateFFmpeg: true, + publish: testPublishConfig, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + })) + + test("AppImage arm, max compression", ({ expect }) => + app(expect, { + targets: Platform.LINUX.createTarget("Appimage", Arch.armv7l), + config: { + toolsets, + publish: testPublishConfig, + compression: "maximum", + }, + })) + + test("AppImage - deprecated systemIntegration", ({ expect }) => + appThrows(expect, { + targets: appImageTarget, + config: { + toolsets, + appImage: { + systemIntegration: "doNotAsk", + } as any, + }, + })) + + test("text license and file associations", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + extraResources: { + from: "build/icons", + }, + fileAssociations: [ + { + ext: "my-app", + name: "Test Foo", + mimeType: "application/x-example", + }, + ], + }, + }, + { + projectDirCreated: projectDir => { + return Promise.all([ + // copy full text to test presentation + copyTestAsset("license_en.txt", path.join(projectDir, "build", "license.txt")), + ]) + }, + } + )) + + test("html license", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + }, + }, + { + projectDirCreated: projectDir => { + return fsExtra.outputFile( + path.join(projectDir, "build", "license.html"), + ` + + + Test link + + ` + ) + }, + } + )) + + test("AppImage - default icon, custom executable and custom desktop", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + linux: { + executableName: "Foo", + // Example Spec: https://specifications.freedesktop.org/desktop-entry-spec/latest/example.html + desktop: { + entry: { + "X-Foo": "bar", + Terminal: "true", + }, + desktopActions: { + Gallery: { + Exec: "fooview --gallery", + Name: "Browse Gallery", + }, + Create: { + Exec: "fooview --create-new", + Name: "Create a new Foo!", + Icon: "fooview-new", + }, + EmptyEntry: {}, + NullEntry: null, + }, + }, + }, + appImage: { + // tslint:disable-next-line:no-invalid-template-strings + artifactName: "boo-${productName}", + }, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + effectiveOptionComputed: async it => { + const content: string = it.desktop + expect( + content + .split("\n") + .filter(it => !it.includes("X-AppImage-BuildId") && !it.includes("X-AppImage-Version")) + .join("\n") + ).toMatchSnapshot() + return Promise.resolve(false) + }, + }, + { + projectDirCreated: it => fs.rm(path.join(it, "build"), { recursive: true, force: true }), + packed: async context => { + const projectDir = context.getContent(Platform.LINUX) + await assertThat(expect, path.join(projectDir, "Foo")).isFile() + }, + } + )) + + test("icons from ICNS (mac)", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + publish: null, + mac: { + icon: "resources/time.icns", + }, + // test https://github.com/electron-userland/electron-builder/issues/3510 + linux: { + artifactName: "app-${version}-${arch}.${ext}", + }, + }, + }, + { + projectDirCreated: async projectDir => { + await fs + .mkdir(path.join(projectDir, "resources"), { recursive: true }) + .then(() => fs.rename(path.join(projectDir, "build", "icon.icns"), path.join(projectDir, "resources", "time.icns"))) + await fs.rm(path.join(projectDir, "build"), { recursive: true, force: true }) + }, + packed: async context => { + const projectDir = context.getResources(Platform.LINUX) + await assertThat(expect, projectDir).isDirectory() + }, + } + )) + + test("icons from ICNS if nothing specified", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + publish: null, + }, + }, + { + projectDirCreated: async projectDir => { + await fs.rm(path.join(projectDir, "build", "icons"), { recursive: true, force: true }) + }, + } + )) + + test("icons from dir and one icon with suffix", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + publish: null, + }, + }, + { + projectDirCreated: async projectDir => { + await fs.copyFile(path.join(projectDir, "build", "icons", "16x16.png"), path.join(projectDir, "build", "icons", "16x16-dev.png")) + }, + packed: async context => { + const projectDir = context.getResources(Platform.LINUX) + await assertThat(expect, projectDir).isDirectory() + }, + } + )) + + test("icons dir with images without size in the filename", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + publish: null, + win: { + // doesn't matter, but just to be sure that presence of this configuration doesn't lead to errors + icon: "icons/icon.ico", + }, + }, + }, + { + projectDirCreated: async projectDir => { + await fs.rename(path.join(projectDir, "build", "icons", "256x256.png"), path.join(projectDir, "build", "icon.png")) + await fs.rm(path.join(projectDir, "build", "icons"), { recursive: true, force: true }) + await fs.rename(path.join(projectDir, "build"), path.join(projectDir, "icons")) + }, + packed: async context => { + const projectDir = context.getResources(Platform.LINUX) + await assertThat(expect, projectDir).isDirectory() + }, + } + )) + + // test prepacked asar also https://github.com/electron-userland/electron-builder/issues/1102 + test("icons from ICNS", ({ expect }) => + app( + expect, + { + targets: appImageTarget, + config: { + toolsets, + publish: null, + }, + }, + { + projectDirCreated: it => fs.rm(path.join(it, "build", "icons"), { recursive: true, force: true }), + packed: async context => { + const projectDir = context.getResources(Platform.LINUX) + + await fs.rm(path.join(projectDir, "inspector"), { recursive: true, force: true }) + + await build({ + targets: appImageTarget, + projectDir, + publish: "never", + config: { + electronVersion: ELECTRON_VERSION, + compression: "store", + npmRebuild: false, + }, + }) + + await assertThat(expect, path.join(projectDir, "dist")).isDirectory() + }, + } + )) + + test("no-author-email", ({ expect }) => + appThrows( + expect, + { + targets: Platform.LINUX.createTarget("deb", Arch.x64), + config: { + toolsets, + }, + }, + { + projectDirCreated: projectDir => + modifyPackageJson(projectDir, data => { + data.author = "Foo" + }), + } + )) + + test("forbid desktop.Exec", ({ expect }) => + appThrows(expect, { + targets: appImageTarget, + config: { + toolsets, + linux: { + desktop: { + entry: { + Exec: "foo", + }, + }, + }, + }, + })) + }) + } +}) diff --git a/test/src/linux/snapTest.ts b/test/src/linux/snapTest.ts index 4d1014b7be6..eb7fc54eee3 100644 --- a/test/src/linux/snapTest.ts +++ b/test/src/linux/snapTest.ts @@ -1,5 +1,5 @@ import { Arch, Platform } from "electron-builder" -import { app, assertPack, snapTarget } from "../helpers/packTester" +import { app, assertPack, snapTarget } from "../helpers/packTester.js" test.ifNotWindows("snap", ({ expect }) => app(expect, { diff --git a/test/src/linux/snapcraftParallelsTest.ts b/test/src/linux/snapcraftParallelsTest.ts index 07e60271d7f..4ef6c4c965c 100644 --- a/test/src/linux/snapcraftParallelsTest.ts +++ b/test/src/linux/snapcraftParallelsTest.ts @@ -1,7 +1,7 @@ import { DebugLogger } from "builder-util" -import { log } from "builder-util/out/util" +import { log } from "builder-util/src/util" import { Platform } from "electron-builder" -import { getLinuxVm } from "app-builder-lib/out/vm/vm" +import { getLinuxVm } from "app-builder-lib/internal" import { readdir } from "fs/promises" import * as path from "path" import { assertPack, EXTENDED_TIMEOUT } from "../helpers/packTester" diff --git a/test/src/mac/MacTargetHelperTest.ts b/test/src/mac/MacTargetHelperTest.ts index 51d3c205d56..796e26f985d 100644 --- a/test/src/mac/MacTargetHelperTest.ts +++ b/test/src/mac/MacTargetHelperTest.ts @@ -1,5 +1,5 @@ import { afterEach, expect } from "vitest" -import { MacTargetHelper } from "app-builder-lib/out/mac/MacTargetHelper" +import { MacTargetHelper } from "app-builder-lib/internal" describe("MacTargetHelper", () => { describe("getCertificateTypes", () => { diff --git a/test/src/mac/dmgLicenseTest.ts b/test/src/mac/dmgLicenseTest.ts index 6b7bfca4f06..ad56c143e42 100644 --- a/test/src/mac/dmgLicenseTest.ts +++ b/test/src/mac/dmgLicenseTest.ts @@ -218,7 +218,7 @@ describe("addLicenseToDmg", () => { const result = await addLicenseToDmg(packager) - expect(Object.keys(result!.buttons!).sort()).toEqual(["en_US", "fr_FR"]) + expect(Object.keys(result!.buttons).sort()).toEqual(["en_US", "fr_FR"]) expect(result!.buttons!["en_US"].language).toBe("English") expect(result!.buttons!["fr_FR"].language).toBe("Français") }) diff --git a/test/src/mac/dmgTest.ts b/test/src/mac/dmgTest.ts index 6501659640b..ad374ced3e6 100644 --- a/test/src/mac/dmgTest.ts +++ b/test/src/mac/dmgTest.ts @@ -4,10 +4,10 @@ import { Arch, copyFile, exec } from "builder-util" import { Platform } from "electron-builder" import * as fs from "fs/promises" import * as path from "path" -import { assertThat } from "../helpers/fileAssert" -import { app, assertPack, copyTestAsset } from "../helpers/packTester" +import { assertThat } from "../helpers/fileAssert.js" +import { app, assertPack, copyTestAsset } from "../helpers/packTester.js" import { beforeAll } from "vitest" -import type { attachAndExecute as aAndE, getDmgTemplatePath as dmgTemplate } from "dmg-builder/out/dmgUtil" +import type { attachAndExecute as aAndE, getDmgTemplatePath as dmgTemplate } from "dmg-builder" const dmgTarget = Platform.MAC.createTarget("dmg", Arch.x64) const defaultTarget = Platform.MAC.createTarget(undefined, Arch.x64) @@ -18,7 +18,7 @@ describe.heavy.ifMac("dmg", { sequential: true }, () => { beforeAll(async () => { // import at runtime to avoid issues on non-macOS platforms - const { attachAndExecute: a, getDmgTemplatePath: d } = await import("dmg-builder/out/dmgUtil") + const { attachAndExecute: a, getDmgTemplatePath: d } = await import("dmg-builder") attachAndExecute = a getDmgTemplatePath = d }) diff --git a/test/src/mac/macArchiveTest.ts b/test/src/mac/macArchiveTest.ts index 2843d231dfe..814f608482b 100644 --- a/test/src/mac/macArchiveTest.ts +++ b/test/src/mac/macArchiveTest.ts @@ -1,12 +1,12 @@ import { Arch, exec } from "builder-util" import { parseXml } from "builder-util-runtime" import { Platform } from "electron-builder" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import * as fs from "fs/promises" import * as path from "path" import pathSorter from "path-sort" -import { assertThat } from "../helpers/fileAssert" -import { app, copyTestAsset, createMacTargetTest, getFixtureDir, parseFileList } from "../helpers/packTester" +import { assertThat } from "../helpers/fileAssert.js" +import { app, copyTestAsset, createMacTargetTest, getFixtureDir, parseFileList } from "../helpers/packTester.js" test.ifMac("invalid target", ({ expect }) => expect(createMacTargetTest(expect, ["ttt" as any])).rejects.toThrow()) @@ -54,7 +54,7 @@ test.ifMac("extraDistFiles", ({ expect }) => { signed: false, projectDirCreated: projectDir => { - return Promise.all([outputFile(path.join(projectDir, "extra.txt"), "test")]) + return Promise.all([fsExtra.outputFile(path.join(projectDir, "extra.txt"), "test")]) }, } ) diff --git a/test/src/mac/macCodeSignTest.ts b/test/src/mac/macCodeSignTest.ts index 324b88d6c78..dd7b045f3c2 100644 --- a/test/src/mac/macCodeSignTest.ts +++ b/test/src/mac/macCodeSignTest.ts @@ -1,6 +1,6 @@ -import { createKeychain, removeKeychain } from "app-builder-lib/out/codeSign/macCodeSign" +import { createKeychain, removeKeychain } from "app-builder-lib/internal" import { removePassword, TmpDir } from "builder-util" -import { MAC_CSC_LINK } from "../helpers/codeSignData" +import { MAC_CSC_LINK } from "../helpers/codeSignData.js" import { afterEach } from "vitest" describe.ifMac.runIf(MAC_CSC_LINK && process.env.CSC_KEY_PASSWORD)("macos keychain", { sequential: true }, () => { diff --git a/test/src/mac/macIconTest.ts b/test/src/mac/macIconTest.ts index 18473bd5b7d..8fcdb753147 100644 --- a/test/src/mac/macIconTest.ts +++ b/test/src/mac/macIconTest.ts @@ -1,9 +1,9 @@ -import { parsePlistFile, PlistObject } from "app-builder-lib/out/util/plist" +import { parsePlistFile, PlistObject } from "app-builder-lib/internal" import { Arch, DIR_TARGET, Platform } from "electron-builder" import * as fs from "fs/promises" import * as path from "path" -import { CheckingMacPackager } from "../helpers/CheckingPackager" -import { app } from "../helpers/packTester" +import { CheckingMacPackager } from "../helpers/CheckingPackager.js" +import { app } from "../helpers/packTester.js" import { ExpectStatic } from "vitest" async function assertIcon(expect: ExpectStatic, platformPackager: CheckingMacPackager) { @@ -19,7 +19,7 @@ async function assertIcon(expect: ExpectStatic, platformPackager: CheckingMacPac const targets = Platform.MAC.createTarget(DIR_TARGET, Arch.x64) -const iconComposerFixture = path.join(__dirname, "..", "..", "fixtures", "macos-icon-composer-assets", "electron.icon") +const iconComposerFixture = path.join(import.meta.dirname, "..", "..", "fixtures", "macos-icon-composer-assets", "electron.icon") test.ifMac("icon composer generate asset catalog", ({ expect }) => { return app( diff --git a/test/src/mac/masTest.ts b/test/src/mac/masTest.ts index 7534cef4b07..b0d57625b5b 100644 --- a/test/src/mac/masTest.ts +++ b/test/src/mac/masTest.ts @@ -1,7 +1,7 @@ import { Arch, Platform } from "electron-builder" import * as path from "path" -import { CheckingMacPackager } from "../helpers/CheckingPackager" -import { assertPack, createMacTargetTest, signed } from "../helpers/packTester" +import { CheckingMacPackager } from "../helpers/CheckingPackager.js" +import { assertPack, createMacTargetTest, signed } from "../helpers/packTester.js" describe.ifEnv(process.platform === "darwin" && process.env.CSC_KEY_PASSWORD != null)("mas", () => { test("mas", ({ expect }) => createMacTargetTest(expect, ["mas"])) diff --git a/test/src/macroExpanderTest.ts b/test/src/macroExpanderTest.ts index 6cdb81fc3a4..1eb073d8ed1 100644 --- a/test/src/macroExpanderTest.ts +++ b/test/src/macroExpanderTest.ts @@ -1,4 +1,4 @@ -import { expandMacro } from "app-builder-lib/out/util/macroExpander" +import { expandMacro } from "app-builder-lib/internal" const appInfoStub: any = { sanitizedProductName: "1", diff --git a/test/src/mainEntryTest.ts b/test/src/mainEntryTest.ts index 15237cb87f7..72d2904a7ab 100644 --- a/test/src/mainEntryTest.ts +++ b/test/src/mainEntryTest.ts @@ -1,7 +1,7 @@ import { createTargets, DIR_TARGET, Platform } from "electron-builder" import * as fs from "fs/promises" import * as path from "path" -import { appTwoThrows, assertPack, modifyPackageJson } from "./helpers/packTester" +import { appTwoThrows, assertPack, modifyPackageJson } from "./helpers/packTester.js" const packagerOptions = { targets: createTargets([Platform.LINUX, Platform.MAC], DIR_TARGET), diff --git a/test/src/node-module-collector/moduleManagerTest.ts b/test/src/node-module-collector/moduleManagerTest.ts index 7df98e48cbf..f4bea8afadd 100644 --- a/test/src/node-module-collector/moduleManagerTest.ts +++ b/test/src/node-module-collector/moduleManagerTest.ts @@ -2,7 +2,7 @@ import { afterEach, describe, test } from "vitest" import * as fse from "fs-extra" import * as os from "os" import * as path from "path" -import { ModuleManager, LogMessageByKey } from "app-builder-lib/src/node-module-collector/moduleManager" +import { ModuleManager, LogMessageByKey } from "app-builder-lib/internal" // --------------------------------------------------------------------------- // Helpers @@ -84,7 +84,9 @@ describe("ModuleManager.locatePackageVersion", () => { describe("upward (hoisted) resolution", () => { let root = "" afterEach(async () => { - if (root) await fse.rm(root, { recursive: true, force: true }) + if (root) { + await fse.rm(root, { recursive: true, force: true }) + } }) test("finds hoisted package that satisfies range", async ({ expect }) => { @@ -108,7 +110,9 @@ describe("ModuleManager.locatePackageVersion", () => { describe("override fallback (two-pass search)", () => { let root = "" afterEach(async () => { - if (root) await fse.rm(root, { recursive: true, force: true }) + if (root) { + await fse.rm(root, { recursive: true, force: true }) + } }) test("accepts package whose installed version is outside the declared range", async ({ expect }) => { @@ -192,7 +196,9 @@ describe("ModuleManager.locatePackageVersion", () => { describe("ModuleManager downward search", () => { let root = "" afterEach(async () => { - if (root) await fse.rm(root, { recursive: true, force: true }) + if (root) { + await fse.rm(root, { recursive: true, force: true }) + } }) test("finds package nested under another package's node_modules", async ({ expect }) => { @@ -283,7 +289,9 @@ describe("ModuleManager downward search", () => { describe("ModuleManager.semverSatisfies (via locatePackageVersion)", () => { let root = "" afterEach(async () => { - if (root) await fse.rm(root, { recursive: true, force: true }) + if (root) { + await fse.rm(root, { recursive: true, force: true }) + } }) async function locateWith(version: string, range: string): Promise<{ found: boolean; usedFallback: boolean }> { diff --git a/test/src/node-module-collector/pnpmHoistedTest.ts b/test/src/node-module-collector/pnpmHoistedTest.ts index b5725f84c61..139cdd8ba5a 100644 --- a/test/src/node-module-collector/pnpmHoistedTest.ts +++ b/test/src/node-module-collector/pnpmHoistedTest.ts @@ -2,7 +2,7 @@ import { describe, test, vi, afterEach } from "vitest" import * as fse from "fs-extra" import * as os from "os" import * as path from "path" -import { ModuleManager } from "app-builder-lib/src/node-module-collector/moduleManager" +import { ModuleManager } from "app-builder-lib/internal" // --------------------------------------------------------------------------- // Helpers diff --git a/test/src/node-module-collector/streamCollectorTest.ts b/test/src/node-module-collector/streamCollectorTest.ts index b07e80815de..d54cbd672e7 100644 --- a/test/src/node-module-collector/streamCollectorTest.ts +++ b/test/src/node-module-collector/streamCollectorTest.ts @@ -1,7 +1,5 @@ import { afterEach, beforeEach, describe, test, vi } from "vitest" -import { NodeModulesCollector } from "app-builder-lib/src/node-module-collector/nodeModulesCollector" -import { LogMessageByKey } from "app-builder-lib/src/node-module-collector/moduleManager" -import { PM } from "app-builder-lib/src/node-module-collector/packageManager" +import { LogMessageByKey, NodeModulesCollector, PM } from "app-builder-lib/internal" import * as childProcess from "child_process" import * as fsExtra from "fs-extra" import type { TmpDir } from "builder-util" diff --git a/test/src/node-module-collector/traversalCollectorTest.ts b/test/src/node-module-collector/traversalCollectorTest.ts index aae61f33dd5..ba62573a575 100644 --- a/test/src/node-module-collector/traversalCollectorTest.ts +++ b/test/src/node-module-collector/traversalCollectorTest.ts @@ -2,8 +2,7 @@ import { afterEach, describe, test, vi } from "vitest" import * as fse from "fs-extra" import * as os from "os" import * as path from "path" -import { TraversalNodeModulesCollector } from "app-builder-lib/src/node-module-collector/traversalNodeModulesCollector" -import { LogMessageByKey } from "app-builder-lib/src/node-module-collector/moduleManager" +import { LogMessageByKey, TraversalNodeModulesCollector } from "app-builder-lib/internal" import type { TmpDir } from "builder-util" // --------------------------------------------------------------------------- diff --git a/test/src/packageManagerTest.ts b/test/src/packageManagerTest.ts index 9a9b8002dd2..362ca530d3e 100644 --- a/test/src/packageManagerTest.ts +++ b/test/src/packageManagerTest.ts @@ -1,10 +1,10 @@ import { Platform } from "app-builder-lib" -import { PM } from "app-builder-lib/src/node-module-collector" -import { copyFile, outputFile, rm, writeFile } from "fs-extra" +import { PM } from "app-builder-lib/internal" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "./helpers/fileAssert" -import { app, assertPack, getFixtureDir, getPackageManagerWithVersion, linuxDirTarget, modifyPackageJson, verifyAsarFileTree } from "./helpers/packTester" -import { ELECTRON_VERSION } from "./helpers/testConfig" +import { assertThat } from "./helpers/fileAssert.js" +import { app, assertPack, getFixtureDir, getPackageManagerWithVersion, linuxDirTarget, modifyPackageJson, verifyAsarFileTree } from "./helpers/packTester.js" +import { ELECTRON_VERSION } from "./helpers/testConfig.js" import { isEmptyOrSpaces, spawn } from "builder-util" import * as which from "which" @@ -48,10 +48,10 @@ describe("Package Managers", () => { false ) await modifyPackageJson(projectDir, data => packageConfig(data, yarnVersion), true) - await writeFile(path.join(projectDir, "yarn.lock"), "") - await writeFile(path.join(projectDir, "app", "yarn.lock"), "") - await copyFile(path.join(getFixtureDir(), ".pnp.cjs"), path.join(projectDir, ".pnp.cjs")) - await rm(path.join(projectDir, ".yarnrc.yml")) + await fsExtra.writeFile(path.join(projectDir, "yarn.lock"), "") + await fsExtra.writeFile(path.join(projectDir, "app", "yarn.lock"), "") + await fsExtra.copyFile(path.join(getFixtureDir(), ".pnp.cjs"), path.join(projectDir, ".pnp.cjs")) + await fsExtra.rm(path.join(projectDir, ".yarnrc.yml")) await spawn("yarn", ["install"], { cwd: projectDir, env: testEnv, @@ -85,9 +85,9 @@ describe("Package Managers", () => { false ) await modifyPackageJson(projectDir, data => packageConfig(data, yarnBerryVersion), true) - await writeFile(path.join(projectDir, "yarn.lock"), "") - await writeFile(path.join(projectDir, "app", "yarn.lock"), "") - await copyFile(path.join(getFixtureDir(), ".pnp.cjs"), path.join(projectDir, ".pnp.cjs")) + await fsExtra.writeFile(path.join(projectDir, "yarn.lock"), "") + await fsExtra.writeFile(path.join(projectDir, "app", "yarn.lock"), "") + await fsExtra.copyFile(path.join(getFixtureDir(), ".pnp.cjs"), path.join(projectDir, ".pnp.cjs")) await spawn("yarn", ["install"], { cwd: projectDir, env: testEnv, @@ -255,7 +255,7 @@ describe("Package Managers", () => { "left-pad": "1.3.0", } }), - outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "isolated"\n'), + fsExtra.outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "isolated"\n'), ]) }, packed: context => verifyAsarFileTree(expect, context.getResources(Platform.LINUX)), @@ -298,7 +298,7 @@ describe("Package Managers", () => { "is-bigint": "1.0.4", } }), - outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "isolated"\n'), + fsExtra.outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "isolated"\n'), ]) }, packed: context => verifyAsarFileTree(expect, context.getResources(Platform.LINUX)), @@ -339,7 +339,7 @@ describe("Package Managers", () => { "left-pad": "1.3.0", } }), - outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "hoisted"\n'), + fsExtra.outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "hoisted"\n'), ]) }, packed: context => verifyAsarFileTree(expect, context.getResources(Platform.LINUX)), @@ -382,7 +382,7 @@ describe("Package Managers", () => { "is-bigint": "1.0.4", } }), - outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "hoisted"\n'), + fsExtra.outputFile(path.join(projectDir, "bunfig.toml"), '[install]\nlinker = "hoisted"\n'), ]) }, packed: context => verifyAsarFileTree(expect, context.getResources(Platform.LINUX)), @@ -409,8 +409,8 @@ describe("Package Managers", () => { false ) await modifyPackageJson(projectDir, data => packageConfig(data, yarnBerryVersion), true) - await writeFile(path.join(projectDir, "yarn.lock"), "") - await writeFile(path.join(projectDir, "app", "yarn.lock"), "") + await fsExtra.writeFile(path.join(projectDir, "yarn.lock"), "") + await fsExtra.writeFile(path.join(projectDir, "app", "yarn.lock"), "") }, } )) @@ -477,8 +477,8 @@ describe("Package Managers", () => { projectDirCreated: async (projectDir, tmpDir, testEnv) => { const tempDir = await tmpDir.getTempDir() const localPath = path.join(tempDir, "foo") - await outputFile(path.join(localPath, "package.json"), `{"name":"foo","version":"9.0.0","main":"index.js","license":"MIT","dependencies":{"ms":"2.0.0"}}`) - await outputFile(path.join(localPath, "index.js"), `module.exports = require("ms")`) + await fsExtra.outputFile(path.join(localPath, "package.json"), `{"name":"foo","version":"9.0.0","main":"index.js","license":"MIT","dependencies":{"ms":"2.0.0"}}`) + await fsExtra.outputFile(path.join(localPath, "index.js"), `module.exports = require("ms")`) const pmCommand = getPackageManagerWithVersion(pm).cli await spawn(pmCommand, ["install"], { diff --git a/test/src/parseNameVersionTest.ts b/test/src/parseNameVersionTest.ts index 1b6bc2fd836..7fcb0155f09 100644 --- a/test/src/parseNameVersionTest.ts +++ b/test/src/parseNameVersionTest.ts @@ -1,4 +1,4 @@ -import { PnpmNodeModulesCollector } from "app-builder-lib/out/node-module-collector/pnpmNodeModulesCollector" +import { PnpmNodeModulesCollector } from "app-builder-lib/internal" import { TmpDir } from "temp-file" import { describe, expect, test } from "vitest" diff --git a/test/src/protonTest.ts b/test/src/protonTest.ts index db3ba672e4e..712318615f3 100644 --- a/test/src/protonTest.ts +++ b/test/src/protonTest.ts @@ -1,6 +1,6 @@ import { copyDir } from "builder-util" import { Arch, Platform } from "electron-builder" -import { app, AssertPackOptions } from "./helpers/packTester" +import { app, AssertPackOptions } from "./helpers/packTester.js" const checkOptions: AssertPackOptions = { projectDirCreated: async projectDir => { diff --git a/test/src/provider/bitbucketProviderTest.ts b/test/src/provider/bitbucketProviderTest.ts index 6be64a26492..8aa89124e0a 100644 --- a/test/src/provider/bitbucketProviderTest.ts +++ b/test/src/provider/bitbucketProviderTest.ts @@ -1,6 +1,6 @@ import { BitbucketOptions } from "builder-util-runtime" -import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil" -import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil.js" +import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil.js" const MOCK_OWNER = "test-owner" const MOCK_SLUG = "test-repo" diff --git a/test/src/provider/githubProviderTest.ts b/test/src/provider/githubProviderTest.ts index fa897a86406..b2dea165234 100644 --- a/test/src/provider/githubProviderTest.ts +++ b/test/src/provider/githubProviderTest.ts @@ -1,7 +1,7 @@ import { GithubOptions, HttpError, UpdateInfo } from "builder-util-runtime" -import { GitHubProvider } from "electron-updater/src/providers/GitHubProvider" -import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil" -import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { GitHubProvider } from "electron-updater/src/providers/GitHubProvider.js" +import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil.js" +import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil.js" const MOCK_OWNER = "test-owner" const MOCK_REPO = "test-public-repo" diff --git a/test/src/provider/gitlabProviderTest.ts b/test/src/provider/gitlabProviderTest.ts index f97521b2532..ad9a7ad1207 100644 --- a/test/src/provider/gitlabProviderTest.ts +++ b/test/src/provider/gitlabProviderTest.ts @@ -1,7 +1,7 @@ import { GitlabOptions, GitlabReleaseInfo, HttpError } from "builder-util-runtime" -import { GitLabProvider } from "electron-updater/src/providers/GitLabProvider" -import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil" -import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { GitLabProvider } from "electron-updater/src/providers/GitLabProvider.js" +import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil.js" +import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil.js" const MOCK_PROJECT_ID = 99999999 const STABLE_VERSION = "1.1.0" diff --git a/test/src/provider/keygenProviderTest.ts b/test/src/provider/keygenProviderTest.ts index f48329730d5..6ec7c234074 100644 --- a/test/src/provider/keygenProviderTest.ts +++ b/test/src/provider/keygenProviderTest.ts @@ -1,6 +1,6 @@ import { KeygenOptions } from "builder-util-runtime" -import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil" -import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil.js" +import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil.js" const MOCK_ACCOUNT = "test-account-id" const MOCK_PRODUCT = "test-product-id" diff --git a/test/src/provider/privateGithubProviderTest.ts b/test/src/provider/privateGithubProviderTest.ts index f3e82623c09..aa2a3669cb6 100644 --- a/test/src/provider/privateGithubProviderTest.ts +++ b/test/src/provider/privateGithubProviderTest.ts @@ -1,7 +1,7 @@ import { GithubOptions, HttpError } from "builder-util-runtime" -import { PrivateGitHubProvider, PrivateGitHubUpdateInfo } from "electron-updater/src/providers/PrivateGitHubProvider" -import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil" -import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { PrivateGitHubProvider, PrivateGitHubUpdateInfo } from "electron-updater/src/providers/PrivateGitHubProvider.js" +import { assertDownloadNotTriggered, getProvider, mockYaml } from "../helpers/providerTestUtil.js" +import { createMockRequest, createNsisUpdater, trackEvents, writeUpdateConfig } from "../helpers/updaterTestUtil.js" const MOCK_TOKEN = "ghp_test-token-12345" const MOCK_OWNER = "test-owner" diff --git a/test/src/provider/providerTest.ts b/test/src/provider/providerTest.ts index 2e7786138f6..174f9db07b5 100644 --- a/test/src/provider/providerTest.ts +++ b/test/src/provider/providerTest.ts @@ -1,10 +1,10 @@ import { CancellationToken, UpdateInfo } from "builder-util-runtime" -import { Provider, ProviderRuntimeOptions } from "electron-updater/src/providers/Provider" -import { ResolvedUpdateFileInfo } from "electron-updater/src/types" +import { Provider, ProviderRuntimeOptions } from "electron-updater" +import { ResolvedUpdateFileInfo } from "electron-updater/src/types.js" import { OutgoingHttpHeaders } from "http" import { URL } from "url" import { MockInstance, afterEach, beforeEach, vi } from "vitest" -import { httpExecutor } from "../helpers/updaterTestUtil" +import { httpExecutor } from "../helpers/updaterTestUtil.js" let requestSpy: MockInstance diff --git a/test/src/publisher/gitlab/GitlabPublisher.integration.test.ts b/test/src/publisher/gitlab/GitlabPublisher.integration.test.ts index 3321d335553..e5e58eb0d85 100644 --- a/test/src/publisher/gitlab/GitlabPublisher.integration.test.ts +++ b/test/src/publisher/gitlab/GitlabPublisher.integration.test.ts @@ -2,8 +2,8 @@ import { Arch } from "builder-util" import { CancellationToken } from "builder-util-runtime" import { GitlabPublisher, PublishContext } from "electron-publish" import { afterAll, beforeEach, describe, expect, test } from "vitest" -import { GitlabTestFixtures } from "./GitlabTestFixtures" -import { GitlabTestHelper } from "./GitlabTestHelper" +import { GitlabTestFixtures } from "./GitlabTestFixtures.js" +import { GitlabTestHelper } from "./GitlabTestHelper.js" /** * GitLab Publisher Integration Tests diff --git a/test/src/publisher/gitlab/GitlabPublisherTest.ts b/test/src/publisher/gitlab/GitlabPublisherTest.ts index 8563fb86e1d..c09ac27b953 100644 --- a/test/src/publisher/gitlab/GitlabPublisherTest.ts +++ b/test/src/publisher/gitlab/GitlabPublisherTest.ts @@ -1,7 +1,7 @@ import { CancellationToken, GitlabOptions } from "builder-util-runtime" import { GitlabPublisher, PublishContext } from "electron-publish" import { beforeEach, describe, test, vi } from "vitest" -import { GitlabTestFixtures } from "./GitlabTestFixtures" +import { GitlabTestFixtures } from "./GitlabTestFixtures.js" // Mock the HTTP executor to avoid real network calls vi.mock("builder-util", async () => { diff --git a/test/src/publisher/gitlab/GitlabTestFixtures.ts b/test/src/publisher/gitlab/GitlabTestFixtures.ts index e34bcebff6d..17e202881a6 100644 --- a/test/src/publisher/gitlab/GitlabTestFixtures.ts +++ b/test/src/publisher/gitlab/GitlabTestFixtures.ts @@ -3,8 +3,8 @@ import { GitlabOptions } from "builder-util-runtime" export class GitlabTestFixtures { // Test file paths - static readonly ICON_PATH = path.join(__dirname, "..", "..", "..", "fixtures", "test-app", "build", "icon.icns") - static readonly ICO_PATH = path.join(__dirname, "..", "..", "..", "fixtures", "test-app", "build", "icon.ico") + static readonly ICON_PATH = path.join(import.meta.dirname, "..", "..", "..", "fixtures", "test-app", "build", "icon.icns") + static readonly ICO_PATH = path.join(import.meta.dirname, "..", "..", "..", "fixtures", "test-app", "build", "icon.ico") // Test versions static readonly VERSIONS = { diff --git a/test/src/publisher/snap/SnapStorePublisherTest.ts b/test/src/publisher/snap/SnapStorePublisherTest.ts index eba67c74b0c..1c656f7cc9b 100644 --- a/test/src/publisher/snap/SnapStorePublisherTest.ts +++ b/test/src/publisher/snap/SnapStorePublisherTest.ts @@ -1,6 +1,6 @@ import { exec, spawn } from "builder-util" import { CancellationToken } from "builder-util-runtime" -import { SnapStoreOptions } from "builder-util-runtime/out/publishOptions" +import { SnapStoreOptions } from "builder-util-runtime/src/publishOptions" import { PublishContext, UploadTask } from "electron-publish" import { beforeEach, describe, test, vi } from "vitest" // Import from source so Vitest's vi.mock intercepts builder-util in the same module graph diff --git a/test/src/rebuilderTest.ts b/test/src/rebuilderTest.ts index 5011f0d6010..4bc3a4edb01 100644 --- a/test/src/rebuilderTest.ts +++ b/test/src/rebuilderTest.ts @@ -1,6 +1,6 @@ import { Configuration, Platform } from "app-builder-lib" -import { PM } from "app-builder-lib/out/node-module-collector" -import { exists } from "builder-util/out/util" +import { PM } from "app-builder-lib/internal" +import { exists } from "builder-util/src/util" import path from "path" import { assertPack, linuxDirTarget, modifyPackageJson } from "./helpers/packTester" import { ELECTRON_VERSION } from "./helpers/testConfig" diff --git a/test/src/s3BucketLocationTest.ts b/test/src/s3BucketLocationTest.ts index 03e679d8283..244d35e3fed 100644 --- a/test/src/s3BucketLocationTest.ts +++ b/test/src/s3BucketLocationTest.ts @@ -30,7 +30,7 @@ function mockHttpResponse(statusCode: number, body: string): void { setImmediate(() => { const res = new EventEmitter() as any res.statusCode = statusCode - ;(callback as Function)(res) + ;(callback as (arg: unknown) => void)(res) setImmediate(() => { res.emit("data", body) res.emit("end") diff --git a/test/src/s3PublishTest.ts b/test/src/s3PublishTest.ts index f7500c69d7f..e5e7e36d3f2 100644 --- a/test/src/s3PublishTest.ts +++ b/test/src/s3PublishTest.ts @@ -65,7 +65,7 @@ function mockSuccessfulUpload(): { capturedOpts: () => any } { const res = new EventEmitter() as any res.statusCode = 200 res.resume = vi.fn() - ;(callback as Function)(res) + ;(callback as (arg: unknown) => void)(res) setImmediate(() => res.emit("end")) }) // Handle piped stream diff --git a/test/src/schemaValidatorTest.ts b/test/src/schemaValidatorTest.ts index 59ac012df80..f959dd26ea4 100644 --- a/test/src/schemaValidatorTest.ts +++ b/test/src/schemaValidatorTest.ts @@ -1,4 +1,4 @@ -import { validateSchema } from "app-builder-lib/out/util/config/schemaValidator" +import { validateSchema } from "app-builder-lib/internal" import { describe, expect, it } from "vitest" const simpleSchema = { @@ -176,7 +176,7 @@ describe("validateSchema - postFormatter", () => { { name: "x", nested: { value: "ok", extra: 1 } }, { postFormatter: (msg, error) => { - capturedPath = (error as any).instancePath + capturedPath = error.instancePath return msg }, } diff --git a/test/src/updateInfoBuilderTest.ts b/test/src/updateInfoBuilderTest.ts index f175fe44b3e..04c3b973714 100644 --- a/test/src/updateInfoBuilderTest.ts +++ b/test/src/updateInfoBuilderTest.ts @@ -1,7 +1,7 @@ import * as fsp from "fs/promises" import * as os from "os" import * as path from "path" -import { createUpdateInfoTasks, writeUpdateInfoFiles, UpdateInfoFileTask } from "app-builder-lib/out/publish/updateInfoBuilder" +import { createUpdateInfoTasks, writeUpdateInfoFiles, UpdateInfoFileTask } from "app-builder-lib/internal" import { Platform } from "app-builder-lib" import { Arch } from "builder-util" import { load as yamlLoad } from "js-yaml" diff --git a/test/src/updater/baseUpdaterUnitTest.ts b/test/src/updater/baseUpdaterUnitTest.ts index 84f5ca947a5..58f0c93ba26 100644 --- a/test/src/updater/baseUpdaterUnitTest.ts +++ b/test/src/updater/baseUpdaterUnitTest.ts @@ -1,8 +1,8 @@ import * as path from "path" import { afterEach, beforeEach, expect, it, vi } from "vitest" import { AppImageUpdater, DebUpdater } from "electron-updater" -import type { AppAdapter } from "electron-updater/out/AppAdapter" -import type { InstallOptions } from "electron-updater/out/BaseUpdater" +import type { AppAdapter } from "electron-updater/src/AppAdapter" +import type { InstallOptions } from "electron-updater/src/BaseUpdater" const stubApp: AppAdapter = { name: "TestApp", diff --git a/test/src/updater/blackboxInstallMac.ts b/test/src/updater/blackboxInstallMac.ts index 7b3d1b760fc..7bc77e25ccb 100644 --- a/test/src/updater/blackboxInstallMac.ts +++ b/test/src/updater/blackboxInstallMac.ts @@ -1,4 +1,4 @@ -import { getArchSuffix } from "builder-util/out/util" +import { getArchSuffix } from "builder-util/src/util" import { Arch } from "electron-builder" import path from "path" diff --git a/test/src/updater/blackboxInstallTest.ts b/test/src/updater/blackboxInstallTest.ts index 74f02b91253..2f731117105 100644 --- a/test/src/updater/blackboxInstallTest.ts +++ b/test/src/updater/blackboxInstallTest.ts @@ -1,8 +1,8 @@ import { AppImageOptions, Configuration, DebOptions, PacmanOptions, RpmOptions, Target, ToolsetConfig } from "app-builder-lib" -import { PM } from "app-builder-lib/out/node-module-collector" +import { PM } from "app-builder-lib/internal" import { Arch, Platform } from "electron-builder" import { DebUpdater, PacmanUpdater, RpmUpdater } from "electron-updater" -import { archFromString, log, spawn, TmpDir } from "builder-util/out/util" +import { archFromString, log, spawn, TmpDir } from "builder-util/src/util" import { deepAssign, GenericServerOptions } from "builder-util-runtime" import { execSync } from "child_process" import { move, outputFile, readJsonSync } from "fs-extra" diff --git a/test/src/updater/blackboxInstallWindows.ts b/test/src/updater/blackboxInstallWindows.ts index f563278a8ed..6f713830b72 100644 --- a/test/src/updater/blackboxInstallWindows.ts +++ b/test/src/updater/blackboxInstallWindows.ts @@ -1,4 +1,4 @@ -import { ParallelsVmManager } from "app-builder-lib/out/vm/ParallelsVm" +import { ParallelsVmManager } from "app-builder-lib/internal" import { execFileSync, execSync } from "child_process" import { randomUUID } from "crypto" import { Arch } from "electron-builder" diff --git a/test/src/updater/blackboxUpdateHelpers.ts b/test/src/updater/blackboxUpdateHelpers.ts index c27c49a29c5..7dc4918b221 100644 --- a/test/src/updater/blackboxUpdateHelpers.ts +++ b/test/src/updater/blackboxUpdateHelpers.ts @@ -1,9 +1,7 @@ import { ToolsetConfig } from "app-builder-lib" -import { PM } from "app-builder-lib/out/node-module-collector" -import { ParallelsVmManager } from "app-builder-lib/out/vm/ParallelsVm" -import { getWindowsVm, VmManager } from "app-builder-lib/out/vm/vm" +import { getWindowsVm, ParallelsVmManager, PM, VmManager } from "app-builder-lib/internal" import { GenericServerOptions, Nullish } from "builder-util-runtime" -import { archFromString, deepAssign, DebugLogger, log, serializeToYaml, spawn, TmpDir } from "builder-util/out/util" +import { archFromString, deepAssign, DebugLogger, log, serializeToYaml, spawn, TmpDir } from "builder-util/src/util" import { Arch, Configuration, Platform } from "electron-builder" import { copy, existsSync, move, outputFile, readJsonSync, remove } from "fs-extra" import { homedir } from "os" diff --git a/test/src/updater/blackboxUpdateLinuxSuite.ts b/test/src/updater/blackboxUpdateLinuxSuite.ts index 6d3286463d2..4e1b2323097 100644 --- a/test/src/updater/blackboxUpdateLinuxSuite.ts +++ b/test/src/updater/blackboxUpdateLinuxSuite.ts @@ -1,5 +1,5 @@ import { ToolsetConfig } from "app-builder-lib" -import { isEmptyOrSpaces } from "builder-util/out/util" +import { isEmptyOrSpaces } from "builder-util/src/util" import { execSync } from "child_process" import { Arch } from "electron-builder" import { TestContext } from "vitest" diff --git a/test/src/updater/blackboxUpdateTest.ts b/test/src/updater/blackboxUpdateTest.ts new file mode 100644 index 00000000000..f312cf02b14 --- /dev/null +++ b/test/src/updater/blackboxUpdateTest.ts @@ -0,0 +1,429 @@ +import { ToolsetConfig } from "app-builder-lib" +import { PM } from "app-builder-lib/internal" +import { GenericServerOptions, Nullish } from "builder-util-runtime" +import { archFromString, doSpawn, getArchSuffix, isEmptyOrSpaces, log, spawn, TmpDir } from "builder-util" +import { execFileSync, execSync } from "child_process" +import { Arch, Configuration, Platform } from "electron-builder" +import { DebUpdater, PacmanUpdater, RpmUpdater } from "electron-updater" +import { copy, existsSync, move, outputFile, readJsonSync } from "fs-extra" +import { homedir } from "os" +import path from "path" +import { ExpectStatic, TestContext } from "vitest" +import { getRanLocalServerPath, launchAndWaitForQuit } from "../helpers/launchAppCrossPlatform.js" +import { assertPack, modifyPackageJson, PackedContext } from "../helpers/packTester.js" +import { ELECTRON_VERSION } from "../helpers/testConfig.js" +import { NEW_VERSION_NUMBER, OLD_VERSION_NUMBER, writeUpdateConfig } from "../helpers/updaterTestUtil.js" + +const optionsForFlakyE2E = { sequential: true, retry: 2 } +// Linux Tests MUST be run in docker containers for proper ephemeral testing environment (e.g. fresh install + update + relaunch) +// Currently this test logic does not handle uninstalling packages (yet) +describe.ifMac.heavy("mac", optionsForFlakyE2E, () => { + // can test on x64 and also arm64 (via rosetta) + test("x64", async context => { + await runTest(context, "zip", "", Arch.x64) + }) + test("universal", async context => { + await runTest(context, "zip", "", Arch.universal) + }) + // only will update on arm64 mac + test.ifEnv(process.arch === "arm64")("arm64", async context => { + await runTest(context, "zip", "", Arch.arm64) + }) +}) + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] + +for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, optionsForFlakyE2E, () => { + describe.heavy.ifWindows("windows", optionsForFlakyE2E, () => { + test("nsis", async context => { + await runTest(context, "nsis", "", Arch.x64, { winCodeSign }) + }) + }) + }) +} + +const appImageToolVersions: ToolsetConfig["appimage"][] = ["0.0.0", "1.0.2", "1.0.3"] +// must be sequential in order for process.env.ELECTRON_BUILDER_LINUX_PACKAGE_MANAGER to be respected per-test +describe.heavy.ifLinux("linux", optionsForFlakyE2E, () => { + for (const appimage of appImageToolVersions) { + describe(`appimage tool: ${appimage}`, optionsForFlakyE2E, () => { + test.ifEnv(process.env.RUN_APP_IMAGE_TEST === "true" && process.arch === "arm64")("AppImage - arm64", async context => { + await runTest(context, "AppImage", "appimage", Arch.arm64, { appimage }) + }) + + // only works on x64, so this will fail on arm64 macs due to arch mismatch + test.ifEnv(process.env.RUN_APP_IMAGE_TEST === "true" && process.arch === "x64")("AppImage - x64", async context => { + await runTest(context, "AppImage", "appimage", Arch.x64, { appimage }) + }) + }) + } + + // package manager tests specific to each distro (and corresponding docker image) + for (const distro in packageManagerMap) { + const { pms, target } = packageManagerMap[distro as keyof typeof packageManagerMap] + for (const pm of pms) { + test(`${distro} - (${pm})`, optionsForFlakyE2E, async context => { + if (!determineEnvironment(distro)) { + context.skip() + } + // skip if already set to avoid interfering with other package manager tests + if (!isEmptyOrSpaces(process.env.PACKAGE_MANAGER_TO_TEST) && process.env.PACKAGE_MANAGER_TO_TEST !== pm) { + context.skip() + } + await runTest(context, target, pm, Arch.x64) + }) + } + } +}) + +const determineEnvironment = (target: string) => { + return execSync(`cat /etc/*release | grep "^ID="`).toString().includes(target) +} + +const packageManagerMap: { + [key: string]: { + pms: string[] + target: string + } +} = { + fedora: { + pms: ["zypper", "dnf", "yum", "rpm"], + target: "rpm", + }, + debian: { + pms: ["apt", "dpkg"], + target: "deb", + }, + arch: { + pms: ["pacman"], + target: "pacman", + }, +} + +async function runTest(context: TestContext, target: string, packageManager: string, arch: Arch = Arch.x64, toolsets: ToolsetConfig = {}) { + const { expect } = context + + const tmpDir = new TmpDir("auto-update") + const outDirs: ApplicationUpdatePaths[] = [] + await doBuild(expect, outDirs, target, arch, tmpDir, process.platform === "win32", { toolsets }) + + const oldAppDir = outDirs[0] + const newAppDir = outDirs[1] + + const dirPath = oldAppDir.dir + // Setup tests by installing the previous version + const appPath = await handleInitialInstallPerOS({ target, dirPath, arch }) + + if (!existsSync(appPath)) { + throw new Error(`App not found: ${appPath}`) + } + + let queuedError: Error | null = null + try { + await runTestWithinServer(async (rootDirectory: string, updateConfigPath: string) => { + // Move app update to the root directory of the server + await copy(newAppDir.dir, rootDirectory, { recursive: true, overwrite: true }) + + const verifyAppVersion = async (expectedVersion: string) => + await launchAndWaitForQuit({ appPath, timeoutMs: 2 * 60 * 1000, updateConfigPath, expectedVersion, packageManagerToTest: packageManager }) + + const result = await verifyAppVersion(OLD_VERSION_NUMBER) + log.debug(result, "Test App version") + expect(result.version).toMatch(OLD_VERSION_NUMBER) + + // Wait for quitAndInstall to take effect, increase delay if updates are slower + // (shouldn't be the case for such a small test app, but Windows with Debugger attached is pretty dam slow) + const delay = 60 * 1000 + await new Promise(resolve => setTimeout(resolve, delay)) + + expect((await verifyAppVersion(NEW_VERSION_NUMBER)).version).toMatch(NEW_VERSION_NUMBER) + }) + } catch (error: any) { + log.error({ error: error.message }, "Blackbox Updater Test failed to run") + queuedError = error + } finally { + // windows needs to release file locks, so a delay seems to be needed + await new Promise(resolve => setTimeout(resolve, 1000)) + await tmpDir.cleanup() + try { + await handleCleanupPerOS({ target }) + } catch (error: any) { + log.error({ error: error.message }, "Blackbox Updater Test cleanup failed") + // ignore + } + } + if (queuedError) { + throw queuedError + } +} + +type ApplicationUpdatePaths = { + dir: string + appPath: string +} + +async function doBuild( + expect: ExpectStatic, + outDirs: Array, + target: string, + arch: Arch, + tmpDir: TmpDir, + isWindows: boolean, + extraConfig?: Configuration | null +) { + const currentPlatform = Platform.current() + async function buildApp({ + version, + target, + arch, + extraConfig, + packed, + }: { + version: string + target: string + arch: Arch + extraConfig: Configuration | Nullish + packed: (context: PackedContext) => Promise + }) { + await assertPack( + expect, + "test-app", + { + targets: currentPlatform.createTarget(target, arch), + config: { + npmRebuild: true, + productName: "TestApp", + executableName: "TestApp", + appId: "com.test.app", + artifactName: "${productName}.${ext}", + // asar: false, // not necessarily needed, just easier debugging tbh + electronLanguages: ["en"], + extraMetadata: { + name: "testapp", + version, + }, + electronFuses: { + runAsNode: false, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: false, + enableNodeCliInspectArguments: false, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: false, + grantFileProtocolExtraPrivileges: false, + }, + electronUpdaterCompatibility: "1.1", // anything above 1.0.0 works. This is to allow testing via `link:` protocol with the current workspace electron-updater package version + ...extraConfig, + compression: "store", + publish: { + provider: "s3", + bucket: "develar", + path: "test", + }, + files: ["**/*", "../**/node_modules/**", "!path/**"], + nsis: { + artifactName: "${productName} Setup.${ext}", + // one click installer required. don't run after install otherwise we lose stdout pipe + oneClick: true, + runAfterFinish: false, + }, + }, + }, + { + storeDepsLockfileSnapshot: false, + signed: !isWindows, + signedWin: isWindows, + packed, + packageManager: PM.PNPM, + projectDirCreated: async (projectDir, _tmpDir, runtimeEnv) => { + // await outputFile(path.join(projectDir, "package-lock.json"), "{}") + await outputFile(path.join(projectDir, ".npmrc"), "node-linker=hoisted") + + await modifyPackageJson( + projectDir, + data => { + data.devDependencies = { + electron: ELECTRON_VERSION, + "node-addon-api": "^8", + } + const electronUpdaterPath = (pkg: string) => path.resolve(import.meta.dirname, "../../../packages", pkg) + const updaterPath = electronUpdaterPath("electron-updater") + const utilPath = electronUpdaterPath("builder-util-runtime") + data.dependencies = { + ...data.dependencies, + sqlite3: "5.1.7", // for testing native dependency handling in auto-update + "@electron/remote": "2.1.3", // for debugging live application with GUI so that app.getVersion is accessible in renderer process + "electron-updater": `link:${updaterPath}`, + ...readJsonSync(path.join(updaterPath, "package.json")).dependencies, + "builder-util-runtime": `link:${utilPath}`, // needs to be last to overwrite electron-updater's builder-util-runtime dependency for testing with workspace version of builder-util-runtime (workspace:* doesn't resolve and needs to be linked explicitly) + ...readJsonSync(path.join(utilPath, "package.json")).dependencies, + } + }, + true + ) + await modifyPackageJson( + projectDir, + data => { + data.pnpm = { + supportedArchitectures: { + os: ["current"], + cpu: ["x64", "arm64"], + }, + } + }, + false + ) + await spawn("pnpm", ["install"], { cwd: projectDir, stdio: "inherit", env: runtimeEnv }) + }, + } + ) + } + + const build = (version: string) => + buildApp({ + version, + target, + arch, + extraConfig, + packed: async context => { + // move dist temporarily out of project dir so each downloader can reference it + const dir = await tmpDir.getTempDir({ prefix: version }) + await move(context.outDir, dir) + const appPath = path.join(dir, path.relative(context.outDir, context.getAppPath(Platform.current(), archFromString(process.arch)))) + outDirs.push({ dir, appPath }) + }, + }) + try { + await build(OLD_VERSION_NUMBER) + await build(NEW_VERSION_NUMBER) + } catch (e: any) { + await tmpDir.cleanup() + throw e + } +} + +async function handleInitialInstallPerOS({ target, dirPath, arch }: { target: string; dirPath: string; arch: Arch }): Promise { + let appPath: string + if (target === "AppImage") { + appPath = path.join(dirPath, `TestApp.AppImage`) + } else if (target === "deb") { + DebUpdater.installWithCommandRunner( + "dpkg", + path.join(dirPath, `TestApp.deb`), + commandWithArgs => { + execSync(commandWithArgs.join(" "), { stdio: "inherit" }) + }, + console + ) + appPath = path.join("/opt", "TestApp", "TestApp") + } else if (target === "rpm") { + RpmUpdater.installWithCommandRunner( + "zypper", + path.join(dirPath, `TestApp.rpm`), + commandWithArgs => { + execSync(commandWithArgs.join(" "), { stdio: "inherit" }) + }, + console + ) + appPath = path.join("/opt", "TestApp", "TestApp") + } else if (target === "pacman") { + PacmanUpdater.installWithCommandRunner( + path.join(dirPath, `TestApp.pacman`), + commandWithArgs => { + execSync(commandWithArgs.join(" "), { stdio: "inherit" }) + }, + console + ) + // execSync(`sudo pacman -Syyu --noconfirm`, { stdio: "inherit" }) + // execSync(`sudo pacman -U --noconfirm "${path.join(dirPath, `TestApp.pacman`)}"`, { stdio: "inherit" }) + appPath = path.join("/opt", "TestApp", "TestApp") + } else if (process.platform === "win32") { + // access installed app's location + const localProgramsPath = path.join(process.env.LOCALAPPDATA || path.join(homedir(), "AppData", "Local"), "Programs", "TestApp") + // this is to clear dev environment when not running on an ephemeral GH runner. + // Reinstallation will otherwise fail due to "uninstall" message prompt, so we must uninstall first (hence the setTimeout delay) + const uninstaller = path.join(localProgramsPath, "Uninstall TestApp.exe") + if (existsSync(uninstaller)) { + console.log("Uninstalling", uninstaller) + execFileSync(uninstaller, ["/S", "/C", "exit"], { stdio: "inherit" }) + await new Promise(resolve => setTimeout(resolve, 5000)) + } + + const installerPath = path.join(dirPath, "TestApp Setup.exe") + console.log("Installing windows", installerPath) + // Don't use /S for silent install as we lose stdout pipe + execFileSync(installerPath, ["/S"], { stdio: "inherit" }) + + appPath = path.join(localProgramsPath, "TestApp.exe") + } else if (process.platform === "darwin") { + appPath = path.join(dirPath, `mac${getArchSuffix(arch)}`, `TestApp.app`, "Contents", "MacOS", "TestApp") + } else { + throw new Error(`Unsupported Update test target: ${target}`) + } + return appPath +} + +async function handleCleanupPerOS({ target }: { target: string }) { + // TODO: ignore for now, this doesn't block CI, but proper uninstall logic should be implemented + if (target === "deb") { + // execSync("dpkg -r testapp", { stdio: "inherit" }); + } else if (target === "rpm") { + // execSync(`zypper rm -y testapp`, { stdio: "inherit" }) + } else if (target === "pacman") { + execSync(`pacman -R --noconfirm testapp`, { stdio: "inherit" }) + } else if (process.platform === "win32") { + // access installed app's location + const localProgramsPath = path.join(process.env.LOCALAPPDATA || path.join(homedir(), "AppData", "Local"), "Programs", "TestApp") + const uninstaller = path.join(localProgramsPath, "Uninstall TestApp.exe") + console.log("Uninstalling", uninstaller) + execFileSync(uninstaller, ["/S", "/C", "exit"], { stdio: "inherit" }) + await new Promise(resolve => setTimeout(resolve, 5000)) + } else if (process.platform === "darwin") { + // ignore, nothing to uninstall, it's running/updating out of the local `dist` directory + } +} + +async function runTestWithinServer(doTest: (rootDirectory: string, updateConfigPath: string) => Promise) { + const tmpDir = new TmpDir("blackbox-update-test") + const root = await tmpDir.getTempDir({ prefix: "server-root" }) + + // 65535 is the max port number + // Math.random() / Math.random() is used to avoid zero + // Math.floor(((Math.random() / Math.random()) * 1000) % 65535) is used to avoid port number collision + const port = 8000 + Math.floor(((Math.random() / Math.random()) * 1000) % 65535) + const serverBin = await getRanLocalServerPath() + const httpServerProcess = doSpawn(serverBin, [`-root=${root}`, `-port=${port}`, "-gzip=false", "-listdir=true"]) + + const updateConfig = await writeUpdateConfig({ + provider: "generic", + url: `http://127.0.0.1:${port}`, + }) + + const cleanup = () => { + try { + tmpDir.cleanupSync() + } catch (error) { + console.error("Failed to cleanup tmpDir", error) + } + try { + httpServerProcess.kill() + } catch (error) { + console.error("Failed to kill httpServerProcess", error) + } + } + + return await new Promise((resolve, reject) => { + httpServerProcess.on("error", reject) + doTest(root, updateConfig).then(resolve).catch(reject) + }).then( + v => { + cleanup() + return v + }, + e => { + cleanup() + throw e + } + ) +} diff --git a/test/src/updater/blackboxUpdateWinSuite.ts b/test/src/updater/blackboxUpdateWinSuite.ts index b78d5556b56..c8a6de9b24a 100644 --- a/test/src/updater/blackboxUpdateWinSuite.ts +++ b/test/src/updater/blackboxUpdateWinSuite.ts @@ -1,12 +1,12 @@ import { ToolsetConfig } from "app-builder-lib" -import { ParallelsVmManager } from "app-builder-lib/out/vm/ParallelsVm" +import { ParallelsVmManager } from "app-builder-lib/internal" import { copyFileSync, unlinkSync } from "fs" import { tmpdir } from "os" import { Arch, Configuration } from "electron-builder" import { spawn as nodeSpawn } from "child_process" import * as path from "path" import { TestContext } from "vitest" -import { deepAssign, TmpDir } from "builder-util/out/util" +import { deepAssign, TmpDir } from "builder-util/src/util" import { ApplicationUpdatePaths, doBuild, optionsForFlakyE2E, runTest, windowsVmPromise } from "./blackboxUpdateHelpers" import { installWindowsVm } from "./blackboxInstallWindows" diff --git a/test/src/updater/blackboxWebInstallerTest.ts b/test/src/updater/blackboxWebInstallerTest.ts index 97024b4a7b0..10aac12f223 100644 --- a/test/src/updater/blackboxWebInstallerTest.ts +++ b/test/src/updater/blackboxWebInstallerTest.ts @@ -1,4 +1,4 @@ -import { TmpDir } from "builder-util/out/util" +import { TmpDir } from "builder-util/src/util" import { execFileSync, execSync } from "child_process" import { randomUUID } from "crypto" import { Arch, Platform } from "electron-builder" @@ -11,7 +11,7 @@ import { createLocalServer, getParallelsHostIP, sha256File, toVmHomePath } from import { assertPack, modifyPackageJson, PackedContext } from "../helpers/packTester" import { ELECTRON_VERSION } from "../helpers/testConfig" import { optionsForFlakyE2E, windowsVmPromise } from "./blackboxUpdateHelpers" -import { PM } from "app-builder-lib/out/node-module-collector" +import { PM } from "app-builder-lib/internal" import { spawn } from "builder-util" // --------------------------------------------------------------------------- diff --git a/test/src/updater/differentialUpdateHelpers.ts b/test/src/updater/differentialUpdateHelpers.ts index 3dcc17a5678..939a52855bc 100644 --- a/test/src/updater/differentialUpdateHelpers.ts +++ b/test/src/updater/differentialUpdateHelpers.ts @@ -12,7 +12,7 @@ import { NEW_VERSION_NUMBER, OLD_VERSION_NUMBER, tuneTestUpdater, writeUpdateCon import { mockForNodeRequire } from "vitest-mock-commonjs" import { ExpectStatic } from "vitest" import { createLocalServer } from "../helpers/launchAppCrossPlatform" -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" export async function doBuild( expect: ExpectStatic, diff --git a/test/src/updater/differentialUpdateLinuxSuite.ts b/test/src/updater/differentialUpdateLinuxSuite.ts index 24afb0f411f..3157d3d1ef8 100644 --- a/test/src/updater/differentialUpdateLinuxSuite.ts +++ b/test/src/updater/differentialUpdateLinuxSuite.ts @@ -1,5 +1,5 @@ import { Arch } from "app-builder-lib" -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" import { testLinux } from "./differentialUpdateHelpers" const supportedArchs = [ diff --git a/test/src/updater/differentialUpdateWinSuite.ts b/test/src/updater/differentialUpdateWinSuite.ts index f2ecb3eab65..f9250f69b53 100644 --- a/test/src/updater/differentialUpdateWinSuite.ts +++ b/test/src/updater/differentialUpdateWinSuite.ts @@ -5,7 +5,7 @@ import { move } from "fs-extra" import { TmpDir } from "temp-file" import { OLD_VERSION_NUMBER, testAppCacheDirName } from "../helpers/updaterTestUtil" import { NsisUpdater } from "electron-updater" -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" import { doBuild, getTestUpdaterCacheDir, testBlockMap } from "./differentialUpdateHelpers" export function registerDifferentialWinTests(toolsets: ToolsetConfig): void { diff --git a/test/src/updater/downloadPlanBuilderTest.ts b/test/src/updater/downloadPlanBuilderTest.ts index 94f067b61e6..c4d34c43d1b 100644 --- a/test/src/updater/downloadPlanBuilderTest.ts +++ b/test/src/updater/downloadPlanBuilderTest.ts @@ -1,7 +1,7 @@ -import { BlockMap } from "builder-util-runtime/out/blockMapApi" -import { computeOperations, OperationKind } from "electron-updater/out/differentialDownloader/downloadPlanBuilder" +import { BlockMap } from "builder-util-runtime/src/blockMapApi" +import { computeOperations, OperationKind } from "electron-updater/src/differentialDownloader/downloadPlanBuilder" import { describe, expect, test } from "vitest" -import type { Logger } from "electron-updater/out/types" +import type { Logger } from "electron-updater/src/types" function makeBlockMap(checksums: string[], sizes: number[], offset = 0, name = "file"): BlockMap { return { version: "2", files: [{ name, offset, checksums, sizes }] } diff --git a/test/src/updater/downloadedUpdateHelperTest.ts b/test/src/updater/downloadedUpdateHelperTest.ts index e5e4d24e7a4..eff469ec77f 100644 --- a/test/src/updater/downloadedUpdateHelperTest.ts +++ b/test/src/updater/downloadedUpdateHelperTest.ts @@ -1,12 +1,12 @@ -import { createTempUpdateFile, DownloadedUpdateHelper } from "electron-updater/out/DownloadedUpdateHelper" +import { createTempUpdateFile, DownloadedUpdateHelper } from "electron-updater/src/DownloadedUpdateHelper" import { outputFile, outputJson, pathExists } from "fs-extra" import { mkdtemp, rm } from "fs/promises" import { tmpdir } from "os" import * as path from "path" import { afterEach, beforeEach, describe, expect, test } from "vitest" -import type { Logger } from "electron-updater/out/types" +import type { Logger } from "electron-updater/src/types" import type { UpdateInfo } from "builder-util-runtime" -import type { ResolvedUpdateFileInfo } from "electron-updater/out/types" +import type { ResolvedUpdateFileInfo } from "electron-updater/src/types" function makeLogger(): Logger & { infos: string[]; warns: string[] } { const infos: string[] = [] diff --git a/test/src/updater/linuxUpdaterUnitTest.ts b/test/src/updater/linuxUpdaterUnitTest.ts index 3f5a1bfe37f..e685b680c6a 100644 --- a/test/src/updater/linuxUpdaterUnitTest.ts +++ b/test/src/updater/linuxUpdaterUnitTest.ts @@ -1,6 +1,6 @@ import { afterEach, beforeEach, describe, expect, it, vi } from "vitest" import { DebUpdater } from "electron-updater" -import type { AppAdapter } from "electron-updater/out/AppAdapter" +import type { AppAdapter } from "electron-updater/src/AppAdapter" const stubApp: AppAdapter = { name: "TestApp", diff --git a/test/src/updater/macUpdaterLogicTest.ts b/test/src/updater/macUpdaterLogicTest.ts index 61f38e6c32c..eb46f3551ae 100644 --- a/test/src/updater/macUpdaterLogicTest.ts +++ b/test/src/updater/macUpdaterLogicTest.ts @@ -1,6 +1,6 @@ -import { MacUpdater } from "electron-updater/out/MacUpdater" +import { MacUpdater } from "electron-updater/src/MacUpdater" import { describe, expect, test } from "vitest" -import type { ResolvedUpdateFileInfo } from "electron-updater/out/types" +import type { ResolvedUpdateFileInfo } from "electron-updater/src/types" // MacUpdater is in skipPerOSTests.darwin (requires live Electron), but // filterFilesForArch is a protected static with no Electron dependency — it diff --git a/test/src/updater/macUpdaterTest.ts b/test/src/updater/macUpdaterTest.ts index f107e4d66dc..f51c0fb1ae0 100644 --- a/test/src/updater/macUpdaterTest.ts +++ b/test/src/updater/macUpdaterTest.ts @@ -1,8 +1,8 @@ import { configureRequestOptionsFromUrl, GithubOptions } from "builder-util-runtime" -import { MacUpdater } from "electron-updater/out/MacUpdater" +import { MacUpdater } from "electron-updater" import { EventEmitter } from "events" -import { assertThat } from "../helpers/fileAssert" -import { createTestAppAdapter, httpExecutor, trackEvents, tuneTestUpdater, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { assertThat } from "../helpers/fileAssert.js" +import { createTestAppAdapter, httpExecutor, trackEvents, tuneTestUpdater, writeUpdateConfig } from "../helpers/updaterTestUtil.js" import { mockForNodeRequire } from "vitest-mock-commonjs" class TestNativeUpdater extends EventEmitter { diff --git a/test/src/updater/nsisUpdaterTest.ts b/test/src/updater/nsisUpdaterTest.ts index 41b546d8466..6fb1e23e6ea 100644 --- a/test/src/updater/nsisUpdaterTest.ts +++ b/test/src/updater/nsisUpdaterTest.ts @@ -1,15 +1,14 @@ import { BitbucketOptions, GenericServerOptions, GithubOptions, GitlabOptions, KeygenOptions, S3Options, SpacesOptions } from "builder-util-runtime" import { BitbucketPublisher } from "electron-publish" import { UpdateCheckResult } from "electron-updater" -import { outputFile } from "fs-extra" +import fsExtra from "fs-extra" import { tmpdir } from "os" import * as path from "path" -import { assertThat } from "../helpers/fileAssert" -import { removeUnstableProperties } from "../helpers/packTester" -import { createNsisUpdater, trackEvents, validateDownload, writeUpdateConfig } from "../helpers/updaterTestUtil" +import { assertThat } from "../helpers/fileAssert.js" +import { removeUnstableProperties } from "../helpers/packTester.js" +import { createNsisUpdater, trackEvents, validateDownload, writeUpdateConfig } from "../helpers/updaterTestUtil.js" import { ExpectStatic } from "vitest" -import { GitLabProvider } from "electron-updater/src/providers/GitLabProvider" -import { GitHubProvider } from "electron-updater/src/providers/GitHubProvider" +import { GitLabProvider, GitHubProvider } from "electron-updater" const config = { retry: 3 } @@ -473,7 +472,7 @@ test.ifWindows("test custom signature verifier - signing error message", config, // disable for now test("90 staging percentage", config, async ({ expect }) => { const userIdFile = path.join(tmpdir(), "electron-updater-test", "userData", ".updaterId") - await outputFile(userIdFile, "1wa70172-80f8-5cc4-8131-28f5e0edd2a1") + await fsExtra.outputFile(userIdFile, "1wa70172-80f8-5cc4-8131-28f5e0edd2a1") const updater = await createNsisUpdater("0.0.1") updater.updateConfigPath = await writeUpdateConfig({ @@ -487,7 +486,7 @@ test("90 staging percentage", config, async ({ expect }) => { test("1 staging percentage", config, async ({ expect }) => { const userIdFile = path.join(tmpdir(), "electron-updater-test", "userData", ".updaterId") - await outputFile(userIdFile, "12a70172-80f8-5cc4-8131-28f5e0edd2a1") + await fsExtra.outputFile(userIdFile, "12a70172-80f8-5cc4-8131-28f5e0edd2a1") const updater = await createNsisUpdater("0.0.1") updater.updateConfigPath = await writeUpdateConfig({ diff --git a/test/src/urlUtilTest.ts b/test/src/urlUtilTest.ts index 93635d211df..f9aeb73c2ff 100644 --- a/test/src/urlUtilTest.ts +++ b/test/src/urlUtilTest.ts @@ -1,14 +1,14 @@ -import { newUrlFromBase } from "electron-updater/out/util" +import { utils } from "electron-updater/internal" import { URL } from "url" test("newUrlFromBase", ({ expect }) => { const fileUrl = new URL("https://AWS_S3_HOST/bucket-yashraj/electron%20Setup%2011.0.3.exe") - const newBlockMapUrl = newUrlFromBase(`${fileUrl.pathname}.blockmap`, fileUrl) + const newBlockMapUrl = utils.newUrlFromBase(`${fileUrl.pathname}.blockmap`, fileUrl) expect(newBlockMapUrl.href).toBe("https://aws_s3_host/bucket-yashraj/electron%20Setup%2011.0.3.exe.blockmap") }) test("add no cache", ({ expect }) => { const baseUrl = new URL("https://gitlab.com/artifacts/master/raw/dist?job=build_electron_win") - const newBlockMapUrl = newUrlFromBase("latest.yml", baseUrl, true) + const newBlockMapUrl = utils.newUrlFromBase("latest.yml", baseUrl, true) expect(newBlockMapUrl.href).toBe("https://gitlab.com/artifacts/master/raw/latest.yml?job=build_electron_win") }) diff --git a/test/src/windows/appxTest.ts b/test/src/windows/appxTest.ts new file mode 100644 index 00000000000..b4acba43b6b --- /dev/null +++ b/test/src/windows/appxTest.ts @@ -0,0 +1,194 @@ +import { Arch, Platform } from "electron-builder" +import fsExtra from "fs-extra" +import { mkdir } from "fs/promises" +import * as path from "path" +import { app, appThrows, copyTestAsset } from "../helpers/packTester.js" +import { ToolsetConfig } from "app-builder-lib" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = [ + // "0.0.0", // doesn't work for appx specifically, signtool.exe is too old. + "1.0.0", + "1.1.0", +] +const target = Platform.WINDOWS.createTarget(["appx"], Arch.x64) + +describe.ifWindows("AppX", () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + + // test that we can get info from protected pfx + const protectedCscLink = + "MIIJWQIBAzCCCR8GCSqGSIb3DQEHAaCCCRAEggkMMIIJCDCCA78GCSqGSIb3DQEHBqCCA7AwggOsAgEAMIIDpQYJKoZIhvcNAQcBMBwGCiqGSIb3DQEMAQYwDgQIarkfkLfaZxICAggAgIIDeM22vRfcAQpRZhx+F9DP3lEsOAoFeUT88x2raMceAyrvErA8BNF4HY6JqHcWKXDkOviMz7zI5wfbjxxVal7sBBFtglCksHRDjC0+xjRce5QgGQ0iF6zay5PcM000AmHDrT9MIM8uFt/98ApK1AqVmuSZjkI5ySFlXT8Vd6FrR32xIk0vGVxRCRHZQ0OXj2TyJfF/sjzkFjJMBB/xplFiotFagSnRm4nM5TACSJ2IMBXDToZ1l8ki+PkTn5m0VEZmZQ3FNaGHTrpSu2p/mA+AjG2Iz/ILIUJMYemR7gQMIp39ul+DCSdZZZqbUNtk7eefLLBr2aLA5AcDkLNur3IkxnuJ5NJoCaLHUHtOEeUbZeqqwfBBIZtgNFUPZjHVU2kLoOS3SIl0guicixOuALZrxSjoxpIfQFNm4v24iUUx7WCUz488fwOmY3SANHKY2clz30Ta0q6dwaybE4pf/ohy6ofXfLk7rcv63JpbB1VN0vfKs633D0HZobW8PlwdJ6DpgkiKggI8TONNNguN/ebOV10tG3B8GlIQjmup5HezI9+rWkRwLcQaIccyIRqixPFoCWeaq1nT8P+PTx9JSdmYn6Yx+revYMh8jeB9UJ4kVrCsFzn0J+qEVLquuOTcQUvhi2FZQuZaYpwy0iGBkwOBXUkjn+SehbIcHvf4zXIUR4NE3Zk5zu5f+nkGBgIC5qKnZJEquO9BR57/reTPByNpknmTjPlcWZE2Jc4QrytVL+QLrLYFejUxi5JxcHtmV0mP5opi7fXfQsaJ0XjvhdEaLUehzlttUuPQrMH87iNtpQzEZEHDwx07Xwo4NoitBMrWZKkkz6jT92cdTB+kHcsiGIxm5REmQQgMiuwKNMSWIg4pcXeXz9d+AuZGSF91mM9/W0rZM1d14V44cfGBLIXfdViryP96Mm8KqqWMtvYh2w3xQjDP80dtnhw/95DVEPBnIXxT7WNRXyXZ+pYhtsnPIMlnJXH5J4QfkHmIH3akJa7gNuvpoFbjxvfFBBFs28pUSxAH4MZuq3Ndid8PhoMpq6a6B+TtXVVtv6mJ3y3x6Mattm0NYb6c4P3yXIjBfUVOZE1GQhMP9uQkduccR8pI1gui75kEVAkvVGzZriMZK/ia56Hswl7IBJKoc7byExaXJLBXJo/mZK93QbUX5EoMZ1NIFlWwT+NeYjCCBUEGCSqGSIb3DQEHAaCCBTIEggUuMIIFKjCCBSYGCyqGSIb3DQEMCgECoIIE7jCCBOowHAYKKoZIhvcNAQwBAzAOBAhs6OszcQq/sgICCAAEggTImLprl43zViu8OhQGba0MIWYO0GQkMqBWlpV0By5rIfeqRe9ieqOkNIl+ahTglGboZ9X1lUZF/6AsITMo1c2PioS2Cf2P9I/PQrJJZUmomLoWeciVzgLtY+lssUx7/LG7wZ238+5KxjcY0eiOjVksTxuRcLT8+pmxEzdTZDzDOgayadoidrs1xsOnCQtjN8EYrFB7TLxoAhUTwCbH6AHSutw6h/uGEf9UOA13/YSe3YFzkGyS1/BYZyUg5OV9/WUVMJBo6c+W0ZCf/yhtnPJQFWPwcUSc5qdA+8EMYGE04+rIr7oyGByuHd4HjLuZHQXoUGQH/Bf9JlE6t7L0EqGpLGAxtW1eOTRrjU7cUmAVbj/Op5qoDb4wH0FdonFE52pfLCDwjYjf7C0hAJVLCvJEWGqjkIx0IRGf4jLOzSnzFAh+s8+F+XqeHFHfBT9RHrj9YWwyi+kcx+7tLGhQtoUSosCm2USwT01f7i3W1GUF4ggS+vxDylOkcvHtziKAGqFCu5vpKf+UemDk2wYu8G0S/JoBGYbDyxN8cGhT7Ci4X6HxDcsLBYgrJAJgVRu3sccE+pEEOzhler8z2NiGTv1N/h80uTOZJpaZiRePv53Y1W7Cn0i0pEMo7GERoUn5lx8U3Lsi8iPIf2z/P4zfyp4a+LGco8b/cgA9npz4/+78dN6ode+u2IuyhyacyfHiTR4ZExfGFPmByf2sWs2ewJYZV4aGTk9sW/koRGza3Mgda1tYZsgcCiDy86S7zmg1FJJAqq0prTLeaZtJxBJSHsAaH9QPXjOJyksjNfQjk5+iI8rcSAeDF3DZ6PqtcBpJdk10YBVvfTYDWsoS6w/w0mAvnpNGAQB1U69wC09Uqqvd+ulv4ilzdSmKnu0aMOKq7G9TwSwoizFbJoyOvtHgKWjmhuo+MfdwxOjTuMelxGrwgUhxOT+1a2J9xe4/a+XBIbqwzwl+UsZFqrIwL46ZXjwO18yYwbC1P6kAPxFix9vXvzCW/9NXQP1DzuAIrlah9OHgolY/eVFvqDHMTrHKdd9MlqXXZG3+V0wyXuanSx90ot+pA0q0HXS+7rYaCbjDdAhPfSCktK0JSeQ6/b3tqhcUr85+LtHnqnVMJC4oAovnnhkpPve5nwVb9nxVy7YQfFJ6BZJIsReJwZJWjruepcULs0C6U7bgtntb4G0zDDNO3M6CJbcad3XdAS3g+DU7Z3SpYsAL7oy7FyfhifxhGGdlIF9d6oemGPCINkrHlbXMZVjHpXTxpUHZD8Z8uKqqXyGUvdYdI1V53rJRMBtme2ZjQS22XooSytGJRyARx5jFklfu1d7I06w+zk/OTsR/1CCqw5AzN+jusv+vxNtqMh+eA/HHbNCciU0PZQOhCVmzbIwlgV1LaU4eg/l7b4cAc4wv+fB1fVbBZwnbgXwYeE0dk1MKmiMebFVTfa/SaKF0mhfYlh2JvB/prLSi9tNCKzFm9MeusVeGh9WSdv0RT1MGHxs2rVJhMcKcauokYXsJ4fbJtoOF2k9xTbAoP1RQ10AdtbmKkA/s8sXhFFUgb9L43d9qaoW+mFrUhKs5KFPHrIXv4b8njBFTM17BUH6qSl6W2g4MzG87Vy9tSRrKzVD93X40l61kWe/EMSUwIwYJKoZIhvcNAQkVMRYEFCrpr+tDgu4QhTgZmTVVYL5ecKYQMDEwITAJBgUrDgMCGgUABBTe3zOIgwBb2nek2a9OiZ06Rf+zQQQI5vFHTW+9QnICAggA" + test("AppX", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + { + projectDirCreated: async projectDir => { + const targetDir = path.join(projectDir, "build", "appx") + await mkdir(targetDir, { recursive: true }) + await Promise.all( + ["BadgeLogo.scale-100.png", "BadgeLogo.scale-140.png", "BadgeLogo.scale-180.png"].map(it => copyTestAsset(`appx-assets/${it}`, path.join(targetDir, it))) + ) + }, + signedWin: true, + } + )) + + test("auto launch", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + appx: { + addAutoLaunchExtension: true, + }, + }, + }, + {} + )) + + // use identityName and same setting for applicationId + test("application id", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + cscLink: protectedCscLink, + cscKeyPassword: "test", + appx: { + identityName: "01234Test.ApplicationDataSample", + }, + }, + }, + {} + )) + + test.ifEnv(!!process.env.DO_APPX_CERT_STORE_AWARE_TEST)("certificateSubjectName", ({ expect }) => + app(expect, { + targets: target, + config: { + toolsets, + win: { + signtoolOptions: { + certificateSubjectName: "Foo", + }, + }, + }, + }) + ) + + // todo - check manifest + test("languages and not signed (windows store only)", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget(["appx"], Arch.ia32, Arch.x64), + config: { + toolsets, + cscLink: protectedCscLink, + cscKeyPassword: "test", + appx: { + languages: ["de-DE", "ru-RU"], + minVersion: "10.0.16299.0", + maxVersionTested: "10.0.16299.0", + }, + }, + })) + + test("custom template appmanifest.xml", ({ expect }) => + app(expect, { + targets: target, + config: { + toolsets, + appx: { + customManifestPath: "custom-template-manifest.xml", + }, + appxManifestCreated: async filepath => { + const fileContent = await fsExtra.readFile(filepath, "utf-8") + expect(fileContent).toMatchSnapshot() + }, + }, + })) + + test("custom raw appmanifest.xml", ({ expect }) => + app(expect, { + targets: target, + config: { + toolsets, + appx: { + customManifestPath: "custom-manifest.xml", + }, + appxManifestCreated: async filepath => { + const fileContent = await fsExtra.readFile(filepath, "utf-8") + expect(fileContent).toMatchSnapshot() + }, + }, + })) + + test("valid capabilities (windows store only)", ({ expect }) => + app(expect, { + targets: target, + config: { + toolsets, + cscLink: protectedCscLink, + cscKeyPassword: "test", + appx: { + capabilities: ["internetClient", "picturesLibrary", "webcam", "screenDuplication", "graphicsCapture", "globalMediaControl"], + }, + appxManifestCreated: async filepath => { + const fileContent = await fsExtra.readFile(filepath, "utf-8") + console.log("APPX-MANIFEST: " + fileContent) + expect(fileContent).toContain('') + expect(fileContent).toContain('') + expect(fileContent).toContain('') + expect(fileContent).toContain('') + expect(fileContent).toContain('') + expect(fileContent).toContain('') + expect(fileContent).toContain('') + }, + }, + })) + + test("invalid capabilities (windows store only)", ({ expect }) => + appThrows( + expect, + { + targets: target, + config: { + toolsets, + cscLink: protectedCscLink, + cscKeyPassword: "test", + appx: { + capabilities: ["invalid01", "invalid02"], + }, + }, + }, + {}, + error => { + expect(error.message).toContain("invalid windows capabilities") + } + )) + }) + } +}) diff --git a/test/src/windows/assistedInstallerTest.ts b/test/src/windows/assistedInstallerTest.ts new file mode 100644 index 00000000000..24862ce1cad --- /dev/null +++ b/test/src/windows/assistedInstallerTest.ts @@ -0,0 +1,216 @@ +import { Arch, Platform } from "electron-builder" +import * as fs from "fs/promises" +import * as path from "path" +import { app, assertPack, copyTestAsset } from "../helpers/packTester.js" +import { checkHelpers, doTest, expectUpdateMetadata } from "../helpers/winHelper.js" +import { ToolsetConfig } from "app-builder-lib" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] +const nsisTarget = Platform.WINDOWS.createTarget("nsis", Arch.x64) + +describe.ifWindows("assisted", () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + test("assisted", ({ expect }) => + app( + expect, + { + targets: nsisTarget, + config: { + toolsets, + nsis: { + oneClick: false, + language: "1031", + }, + win: { + legalTrademarks: "My Trademark", + }, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + { + signedWin: true, + projectDirCreated: projectDir => copyTestAsset("license.txt", path.join(projectDir, "build", "license.txt")), + } + )) + + test("allowElevation false, app requestedExecutionLevel admin", ({ expect }) => + app(expect, { + targets: nsisTarget, + config: { + toolsets, + publish: null, + extraMetadata: { + // mt.exe doesn't like unicode names from wine + name: "test", + productName: "test", + }, + win: { + requestedExecutionLevel: "requireAdministrator", + }, + nsis: { + oneClick: false, + allowElevation: false, + perMachine: true, + displayLanguageSelector: true, + installerLanguages: ["en_US", "ru_RU"], + differentialPackage: false, + }, + }, + })) + + test("assisted, MUI_HEADER", ({ expect }) => { + let installerHeaderPath: string | null = null + return assertPack( + expect, + "test-app-one", + { + targets: nsisTarget, + config: { + toolsets, + publish: null, + nsis: { + oneClick: false, + differentialPackage: false, + }, + }, + effectiveOptionComputed: async it => { + const defines = it[0] + expect(defines.MUI_HEADERIMAGE).toBeNull() + expect(defines.MUI_HEADERIMAGE_BITMAP).toEqual(installerHeaderPath) + expect(defines.MUI_HEADERIMAGE_RIGHT).toBeNull() + // speedup, do not build - another MUI_HEADER test will test build + return Promise.resolve(true) + }, + }, + { + projectDirCreated: projectDir => { + installerHeaderPath = path.join(projectDir, "build", "installerHeader.bmp") + return copyTestAsset("installerHeader.bmp", installerHeaderPath) + }, + } + ) + }) + + test.ifWindows("assisted, MUI_HEADER as option", ({ expect }) => { + let installerHeaderPath: string | null = null + return assertPack( + expect, + "test-app-one", + { + targets: Platform.WINDOWS.createTarget(["nsis"], Arch.ia32, Arch.x64), + config: { + toolsets, + publish: null, + nsis: { + oneClick: false, + installerHeader: "foo.bmp", + differentialPackage: false, + }, + }, + effectiveOptionComputed: async it => { + const defines = it[0] + expect(defines.MUI_HEADERIMAGE).toBeNull() + expect(defines.MUI_HEADERIMAGE_BITMAP).toEqual(installerHeaderPath) + expect(defines.MUI_HEADERIMAGE_RIGHT).toBeNull() + // test that we can build such installer + return Promise.resolve(false) + }, + }, + { + projectDirCreated: projectDir => { + installerHeaderPath = path.join(projectDir, "foo.bmp") + return copyTestAsset("installerHeader.bmp", installerHeaderPath) + }, + } + ) + }) + + test.skip("debug logging enabled", ({ expect }) => + app(expect, { + targets: nsisTarget, + config: { + toolsets, + nsis: { + customNsisBinary: { + url: "https://github.com/electron-userland/electron-builder-binaries/releases/download/nsis-3.0.4.2/nsis-3.0.4.2.7z", + version: "3.0.4.2", + checksum: "o+YZsXHp8LNihhuk7JsCDhdIgx0MKKK+1b3sGD+4zX5djZULe4/4QMcAsfQ+0r+a8FnwBt7BVBHkIkJHjKQ0sg==", + debugLogging: true, + }, + }, + }, + })) + + test("assisted, only perMachine", ({ expect }) => + app(expect, { + targets: nsisTarget, + config: { + toolsets, + nsis: { + oneClick: false, + perMachine: true, + }, + }, + })) + + test("assisted, only perMachine and elevated", ({ expect }) => + app(expect, { + targets: nsisTarget, + config: { + toolsets, + nsis: { + oneClick: false, + perMachine: true, + packElevateHelper: true, + }, + }, + })) + + // test release notes also + test("allowToChangeInstallationDirectory", ({ expect }) => + app( + expect, + { + targets: nsisTarget, + config: { + toolsets, + extraMetadata: { + name: "test-custom-inst-dir", + productName: "Test Custom Installation Dir", + repository: "foo/bar", + }, + nsis: { + allowToChangeInstallationDirectory: true, + oneClick: false, + multiLanguageInstaller: false, + }, + }, + }, + { + projectDirCreated: async projectDir => { + await fs.writeFile(path.join(projectDir, "build", "release-notes.md"), "New release with new bugs and\n\nwithout features") + await copyTestAsset("license.txt", path.join(projectDir, "build", "license.txt")) + }, + packed: async context => { + await expectUpdateMetadata(expect, context, Arch.x64) + await checkHelpers(expect, context.getResources(Platform.WINDOWS), true) + await doTest(expect, context.outDir, false) + }, + } + )) + }) + } +}) diff --git a/test/src/windows/assistedInstallerTestSuite.ts b/test/src/windows/assistedInstallerTestSuite.ts index b6b71e83ec6..7a3b51633d5 100644 --- a/test/src/windows/assistedInstallerTestSuite.ts +++ b/test/src/windows/assistedInstallerTestSuite.ts @@ -3,7 +3,7 @@ import * as fs from "fs/promises" import * as path from "path" import { app, assertPack, copyTestAsset } from "../helpers/packTester" import { checkHelpers, doTest, expectUpdateMetadata } from "../helpers/winHelper" -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" const nsisTarget = Platform.WINDOWS.createTarget("nsis", Arch.x64) diff --git a/test/src/windows/msiTest.ts b/test/src/windows/msiTest.ts new file mode 100644 index 00000000000..bf21c72c1fb --- /dev/null +++ b/test/src/windows/msiTest.ts @@ -0,0 +1,148 @@ +import { Arch, Platform } from "electron-builder" +import * as fs from "fs" +import { app } from "../helpers/packTester.js" +import { ToolsetConfig } from "app-builder-lib" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] +const target = Platform.WINDOWS.createTarget("msi", Arch.x64) + +describe.ifWindows("msi", { sequential: true }, () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + test("msi", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI", + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + { + // signed: true, + } + )) + + test("msi no asar", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI", + asar: false, + }, + }, + { + // signed: true, + } + )) + + test("per-user", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perUser", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI Per User", + msi: { + perMachine: false, + }, + }, + }, + { + // signed: true, + } + )) + + const wixArgsProductName = "Test WiX Args" + test("wix args", ({ expect }) => + app( + expect, + { + targets: target, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.wixArgs", + extraMetadata: { + // version: "1.0.0", + }, + productName: wixArgsProductName, + // Inject a custom-action which requires the WixUtilExtension DLL + msiProjectCreated: async path => { + await fs.promises.writeFile( + path, + (await fs.promises.readFile(path, "utf8")).replace( + "", + ` + ` + ) + ) + }, + msi: { + // Apply the needed DLL + additionalWixArgs: ["-ext", "WixUtilExtension"], + }, + }, + }, + { + // signed: true, + } + )) + + test.skip("assisted", ({ expect }) => + app(expect, { + targets: target, + config: { + toolsets, + appId: "build.electron.test.msi.assisted", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI Assisted", + // test lzx (currently, doesn't work on wine) + compression: "maximum", + msi: { + oneClick: false, + menuCategory: "TestMenuDirectory", + }, + }, + })) + }) + } +}) diff --git a/test/src/windows/msiWrappedTest.ts b/test/src/windows/msiWrappedTest.ts new file mode 100644 index 00000000000..5a87a12ae6f --- /dev/null +++ b/test/src/windows/msiWrappedTest.ts @@ -0,0 +1,176 @@ +import { Arch, Platform } from "electron-builder" +import { XMLParser } from "fast-xml-parser" +import * as fs from "fs" +import { app, appThrows } from "../helpers/packTester.js" +import { ToolsetConfig } from "app-builder-lib" + +const parser = new XMLParser({ + ignoreAttributes: false, + ignoreDeclaration: true, + parseTagValue: true, +}) + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] +const wrappedTarget = Platform.WINDOWS.createTarget(["NSIS", "msiWrapped"], Arch.x64) + +describe.ifWindows("msiWrapped", { sequential: true }, () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + test("msiWrapped requires nsis", ({ expect }) => + appThrows( + expect, + { + targets: Platform.WINDOWS.createTarget("msiWrapped", Arch.x64), + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI", + win: { + target: ["msiWrapped"], + }, + }, + }, + {}, + error => { + expect(error).toBeInstanceOf(Error) + expect(error.message).toBe("No nsis target found! Please specify an nsis target") + } + )) + + test("msiWrapped allows capitalized nsis target", ({ expect }) => + app( + expect, + { + targets: wrappedTarget, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "Test MSI", + win: { + target: ["msiWrapped", "NSIS"], + }, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + {} + )) + + test("msiWrapped includes packaged exe", ({ expect }) => + app(expect, { + targets: wrappedTarget, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "MSIWrappingEXE", + win: { + target: ["msiWrapped", "nsis"], + }, + msiProjectCreated: async path => { + const msiContents = await fs.promises.readFile(path, "utf8") + + const contents = parser.parse(msiContents) + + expect(contents["Wix"]["Product"]["Binary"]["@_SourceFile"]).toMatch(/^.*\.(exe|EXE)/) + expect(contents["Wix"]["Product"]["InstallExecuteSequence"]).toBeTruthy() + }, + }, + })) + + test("msiWrapped impersonate no if not provided", ({ expect }) => + app(expect, { + targets: wrappedTarget, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "MSIWrappingEXE", + win: { + target: ["msiWrapped", "nsis"], + }, + msiProjectCreated: async path => { + const msiContents = await fs.promises.readFile(path, "utf8") + + const contents = parser.parse(msiContents) + + expect(contents["Wix"]["Product"]["CustomAction"]["@_Impersonate"]).toEqual("no") + }, + }, + })) + + test("msiWrapped impersonate yes if true", ({ expect }) => + app(expect, { + targets: wrappedTarget, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "MSIWrappingEXE", + win: { + target: ["msiWrapped", "nsis"], + }, + msiWrapped: { + impersonate: true, + }, + msiProjectCreated: async path => { + const msiContents = await fs.promises.readFile(path, "utf8") + + const contents = parser.parse(msiContents) + + expect(contents["Wix"]["Product"]["CustomAction"]["@_Impersonate"]).toEqual("yes") + }, + }, + })) + + test("msiWrapped wrappedInstallerArgs provided", ({ expect }) => + app(expect, { + targets: wrappedTarget, + config: { + toolsets, + appId: "build.electron.test.msi.oneClick.perMachine", + extraMetadata: { + // version: "1.0.0", + }, + productName: "MSIWrappingEXE", + win: { + target: ["msiWrapped", "nsis"], + }, + msiWrapped: { + wrappedInstallerArgs: "/currentuser /S /wut", + }, + msiProjectCreated: async path => { + const msiContents = await fs.promises.readFile(path, "utf8") + + const contents = parser.parse(msiContents) + + expect(contents["Wix"]["Product"]["CustomAction"]["@_ExeCommand"]).toEqual("/currentuser /S /wut") + }, + }, + })) + }) + } +}) diff --git a/test/src/windows/msiWrappedTestSuite.ts b/test/src/windows/msiWrappedTestSuite.ts index f7e2d99c2bd..7cad7c5c326 100644 --- a/test/src/windows/msiWrappedTestSuite.ts +++ b/test/src/windows/msiWrappedTestSuite.ts @@ -2,7 +2,7 @@ import { Arch, Platform } from "electron-builder" import { XMLParser } from "fast-xml-parser" import * as fs from "fs" import { app, appThrows } from "../helpers/packTester" -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" const parser = new XMLParser({ ignoreAttributes: false, diff --git a/test/src/windows/nsisOutputValidationTest.ts b/test/src/windows/nsisOutputValidationTest.ts index 82f25bc29a4..c596a12de95 100644 --- a/test/src/windows/nsisOutputValidationTest.ts +++ b/test/src/windows/nsisOutputValidationTest.ts @@ -2,8 +2,8 @@ import { promises as fsp } from "fs" import * as os from "os" import * as path from "path" import { afterEach, beforeEach } from "vitest" -import { checkMakensisOutput, verifyInstallerSize } from "app-builder-lib/src/targets/nsis/nsisValidation" -import type { Defines } from "app-builder-lib/src/targets/nsis/Defines" +import { checkMakensisOutput, verifyInstallerSize } from "app-builder-lib/internal" +import type { Defines } from "app-builder-lib/internal" // ─── checkMakensisOutput ──────────────────────────────────────────────────── diff --git a/test/src/windows/nsisScriptGeneratorTest.ts b/test/src/windows/nsisScriptGeneratorTest.ts index e3d584eec07..0a681cfb7e5 100644 --- a/test/src/windows/nsisScriptGeneratorTest.ts +++ b/test/src/windows/nsisScriptGeneratorTest.ts @@ -1,4 +1,4 @@ -import { NsisScriptGenerator, nsisEscapeString } from "app-builder-lib/src/targets/nsis/nsisScriptGenerator" +import { NsisScriptGenerator, nsisEscapeString } from "app-builder-lib/internal" describe("NsisScriptGenerator.file", () => { test("preserves $INSTDIR variable in output name without escaping", ({ expect }) => { diff --git a/test/src/windows/oneClickInstallerTest.ts b/test/src/windows/oneClickInstallerTest.ts index 0b2648c3be6..1b56555c214 100644 --- a/test/src/windows/oneClickInstallerTest.ts +++ b/test/src/windows/oneClickInstallerTest.ts @@ -1,9 +1,9 @@ import { Arch, Platform } from "electron-builder" -import { copyFile, writeFile } from "fs-extra" +import fsExtra from "fs-extra" import * as path from "path" -import { assertThat } from "../helpers/fileAssert" -import { app, assertPack, copyTestAsset, EXTENDED_TIMEOUT, modifyPackageJson } from "../helpers/packTester" -import { checkHelpers, doTest, expectUpdateMetadata } from "../helpers/winHelper" +import { assertThat } from "../helpers/fileAssert.js" +import { app, assertPack, copyTestAsset, EXTENDED_TIMEOUT, modifyPackageJson } from "../helpers/packTester.js" +import { checkHelpers, doTest, expectUpdateMetadata } from "../helpers/winHelper.js" const nsisTarget = Platform.WINDOWS.createTarget(["nsis"], Arch.x64) @@ -98,10 +98,10 @@ test("multi language license", { timeout: EXTENDED_TIMEOUT }, ({ expect }) => { projectDirCreated: projectDir => { return Promise.all([ - writeFile(path.join(projectDir, "build", "license_en.txt"), "Hi"), - writeFile(path.join(projectDir, "build", "license_ru.txt"), "Привет"), - writeFile(path.join(projectDir, "build", "license_ko.txt"), "Привет"), - writeFile(path.join(projectDir, "build", "license_fi.txt"), "Привет"), + fsExtra.writeFile(path.join(projectDir, "build", "license_en.txt"), "Hi"), + fsExtra.writeFile(path.join(projectDir, "build", "license_ru.txt"), "Привет"), + fsExtra.writeFile(path.join(projectDir, "build", "license_ko.txt"), "Привет"), + fsExtra.writeFile(path.join(projectDir, "build", "license_fi.txt"), "Привет"), ]) }, } @@ -124,7 +124,7 @@ test("html license", { timeout: EXTENDED_TIMEOUT }, ({ expect }) => { projectDirCreated: projectDir => { return Promise.all([ - writeFile(path.join(projectDir, "build", "license.html"), '

Hi google

'), + fsExtra.writeFile(path.join(projectDir, "build", "license.html"), '

Hi google

'), ]) }, } @@ -239,7 +239,7 @@ test.skip("big file pack", { timeout: EXTENDED_TIMEOUT }, ({ expect }) => }, { projectDirCreated: async projectDir => { - await copyFile("/Volumes/Pegasus/15.02.18.m4v", path.join(projectDir, "foo/bar/video.mov")) + await fsExtra.copyFile("/Volumes/Pegasus/15.02.18.m4v", path.join(projectDir, "foo/bar/video.mov")) }, } ) diff --git a/test/src/windows/portableTest.ts b/test/src/windows/portableTest.ts new file mode 100644 index 00000000000..de75249bc53 --- /dev/null +++ b/test/src/windows/portableTest.ts @@ -0,0 +1,108 @@ +import { Arch, Platform } from "electron-builder" +import * as path from "path" +import { app, copyTestAsset, getFixtureDir } from "../helpers/packTester.js" +import { ToolsetConfig } from "app-builder-lib" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] + +describe.ifWindows("portable", () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + // build in parallel - https://github.com/electron-userland/electron-builder/issues/1340#issuecomment-286061789 + test("portable", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget(["portable", "nsis"], Arch.x64), + config: { + toolsets, + publish: null, + nsis: { + differentialPackage: false, + }, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + })) + + test("portable zip", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget("portable", Arch.x64), + config: { + toolsets, + publish: null, + portable: { + useZip: true, + unpackDirName: "0ujssxh0cECutqzMgbtXSGnjorm", + }, + compression: "normal", + }, + })) + + test.ifWindows("portable zip several archs", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget("portable", Arch.ia32, Arch.x64), + config: { + toolsets, + publish: null, + portable: { + useZip: true, + unpackDirName: false, + }, + compression: "store", + }, + }) + ) + + test("portable - artifactName and request execution level", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["portable"], Arch.x64), + config: { + toolsets, + nsis: { + //tslint:disable-next-line:no-invalid-template-strings + artifactName: "${productName}Installer.${version}.${ext}", + installerIcon: "foo test space.ico", + }, + portable: { + unpackDirName: true, + requestExecutionLevel: "admin", + //tslint:disable-next-line:no-invalid-template-strings + artifactName: "${productName}Portable.${version}.${ext}", + }, + }, + }, + { + projectDirCreated: projectDir => { + return copyTestAsset("headerIcon.ico", path.join(projectDir, "build", "foo test space.ico")) + }, + } + )) + + test("portable - splashImage", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget(["portable"], Arch.x64), + config: { + toolsets, + publish: null, + portable: { + //tslint:disable-next-line:no-invalid-template-strings + artifactName: "${productName}Portable.${version}.${ext}", + splashImage: path.resolve(getFixtureDir(), "installerHeader.bmp"), + }, + }, + })) + }) + } +}) diff --git a/test/src/windows/squirrelWindowsSecurityTest.ts b/test/src/windows/squirrelWindowsSecurityTest.ts index fae15922877..4ac86453001 100644 --- a/test/src/windows/squirrelWindowsSecurityTest.ts +++ b/test/src/windows/squirrelWindowsSecurityTest.ts @@ -1,4 +1,4 @@ -import SquirrelWindowsTarget from "electron-builder-squirrel-windows/out/SquirrelWindowsTarget" +import SquirrelWindowsTarget from "electron-builder-squirrel-windows/src/SquirrelWindowsTarget" import { mkdtemp, realpath, rm } from "fs/promises" import { tmpdir } from "os" import * as path from "path" diff --git a/test/src/windows/squirrelWindowsTest.ts b/test/src/windows/squirrelWindowsTest.ts new file mode 100644 index 00000000000..99f2b8a9e17 --- /dev/null +++ b/test/src/windows/squirrelWindowsTest.ts @@ -0,0 +1,136 @@ +import { Arch, Platform } from "electron-builder" +import * as path from "path" +import { CheckingWinPackager } from "../helpers/CheckingPackager.js" +import { app, assertPack, copyTestAsset } from "../helpers/packTester.js" +import { ToolsetConfig } from "app-builder-lib" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] + +describe.ifWindows("squirrel-windows", { sequential: true }, () => { + for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + const toolsets: ToolsetConfig = { + winCodeSign, + } + test("Squirrel.Windows", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["squirrel"], Arch.x64), + config: { + toolsets, + win: { + compression: "normal", + }, + executableName: "test with spaces", + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + { signedWin: true } + )) + + test("artifactName", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget(["squirrel", "zip"], Arch.x64), + config: { + toolsets, + win: { + // tslint:disable:no-invalid-template-strings + artifactName: "Test ${name} foo.${ext}", + }, + }, + })) + + // very slow + test.skip("delta and msi", ({ expect }) => + app(expect, { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.ia32), + config: { + toolsets, + squirrelWindows: { + remoteReleases: "https://github.com/develar/__test-app-releases", + msi: true, + }, + }, + })) + + test("squirrel window arm64 msi", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.arm64), + config: { + toolsets, + squirrelWindows: { + msi: true, + }, + }, + }, + { signedWin: true } + )) + + test("squirrel window x64 msi", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.x64), + config: { + toolsets, + squirrelWindows: { + msi: true, + }, + }, + }, + { signedWin: true } + )) + + test("squirrel window ia32 msi", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.ia32), + config: { + toolsets, + squirrelWindows: { + msi: true, + }, + }, + }, + { signedWin: true } + )) + + test("detect install-spinner", ({ expect }) => { + let platformPackager: CheckingWinPackager | null = null + let loadingGifPath: string | null = null + + return assertPack( + expect, + "test-app-one", + { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.x64), + platformPackagerFactory: (packager, _platform) => (platformPackager = new CheckingWinPackager(packager)), + }, + { + projectDirCreated: it => { + loadingGifPath = path.join(it, "build", "install-spinner.gif") + return copyTestAsset("install-spinner.gif", loadingGifPath) + }, + packed: async () => { + expect(platformPackager!.effectiveDistOptions.loadingGif).toEqual(loadingGifPath) + return Promise.resolve() + }, + } + ) + }) + }) + } +}) diff --git a/test/src/windows/winCodeSignTest.ts b/test/src/windows/winCodeSignTest.ts index edfcabcca55..8336b871b45 100644 --- a/test/src/windows/winCodeSignTest.ts +++ b/test/src/windows/winCodeSignTest.ts @@ -1,7 +1,6 @@ import { parseDn } from "builder-util-runtime" import { ToolInfo, WinPackager, WindowsSignToolManager } from "app-builder-lib" -import { CustomWindowsSign } from "app-builder-lib/out/codeSign/windowsSignToolManager" -import { Configuration, ToolsetConfig } from "app-builder-lib/out/configuration" +import { Configuration, CustomWindowsSign, ToolsetConfig } from "app-builder-lib/internal" import { AsyncTaskManager } from "builder-util" import { Arch, DIR_TARGET, Platform, Target } from "electron-builder" import { Packager } from "electron-builder" diff --git a/test/src/windows/winPackagerTest.ts b/test/src/windows/winPackagerTest.ts new file mode 100644 index 00000000000..8d327a822ab --- /dev/null +++ b/test/src/windows/winPackagerTest.ts @@ -0,0 +1,173 @@ +import { ToolsetConfig } from "app-builder-lib" +import { Arch, DIR_TARGET, Platform } from "electron-builder" +import * as fs from "fs/promises" +import * as path from "path" +import { CheckingWinPackager } from "../helpers/CheckingPackager.js" +import { app, appThrows, assertPack, platform } from "../helpers/packTester.js" + +const winCodeSignVersions: ToolsetConfig["winCodeSign"][] = ["0.0.0", "1.0.0", "1.1.0"] + +for (const winCodeSign of winCodeSignVersions) { + describe(`winCodeSign: ${winCodeSign}`, () => { + test("beta version", { retry: 3 }, ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["nsis"], Arch.x64, Arch.arm64), + config: { + extraMetadata: { + version: "3.0.0-beta.2", + }, + nsis: { + buildUniversalInstaller: false, + }, + toolsets: { + winCodeSign, + }, + }, + }, + { + signedWin: true, + } + ) + ) + + test("win zip", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["zip"], Arch.x64, Arch.arm64), + config: { + extraResources: [ + { from: "build", to: "./", filter: "*.asar" }, + { from: "build/subdir", to: "./subdir", filter: "*.asar" }, + ], + toolsets: { + winCodeSign, + }, + electronLanguages: "en", + downloadAlternateFFmpeg: true, + electronFuses: { + runAsNode: true, + enableCookieEncryption: true, + enableNodeOptionsEnvironmentVariable: true, + enableNodeCliInspectArguments: true, + enableEmbeddedAsarIntegrityValidation: true, + onlyLoadAppFromAsar: true, + loadBrowserProcessSpecificV8Snapshot: true, + grantFileProtocolExtraPrivileges: undefined, // unsupported on current electron version in our tests + }, + }, + }, + { + signed: false, + projectDirCreated: async projectDir => { + await fs.mkdir(path.join(projectDir, "build", "subdir")) + await fs.copyFile(path.join(projectDir, "build", "extraAsar.asar"), path.join(projectDir, "build", "subdir", "extraAsar2.asar")) + }, + } + )) + + test("zip artifactName", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["zip"], Arch.x64), + config: { + //tslint:disable-next-line:no-invalid-template-strings + artifactName: "${productName}-${version}-${os}-${arch}.${ext}", + toolsets: { + winCodeSign, + }, + }, + }, + { + signedWin: true, + } + )) + + test("legacy win-codesign", ({ expect }) => + app( + expect, + { + targets: Platform.WINDOWS.createTarget(["zip"], Arch.x64), + config: { + toolsets: { + winCodeSign, + }, + }, + }, + { + signedWin: true, + } + )) + + test("icon < 256", ({ expect }) => + appThrows(expect, platform(Platform.WINDOWS), { + projectDirCreated: projectDir => fs.rename(path.join(projectDir, "build", "incorrect.ico"), path.join(projectDir, "build", "icon.ico")), + })) + + test("icon not an image", ({ expect }) => + appThrows(expect, platform(Platform.WINDOWS), { + projectDirCreated: async projectDir => { + const file = path.join(projectDir, "build", "icon.ico") + // because we use hardlinks + await fs.unlink(file) + await fs.writeFile(file, "foo") + }, + })) + + test.ifMac("custom icon", ({ expect }) => { + let platformPackager: CheckingWinPackager | null = null + return assertPack( + expect, + "test-app-one", + { + targets: Platform.WINDOWS.createTarget("squirrel", Arch.x64), + platformPackagerFactory: packager => (platformPackager = new CheckingWinPackager(packager)), + config: { + win: { + icon: "customIcon", + }, + toolsets: { + winCodeSign, + }, + }, + }, + { + projectDirCreated: projectDir => fs.rename(path.join(projectDir, "build", "icon.ico"), path.join(projectDir, "customIcon.ico")), + packed: async context => { + expect(await platformPackager!.getIconPath()).toEqual(path.join(context.projectDir, "customIcon.ico")) + }, + } + ) + }) + + test("win icon from icns", ({ expect }) => { + let platformPackager: CheckingWinPackager | null = null + return app( + expect, + { + targets: Platform.WINDOWS.createTarget(DIR_TARGET, Arch.x64), + config: { + mac: { + icon: "icons/icon.icns", + }, + toolsets: { + winCodeSign, + }, + }, + platformPackagerFactory: packager => (platformPackager = new CheckingWinPackager(packager)), + }, + { + projectDirCreated: projectDir => + Promise.all([fs.unlink(path.join(projectDir, "build", "icon.ico")), fs.rm(path.join(projectDir, "build", "icons"), { recursive: true, force: true })]), + packed: async () => { + const file = await platformPackager!.getIconPath() + expect(file).toBeDefined() + }, + } + ) + }) + }) +} diff --git a/test/src/windows/winPackagerTestSuite.ts b/test/src/windows/winPackagerTestSuite.ts index 77f59fb4020..62b5b95fdaf 100644 --- a/test/src/windows/winPackagerTestSuite.ts +++ b/test/src/windows/winPackagerTestSuite.ts @@ -1,4 +1,4 @@ -import { ToolsetConfig } from "app-builder-lib/src/configuration" +import { ToolsetConfig } from "app-builder-lib/internal" import { Arch, DIR_TARGET, Platform } from "electron-builder" import * as fs from "fs/promises" import * as path from "path" diff --git a/test/src/windows/winReseditTest.ts b/test/src/windows/winReseditTest.ts index 3947516f67a..02eee2d6e5f 100644 --- a/test/src/windows/winReseditTest.ts +++ b/test/src/windows/winReseditTest.ts @@ -1,4 +1,4 @@ -import { ResourceEditOptions, editWindowsResources } from "app-builder-lib/out/util/resEdit" +import { ResourceEditOptions, editWindowsResources } from "app-builder-lib/internal" import * as fs from "fs/promises" import * as os from "os" import path from "path" diff --git a/test/src/windows/winSignToolManagerTest.ts b/test/src/windows/winSignToolManagerTest.ts index 9bfb2807d07..ca5f022c54f 100644 --- a/test/src/windows/winSignToolManagerTest.ts +++ b/test/src/windows/winSignToolManagerTest.ts @@ -1,5 +1,5 @@ import { WindowsSignToolManager } from "app-builder-lib" -import { WindowsSignTaskConfiguration } from "app-builder-lib/out/codeSign/windowsSignToolManager" +import { WindowsSignTaskConfiguration } from "app-builder-lib/internal" import { mkdtemp, rm, writeFile } from "fs/promises" import { tmpdir } from "os" import * as path from "path" diff --git a/test/tsconfig.json b/test/tsconfig.json index 89132d18648..9df935d7656 100644 --- a/test/tsconfig.json +++ b/test/tsconfig.json @@ -3,26 +3,8 @@ "compilerOptions": { "rootDir": ".", "outDir": "out", - "skipLibCheck": true, - "baseUrl": "../packages" + "skipLibCheck": true }, - "references": [ - { - "path": "../packages/builder-util" - }, - { - "path": "../packages/builder-util-runtime" - }, - { - "path": "../packages/electron-builder" - }, - { - "path": "../packages/electron-publish" - }, - { - "path": "../packages/electron-updater" - } - ], "declaration": false, "include": [ "../typings/*.d.ts", @@ -31,6 +13,5 @@ "vitest-scripts/*.ts" ], "types": ["vitest/globals"], - "exclude": [ - ] + "exclude": [] } diff --git a/test/vitest-scripts/generate-tests.ts b/test/vitest-scripts/generate-tests.ts index aedcf9d651f..2e7e298ce87 100644 --- a/test/vitest-scripts/generate-tests.ts +++ b/test/vitest-scripts/generate-tests.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx import { existsSync, rmSync } from "fs-extra" import { generateLinuxToolsetTests } from "./generate-toolset-tests-linux" import { GENERATED_TESTS_DIR } from "./generate-toolset-tests-shared" diff --git a/test/vitest-scripts/run-vitest.ts b/test/vitest-scripts/run-vitest.ts index ef016dbbde9..9542a29115c 100644 --- a/test/vitest-scripts/run-vitest.ts +++ b/test/vitest-scripts/run-vitest.ts @@ -1,6 +1,7 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx import isCI from "is-ci" +import * as path from "path" import { startVitest } from "vitest/node" import { getAllTestFiles } from "./file-discovery" import { generateTests } from "./generate-tests" @@ -8,9 +9,37 @@ import { buildWeightedFiles, computeShardCount, splitIntoShards } from "./shard- import { SHARD_INDEX, SupportedPlatforms, TEST_FILES_PATTERN } from "./smart-config" import SmartSequencer from "./vitest-smart-sequencer" -const testRegex = TEST_FILES_PATTERN?.split(",") -const includeRegex = `(${testRegex.join("|")}|${testRegex.map(t => `${t}*Test`).join("|")})` -console.log("TEST_FILES pattern", includeRegex) +// Resolve workspace packages to their TypeScript sources during tests. The published packages are +// bundled (CJS+ESM) by tsup, but tests must run against un-bundled source so vite handles CJS interop +// (e.g. fs-extra) and circular deps, and so `vi.mock` can intercept individual internal modules. +const PACKAGES_DIR = path.join(__dirname, "..", "..", "packages") +const escapeRegex = (s: string) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&") +const sourceAlias = (specifier: string, relPath: string) => ({ + find: new RegExp(`^${escapeRegex(specifier)}$`), + replacement: path.join(PACKAGES_DIR, relPath), +}) +const workspaceSourceAliases = [ + sourceAlias("app-builder-lib/internal", "app-builder-lib/src/indexInternal.ts"), + sourceAlias("app-builder-lib", "app-builder-lib/src/index.ts"), + sourceAlias("builder-util/internal", "builder-util/src/indexInternal.ts"), + sourceAlias("builder-util", "builder-util/src/util.ts"), + sourceAlias("builder-util-runtime/internal", "builder-util-runtime/src/indexInternal.ts"), + sourceAlias("builder-util-runtime", "builder-util-runtime/src/index.ts"), + sourceAlias("electron-publish/internal", "electron-publish/src/indexInternal.ts"), + sourceAlias("electron-publish", "electron-publish/src/index.ts"), + sourceAlias("electron-updater/internal", "electron-updater/src/indexInternal.ts"), + sourceAlias("electron-updater", "electron-updater/src/index.ts"), + sourceAlias("dmg-builder", "dmg-builder/src/dmgUtil.ts"), + sourceAlias("electron-builder-squirrel-windows", "electron-builder-squirrel-windows/src/SquirrelWindowsTarget.ts"), + sourceAlias("electron-builder/internal", "electron-builder/src/indexInternal.ts"), + sourceAlias("electron-builder", "electron-builder/src/index.ts"), +] + +const testPatterns = TEST_FILES_PATTERN.split(",") + .map(s => s.trim()) + .filter(Boolean) +const includeGlob = `(${testPatterns.join("|")}|${testPatterns.map(t => `${t}*Test`).join("|")})` +console.log("TEST_FILES pattern", includeGlob) async function main() { generateTests() @@ -44,53 +73,62 @@ async function main() { console.log(`\n=== Shard ${index + 1} of ${shardCount} ===`) console.log(`Scanned Files: ${selectedFiles.length}`) - return startVitest("test", selectedFiles, { - allowOnly: !isCI, // Prevent accidental commit of `test.only` in CI - update: process.env.UPDATE_SNAPSHOT === "true", - - // we manually set `globalThis.test` and `globalThis.describe` in vitest-setup.ts to make sure everything works correctly - globals: false, - - // Allow test metadata - includeTaskLocation: true, - setupFiles: [__dirname + "/vitest-setup.ts", __dirname + "/vitest-heavy-mutex.ts"], - include: [`test/src/**/${includeRegex}.ts`], - - printConsoleTrace: true, - runner: __dirname + "/vitest-network-retry-runner.ts", - reporters: ["default", __dirname + "/vitest-smart-reporter.ts"], - - // 2 on Windows (heavy MSI/Squirrel builds saturate the vitest main-thread RPC at 3); 3 elsewhere - maxWorkers: process.platform === "win32" ? 2 : 3, - - fileParallelism: process.env.TEST_SEQUENTIAL_FILES !== "true", - sequence: { - sequencer: SmartSequencer, - concurrent: process.env.TEST_SEQUENTIAL === "false", - }, - - slowTestThreshold: 2 * 60 * 1000, - testTimeout: 10 * 60 * 1000, // disk operations can be slow. We're generous with the timeout here to account for less-performant hardware - - snapshotFormat: { - printBasicPrototype: false, - }, - resolveSnapshotPath: (testPath, snapshotExtension) => { - const snapshotPath = testPath - .replace(/\.[tj]s$/, `.js${snapshotExtension}`) - .replace("/src/", "/snapshots/") - .replace("\\src\\", "\\snapshots\\") - // These suites assert the packed asar file tree across every package manager. The tree - // content (files + sizes) is identical on all hosts, but two header fields are inherently - // host-specific: the data-section packing `offset` (write order differs by OS) and the - // Unix `executable` bit (NTFS does not carry it). Keep a dedicated Windows baseline so the - // POSIX snapshots retain full fidelity and neither platform has to discard real data. - if (process.platform === "win32" && /(?:packageManagerTest|HoistedNodeModuleTest)\.js\.snap$/.test(snapshotPath)) { - return snapshotPath.replace(/\.snap$/, ".win.snap") - } - return snapshotPath + return startVitest( + "test", + selectedFiles, + { + allowOnly: !isCI, // Prevent accidental commit of `test.only` in CI + update: process.env.UPDATE_SNAPSHOT === "true", + + // we manually set `globalThis.test` and `globalThis.describe` in vitest-setup.ts to make sure everything works correctly + globals: false, + + // Allow test metadata + includeTaskLocation: true, + setupFiles: [__dirname + "/vitest-setup.ts", __dirname + "/vitest-heavy-mutex.ts"], + include: [`test/src/**/${includeGlob}.ts`], + + printConsoleTrace: true, + runner: __dirname + "/vitest-network-retry-runner.ts", + reporters: ["default", __dirname + "/vitest-smart-reporter.ts"], + + // 2 on Windows (heavy MSI/Squirrel builds saturate the vitest main-thread RPC at 3); 3 elsewhere + maxWorkers: process.platform === "win32" ? 2 : 3, + + fileParallelism: false, + sequence: { + sequencer: SmartSequencer, + concurrent: process.env.TEST_SEQUENTIAL === "false", + }, + + slowTestThreshold: 2 * 60 * 1000, + testTimeout: 10 * 60 * 1000, // disk operations can be slow. We're generous with the timeout here to account for less-performant hardware + + snapshotFormat: { + printBasicPrototype: false, + }, + resolveSnapshotPath: (testPath, snapshotExtension) => { + const snapshotPath = testPath + .replace(/\.[tj]s$/, `.js${snapshotExtension}`) + .replace("/src/", "/snapshots/") + .replace("\\src\\", "\\snapshots\\") + // These suites assert the packed asar file tree across every package manager. The tree + // content (files + sizes) is identical on all hosts, but two header fields are inherently + // host-specific: the data-section packing `offset` (write order differs by OS) and the + // Unix `executable` bit (NTFS does not carry it). Keep a dedicated Windows baseline so the + // POSIX snapshots retain full fidelity and neither platform has to discard real data. + if (process.platform === "win32" && /(?:packageManagerTest|HoistedNodeModuleTest)\.js\.snap$/.test(snapshotPath)) { + return snapshotPath.replace(/\.snap$/, ".win.snap") + } + return snapshotPath + }, }, - }) + { + resolve: { + alias: workspaceSourceAliases, + }, + } + ) .then(() => { console.log("Vitest run completed") }) diff --git a/test/vitest-scripts/shard-builder.ts b/test/vitest-scripts/shard-builder.ts index 97a005812a8..64e3777f411 100644 --- a/test/vitest-scripts/shard-builder.ts +++ b/test/vitest-scripts/shard-builder.ts @@ -1,6 +1,6 @@ import * as path from "path" -import { loadCache } from "./cache" -import { DEFAULT_FILE_MS, SAFEGUARD_MAX_SHARDS, SupportedPlatforms, TARGET_MS, TargetPlatform } from "./smart-config" +import { loadCache } from "./cache.js" +import { DEFAULT_FILE_MS, SAFEGUARD_MAX_SHARDS, SupportedPlatforms, TARGET_MS, TargetPlatform } from "./smart-config.js" export interface WeightedFile { filename: string diff --git a/test/vitest-scripts/smart-shard-count.ts b/test/vitest-scripts/smart-shard-count.ts index fd5164ae97c..6faea65e582 100644 --- a/test/vitest-scripts/smart-shard-count.ts +++ b/test/vitest-scripts/smart-shard-count.ts @@ -1,4 +1,4 @@ -#!/usr/bin/env ts-node +#!/usr/bin/env tsx import { getAllTestFiles } from "./file-discovery" import { buildWeightedFiles, computeShardCount } from "./shard-builder" diff --git a/test/vitest-scripts/vitest-setup.ts b/test/vitest-scripts/vitest-setup.ts index 129f801b332..513948934a6 100644 --- a/test/vitest-scripts/vitest-setup.ts +++ b/test/vitest-scripts/vitest-setup.ts @@ -1,5 +1,5 @@ import { test as baseTest, describe as baseDescribe, expect } from "vitest" -import { ConditionalSuiteAPI, ConditionalTestAPI } from "../typings/vitest" +import { ConditionalSuiteAPI, ConditionalTestAPI } from "../typings/vitest.js" const isWindows = process.platform === "win32" const isMac = process.platform === "darwin" diff --git a/test/vitest-scripts/vitest-smart-reporter.ts b/test/vitest-scripts/vitest-smart-reporter.ts index a9a471bfc2e..3a52c78ca2e 100644 --- a/test/vitest-scripts/vitest-smart-reporter.ts +++ b/test/vitest-scripts/vitest-smart-reporter.ts @@ -1,7 +1,7 @@ import * as path from "path" import type { Reporter, TestCase, TestModule } from "vitest/node" -import { FileStats, loadCache, saveCache, TestStats } from "./cache" -import { UNSTABLE_FAIL_RATIO, SupportedPlatforms } from "./smart-config" +import { FileStats, loadCache, saveCache, TestStats } from "./cache.js" +import { UNSTABLE_FAIL_RATIO, SupportedPlatforms } from "./smart-config.js" const defaultStat: TestStats = { platformRuns: { diff --git a/tsconfig-base.json b/tsconfig-base.json index f05e98abd57..a25267f8bed 100644 --- a/tsconfig-base.json +++ b/tsconfig-base.json @@ -1,25 +1,25 @@ { + "extends": "@tsconfig/node22/tsconfig.json", "compilerOptions": { - "target": "es2019", - "module": "CommonJS", - "esModuleInterop": false, + "module": "ESNext", + "moduleResolution": "bundler", + "forceConsistentCasingInFileNames": true, - "moduleResolution": "node", - "skipLibCheck": true, - "strict": true, + "noUnusedLocals": true, "noFallthroughCasesInSwitch": true, "noImplicitReturns": true, + "allowJs": true, "inlineSources": true, "sourceMap": true, - "allowSyntheticDefaultImports": true, + "useDefineForClassFields": false, "experimentalDecorators": true, "newLine": "lf", "noEmitOnError": true } -} \ No newline at end of file +} diff --git a/tsconfig.json b/tsconfig.json index 3a444e40ee6..deccc2d0102 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -2,25 +2,31 @@ "files": [], "references": [ { - "path": "./packages/electron-builder" + "path": "./packages/builder-util-runtime" }, { - "path": "./packages/electron-publish" + "path": "./packages/builder-util" }, { - "path": "./packages/electron-updater" + "path": "./packages/app-builder-lib" }, { - "path": "./packages/electron-builder-squirrel-windows" + "path": "./packages/dmg-builder" + }, + { + "path": "./packages/electron-builder" + }, + { + "path": "./packages/electron-publish" }, { - "path": "./test" + "path": "./packages/electron-updater" }, { - "path": "./website" + "path": "./packages/electron-builder-squirrel-windows" }, { "path": "./scripts" } ] -} \ No newline at end of file +} diff --git a/website/docs/cli.md b/website/docs/cli.md index 39094836079..184d7564c14 100644 --- a/website/docs/cli.md +++ b/website/docs/cli.md @@ -4,62 +4,21 @@ title: CLI ``` -electron-builder - -Build - -Commands: - electron-builder build Build [default] - electron-builder install-app-deps Install app deps - electron-builder node-gyp-rebuild Rebuild own native code - electron-builder publish Publish a list of artifacts - electron-builder create-self-signed-cert Create self-signed code signing cert for - Windows apps - electron-builder start Run application in a development mode using - electron-webpack - electron-builder clear-cache Clear the electron-builder default cache - directory - -Building: - -m, -o, --mac, --macos Build for macOS, accepts target list (see - https://www.electron.build/mac). [array] - -l, --linux Build for Linux, accepts target list (see - https://www.electron.build/linux) [array] - -w, --win, --windows Build for Windows, accepts target list (see - https://www.electron.build/win) [array] - --x64 Build for x64 [boolean] - --ia32 Build for ia32 [boolean] - --armv7l Build for armv7l [boolean] - --arm64 Build for arm64 [boolean] - --universal Build for universal [boolean] - --dir Build unpacked dir. Useful to test. [boolean] - --prepackaged, --pd The path to prepackaged app (to pack in a - distributable format) - --projectDir, --project The path to project directory. Defaults to - current working directory. - -c, --config The path to an electron-builder config. Defaults - to `electron-builder.yml` (or `json`, or `json5`, - or `js`, or `ts`), see - https://www.electron.build/configuration - -Publishing: - -p, --publish Publish artifacts, see https://www.electron.build/publish - [choices: "onTag", "onTagOrDraft", "always", "never", undefined] - -Other: - --help Show help [boolean] - --version Show version number [boolean] - -Examples: - electron-builder -mwl build for macOS, Windows and Linux - electron-builder --linux deb tar.xz build deb and tar.xz for Linux - electron-builder --win --ia32 build for Windows ia32 - electron-builder set package.json property `foo` to - -c.extraMetadata.foo=bar `bar` - electron-builder configure unicode options for NSIS - --config.nsis.unicode=false - -See https://electron.build for more documentation. + • please use as subcommand: electron-builder publish +Options: + --help Show help [boolean] + -f, --files The file(s) to upload to your publisher + [array] [required] + -v, --version The app/build version used when + searching for an upload release (used + by some Publishers) [string] + -c, --config, --configurationFilePath The path to an electron-builder config. + Defaults to `electron-builder.yml` (or + `json`, or `json5`, or `js`, or `ts`), + see https://goo.gl/YFRJOM [string] + -p, --policy Publish trigger policy, see + https://www.electron.build/publish + [string] [choices: "onTag", "onTagOrDraft", "always", "never", undefined] ``` diff --git a/website/scripts/docusaurus-plugin-prebuild.ts b/website/scripts/docusaurus-plugin-prebuild.ts index b3ffb9c4303..73cbefb5532 100644 --- a/website/scripts/docusaurus-plugin-prebuild.ts +++ b/website/scripts/docusaurus-plugin-prebuild.ts @@ -5,7 +5,7 @@ import type { LoadContext, Plugin } from "@docusaurus/types" function generateCliDocs(siteDir: string): void { const root = join(siteDir, "..") - const help = execSync("node packages/electron-builder/out/cli/cli.js --help", { + const help = execSync("node packages/electron-builder/dist/cli/cli.js --help", { encoding: "utf-8", cwd: root, })