diff --git a/package.json b/package.json index cedc1805b..ab604d64b 100644 --- a/package.json +++ b/package.json @@ -125,6 +125,7 @@ "@astrojs/mdx": "4.3.13", "@astrojs/sitemap": "3.7.0", "@astrojs/tailwind": "6.0.2", + "@electron/asar": "3.4.1", "@eslint/eslintrc": "3.3.1", "@eslint/js": "^9.38.0", "@faker-js/faker": "10.3.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 1783ebcc6..f80140247 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -209,6 +209,9 @@ importers: '@astrojs/tailwind': specifier: 6.0.2 version: 6.0.2(astro@5.18.1(@types/node@20.19.9)(jiti@1.21.7)(less@4.5.1)(rollup@4.59.0)(sass-embedded@1.97.1)(sass@1.97.1)(terser@5.44.1)(tsx@4.21.0)(typescript@5.9.3)(yaml@2.8.2))(tailwindcss@3.4.19(tsx@4.21.0)(yaml@2.8.2))(ts-node@10.9.2(@swc/core@1.15.8(@swc/helpers@0.5.18))(@types/node@20.19.9)(typescript@5.9.3)) + '@electron/asar': + specifier: 3.4.1 + version: 3.4.1 '@eslint/eslintrc': specifier: 3.3.1 version: 3.3.1 @@ -8795,10 +8798,6 @@ packages: resolution: {integrity: sha512-enIvLvRAFZYXJzkCYG5RKmPfrFArdLv+R+lbQ53BmIMLIry74bjKzX6iHAm8WYamJkhSSEabrWN5D97XnKObjQ==} engines: {node: 20 || >=22} - minimatch@10.2.2: - resolution: {integrity: sha512-+G4CpNBxa5MprY+04MbgOw1v7So6n5JY166pFi9KfYwT78fxScCeSNQSNzp6dpPSW2rONOps6Ocam1wFhCgoVw==} - engines: {node: 18 || 20 || >=22} - minimatch@10.2.4: resolution: {integrity: sha512-oRjTw/97aTBN0RHbYCdtF1MQfvusSIBQM0IZEgzl6426+8jSC0nF1a/GmnVLpfB9yyr6g6FTqWqiZVbxrtaCIg==} engines: {node: 18 || 20 || >=22} @@ -13794,7 +13793,7 @@ snapshots: '@electron/universal@2.0.1': dependencies: - '@electron/asar': 3.2.18 + '@electron/asar': 3.4.1 '@malept/cross-spawn-promise': 2.0.0 debug: 4.4.3 dir-compare: 4.2.0 @@ -16744,7 +16743,7 @@ snapshots: '@tufjs/models@4.1.0': dependencies: '@tufjs/canonical-json': 2.0.0 - minimatch: 10.2.2 + minimatch: 10.2.4 '@tybys/wasm-util@0.10.1': dependencies: @@ -20184,7 +20183,7 @@ snapshots: glob@13.0.6: dependencies: - minimatch: 10.2.2 + minimatch: 10.2.4 minipass: 7.1.3 path-scurry: 2.0.2 @@ -20685,7 +20684,7 @@ snapshots: ignore-walk@8.0.0: dependencies: - minimatch: 10.2.2 + minimatch: 10.2.4 ignore@5.3.2: {} @@ -22338,10 +22337,6 @@ snapshots: dependencies: '@isaacs/brace-expansion': 5.0.0 - minimatch@10.2.2: - dependencies: - brace-expansion: 5.0.2 - minimatch@10.2.4: dependencies: brace-expansion: 5.0.2 diff --git a/tools/packaging/electron-package-identity.test.mjs b/tools/packaging/electron-package-identity.test.mjs index 411271368..e68d54c1d 100644 --- a/tools/packaging/electron-package-identity.test.mjs +++ b/tools/packaging/electron-package-identity.test.mjs @@ -40,6 +40,10 @@ const makerOptions = JSON.parse( ); const generatedMetadataConfigPath = 'apps/electron-backend/src/app/options/electron-builder.metadata.generated.json'; +const packageLayoutVerifier = fs.readFileSync( + join(currentDir, 'verify-electron-package-layout.mjs'), + 'utf8' +); test('Linux package identity does not expose the internal Electron backend project name', () => { assert.equal(electronBuilderConfig.productName, 'IPTVnator'); @@ -125,6 +129,24 @@ test('nx-electron packaging prepares metadata before make/package', () => { ); }); +test('package layout verifier uses canonical helpers and direct dependencies', () => { + assert.ok(packageMetadata.devDependencies?.['@electron/asar']); + assert.match(packageLayoutVerifier, /require\(['"]@electron\/asar['"]\)/); + assert.doesNotMatch(packageLayoutVerifier, /electronBuilderRequire/); + assert.match( + packageLayoutVerifier, + /buildElectronBuilderMetadata\(\s*packageMetadata,\s*electronBuilderConfig\s*\)\.extraMetadata/s + ); + assert.doesNotMatch( + packageLayoutVerifier, + /const packagedPackageMetadata = \{\s*name:/s + ); + assert.doesNotMatch( + packageLayoutVerifier, + /builderEffectiveConfigPath && fileExists\(builderEffectiveConfigPath\)/ + ); +}); + test('nx-electron packaging does not copy duplicate root package metadata', () => { const nxElectronExecutorPath = require.resolve( 'nx-electron/src/executors/package/executor.js' diff --git a/tools/packaging/verify-electron-package-layout.mjs b/tools/packaging/verify-electron-package-layout.mjs index f3652a474..070b4d16a 100644 --- a/tools/packaging/verify-electron-package-layout.mjs +++ b/tools/packaging/verify-electron-package-layout.mjs @@ -2,9 +2,10 @@ import fs from 'fs'; import { createRequire } from 'module'; import path from 'path'; +import { buildElectronBuilderMetadata } from './generate-electron-builder-metadata.mjs'; + const require = createRequire(import.meta.url); -const electronBuilderRequire = createRequire(require.resolve('electron-builder')); -const { extractFile } = electronBuilderRequire('@electron/asar'); +const { extractFile } = require('@electron/asar'); const { validatePackagedEmbeddedMpv } = require('./embedded-mpv-macos.cjs'); const args = process.argv.slice(2); const normalizedArgs = args[0] === '--' ? args.slice(1) : args; @@ -51,20 +52,10 @@ const workerRelativeDir = path.join( 'workers' ); const workerFiles = ['epg-parser.worker.js', 'database.worker.js']; -const packagedPackageMetadata = { - name: packageMetadata.name, - productName: - electronBuilderConfig.productName ?? - electronBuilderConfig.extraMetadata?.productName, - version: packageMetadata.version, - description: packageMetadata.description, - author: packageMetadata.author, - homepage: packageMetadata.homepage, - license: packageMetadata.license, - main: - electronBuilderConfig.extraMetadata?.main ?? - 'electron-backend/main.js', -}; +const packagedPackageMetadata = buildElectronBuilderMetadata( + packageMetadata, + electronBuilderConfig +).extraMetadata; const nativeModuleRelativeDirs = [ path.join('app.asar.unpacked', 'node_modules'), path.join('app.asar.unpacked', 'electron-backend', 'node_modules'), @@ -373,7 +364,7 @@ function parseEffectiveSnapConfig(yamlContent) { function loadSnapConfigInspection() { const builderEffectiveConfigPath = builderEffectiveConfigPaths.find(fileExists); - if (builderEffectiveConfigPath && fileExists(builderEffectiveConfigPath)) { + if (builderEffectiveConfigPath) { const effectiveConfigContent = fs.readFileSync( builderEffectiveConfigPath, 'utf8'