app-builder-lib 26.12.1 → 26.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/out/asar/asarFileChecker.d.ts +2 -2
- package/out/asar/asarFileChecker.js +3 -2
- package/out/asar/asarFileChecker.js.map +1 -1
- package/out/asar/asarUtil.js +3 -2
- package/out/asar/asarUtil.js.map +1 -1
- package/out/binDownload.js +4 -4
- package/out/binDownload.js.map +1 -1
- package/out/codeSign/certInfo.d.ts +54 -0
- package/out/codeSign/certInfo.js +466 -0
- package/out/codeSign/certInfo.js.map +1 -0
- package/out/codeSign/macCodeSign.d.ts +1 -1
- package/out/codeSign/macCodeSign.js +8 -7
- package/out/codeSign/macCodeSign.js.map +1 -1
- package/out/codeSign/windowsSignToolManager.d.ts +2 -0
- package/out/codeSign/windowsSignToolManager.js +10 -9
- package/out/codeSign/windowsSignToolManager.js.map +1 -1
- package/out/configuration.d.ts +5 -0
- package/out/configuration.js.map +1 -1
- package/out/index.d.ts +2 -1
- package/out/index.js +3 -1
- package/out/index.js.map +1 -1
- package/out/mac/MacTargetHelper.d.ts +3 -3
- package/out/mac/MacTargetHelper.js +7 -5
- package/out/mac/MacTargetHelper.js.map +1 -1
- package/out/macPackager.js +3 -2
- package/out/macPackager.js.map +1 -1
- package/out/node-module-collector/moduleManager.d.ts +15 -3
- package/out/node-module-collector/moduleManager.js +24 -0
- package/out/node-module-collector/moduleManager.js.map +1 -1
- package/out/node-module-collector/nodeModulesCollector.d.ts +6 -0
- package/out/node-module-collector/nodeModulesCollector.js +40 -21
- package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
- package/out/options/linuxOptions.d.ts +4 -3
- package/out/options/linuxOptions.js.map +1 -1
- package/out/options/macOptions.d.ts +6 -0
- package/out/options/macOptions.js.map +1 -1
- package/out/options/metadata.d.ts +2 -0
- package/out/options/metadata.js.map +1 -1
- package/out/platformPackager.d.ts +1 -1
- package/out/platformPackager.js +19 -17
- package/out/platformPackager.js.map +1 -1
- package/out/targets/LinuxTargetHelper.js +12 -5
- package/out/targets/LinuxTargetHelper.js.map +1 -1
- package/out/targets/appimage/AppImageTarget.d.ts +0 -2
- package/out/targets/appimage/AppImageTarget.js +25 -41
- package/out/targets/appimage/AppImageTarget.js.map +1 -1
- package/out/targets/appimage/appImageUtil.d.ts +3 -1
- package/out/targets/appimage/appImageUtil.js +33 -0
- package/out/targets/appimage/appImageUtil.js.map +1 -1
- package/out/targets/nsis/NsisTarget.js +29 -9
- package/out/targets/nsis/NsisTarget.js.map +1 -1
- package/out/targets/nsis/WebInstallerTarget.js +2 -2
- package/out/targets/nsis/WebInstallerTarget.js.map +1 -1
- package/out/targets/nsis/nsisValidation.d.ts +18 -0
- package/out/targets/nsis/nsisValidation.js +52 -0
- package/out/targets/nsis/nsisValidation.js.map +1 -0
- package/out/toolsets/linux.d.ts +3 -1
- package/out/toolsets/linux.js +49 -21
- package/out/toolsets/linux.js.map +1 -1
- package/out/util/config/config.js +6 -7
- package/out/util/config/config.js.map +1 -1
- package/out/util/config/schemaValidator.d.ts +7 -0
- package/out/util/config/schemaValidator.js +154 -0
- package/out/util/config/schemaValidator.js.map +1 -0
- package/out/util/dynamicImport.d.ts +1 -0
- package/out/util/dynamicImport.js +14 -0
- package/out/util/dynamicImport.js.map +1 -0
- package/out/util/electronGet.js +31 -1
- package/out/util/electronGet.js.map +1 -1
- package/out/util/rebuild.d.ts +1 -1
- package/out/util/rebuild.js.map +1 -1
- package/out/util/resEdit.js +16 -15
- package/out/util/resEdit.js.map +1 -1
- package/out/util/yarn.js.map +1 -1
- package/out/version.d.ts +1 -1
- package/out/version.js +1 -1
- package/out/version.js.map +1 -1
- package/out/winPackager.d.ts +1 -0
- package/out/winPackager.js +12 -9
- package/out/winPackager.js.map +1 -1
- package/package.json +12 -9
- package/scheme.json +22 -1
- package/templates/linux/after-remove.tpl +14 -2
- package/templates/nsis/include/allowOnlyOneInstallerInstance.nsh +5 -5
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AppImageTarget.js","sourceRoot":"","sources":["../../../src/targets/appimage/AppImageTarget.ts"],"names":[],"mappings":";;;AACA,+CAAyD;AACzD,uCAAqC;AACrC,uCAA+B;AAC/B,6BAA4B;AAC5B,qCAAmC;AAGnC,iEAA+E;AAC/E,sDAA6E;AAC7E,gDAA+D;AAE/D,8CAAwD;AACxD,iDAA2D;AAC3D,+DAAqE;AAErE,+FAA+F;AAElF,QAAA,kBAAkB,GAAG,QAAQ,CAAA;AAE1C,MAAqB,cAAe,SAAQ,aAAM;IAKhD,YACE,QAAgB,EACC,QAAuB,EACvB,MAAyB,EACjC,MAAc;QAEvB,KAAK,CAAC,UAAU,CAAC,CAAA;QAJA,aAAQ,GAAR,QAAQ,CAAe;QACvB,WAAM,GAAN,MAAM,CAAmB;QACjC,WAAM,GAAN,MAAM,CAAQ;QARhB,YAAO,GAAoB,IAAA,iCAAU,EAAC,EAAE,EAAE,IAAI,CAAC,QAAQ,CAAC,4BAA4B,EAAG,IAAI,CAAC,QAAQ,CAAC,MAAc,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAA;QAYtI,IAAI,CAAC,YAAY,GAAG,IAAI,eAAI,CAAS,GAAG,EAAE;;YACxC,MAAM,YAAY,GAAG,MAAA,QAAQ,CAAC,MAAM,CAAC,QAAQ,0CAAE,QAAQ,CAAA;YACvD,MAAM,WAAW,GAAG,YAAY,IAAI,IAAI,IAAI,YAAY,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EAAE,CAAA;YAC5F,MAAM,IAAI,GAAG,MAAA,IAAI,CAAC,OAAO,CAAC,cAAc,mCAAI,WAAW,CAAA;YACvD,MAAM,IAAI,GAAG,CAAC,0BAAkB,EAAE,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAA;YAC1D,OAAO,MAAM,CAAC,mBAAmB,CAAC,IAAI,CAAC,OAAO,EAAE,IAAI,EAAE;gBACpD,oBAAoB,EAAE,GAAG,QAAQ,CAAC,OAAO,CAAC,YAAY,EAAE;aACzD,CAAC,CAAA;QACJ,CAAC,CAAC,CAAA;IACJ,CAAC;IAED,KAAK,CAAC,KAAK,CAAC,SAAiB,EAAE,IAAU;;QACvC,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAA;QAE9B,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAA;QAC5B,mEAAmE;QACnE,oEAAoE;QACpE,MAAM,YAAY,GAAG,QAAQ,CAAC,yBAAyB,CAAC,OAAO,EAAE,UAAU,EAAE,IAAI,CAAC,CAAA;QAClF,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,YAAY,CAAC,CAAA;QAEzD,MAAM,QAAQ,CAAC,IAAI,CAAC,wBAAwB,CAAC;YAC3C,qBAAqB,EAAE,UAAU;YACjC,IAAI,EAAE,YAAY;YAClB,IAAI;SACL,CAAC,CAAA;QAEF,2CAA2C;QAC3C,MAAM,CAAC,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;YAChF,IAAA,iDAAgC,EAAC,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC;YAChE,IAAA,2BAAc,EAAC,IAAI,EAAE,QAAQ,EAAE,IAAI,CAAC;YACpC,IAAI,CAAC,YAAY,CAAC,KAAK;YACvB,IAAI,CAAC,MAAM,CAAC,KAAK;YACjB,IAAA,oCAA0B,EAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC;SAC5E,CAAC,CAAA;QAEF,IAAI,aAAa,IAAI,IAAI,EAAE,CAAC;YAC1B,MAAM,IAAA,qBAAU,EAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,SAAS,CAAC,EAAE,gBAAgB,CAAC,EAAE,IAAA,8BAAe,EAAC,aAAa,CAAC,CAAC,CAAA;QACpH,CAAC;QAED,IAAI,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,uBAAuB,IAAI,IAAI,IAAI,CAAC,MAAM,IAAI,CAAC,QAAQ,CAAC,eAAe,CAAC,uBAAuB,CAAC,EAAE,OAAO,EAAE,YAAY,EAAE,CAAC,CAAC,EAAE,CAAC;YAC9J,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAA;YACxB,OAAM;QACR,CAAC;QAED,IAAI,UAA8B,CAAA;QAClC,IAAI,CAAC;YACH,MAAM,YAAY,GAAG,MAAA,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,0CAAE,QAAQ,CAAA;YAC5D,IAAI,YAAY,IAAI,IAAI,IAAI,YAAY,KAAK,OAAO,EAAE,CAAC;gBACrD,UAAU,GAAG,MAAM,IAAI,CAAC,kBAAkB,CAAC,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC,CAAA;YAC1I,CAAC;iBAAM,CAAC;gBACN,UAAU,GAAG,MAAM,IAAA,yCAA0B,EAAC,YAAY,EAAE;oBAC1D,MAAM,EAAE,SAAS;oBACjB,QAAQ,EAAE,QAAQ,CAAC,GAAG;oBACtB,IAAI;oBACJ,MAAM,EAAE,YAAY;oBACpB,OAAO,EAAE;wBACP,WAAW,EAAE,QAAQ,CAAC,OAAO,CAAC,WAAW;wBACzC,eAAe,EAAE,QAAQ,CAAC,OAAO,CAAC,eAAe;wBACjD,cAAc,EAAE,QAAQ,CAAC,cAAc;wBACvC,OAAO;wBACP,YAAY;wBACZ,KAAK;wBACL,gBAAgB,EAAE,QAAQ,CAAC,gBAAgB;wBAC3C,WAAW,EAAE,CAAC,GAAG,EAAE;4BACjB,MAAM,CAAC,GAAG,OAAO,CAAC,WAAW,CAAA;4BAC7B,IAAI,CAAC,KAAK,MAAM,IAAI,CAAC,KAAK,MAAM,EAAE,CAAC;gCACjC,OAAO,CAAC,CAAA;4BACV,CAAC;4BACD,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;gCACf,OAAO,MAAM,CAAA,CAAC,yDAAyD;4BACzE,CAAC;4BACD,IAAI,QAAQ,CAAC,WAAW,KAAK,OAAO,EAAE,CAAC;gCACrC,OAAO,MAAM,CAAA;4BACf,CAAC;4BACD,OAAO,MAAM,CAAA,CAAC,iDAAiD;wBACjE,CAAC,CAAC,EAAE;qBACL;iBACF,CAAC,CAAA;YACJ,CAAC;QACH,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,kBAAG,CAAC,KAAK,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,EAAE,0BAA0B,CAAC,CAAA;YAC/D,MAAM,KAAK,CAAA;QACb,CAAC;gBAAS,CAAC;YACT,MAAM,QAAQ,CAAC,OAAO,EAAE,CAAC,KAAK,CAAC,GAAG,EAAE,GAAE,CAAC,CAAC,CAAA;QAC1C,CAAC;QAED,MAAM,QAAQ,CAAC,IAAI,CAAC,0BAA0B,CAAC;YAC7C,IAAI,EAAE,YAAY;YAClB,gBAAgB,EAAE,QAAQ,CAAC,uBAAuB,CAAC,YAAY,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,CAAC;YACzF,MAAM,EAAE,IAAI;YACZ,IAAI;YACJ,QAAQ;YACR,iBAAiB,EAAE,IAAI;YACvB,UAAU;SACX,CAAC,CAAA;IACJ,CAAC;IAED,iHAAiH;IACzG,KAAK,CAAC,kBAAkB,CAAC,KAUhC;QACC,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,EAAE,SAAS,EAAE,OAAO,EAAE,YAAY,EAAE,KAAK,EAAE,OAAO,EAAE,GAAG,KAAK,CAAA;QAEhG,MAAM,IAAI,GAAG;YACX,UAAU;YACV,SAAS;YACT,QAAQ,CAAC,GAAG;YACZ,QAAQ;YACR,mBAAI,CAAC,IAAI,CAAC;YACV,UAAU;YACV,YAAY;YACZ,OAAO;YACP,SAAS;YACT,iBAAiB;YACjB,IAAI,CAAC,SAAS,CAAC;gBACb,WAAW,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,WAAW;gBAC9C,eAAe,EAAE,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,eAAe;gBACtD,YAAY;gBACZ,cAAc,EAAE,IAAI,CAAC,QAAQ,CAAC,cAAc;gBAC5C,KAAK;gBACL,gBAAgB,EAAE,IAAI,CAAC,QAAQ,CAAC,gBAAgB;gBAChD,GAAG,OAAO;aACX,CAAC;SACH,CAAA;QACD,IAAA,yBAAY,EAAC,IAAI,EAAE;YACjB,OAAO;SACR,CAAC,CAAA;QACF,0HAA0H;QAC1H,MAAM,WAAW,GAAG,CAAC,IAAI,CAAU,CAAA;QACnC,MAAM,YAAY,GAAG,OAAO,CAAC,WAAW,CAAA;QACxC,IAAI,YAAY,IAAI,IAAI,IAAK,WAAiC,CAAC,QAAQ,CAAC,YAAY,CAAC,EAAE,CAAC;YACtF,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,YAAY,CAAC,CAAA;QAC1C,CAAC;aAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,WAAW,KAAK,SAAS,EAAE,CAAC;YACnD,IAAI,CAAC,IAAI,CAAC,eAAe,EAAE,IAAI,CAAC,CAAA;QAClC,CAAC;QAED,MAAM,UAAU,GAAG,MAAM,IAAA,oCAAuB,EAAqB,IAAI,CAAC,CAAA;QAC1E,OAAO,UAAU,CAAA;IACnB,CAAC;CACF;AAhKD,iCAgKC","sourcesContent":["import { IconInfo } from \"../../platformPackager\"\nimport { Arch, log, serializeToYaml } from \"builder-util\"\nimport { outputFile } from \"fs-extra\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { Target } from \"../../core\"\nimport { LinuxPackager } from \"../../linuxPackager\"\nimport { AppImageOptions } from \"../../options/linuxOptions\"\nimport { getAppUpdatePublishConfiguration } from \"../../publish/PublishManager\"\nimport { executeAppBuilderAsJson, objectToArgs } from \"../../util/appBuilder\"\nimport { getNotLocalizedLicenseFile } from \"../../util/license\"\nimport { LinuxTargetHelper } from \"../LinuxTargetHelper\"\nimport { createStageDir, StageDir } from \"../targetUtil\"\nimport { buildStaticRuntimeAppImage } from \"./appImageUtil\"\nimport { BlockMapDataHolder, deepAssign } from \"builder-util-runtime\"\n\n// https://unix.stackexchange.com/questions/375191/append-to-sub-directory-inside-squashfs-file\n\nexport const APP_RUN_ENTRYPOINT = \"AppRun\"\n\nexport default class AppImageTarget extends Target {\n readonly options: AppImageOptions = deepAssign({}, this.packager.platformSpecificBuildOptions, (this.packager.config as any)[this.name])\n\n private readonly desktopEntry: Lazy<string>\n\n constructor(\n _ignored: string,\n private readonly packager: LinuxPackager,\n private readonly helper: LinuxTargetHelper,\n readonly outDir: string\n ) {\n super(\"appImage\")\n\n this.desktopEntry = new Lazy<string>(() => {\n const appimageTool = packager.config.toolsets?.appimage\n const defaultArgs = appimageTool == null || appimageTool === \"0.0.0\" ? [\"--no-sandbox\"] : []\n const args = this.options.executableArgs ?? defaultArgs\n const exec = [APP_RUN_ENTRYPOINT, ...args, \"%U\"].join(\" \")\n return helper.computeDesktopEntry(this.options, exec, {\n \"X-AppImage-Version\": `${packager.appInfo.buildVersion}`,\n })\n })\n }\n\n async build(appOutDir: string, arch: Arch): Promise<any> {\n const packager = this.packager\n\n const options = this.options\n // https://github.com/electron-userland/electron-builder/issues/775\n // https://github.com/electron-userland/electron-builder/issues/1726\n const artifactName = packager.expandArtifactNamePattern(options, \"AppImage\", arch)\n const artifactPath = path.join(this.outDir, artifactName)\n\n await packager.info.emitArtifactBuildStarted({\n targetPresentableName: \"AppImage\",\n file: artifactPath,\n arch,\n })\n\n // Parallelize independent async operations\n const [publishConfig, stageDir, desktopEntry, icons, license] = await Promise.all([\n getAppUpdatePublishConfiguration(packager, options, arch, false),\n createStageDir(this, packager, arch),\n this.desktopEntry.value,\n this.helper.icons,\n getNotLocalizedLicenseFile(options.license, this.packager, [\"txt\", \"html\"]),\n ])\n\n if (publishConfig != null) {\n await outputFile(path.join(packager.getResourcesDir(appOutDir), \"app-update.yml\"), serializeToYaml(publishConfig))\n }\n\n if (this.packager.packagerOptions.effectiveOptionComputed != null && (await this.packager.packagerOptions.effectiveOptionComputed({ desktop: desktopEntry }))) {\n await stageDir.cleanup()\n return\n }\n\n let updateInfo: BlockMapDataHolder\n try {\n const appimageTool = this.packager.config.toolsets?.appimage\n if (appimageTool == null || appimageTool === \"0.0.0\") {\n updateInfo = await this.buildFuse2AppImage({ stageDir, arch, artifactPath, appOutDir, options, packager, desktopEntry, icons, license })\n } else {\n updateInfo = await buildStaticRuntimeAppImage(appimageTool, {\n appDir: appOutDir,\n stageDir: stageDir.dir,\n arch,\n output: artifactPath,\n options: {\n productName: packager.appInfo.productName,\n productFilename: packager.appInfo.productFilename,\n executableName: packager.executableName,\n license,\n desktopEntry,\n icons,\n fileAssociations: packager.fileAssociations,\n compression: (() => {\n const c = options.compression\n if (c === \"gzip\" || c === \"zstd\") {\n return c\n }\n if (c === \"xz\") {\n return \"zstd\" // nearest equivalent; static runtime does not support xz\n }\n if (packager.compression === \"store\") {\n return \"gzip\"\n }\n return \"zstd\" // maximum/normal/unset → zstd for static runtime\n })(),\n },\n })\n }\n } catch (error: any) {\n log.error({ error: error.message }, \"failed to build AppImage\")\n throw error\n } finally {\n await stageDir.cleanup().catch(() => {})\n }\n\n await packager.info.emitArtifactBuildCompleted({\n file: artifactPath,\n safeArtifactName: packager.computeSafeArtifactName(artifactName, \"AppImage\", arch, false),\n target: this,\n arch,\n packager,\n isWriteUpdateInfo: true,\n updateInfo,\n })\n }\n\n /** Builds via the legacy FUSE2 toolset (mksquashfs); used when no static-runtime appimage tool is configured. */\n private async buildFuse2AppImage(props: {\n stageDir: StageDir\n arch: Arch\n artifactPath: string\n appOutDir: string\n options: AppImageOptions\n packager: LinuxPackager\n desktopEntry: string\n icons: IconInfo[]\n license: string | null\n }): Promise<BlockMapDataHolder> {\n const { stageDir, arch, artifactPath, appOutDir, options, desktopEntry, icons, license } = props\n\n const args = [\n \"appimage\",\n \"--stage\",\n stageDir.dir,\n \"--arch\",\n Arch[arch],\n \"--output\",\n artifactPath,\n \"--app\",\n appOutDir,\n \"--configuration\",\n JSON.stringify({\n productName: this.packager.appInfo.productName,\n productFilename: this.packager.appInfo.productFilename,\n desktopEntry,\n executableName: this.packager.executableName,\n icons,\n fileAssociations: this.packager.fileAssociations,\n ...options,\n }),\n ]\n objectToArgs(args, {\n license,\n })\n // app-builder --compression enum for FUSE2 is xz/lzo/zstd; gzip is mksquashfs's default and must not be passed explicitly\n const FUSE2_VALID = [\"xz\"] as const\n const explicitComp = options.compression\n if (explicitComp != null && (FUSE2_VALID as readonly string[]).includes(explicitComp)) {\n args.push(\"--compression\", explicitComp)\n } else if (this.packager.compression === \"maximum\") {\n args.push(\"--compression\", \"xz\")\n }\n\n const updateInfo = await executeAppBuilderAsJson<BlockMapDataHolder>(args)\n return updateInfo\n }\n}\n"]}
|
|
1
|
+
{"version":3,"file":"AppImageTarget.js","sourceRoot":"","sources":["../../../src/targets/appimage/AppImageTarget.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, log, serializeToYaml } from \"builder-util\"\nimport { outputFile } from \"fs-extra\"\nimport { Lazy } from \"lazy-val\"\nimport * as path from \"path\"\nimport { Target } from \"../../core\"\nimport { LinuxPackager } from \"../../linuxPackager\"\nimport { AppImageOptions } from \"../../options/linuxOptions\"\nimport { getAppUpdatePublishConfiguration } from \"../../publish/PublishManager\"\nimport { getNotLocalizedLicenseFile } from \"../../util/license\"\nimport { LinuxTargetHelper } from \"../LinuxTargetHelper\"\nimport { createStageDir } from \"../targetUtil\"\nimport { buildLegacyFuse2AppImage, buildStaticRuntimeAppImage } from \"./appImageUtil\"\nimport { BlockMapDataHolder, deepAssign } from \"builder-util-runtime\"\n\n// https://unix.stackexchange.com/questions/375191/append-to-sub-directory-inside-squashfs-file\n\nexport const APP_RUN_ENTRYPOINT = \"AppRun\"\n\nexport default class AppImageTarget extends Target {\n readonly options: AppImageOptions = deepAssign({}, this.packager.platformSpecificBuildOptions, (this.packager.config as any)[this.name])\n\n private readonly desktopEntry: Lazy<string>\n\n constructor(\n _ignored: string,\n private readonly packager: LinuxPackager,\n private readonly helper: LinuxTargetHelper,\n readonly outDir: string\n ) {\n super(\"appImage\")\n\n this.desktopEntry = new Lazy<string>(() => {\n const appimageTool = packager.config.toolsets?.appimage\n const defaultArgs = appimageTool == null || appimageTool === \"0.0.0\" ? [\"--no-sandbox\"] : []\n const args = this.options.executableArgs ?? defaultArgs\n const exec = [APP_RUN_ENTRYPOINT, ...args, \"%U\"].join(\" \")\n return helper.computeDesktopEntry(this.options, exec, {\n \"X-AppImage-Version\": `${packager.appInfo.buildVersion}`,\n })\n })\n }\n\n async build(appOutDir: string, arch: Arch): Promise<any> {\n const packager = this.packager\n\n const options = this.options\n // https://github.com/electron-userland/electron-builder/issues/775\n // https://github.com/electron-userland/electron-builder/issues/1726\n const artifactName = packager.expandArtifactNamePattern(options, \"AppImage\", arch)\n const artifactPath = path.join(this.outDir, artifactName)\n\n await packager.info.emitArtifactBuildStarted({\n targetPresentableName: \"AppImage\",\n file: artifactPath,\n arch,\n })\n\n // Parallelize independent async operations\n const [publishConfig, stageDir, desktopEntry, icons, license] = await Promise.all([\n getAppUpdatePublishConfiguration(packager, options, arch, false),\n createStageDir(this, packager, arch),\n this.desktopEntry.value,\n this.helper.icons,\n getNotLocalizedLicenseFile(options.license, this.packager, [\"txt\", \"html\"]),\n ])\n\n if (publishConfig != null) {\n await outputFile(path.join(packager.getResourcesDir(appOutDir), \"app-update.yml\"), serializeToYaml(publishConfig))\n }\n\n if (this.packager.packagerOptions.effectiveOptionComputed != null && (await this.packager.packagerOptions.effectiveOptionComputed({ desktop: desktopEntry }))) {\n await stageDir.cleanup()\n return\n }\n\n let updateInfo: BlockMapDataHolder\n try {\n const appimageTool = this.packager.config.toolsets?.appimage\n if (appimageTool == null || appimageTool === \"0.0.0\") {\n updateInfo = await buildLegacyFuse2AppImage({\n appDir: appOutDir,\n stageDir: stageDir.dir,\n arch,\n output: artifactPath,\n options: {\n productName: packager.appInfo.productName,\n productFilename: packager.appInfo.productFilename,\n executableName: packager.executableName,\n license,\n desktopEntry,\n icons,\n fileAssociations: packager.fileAssociations,\n compression: (() => {\n const c = options.compression\n if (c === \"xz\" || c === \"gzip\") {\n return c\n }\n if (packager.compression === \"maximum\") {\n return \"xz\"\n }\n return undefined // normal/store/unset/zstd → mksquashfs defaults to gzip\n })(),\n },\n })\n } else {\n updateInfo = await buildStaticRuntimeAppImage(appimageTool, {\n appDir: appOutDir,\n stageDir: stageDir.dir,\n arch,\n output: artifactPath,\n options: {\n productName: packager.appInfo.productName,\n productFilename: packager.appInfo.productFilename,\n executableName: packager.executableName,\n license,\n desktopEntry,\n icons,\n fileAssociations: packager.fileAssociations,\n compression: (() => {\n const c = options.compression\n if (c === \"gzip\" || c === \"zstd\") {\n return c\n }\n if (c === \"xz\") {\n return \"zstd\" // nearest equivalent; static runtime does not support xz\n }\n if (packager.compression === \"store\") {\n return \"gzip\"\n }\n return \"zstd\" // maximum/normal/unset → zstd for static runtime\n })(),\n },\n })\n }\n } catch (error: any) {\n log.error({ error: error.message }, \"failed to build AppImage\")\n throw error\n } finally {\n await stageDir.cleanup().catch(() => {})\n }\n\n await packager.info.emitArtifactBuildCompleted({\n file: artifactPath,\n safeArtifactName: packager.computeSafeArtifactName(artifactName, \"AppImage\", arch, false),\n target: this,\n arch,\n packager,\n isWriteUpdateInfo: true,\n updateInfo,\n })\n }\n}\n"]}
|
|
@@ -13,13 +13,14 @@ interface Options {
|
|
|
13
13
|
fileAssociations: FileAssociation[];
|
|
14
14
|
/**
|
|
15
15
|
* The compression type available for static runtime is limited as it's only compiled with support for gzip and zstd.
|
|
16
|
+
* "xz" is only valid for the legacy FUSE2 (0.0.0) toolset.
|
|
16
17
|
*
|
|
17
18
|
* [stderr] Squashfs image uses lzo compression, this version supports only zlib, zstd.
|
|
18
19
|
* Failed to open squashfs image
|
|
19
20
|
* Failed to extract AppImage
|
|
20
21
|
*
|
|
21
22
|
*/
|
|
22
|
-
compression?: "gzip" | "zstd";
|
|
23
|
+
compression?: "gzip" | "zstd" | "xz";
|
|
23
24
|
}
|
|
24
25
|
export interface AppImageBuilderOptions {
|
|
25
26
|
appDir: string;
|
|
@@ -29,6 +30,7 @@ export interface AppImageBuilderOptions {
|
|
|
29
30
|
options: Options;
|
|
30
31
|
}
|
|
31
32
|
export declare function buildStaticRuntimeAppImage(appimageToolVersion: ToolsetConfig["appimage"], opts: AppImageBuilderOptions): Promise<BlockMapDataHolder>;
|
|
33
|
+
export declare function buildLegacyFuse2AppImage(opts: AppImageBuilderOptions): Promise<BlockMapDataHolder>;
|
|
32
34
|
/**
|
|
33
35
|
* Validates that critical path fields (executable name, product filename, license filename)
|
|
34
36
|
* contain only characters that are safe for use in filesystem paths and embedded bash strings.
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.buildStaticRuntimeAppImage = buildStaticRuntimeAppImage;
|
|
4
|
+
exports.buildLegacyFuse2AppImage = buildLegacyFuse2AppImage;
|
|
4
5
|
exports.validateCriticalPathString = validateCriticalPathString;
|
|
5
6
|
exports.generateAppRunScript = generateAppRunScript;
|
|
6
7
|
const builder_util_1 = require("builder-util");
|
|
@@ -44,6 +45,38 @@ async function buildStaticRuntimeAppImage(appimageToolVersion, opts) {
|
|
|
44
45
|
throw error;
|
|
45
46
|
}
|
|
46
47
|
}
|
|
48
|
+
async function buildLegacyFuse2AppImage(opts) {
|
|
49
|
+
const { stageDir, output, appDir, options, arch } = opts;
|
|
50
|
+
try {
|
|
51
|
+
await fs.remove(output);
|
|
52
|
+
await writeAppLauncherAndRelatedFiles(opts);
|
|
53
|
+
const { runtime, mksquashfs, runtimeLibraries } = await (0, linux_1.getAppImageTools)("0.0.0", arch);
|
|
54
|
+
// Mirror the app-builder-lib Go implementation: bundle lib/<arch> into usr/lib for x64 and ia32.
|
|
55
|
+
// arm targets don't have a dedicated lib dir in the FUSE2 toolset.
|
|
56
|
+
if (arch === builder_util_1.Arch.x64 || arch === builder_util_1.Arch.ia32) {
|
|
57
|
+
await (0, builder_util_1.copyDir)(runtimeLibraries, path.join(stageDir, "usr", "lib"));
|
|
58
|
+
}
|
|
59
|
+
await (0, builder_util_1.copyDir)(appDir, stageDir);
|
|
60
|
+
const runtimeData = await fs.readFile(runtime);
|
|
61
|
+
const args = [stageDir, output, "-offset", runtimeData.length.toString(), "-all-root", "-noappend", "-no-progress", "-quiet", "-no-xattrs", "-no-fragments"];
|
|
62
|
+
if (options.compression) {
|
|
63
|
+
args.push("-comp", options.compression);
|
|
64
|
+
if (options.compression === "xz") {
|
|
65
|
+
// Match the dictionary/block-size settings used by the original app-builder Go implementation
|
|
66
|
+
args.push("-Xdict-size", "100%", "-b", "1048576");
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
await (0, builder_util_1.exec)(mksquashfs, args, { cwd: stageDir });
|
|
70
|
+
await writeRuntimeData(output, runtimeData);
|
|
71
|
+
await fs.chmod(output, 0o755);
|
|
72
|
+
const updateInfo = await (0, differentialUpdateInfoBuilder_1.appendBlockmap)(output);
|
|
73
|
+
return updateInfo;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
await fs.remove(output).catch(() => { });
|
|
77
|
+
throw error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
47
80
|
async function writeRuntimeData(filePath, runtimeData) {
|
|
48
81
|
const fd = await fs.open(filePath, "r+");
|
|
49
82
|
try {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"appImageUtil.js","sourceRoot":"","sources":["../../../src/targets/appimage/appImageUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, copyDir, copyFile, exec, exists, InvalidConfigurationError, log } from \"builder-util\"\nimport * as fs from \"fs-extra\"\nimport * as path from \"path\"\nimport { FileAssociation } from \"../../options/FileAssociation\"\nimport { IconInfo } from \"../../platformPackager\"\nimport { getAppImageTools } from \"../../toolsets/linux\"\nimport { copyIcons, copyMimeTypes } from \"./appLauncher\"\nimport { appendBlockmap } from \"../differentialUpdateInfoBuilder\"\nimport { BlockMapDataHolder } from \"builder-util-runtime\"\nimport { APP_RUN_ENTRYPOINT } from \"./AppImageTarget\"\nimport { ToolsetConfig } from \"app-builder-lib/src/configuration\"\n\ninterface Options {\n productName: string\n productFilename: string\n executableName: string\n desktopEntry: string\n icons: IconInfo[]\n license?: string | null\n fileAssociations: FileAssociation[]\n /**\n * The compression type available for static runtime is limited as it's only compiled with support for gzip and zstd.\n *\n * [stderr] Squashfs image uses lzo compression, this version supports only zlib, zstd.\n * Failed to open squashfs image\n * Failed to extract AppImage\n *\n */\n compression?: \"gzip\" | \"zstd\"\n}\n\nexport interface AppImageBuilderOptions {\n appDir: string\n stageDir: string\n arch: Arch\n output: string\n options: Options\n}\n\nexport async function buildStaticRuntimeAppImage(appimageToolVersion: ToolsetConfig[\"appimage\"], opts: AppImageBuilderOptions): Promise<BlockMapDataHolder> {\n const { stageDir, output, appDir, options, arch } = opts\n\n try {\n await fs.remove(output)\n\n // Write AppRun launcher and related files\n await writeAppLauncherAndRelatedFiles(opts)\n\n const { runtimeLibraries: libraries, runtime, mksquashfs } = await getAppImageTools(appimageToolVersion, arch)\n await copyDir(libraries, path.join(stageDir, \"usr\", \"lib\"))\n\n // Copy app directory to stage\n // mksquashfs doesn't support merging, so we copy the entire app dir\n await copyDir(appDir, stageDir)\n\n const runtimeData = await fs.readFile(runtime)\n\n // Create squashfs with offset for runtime\n const args: string[] = [stageDir, output, \"-offset\", runtimeData.length.toString(), \"-all-root\", \"-noappend\", \"-no-progress\", \"-quiet\", \"-no-xattrs\", \"-no-fragments\"]\n if (options.compression) {\n args.push(\"-comp\", options.compression)\n }\n await exec(mksquashfs, args, {\n cwd: stageDir,\n })\n\n // Write runtime data at the beginning of the file\n await writeRuntimeData(output, runtimeData)\n\n // Make executable\n await fs.chmod(output, 0o755)\n\n // Append blockmap inside try block to ensure cleanup on failure\n const updateInfo = await appendBlockmap(output)\n return updateInfo\n } catch (error) {\n // Clean up partial build on failure\n await fs.remove(output).catch(() => {})\n throw error\n }\n}\n\nasync function writeRuntimeData(filePath: string, runtimeData: Buffer): Promise<void> {\n const fd = await fs.open(filePath, \"r+\")\n try {\n await fs.write(fd, runtimeData, 0, runtimeData.length, 0)\n } finally {\n try {\n await fs.close(fd)\n } catch (closeError: any) {\n // Log but don't throw - preserve original error if any\n log.warn({ message: closeError.message, file: filePath }, `failed to close file descriptor`)\n }\n }\n}\n\n/**\n * Escapes a string for safe use in shell scripts by wrapping in single quotes\n * and escaping any single quotes within the string.\n *\n * This allows strings with spaces, special characters, etc. to be safely used.\n */\nfunction escapeShellString(str: string): string {\n // Escape single quotes by replacing ' with '\\''\n // Then wrap the whole string in single quotes\n return `'${str.replace(/'/g, \"'\\\\''\")}'`\n}\n\n/**\n * Validates that critical path fields (executable name, product filename, license filename)\n * contain only characters that are safe for use in filesystem paths and embedded bash strings.\n * Allowed: Unicode letters, digits, dots, underscores, hyphens, and spaces.\n */\nexport function validateCriticalPathString(str: string, fieldName: string): void {\n if (!/^[\\p{L}\\p{N}._\\- ]+$/u.test(str)) {\n throw new InvalidConfigurationError(\n `${fieldName} contains characters that cannot be safely used in file paths: ${str}. Please use only letters, digits, hyphens, underscores, dots, and spaces.`\n )\n }\n}\n\nasync function writeAppLauncherAndRelatedFiles(opts: AppImageBuilderOptions): Promise<void> {\n const {\n stageDir,\n options: { license, executableName, productFilename, productName, desktopEntry },\n } = opts\n\n // executableName and productFilename are embedded directly into double-quoted bash strings\n // and used as filesystem paths, so they must pass the whitelist.\n // productName is not validated here because it is only ever passed through escapeShellString().\n validateCriticalPathString(executableName, \"executableName\")\n validateCriticalPathString(productFilename, \"productFilename\")\n\n // Write desktop file\n const desktopFileName = `${executableName}.desktop`\n await fs.writeFile(path.join(stageDir, desktopFileName), desktopEntry, { mode: 0o644 })\n await copyIcons(opts)\n\n const templateConfig: AppRunScriptBase = {\n DesktopFileName: desktopFileName,\n ExecutableName: executableName,\n ProductName: productName,\n ProductFilename: productFilename,\n ResourceName: `appimagekit-${executableName}`,\n }\n\n const mimeTypeFile = await copyMimeTypes(stageDir, opts.options)\n if (mimeTypeFile) {\n templateConfig.MimeTypeFile = mimeTypeFile\n }\n\n let finalConfig: AppRunScript = templateConfig\n\n // Copy license file if provided\n if (license) {\n // Validate license file exists\n if (!(await exists(license))) {\n throw new InvalidConfigurationError(`License file not found: ${license}`)\n }\n\n const licenseBaseName = path.basename(license)\n const ext = path.extname(license).toLowerCase()\n\n // Validate license filename for path safety\n validateCriticalPathString(licenseBaseName, \"licenseBaseName\")\n\n // Validate extension\n if (![\".txt\", \".html\"].includes(ext)) {\n log.warn({ license, expected: \".txt or .html\" }, `license file has unexpected extension`)\n }\n\n await copyFile(license, path.join(stageDir, licenseBaseName))\n\n finalConfig = {\n ...templateConfig,\n EulaFile: licenseBaseName,\n IsHtmlEula: ext === \".html\",\n }\n }\n\n const appRunContent = generateAppRunScript(finalConfig)\n await fs.writeFile(path.join(stageDir, APP_RUN_ENTRYPOINT), appRunContent, { mode: 0o755 })\n}\n\nexport type AppRunScriptBase = {\n ExecutableName: string\n DesktopFileName: string\n ProductFilename: string\n ProductName: string\n ResourceName: string\n MimeTypeFile?: string\n}\n\nexport type AppRunScriptWithEula = AppRunScriptBase & {\n EulaFile: string\n IsHtmlEula: boolean\n}\n\nexport type AppRunScript = AppRunScriptBase | AppRunScriptWithEula\n\nfunction hasEula(config: AppRunScript): config is AppRunScriptWithEula {\n return \"EulaFile\" in config && typeof config.EulaFile === \"string\"\n}\n\nexport function generateAppRunScript(config: AppRunScript): string {\n const eulaEnabled = hasEula(config)\n\n return `#!/usr/bin/env bash\nset -e\n\nTHIS=\"$0\"\n# http://stackoverflow.com/questions/3190818/\nargs=(\"$@\")\nNUMBER_OF_ARGS=\"$#\"\n\nif [ -z \"$APPDIR\" ] ; then\n # Find the AppDir. It is the directory that contains AppRun.\n # This assumes that this script resides inside the AppDir or a subdirectory.\n # If this script is run inside an AppImage, then the AppImage runtime likely has already set $APPDIR\n path=\"$(dirname \"$(readlink -f \"\\${THIS}\")\")\"\n while [[ \"$path\" != \"\" && ! -e \"$path/${APP_RUN_ENTRYPOINT}\" ]]; do\n path=\\${path%/*}\n done\n APPDIR=\"$path\"\nfi\n\nif [ -z \"$APPDIR\" ] ; then\n echo \"ERROR: could not locate the AppDir. Ensure this script is run from within a properly structured AppImage.\" >&2\n exit 1\nfi\n\nexport PATH=\"\\${APPDIR}:\\${APPDIR}/usr/sbin\\${PATH:+:\\${PATH}}\"\nexport XDG_DATA_DIRS=\"\\${APPDIR}/usr/share/\\${XDG_DATA_DIRS:+:\\${XDG_DATA_DIRS}}:/usr/share/gnome:/usr/local/share/:/usr/share/\"\nexport LD_LIBRARY_PATH=\"\\${APPDIR}/usr/lib\\${LD_LIBRARY_PATH:+:\\${LD_LIBRARY_PATH}}\"\nexport GSETTINGS_SCHEMA_DIR=\"\\${APPDIR}/usr/share/glib-2.0/schemas\\${GSETTINGS_SCHEMA_DIR:+:\\${GSETTINGS_SCHEMA_DIR}}\"\n\nBIN=\"$APPDIR/${config.ExecutableName}\"\n\nif [ -z \"$APPIMAGE_EXIT_AFTER_INSTALL\" ] ; then\n trap atexit EXIT\nfi\n\nisEulaAccepted=1\n\nHAVE_NO_SANDBOX=0\nfor arg in \"\\${args[@]}\" ; do\n if [ \"$arg\" = --no-sandbox ] ; then\n HAVE_NO_SANDBOX=1\n break\n fi\ndone\nNO_SANDBOX=()\n# Use 'unshare -Ur true' as a heuristic to detect whether user namespaces are available.\n# Notes:\n# - When running as root, this check will always succeed even if the sandbox configuration\n# actually relies on unprivileged user namespaces. In practice, Chrome/Electron usually\n# disables or adjusts the sandbox separately when running as root, so this probe is mostly\n# a no-op in that scenario.\n# - On minimal systems (e.g. Alpine or stripped-down containers) 'unshare' may not exist.\n# In that case the shell will return exit code 127 (\"command not found\"), which will cause\n# us to add '--no-sandbox'. This is an intentional fail-safe: we prefer the app to start\n# without sandboxing rather than crash on startup.\nif [ $HAVE_NO_SANDBOX -eq 0 ] && ! unshare -Ur true 2>/dev/null ; then\n NO_SANDBOX=(--no-sandbox)\nfi\n\natexit()\n{\n if [ $isEulaAccepted == 1 ] ; then\n if [ $NUMBER_OF_ARGS -eq 0 ] ; then\n exec \"$BIN\" \"\\${NO_SANDBOX[@]}\"\n else\n exec \"$BIN\" \"\\${NO_SANDBOX[@]}\" \"\\${args[@]}\"\n fi\n fi\n}\n\nerror()\n{\n if [ -x /usr/bin/zenity ] ; then\n LD_LIBRARY_PATH=\"\" zenity --error --text \"\\${1}\" 2>/dev/null\n elif [ -x /usr/bin/kdialog ] ; then\n LD_LIBRARY_PATH=\"\" kdialog --msgbox \"\\${1}\" 2>/dev/null\n elif [ -x /usr/bin/Xdialog ] ; then\n LD_LIBRARY_PATH=\"\" Xdialog --msgbox \"\\${1}\" 2>/dev/null\n else\n echo \"\\${1}\"\n fi\n exit 1\n}\n\nyesno()\n{\n TITLE=$1\n TEXT=$2\n if [ -x /usr/bin/zenity ] ; then\n LD_LIBRARY_PATH=\"\" zenity --question --title=\"$TITLE\" --text=\"$TEXT\" 2>/dev/null || exit 0\n elif [ -x /usr/bin/kdialog ] ; then\n LD_LIBRARY_PATH=\"\" kdialog --title \"$TITLE\" --yesno \"$TEXT\" || exit 0\n elif [ -x /usr/bin/Xdialog ] ; then\n LD_LIBRARY_PATH=\"\" Xdialog --title \"$TITLE\" --clear --yesno \"$TEXT\" 10 80 || exit 0\n else\n echo \"zenity, kdialog, Xdialog missing. Skipping \\${THIS}.\"\n exit 0\n fi\n}\n\ncheck_dep()\n{\n DEP=$1\n if ! command -v \"$DEP\" &>/dev/null ; then\n echo \"$DEP is missing. Skipping \\${THIS}.\"\n exit 0\n fi\n}\n\nif [ -z \"$APPIMAGE\" ] ; then\n APPIMAGE=\"$APPDIR/${APP_RUN_ENTRYPOINT}\"\n # not running from within an AppImage; hence using the AppRun for Exec=\nfi\n\n${\n eulaEnabled\n ? `if [ -z \"$APPIMAGE_SILENT_INSTALL\" ] ; then\n EULA_MARK_DIR=\"\\${XDG_CONFIG_HOME:-$HOME/.config}/${config.ProductFilename}\"\n EULA_MARK_FILE=\"$EULA_MARK_DIR/eulaAccepted\"\n # show EULA only if desktop file doesn't exist\n if [ ! -e \"$EULA_MARK_FILE\" ] ; then\n if [ -x /usr/bin/zenity ] ; then\n # on cancel simply exits and our trap handler launches app, so, $isEulaAccepted is set here to 0 and then to 1 if EULA accepted\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" zenity --text-info --title=${escapeShellString(config.ProductName)} --filename=\"$APPDIR/${config.EulaFile}\" --ok-label=Agree --cancel-label=Disagree ${config.IsHtmlEula ? \"--html\" : \"\"}\n elif [ -x /usr/bin/Xdialog ] ; then\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" Xdialog --title ${escapeShellString(config.ProductName)} --textbox \"$APPDIR/${config.EulaFile}\" 30 80 --ok-label Agree --cancel-label Disagree\n elif [ -x /usr/bin/kdialog ] ; then\n # cannot find any option to force Agree/Disagree buttons for kdialog. And official example exactly with OK button https://techbase.kde.org/Development/Tutorials/Shell_Scripting_with_KDE_Dialogs#Example_21._--textbox_dialog_box\n # in any case we pass labels text\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" kdialog --textbox \"$APPDIR/${config.EulaFile}\" --yes-label Agree --cancel-label \"Disagree\"\n fi\n\n case $? in\n 0)\n isEulaAccepted=1\n echo \"License accepted\"\n mkdir -p \"$EULA_MARK_DIR\"\n touch \"$EULA_MARK_FILE\"\n ;;\n 1)\n echo \"License not accepted\"\n exit 0\n ;;\n -1)\n echo \"An unexpected error has occurred.\"\n isEulaAccepted=1\n ;;\n esac\n fi\nfi`\n : \"\"\n}\n`\n}\n"]}
|
|
1
|
+
{"version":3,"file":"appImageUtil.js","sourceRoot":"","sources":["../../../src/targets/appimage/appImageUtil.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch, copyDir, copyFile, exec, exists, InvalidConfigurationError, log } from \"builder-util\"\nimport * as fs from \"fs-extra\"\nimport * as path from \"path\"\nimport { FileAssociation } from \"../../options/FileAssociation\"\nimport { IconInfo } from \"../../platformPackager\"\nimport { getAppImageTools } from \"../../toolsets/linux\"\nimport { copyIcons, copyMimeTypes } from \"./appLauncher\"\nimport { appendBlockmap } from \"../differentialUpdateInfoBuilder\"\nimport { BlockMapDataHolder } from \"builder-util-runtime\"\nimport { APP_RUN_ENTRYPOINT } from \"./AppImageTarget\"\nimport { ToolsetConfig } from \"app-builder-lib/src/configuration\"\n\ninterface Options {\n productName: string\n productFilename: string\n executableName: string\n desktopEntry: string\n icons: IconInfo[]\n license?: string | null\n fileAssociations: FileAssociation[]\n /**\n * The compression type available for static runtime is limited as it's only compiled with support for gzip and zstd.\n * \"xz\" is only valid for the legacy FUSE2 (0.0.0) toolset.\n *\n * [stderr] Squashfs image uses lzo compression, this version supports only zlib, zstd.\n * Failed to open squashfs image\n * Failed to extract AppImage\n *\n */\n compression?: \"gzip\" | \"zstd\" | \"xz\"\n}\n\nexport interface AppImageBuilderOptions {\n appDir: string\n stageDir: string\n arch: Arch\n output: string\n options: Options\n}\n\nexport async function buildStaticRuntimeAppImage(appimageToolVersion: ToolsetConfig[\"appimage\"], opts: AppImageBuilderOptions): Promise<BlockMapDataHolder> {\n const { stageDir, output, appDir, options, arch } = opts\n\n try {\n await fs.remove(output)\n\n // Write AppRun launcher and related files\n await writeAppLauncherAndRelatedFiles(opts)\n\n const { runtimeLibraries: libraries, runtime, mksquashfs } = await getAppImageTools(appimageToolVersion, arch)\n await copyDir(libraries, path.join(stageDir, \"usr\", \"lib\"))\n\n // Copy app directory to stage\n // mksquashfs doesn't support merging, so we copy the entire app dir\n await copyDir(appDir, stageDir)\n\n const runtimeData = await fs.readFile(runtime)\n\n // Create squashfs with offset for runtime\n const args: string[] = [stageDir, output, \"-offset\", runtimeData.length.toString(), \"-all-root\", \"-noappend\", \"-no-progress\", \"-quiet\", \"-no-xattrs\", \"-no-fragments\"]\n if (options.compression) {\n args.push(\"-comp\", options.compression)\n }\n await exec(mksquashfs, args, {\n cwd: stageDir,\n })\n\n // Write runtime data at the beginning of the file\n await writeRuntimeData(output, runtimeData)\n\n // Make executable\n await fs.chmod(output, 0o755)\n\n // Append blockmap inside try block to ensure cleanup on failure\n const updateInfo = await appendBlockmap(output)\n return updateInfo\n } catch (error) {\n // Clean up partial build on failure\n await fs.remove(output).catch(() => {})\n throw error\n }\n}\n\nexport async function buildLegacyFuse2AppImage(opts: AppImageBuilderOptions): Promise<BlockMapDataHolder> {\n const { stageDir, output, appDir, options, arch } = opts\n\n try {\n await fs.remove(output)\n\n await writeAppLauncherAndRelatedFiles(opts)\n\n const { runtime, mksquashfs, runtimeLibraries } = await getAppImageTools(\"0.0.0\", arch)\n // Mirror the app-builder-lib Go implementation: bundle lib/<arch> into usr/lib for x64 and ia32.\n // arm targets don't have a dedicated lib dir in the FUSE2 toolset.\n if (arch === Arch.x64 || arch === Arch.ia32) {\n await copyDir(runtimeLibraries, path.join(stageDir, \"usr\", \"lib\"))\n }\n await copyDir(appDir, stageDir)\n\n const runtimeData = await fs.readFile(runtime)\n\n const args: string[] = [stageDir, output, \"-offset\", runtimeData.length.toString(), \"-all-root\", \"-noappend\", \"-no-progress\", \"-quiet\", \"-no-xattrs\", \"-no-fragments\"]\n if (options.compression) {\n args.push(\"-comp\", options.compression)\n if (options.compression === \"xz\") {\n // Match the dictionary/block-size settings used by the original app-builder Go implementation\n args.push(\"-Xdict-size\", \"100%\", \"-b\", \"1048576\")\n }\n }\n await exec(mksquashfs, args, { cwd: stageDir })\n\n await writeRuntimeData(output, runtimeData)\n await fs.chmod(output, 0o755)\n\n const updateInfo = await appendBlockmap(output)\n return updateInfo\n } catch (error) {\n await fs.remove(output).catch(() => {})\n throw error\n }\n}\n\nasync function writeRuntimeData(filePath: string, runtimeData: Buffer): Promise<void> {\n const fd = await fs.open(filePath, \"r+\")\n try {\n await fs.write(fd, runtimeData, 0, runtimeData.length, 0)\n } finally {\n try {\n await fs.close(fd)\n } catch (closeError: any) {\n // Log but don't throw - preserve original error if any\n log.warn({ message: closeError.message, file: filePath }, `failed to close file descriptor`)\n }\n }\n}\n\n/**\n * Escapes a string for safe use in shell scripts by wrapping in single quotes\n * and escaping any single quotes within the string.\n *\n * This allows strings with spaces, special characters, etc. to be safely used.\n */\nfunction escapeShellString(str: string): string {\n // Escape single quotes by replacing ' with '\\''\n // Then wrap the whole string in single quotes\n return `'${str.replace(/'/g, \"'\\\\''\")}'`\n}\n\n/**\n * Validates that critical path fields (executable name, product filename, license filename)\n * contain only characters that are safe for use in filesystem paths and embedded bash strings.\n * Allowed: Unicode letters, digits, dots, underscores, hyphens, and spaces.\n */\nexport function validateCriticalPathString(str: string, fieldName: string): void {\n if (!/^[\\p{L}\\p{N}._\\- ]+$/u.test(str)) {\n throw new InvalidConfigurationError(\n `${fieldName} contains characters that cannot be safely used in file paths: ${str}. Please use only letters, digits, hyphens, underscores, dots, and spaces.`\n )\n }\n}\n\nasync function writeAppLauncherAndRelatedFiles(opts: AppImageBuilderOptions): Promise<void> {\n const {\n stageDir,\n options: { license, executableName, productFilename, productName, desktopEntry },\n } = opts\n\n // executableName and productFilename are embedded directly into double-quoted bash strings\n // and used as filesystem paths, so they must pass the whitelist.\n // productName is not validated here because it is only ever passed through escapeShellString().\n validateCriticalPathString(executableName, \"executableName\")\n validateCriticalPathString(productFilename, \"productFilename\")\n\n // Write desktop file\n const desktopFileName = `${executableName}.desktop`\n await fs.writeFile(path.join(stageDir, desktopFileName), desktopEntry, { mode: 0o644 })\n await copyIcons(opts)\n\n const templateConfig: AppRunScriptBase = {\n DesktopFileName: desktopFileName,\n ExecutableName: executableName,\n ProductName: productName,\n ProductFilename: productFilename,\n ResourceName: `appimagekit-${executableName}`,\n }\n\n const mimeTypeFile = await copyMimeTypes(stageDir, opts.options)\n if (mimeTypeFile) {\n templateConfig.MimeTypeFile = mimeTypeFile\n }\n\n let finalConfig: AppRunScript = templateConfig\n\n // Copy license file if provided\n if (license) {\n // Validate license file exists\n if (!(await exists(license))) {\n throw new InvalidConfigurationError(`License file not found: ${license}`)\n }\n\n const licenseBaseName = path.basename(license)\n const ext = path.extname(license).toLowerCase()\n\n // Validate license filename for path safety\n validateCriticalPathString(licenseBaseName, \"licenseBaseName\")\n\n // Validate extension\n if (![\".txt\", \".html\"].includes(ext)) {\n log.warn({ license, expected: \".txt or .html\" }, `license file has unexpected extension`)\n }\n\n await copyFile(license, path.join(stageDir, licenseBaseName))\n\n finalConfig = {\n ...templateConfig,\n EulaFile: licenseBaseName,\n IsHtmlEula: ext === \".html\",\n }\n }\n\n const appRunContent = generateAppRunScript(finalConfig)\n await fs.writeFile(path.join(stageDir, APP_RUN_ENTRYPOINT), appRunContent, { mode: 0o755 })\n}\n\nexport type AppRunScriptBase = {\n ExecutableName: string\n DesktopFileName: string\n ProductFilename: string\n ProductName: string\n ResourceName: string\n MimeTypeFile?: string\n}\n\nexport type AppRunScriptWithEula = AppRunScriptBase & {\n EulaFile: string\n IsHtmlEula: boolean\n}\n\nexport type AppRunScript = AppRunScriptBase | AppRunScriptWithEula\n\nfunction hasEula(config: AppRunScript): config is AppRunScriptWithEula {\n return \"EulaFile\" in config && typeof config.EulaFile === \"string\"\n}\n\nexport function generateAppRunScript(config: AppRunScript): string {\n const eulaEnabled = hasEula(config)\n\n return `#!/usr/bin/env bash\nset -e\n\nTHIS=\"$0\"\n# http://stackoverflow.com/questions/3190818/\nargs=(\"$@\")\nNUMBER_OF_ARGS=\"$#\"\n\nif [ -z \"$APPDIR\" ] ; then\n # Find the AppDir. It is the directory that contains AppRun.\n # This assumes that this script resides inside the AppDir or a subdirectory.\n # If this script is run inside an AppImage, then the AppImage runtime likely has already set $APPDIR\n path=\"$(dirname \"$(readlink -f \"\\${THIS}\")\")\"\n while [[ \"$path\" != \"\" && ! -e \"$path/${APP_RUN_ENTRYPOINT}\" ]]; do\n path=\\${path%/*}\n done\n APPDIR=\"$path\"\nfi\n\nif [ -z \"$APPDIR\" ] ; then\n echo \"ERROR: could not locate the AppDir. Ensure this script is run from within a properly structured AppImage.\" >&2\n exit 1\nfi\n\nexport PATH=\"\\${APPDIR}:\\${APPDIR}/usr/sbin\\${PATH:+:\\${PATH}}\"\nexport XDG_DATA_DIRS=\"\\${APPDIR}/usr/share/\\${XDG_DATA_DIRS:+:\\${XDG_DATA_DIRS}}:/usr/share/gnome:/usr/local/share/:/usr/share/\"\nexport LD_LIBRARY_PATH=\"\\${APPDIR}/usr/lib\\${LD_LIBRARY_PATH:+:\\${LD_LIBRARY_PATH}}\"\nexport GSETTINGS_SCHEMA_DIR=\"\\${APPDIR}/usr/share/glib-2.0/schemas\\${GSETTINGS_SCHEMA_DIR:+:\\${GSETTINGS_SCHEMA_DIR}}\"\n\nBIN=\"$APPDIR/${config.ExecutableName}\"\n\nif [ -z \"$APPIMAGE_EXIT_AFTER_INSTALL\" ] ; then\n trap atexit EXIT\nfi\n\nisEulaAccepted=1\n\nHAVE_NO_SANDBOX=0\nfor arg in \"\\${args[@]}\" ; do\n if [ \"$arg\" = --no-sandbox ] ; then\n HAVE_NO_SANDBOX=1\n break\n fi\ndone\nNO_SANDBOX=()\n# Use 'unshare -Ur true' as a heuristic to detect whether user namespaces are available.\n# Notes:\n# - When running as root, this check will always succeed even if the sandbox configuration\n# actually relies on unprivileged user namespaces. In practice, Chrome/Electron usually\n# disables or adjusts the sandbox separately when running as root, so this probe is mostly\n# a no-op in that scenario.\n# - On minimal systems (e.g. Alpine or stripped-down containers) 'unshare' may not exist.\n# In that case the shell will return exit code 127 (\"command not found\"), which will cause\n# us to add '--no-sandbox'. This is an intentional fail-safe: we prefer the app to start\n# without sandboxing rather than crash on startup.\nif [ $HAVE_NO_SANDBOX -eq 0 ] && ! unshare -Ur true 2>/dev/null ; then\n NO_SANDBOX=(--no-sandbox)\nfi\n\natexit()\n{\n if [ $isEulaAccepted == 1 ] ; then\n if [ $NUMBER_OF_ARGS -eq 0 ] ; then\n exec \"$BIN\" \"\\${NO_SANDBOX[@]}\"\n else\n exec \"$BIN\" \"\\${NO_SANDBOX[@]}\" \"\\${args[@]}\"\n fi\n fi\n}\n\nerror()\n{\n if [ -x /usr/bin/zenity ] ; then\n LD_LIBRARY_PATH=\"\" zenity --error --text \"\\${1}\" 2>/dev/null\n elif [ -x /usr/bin/kdialog ] ; then\n LD_LIBRARY_PATH=\"\" kdialog --msgbox \"\\${1}\" 2>/dev/null\n elif [ -x /usr/bin/Xdialog ] ; then\n LD_LIBRARY_PATH=\"\" Xdialog --msgbox \"\\${1}\" 2>/dev/null\n else\n echo \"\\${1}\"\n fi\n exit 1\n}\n\nyesno()\n{\n TITLE=$1\n TEXT=$2\n if [ -x /usr/bin/zenity ] ; then\n LD_LIBRARY_PATH=\"\" zenity --question --title=\"$TITLE\" --text=\"$TEXT\" 2>/dev/null || exit 0\n elif [ -x /usr/bin/kdialog ] ; then\n LD_LIBRARY_PATH=\"\" kdialog --title \"$TITLE\" --yesno \"$TEXT\" || exit 0\n elif [ -x /usr/bin/Xdialog ] ; then\n LD_LIBRARY_PATH=\"\" Xdialog --title \"$TITLE\" --clear --yesno \"$TEXT\" 10 80 || exit 0\n else\n echo \"zenity, kdialog, Xdialog missing. Skipping \\${THIS}.\"\n exit 0\n fi\n}\n\ncheck_dep()\n{\n DEP=$1\n if ! command -v \"$DEP\" &>/dev/null ; then\n echo \"$DEP is missing. Skipping \\${THIS}.\"\n exit 0\n fi\n}\n\nif [ -z \"$APPIMAGE\" ] ; then\n APPIMAGE=\"$APPDIR/${APP_RUN_ENTRYPOINT}\"\n # not running from within an AppImage; hence using the AppRun for Exec=\nfi\n\n${\n eulaEnabled\n ? `if [ -z \"$APPIMAGE_SILENT_INSTALL\" ] ; then\n EULA_MARK_DIR=\"\\${XDG_CONFIG_HOME:-$HOME/.config}/${config.ProductFilename}\"\n EULA_MARK_FILE=\"$EULA_MARK_DIR/eulaAccepted\"\n # show EULA only if desktop file doesn't exist\n if [ ! -e \"$EULA_MARK_FILE\" ] ; then\n if [ -x /usr/bin/zenity ] ; then\n # on cancel simply exits and our trap handler launches app, so, $isEulaAccepted is set here to 0 and then to 1 if EULA accepted\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" zenity --text-info --title=${escapeShellString(config.ProductName)} --filename=\"$APPDIR/${config.EulaFile}\" --ok-label=Agree --cancel-label=Disagree ${config.IsHtmlEula ? \"--html\" : \"\"}\n elif [ -x /usr/bin/Xdialog ] ; then\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" Xdialog --title ${escapeShellString(config.ProductName)} --textbox \"$APPDIR/${config.EulaFile}\" 30 80 --ok-label Agree --cancel-label Disagree\n elif [ -x /usr/bin/kdialog ] ; then\n # cannot find any option to force Agree/Disagree buttons for kdialog. And official example exactly with OK button https://techbase.kde.org/Development/Tutorials/Shell_Scripting_with_KDE_Dialogs#Example_21._--textbox_dialog_box\n # in any case we pass labels text\n isEulaAccepted=0\n LD_LIBRARY_PATH=\"\" kdialog --textbox \"$APPDIR/${config.EulaFile}\" --yes-label Agree --cancel-label \"Disagree\"\n fi\n\n case $? in\n 0)\n isEulaAccepted=1\n echo \"License accepted\"\n mkdir -p \"$EULA_MARK_DIR\"\n touch \"$EULA_MARK_FILE\"\n ;;\n 1)\n echo \"License not accepted\"\n exit 0\n ;;\n -1)\n echo \"An unexpected error has occurred.\"\n isEulaAccepted=1\n ;;\n esac\n fi\nfi`\n : \"\"\n}\n`\n}\n"]}
|
|
@@ -22,6 +22,7 @@ const nsisLicense_1 = require("./nsisLicense");
|
|
|
22
22
|
const nsisScriptGenerator_1 = require("./nsisScriptGenerator");
|
|
23
23
|
const windows_1 = require("../../toolsets/windows");
|
|
24
24
|
const nsisUtil_1 = require("./nsisUtil");
|
|
25
|
+
const nsisValidation_1 = require("./nsisValidation");
|
|
25
26
|
const debug = (0, debug_1.default)("electron-builder:nsis");
|
|
26
27
|
// noinspection SpellCheckingInspection
|
|
27
28
|
const ELECTRON_BUILDER_NS_UUID = builder_util_runtime_1.UUID.parse("50e065bc-3134-11e6-9bab-38c9862bdaf3");
|
|
@@ -252,7 +253,7 @@ class NsisTarget extends core_1.Target {
|
|
|
252
253
|
defines.REQUEST_EXECUTION_LEVEL = requestExecutionLevel || "user";
|
|
253
254
|
// https://github.com/electron-userland/electron-builder/issues/5764
|
|
254
255
|
if (typeof unpackDirName === "string" || !unpackDirName) {
|
|
255
|
-
defines.UNPACK_DIR_NAME = unpackDirName || (
|
|
256
|
+
defines.UNPACK_DIR_NAME = unpackDirName || (0, builder_util_1.generateKsuid)();
|
|
256
257
|
}
|
|
257
258
|
if (splashImage != null) {
|
|
258
259
|
defines.SPLASH_IMAGE = path.resolve(packager.projectDir, splashImage);
|
|
@@ -292,12 +293,21 @@ class NsisTarget extends core_1.Target {
|
|
|
292
293
|
}
|
|
293
294
|
this.buildQueueManager.add(async () => {
|
|
294
295
|
const sharedHeader = await this.computeCommonInstallerScriptHeader();
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
296
|
+
let rawScript;
|
|
297
|
+
let isCustomScript = false;
|
|
298
|
+
if (isPortable) {
|
|
299
|
+
rawScript = await (0, fs_extra_1.readFile)(path.join(nsisUtil_1.nsisTemplatesDir, "portable.nsi"), "utf8");
|
|
300
|
+
}
|
|
301
|
+
else {
|
|
302
|
+
const result = await this.computeScriptAndSignUninstaller(definesUninstaller, commandsUninstaller, installerPath, sharedHeader, archs);
|
|
303
|
+
rawScript = result.script;
|
|
304
|
+
isCustomScript = result.isCustomScript;
|
|
305
|
+
}
|
|
298
306
|
// copy outfile name into main options, as the computeScriptAndSignUninstaller function was kind enough to add important data to temporary defines.
|
|
299
307
|
defines.UNINSTALLER_OUT_FILE = definesUninstaller.UNINSTALLER_OUT_FILE;
|
|
300
|
-
|
|
308
|
+
// Skip size verification for portable (NSIS recompresses the archive, installer < archive is normal)
|
|
309
|
+
// and for custom scripts (may not embed archives).
|
|
310
|
+
await this.executeMakensis(defines, commands, sharedHeader + (await this.computeFinalScript(rawScript, true, archs)), { skipSizeVerification: isPortable || isCustomScript });
|
|
301
311
|
await Promise.all([packager.signIf(installerPath), defines.UNINSTALLER_OUT_FILE == null ? Promise.resolve() : (0, fs_extra_1.unlink)(defines.UNINSTALLER_OUT_FILE)]);
|
|
302
312
|
const safeArtifactName = (0, platformPackager_1.computeSafeArtifactNameIfNeeded)(installerFilename, () => this.generateGitHubInstallerName(primaryArch, defaultArch));
|
|
303
313
|
let updateInfo;
|
|
@@ -339,7 +349,7 @@ class NsisTarget extends core_1.Target {
|
|
|
339
349
|
const script = await (0, fs_extra_1.readFile)(customScriptPath || path.join(nsisUtil_1.nsisTemplatesDir, "installer.nsi"), "utf8");
|
|
340
350
|
if (customScriptPath != null) {
|
|
341
351
|
builder_util_1.log.info({ reason: "custom NSIS script is used" }, "uninstaller is not signed by electron-builder");
|
|
342
|
-
return script;
|
|
352
|
+
return { script, isCustomScript: true };
|
|
343
353
|
}
|
|
344
354
|
// https://github.com/electron-userland/electron-builder/issues/2103
|
|
345
355
|
// it is more safe and reliable to write uninstaller to our out dir
|
|
@@ -373,7 +383,7 @@ class NsisTarget extends core_1.Target {
|
|
|
373
383
|
delete defines.BUILD_UNINSTALLER;
|
|
374
384
|
// platform-specific path, not wine
|
|
375
385
|
defines.UNINSTALLER_OUT_FILE = uninstallerPath;
|
|
376
|
-
return script;
|
|
386
|
+
return { script, isCustomScript: false };
|
|
377
387
|
}
|
|
378
388
|
computeVersionKey(short = false) {
|
|
379
389
|
// Error: invalid VIProductVersion format, should be X.X.X.X
|
|
@@ -505,7 +515,7 @@ class NsisTarget extends core_1.Target {
|
|
|
505
515
|
defines.COMPRESSION_METHOD = options.useZip ? "zip" : "7z";
|
|
506
516
|
}
|
|
507
517
|
}
|
|
508
|
-
async executeMakensis(defines, commands, script) {
|
|
518
|
+
async executeMakensis(defines, commands, script, opts = {}) {
|
|
509
519
|
var _a, _b;
|
|
510
520
|
const args = this.options.warningsAsErrors === false ? [] : ["-WX"];
|
|
511
521
|
args.push("-INPUTCHARSET", "UTF8");
|
|
@@ -549,10 +559,20 @@ class NsisTarget extends core_1.Target {
|
|
|
549
559
|
await ensureNotBusy(commands["OutFile"].replace(/"/g, ""));
|
|
550
560
|
}
|
|
551
561
|
const makensis = await (0, windows_1.getMakeNsisPath)((_a = this.packager.config.toolsets) === null || _a === void 0 ? void 0 : _a.nsis, this.options.customNsisBinary);
|
|
552
|
-
await (0, builder_util_1.
|
|
562
|
+
const { stdout, stderr } = await (0, builder_util_1.spawnAndWriteWithOutput)(makensis.path, args, script, {
|
|
553
563
|
env: { ...process.env, ...((_b = makensis.env) !== null && _b !== void 0 ? _b : {}) },
|
|
554
564
|
cwd: nsisUtil_1.nsisTemplatesDir,
|
|
555
565
|
});
|
|
566
|
+
(0, nsisValidation_1.checkMakensisOutput)(stdout, stderr);
|
|
567
|
+
// Only verify output size for the final, non-web installer.
|
|
568
|
+
// BUILD_UNINSTALLER: intermediate uninstaller build — no embedded archives.
|
|
569
|
+
// APP_PACKAGE_STORE_FILE: nsis-web — archives downloaded at install-time.
|
|
570
|
+
// skipSizeVerification: portable builds (NSIS recompresses the archive, so
|
|
571
|
+
// installer < archive_size is normal) and custom scripts (may not embed archives).
|
|
572
|
+
if (!("BUILD_UNINSTALLER" in defines) && !("APP_PACKAGE_STORE_FILE" in defines) && !opts.skipSizeVerification) {
|
|
573
|
+
const outFile = commands["OutFile"].replace(/^"|"$/g, "");
|
|
574
|
+
await (0, nsisValidation_1.verifyInstallerSize)(outFile, defines);
|
|
575
|
+
}
|
|
556
576
|
}
|
|
557
577
|
async computeCommonInstallerScriptHeader() {
|
|
558
578
|
const packager = this.packager;
|