app-builder-lib 26.6.0 → 26.8.0

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.
Files changed (71) hide show
  1. package/out/codeSign/windowsSignToolManager.d.ts +4 -5
  2. package/out/codeSign/windowsSignToolManager.js +76 -86
  3. package/out/codeSign/windowsSignToolManager.js.map +1 -1
  4. package/out/configuration.d.ts +34 -0
  5. package/out/configuration.js.map +1 -1
  6. package/out/index.d.ts +1 -1
  7. package/out/index.js.map +1 -1
  8. package/out/linuxPackager.js +1 -1
  9. package/out/linuxPackager.js.map +1 -1
  10. package/out/macPackager.js +0 -1
  11. package/out/macPackager.js.map +1 -1
  12. package/out/node-module-collector/index.d.ts +1 -2
  13. package/out/node-module-collector/nodeModulesCollector.d.ts +2 -18
  14. package/out/node-module-collector/nodeModulesCollector.js +38 -73
  15. package/out/node-module-collector/nodeModulesCollector.js.map +1 -1
  16. package/out/node-module-collector/npmNodeModulesCollector.js +11 -7
  17. package/out/node-module-collector/npmNodeModulesCollector.js.map +1 -1
  18. package/out/node-module-collector/pnpmNodeModulesCollector.js +1 -1
  19. package/out/node-module-collector/pnpmNodeModulesCollector.js.map +1 -1
  20. package/out/node-module-collector/types.d.ts +0 -4
  21. package/out/node-module-collector/types.js.map +1 -1
  22. package/out/node-module-collector/yarnNodeModulesCollector.d.ts +4 -10
  23. package/out/node-module-collector/yarnNodeModulesCollector.js +7 -197
  24. package/out/node-module-collector/yarnNodeModulesCollector.js.map +1 -1
  25. package/out/options/AppXOptions.d.ts +8 -0
  26. package/out/options/AppXOptions.js.map +1 -1
  27. package/out/options/macOptions.d.ts +12 -0
  28. package/out/options/macOptions.js.map +1 -1
  29. package/out/targets/AppxCapabilities.d.ts +8 -0
  30. package/out/targets/AppxCapabilities.js +258 -0
  31. package/out/targets/AppxCapabilities.js.map +1 -0
  32. package/out/targets/AppxTarget.d.ts +1 -0
  33. package/out/targets/AppxTarget.js +32 -14
  34. package/out/targets/AppxTarget.js.map +1 -1
  35. package/out/targets/FpmTarget.js +3 -3
  36. package/out/targets/FpmTarget.js.map +1 -1
  37. package/out/targets/MsiWrappedTarget.js +4 -3
  38. package/out/targets/MsiWrappedTarget.js.map +1 -1
  39. package/out/targets/appimage/AppImageTarget.d.ts +16 -0
  40. package/out/targets/{AppImageTarget.js → appimage/AppImageTarget.js} +65 -28
  41. package/out/targets/appimage/AppImageTarget.js.map +1 -0
  42. package/out/targets/appimage/appImageUtil.d.ts +23 -0
  43. package/out/targets/appimage/appImageUtil.js +266 -0
  44. package/out/targets/appimage/appImageUtil.js.map +1 -0
  45. package/out/targets/appimage/appLauncher.d.ts +3 -0
  46. package/out/targets/appimage/appLauncher.js +91 -0
  47. package/out/targets/appimage/appLauncher.js.map +1 -0
  48. package/out/targets/archive.js +2 -2
  49. package/out/targets/archive.js.map +1 -1
  50. package/out/toolsets/linux.d.ts +9 -0
  51. package/out/toolsets/linux.js +68 -0
  52. package/out/toolsets/linux.js.map +1 -0
  53. package/out/toolsets/windows.d.ts +42 -0
  54. package/out/toolsets/windows.js +143 -0
  55. package/out/toolsets/windows.js.map +1 -0
  56. package/out/util/packageMetadata.js +9 -5
  57. package/out/util/packageMetadata.js.map +1 -1
  58. package/out/version.d.ts +1 -1
  59. package/out/version.js +1 -1
  60. package/out/version.js.map +1 -1
  61. package/out/winPackager.js +4 -3
  62. package/out/winPackager.js.map +1 -1
  63. package/package.json +9 -9
  64. package/scheme.json +78 -1
  65. package/templates/appx/appxmanifest.xml +1 -3
  66. package/templates/linux/after-install.tpl +1 -1
  67. package/out/targets/AppImageTarget.d.ts +0 -14
  68. package/out/targets/AppImageTarget.js.map +0 -1
  69. package/out/targets/tools.d.ts +0 -2
  70. package/out/targets/tools.js +0 -46
  71. package/out/targets/tools.js.map +0 -1
@@ -0,0 +1,23 @@
1
+ import { Arch } from "builder-util";
2
+ import { FileAssociation } from "../../options/FileAssociation";
3
+ import { IconInfo } from "../../platformPackager";
4
+ import { BlockMapDataHolder } from "builder-util-runtime";
5
+ interface Options {
6
+ productName: string;
7
+ productFilename: string;
8
+ executableName: string;
9
+ desktopEntry: string;
10
+ icons: IconInfo[];
11
+ license?: string | null;
12
+ fileAssociations: FileAssociation[];
13
+ compression?: "xz" | "lzo" | "zstd";
14
+ }
15
+ export interface AppImageBuilderOptions {
16
+ appDir: string;
17
+ stageDir: string;
18
+ arch: Arch;
19
+ output: string;
20
+ options: Options;
21
+ }
22
+ export declare function buildAppImage(opts: AppImageBuilderOptions): Promise<BlockMapDataHolder>;
23
+ export {};
@@ -0,0 +1,266 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildAppImage = buildAppImage;
4
+ const builder_util_1 = require("builder-util");
5
+ const fs = require("fs-extra");
6
+ const path = require("path");
7
+ const linux_1 = require("../../toolsets/linux");
8
+ const appLauncher_1 = require("./appLauncher");
9
+ const differentialUpdateInfoBuilder_1 = require("../differentialUpdateInfoBuilder");
10
+ const AppImageTarget_1 = require("./AppImageTarget");
11
+ async function buildAppImage(opts) {
12
+ const { stageDir, output, appDir, options, arch } = opts;
13
+ try {
14
+ await fs.remove(output);
15
+ // Write AppRun launcher and related files
16
+ await writeAppLauncherAndRelatedFiles(opts);
17
+ const { runtimeLibraries: libraries, runtime, mksquashfs } = await (0, linux_1.getAppImageTools)(arch);
18
+ await (0, builder_util_1.copyDir)(libraries, path.join(stageDir, "usr", "lib"));
19
+ // Copy app directory to stage
20
+ // mksquashfs doesn't support merging, so we copy the entire app dir
21
+ await (0, builder_util_1.copyDir)(appDir, stageDir);
22
+ const runtimeData = await fs.readFile(runtime);
23
+ // Create squashfs with offset for runtime
24
+ const args = [stageDir, output, "-offset", runtimeData.length.toString(), "-all-root", "-noappend", "-no-progress", "-quiet", "-no-xattrs", "-no-fragments"];
25
+ if (options.compression) {
26
+ args.push("-comp", options.compression);
27
+ if (options.compression === "xz") {
28
+ args.push("-Xdict-size", "100%", "-b", "1048576");
29
+ }
30
+ }
31
+ await (0, builder_util_1.exec)(mksquashfs, args, {
32
+ cwd: stageDir,
33
+ });
34
+ // Write runtime data at the beginning of the file
35
+ await writeRuntimeData(output, runtimeData);
36
+ // Make executable
37
+ await fs.chmod(output, 0o755);
38
+ // Append blockmap inside try block to ensure cleanup on failure
39
+ const updateInfo = await (0, differentialUpdateInfoBuilder_1.appendBlockmap)(output);
40
+ return updateInfo;
41
+ }
42
+ catch (error) {
43
+ // Clean up partial build on failure
44
+ await fs.remove(output).catch(() => { });
45
+ throw error;
46
+ }
47
+ }
48
+ async function writeRuntimeData(filePath, runtimeData) {
49
+ const fd = await fs.open(filePath, "r+");
50
+ try {
51
+ await fs.write(fd, runtimeData, 0, runtimeData.length, 0);
52
+ }
53
+ finally {
54
+ try {
55
+ await fs.close(fd);
56
+ }
57
+ catch (closeError) {
58
+ // Log but don't throw - preserve original error if any
59
+ builder_util_1.log.warn({ message: closeError.message, file: filePath }, `failed to close file descriptor`);
60
+ }
61
+ }
62
+ }
63
+ /**
64
+ * Escapes a string for safe use in shell scripts by wrapping in single quotes
65
+ * and escaping any single quotes within the string.
66
+ *
67
+ * This allows strings with spaces, special characters, etc. to be safely used.
68
+ */
69
+ function escapeShellString(str) {
70
+ // Escape single quotes by replacing ' with '\''
71
+ // Then wrap the whole string in single quotes
72
+ return `'${str.replace(/'/g, "'\\''")}'`;
73
+ }
74
+ /**
75
+ * Validates that critical executable/filename fields don't contain dangerous characters
76
+ * that could break paths or cause security issues even when escaped.
77
+ */
78
+ function validateCriticalPathString(str, fieldName) {
79
+ // Only reject characters that would break filesystem paths or cause severe issues
80
+ // Allow quotes, spaces, etc. since they can be escaped
81
+ if (/[`${}|&;<>\n\r\0]/.test(str) || str.includes("/") || str.includes("\\")) {
82
+ throw new builder_util_1.InvalidConfigurationError(`${fieldName} contains characters that cannot be safely used in file paths: ${str}. ` +
83
+ `Please use only alphanumeric characters, hyphens, underscores, dots, spaces, and quotes.`);
84
+ }
85
+ }
86
+ async function writeAppLauncherAndRelatedFiles(opts) {
87
+ const { stageDir, options: { license, executableName, productFilename, productName, desktopEntry }, } = opts;
88
+ // Validate only critical path fields for severe path-breaking characters
89
+ // productName and productFilename can contain quotes, spaces, etc. - they'll be escaped
90
+ validateCriticalPathString(executableName, "executableName");
91
+ validateCriticalPathString(productFilename, "productFilename");
92
+ // Write desktop file
93
+ const desktopFileName = `${executableName}.desktop`;
94
+ await fs.writeFile(path.join(stageDir, desktopFileName), desktopEntry, { mode: 0o644 });
95
+ await (0, appLauncher_1.copyIcons)(opts);
96
+ const templateConfig = {
97
+ DesktopFileName: desktopFileName,
98
+ ExecutableName: executableName,
99
+ ProductName: productName,
100
+ ProductFilename: productFilename,
101
+ ResourceName: `appimagekit-${executableName}`,
102
+ };
103
+ const mimeTypeFile = await (0, appLauncher_1.copyMimeTypes)(opts);
104
+ if (mimeTypeFile) {
105
+ templateConfig.MimeTypeFile = mimeTypeFile;
106
+ }
107
+ let finalConfig = templateConfig;
108
+ // Copy license file if provided
109
+ if (license) {
110
+ // Validate license file exists
111
+ if (!(await (0, builder_util_1.exists)(license))) {
112
+ throw new builder_util_1.InvalidConfigurationError(`License file not found: ${license}`);
113
+ }
114
+ const licenseBaseName = path.basename(license);
115
+ const ext = path.extname(license).toLowerCase();
116
+ // Validate license filename for path safety
117
+ validateCriticalPathString(licenseBaseName, "licenseBaseName");
118
+ // Validate extension
119
+ if (![".txt", ".html"].includes(ext)) {
120
+ builder_util_1.log.warn({ license, expected: ".txt or .html" }, `license file has unexpected extension`);
121
+ }
122
+ await (0, builder_util_1.copyFile)(license, path.join(stageDir, licenseBaseName));
123
+ finalConfig = {
124
+ ...templateConfig,
125
+ EulaFile: licenseBaseName,
126
+ IsHtmlEula: ext === ".html",
127
+ };
128
+ }
129
+ const appRunContent = generateAppRunScript(finalConfig);
130
+ await fs.writeFile(path.join(stageDir, AppImageTarget_1.APP_RUN_ENTRYPOINT), appRunContent, { mode: 0o755 });
131
+ }
132
+ function hasEula(config) {
133
+ return "EulaFile" in config && typeof config.EulaFile === "string";
134
+ }
135
+ function generateAppRunScript(config) {
136
+ const eulaEnabled = hasEula(config);
137
+ return `#!/bin/bash
138
+ set -e
139
+
140
+ THIS="$0"
141
+ # http://stackoverflow.com/questions/3190818/
142
+ args=("$@")
143
+ NUMBER_OF_ARGS="$#"
144
+
145
+ if [ -z "$APPDIR" ] ; then
146
+ # Find the AppDir. It is the directory that contains AppRun.
147
+ # This assumes that this script resides inside the AppDir or a subdirectory.
148
+ # If this script is run inside an AppImage, then the AppImage runtime likely has already set $APPDIR
149
+ path="$(dirname "$(readlink -f "\${THIS}")")"
150
+ while [[ "$path" != "" && ! -e "$path/${AppImageTarget_1.APP_RUN_ENTRYPOINT}" ]]; do
151
+ path=\${path%/*}
152
+ done
153
+ APPDIR="$path"
154
+ fi
155
+
156
+ export PATH="\${APPDIR}:\${APPDIR}/usr/sbin:\${PATH}"
157
+ export XDG_DATA_DIRS="./share/:/usr/share/gnome:/usr/local/share/:/usr/share/:\${XDG_DATA_DIRS}"
158
+ export LD_LIBRARY_PATH="\${APPDIR}/usr/lib:\${LD_LIBRARY_PATH}"
159
+ export XDG_DATA_DIRS="\${APPDIR}"/usr/share/:"\${XDG_DATA_DIRS}":/usr/share/gnome/:/usr/local/share/:/usr/share/
160
+ export GSETTINGS_SCHEMA_DIR="\${APPDIR}/usr/share/glib-2.0/schemas:\${GSETTINGS_SCHEMA_DIR}"
161
+
162
+ BIN="$APPDIR/${config.ExecutableName}"
163
+
164
+ if [ -z "$APPIMAGE_EXIT_AFTER_INSTALL" ] ; then
165
+ trap atexit EXIT
166
+ fi
167
+
168
+ isEulaAccepted=1
169
+
170
+ atexit()
171
+ {
172
+ if [ $isEulaAccepted == 1 ] ; then
173
+ if [ $NUMBER_OF_ARGS -eq 0 ] ; then
174
+ exec "$BIN"
175
+ else
176
+ exec "$BIN" "\${args[@]}"
177
+ fi
178
+ fi
179
+ }
180
+
181
+ error()
182
+ {
183
+ if [ -x /usr/bin/zenity ] ; then
184
+ LD_LIBRARY_PATH="" zenity --error --text "\${1}" 2>/dev/null
185
+ elif [ -x /usr/bin/kdialog ] ; then
186
+ LD_LIBRARY_PATH="" kdialog --msgbox "\${1}" 2>/dev/null
187
+ elif [ -x /usr/bin/Xdialog ] ; then
188
+ LD_LIBRARY_PATH="" Xdialog --msgbox "\${1}" 2>/dev/null
189
+ else
190
+ echo "\${1}"
191
+ fi
192
+ exit 1
193
+ }
194
+
195
+ yesno()
196
+ {
197
+ TITLE=$1
198
+ TEXT=$2
199
+ if [ -x /usr/bin/zenity ] ; then
200
+ LD_LIBRARY_PATH="" zenity --question --title="$TITLE" --text="$TEXT" 2>/dev/null || exit 0
201
+ elif [ -x /usr/bin/kdialog ] ; then
202
+ LD_LIBRARY_PATH="" kdialog --title "$TITLE" --yesno "$TEXT" || exit 0
203
+ elif [ -x /usr/bin/Xdialog ] ; then
204
+ LD_LIBRARY_PATH="" Xdialog --title "$TITLE" --clear --yesno "$TEXT" 10 80 || exit 0
205
+ else
206
+ echo "zenity, kdialog, Xdialog missing. Skipping \${THIS}."
207
+ exit 0
208
+ fi
209
+ }
210
+
211
+ check_dep()
212
+ {
213
+ DEP=$1
214
+ if ! command -v "$DEP" &>/dev/null ; then
215
+ echo "$DEP is missing. Skipping \${THIS}."
216
+ exit 0
217
+ fi
218
+ }
219
+
220
+ if [ -z "$APPIMAGE" ] ; then
221
+ APPIMAGE="$APPDIR/${AppImageTarget_1.APP_RUN_ENTRYPOINT}"
222
+ # not running from within an AppImage; hence using the AppRun for Exec=
223
+ fi
224
+
225
+ ${eulaEnabled
226
+ ? `if [ -z "$APPIMAGE_SILENT_INSTALL" ] ; then
227
+ EULA_MARK_DIR="\${XDG_CONFIG_HOME:-$HOME/.config}/${config.ProductFilename}"
228
+ EULA_MARK_FILE="$EULA_MARK_DIR/eulaAccepted"
229
+ # show EULA only if desktop file doesn't exist
230
+ if [ ! -e "$EULA_MARK_FILE" ] ; then
231
+ if [ -x /usr/bin/zenity ] ; then
232
+ # on cancel simply exits and our trap handler launches app, so, $isEulaAccepted is set here to 0 and then to 1 if EULA accepted
233
+ isEulaAccepted=0
234
+ LD_LIBRARY_PATH="" zenity --text-info --title=${escapeShellString(config.ProductName)} --filename="$APPDIR/${config.EulaFile}" --ok-label=Agree --cancel-label=Disagree ${config.IsHtmlEula ? "--html" : ""}
235
+ elif [ -x /usr/bin/Xdialog ] ; then
236
+ isEulaAccepted=0
237
+ LD_LIBRARY_PATH="" Xdialog --title ${escapeShellString(config.ProductName)} --textbox "$APPDIR/${config.EulaFile}" 30 80 --ok-label Agree --cancel-label Disagree
238
+ elif [ -x /usr/bin/kdialog ] ; then
239
+ # 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
240
+ # in any case we pass labels text
241
+ isEulaAccepted=0
242
+ LD_LIBRARY_PATH="" kdialog --textbox "$APPDIR/${config.EulaFile}" --yes-label Agree --cancel-label "Disagree"
243
+ fi
244
+
245
+ case $? in
246
+ 0)
247
+ isEulaAccepted=1
248
+ echo "License accepted"
249
+ mkdir -p "$EULA_MARK_DIR"
250
+ touch "$EULA_MARK_FILE"
251
+ ;;
252
+ 1)
253
+ echo "License not accepted"
254
+ exit 0
255
+ ;;
256
+ -1)
257
+ echo "An unexpected error has occurred."
258
+ isEulaAccepted=1
259
+ ;;
260
+ esac
261
+ fi
262
+ fi`
263
+ : ""}
264
+ `;
265
+ }
266
+ //# sourceMappingURL=appImageUtil.js.map
@@ -0,0 +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\"\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 compression?: \"xz\" | \"lzo\" | \"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 buildAppImage(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(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 if (options.compression === \"xz\") {\n args.push(\"-Xdict-size\", \"100%\", \"-b\", \"1048576\")\n }\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 executable/filename fields don't contain dangerous characters\n * that could break paths or cause security issues even when escaped.\n */\nfunction validateCriticalPathString(str: string, fieldName: string): void {\n // Only reject characters that would break filesystem paths or cause severe issues\n // Allow quotes, spaces, etc. since they can be escaped\n if (/[`${}|&;<>\\n\\r\\0]/.test(str) || str.includes(\"/\") || str.includes(\"\\\\\")) {\n throw new InvalidConfigurationError(\n `${fieldName} contains characters that cannot be safely used in file paths: ${str}. ` +\n `Please use only alphanumeric characters, hyphens, underscores, dots, spaces, and quotes.`\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 // Validate only critical path fields for severe path-breaking characters\n // productName and productFilename can contain quotes, spaces, etc. - they'll be escaped\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(opts)\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\ntype AppRunScriptBase = {\n ExecutableName: string\n DesktopFileName: string\n ProductFilename: string\n ProductName: string\n ResourceName: string\n MimeTypeFile?: string\n}\n\ntype AppRunScriptWithEula = AppRunScriptBase & {\n EulaFile: string\n IsHtmlEula: boolean\n}\n\ntype AppRunScript = AppRunScriptBase | AppRunScriptWithEula\n\nfunction hasEula(config: AppRunScript): config is AppRunScriptWithEula {\n return \"EulaFile\" in config && typeof config.EulaFile === \"string\"\n}\n\nfunction generateAppRunScript(config: AppRunScript): string {\n const eulaEnabled = hasEula(config)\n\n return `#!/bin/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\nexport PATH=\"\\${APPDIR}:\\${APPDIR}/usr/sbin:\\${PATH}\"\nexport XDG_DATA_DIRS=\"./share/:/usr/share/gnome:/usr/local/share/:/usr/share/:\\${XDG_DATA_DIRS}\"\nexport LD_LIBRARY_PATH=\"\\${APPDIR}/usr/lib:\\${LD_LIBRARY_PATH}\"\nexport XDG_DATA_DIRS=\"\\${APPDIR}\"/usr/share/:\"\\${XDG_DATA_DIRS}\":/usr/share/gnome/:/usr/local/share/:/usr/share/\nexport GSETTINGS_SCHEMA_DIR=\"\\${APPDIR}/usr/share/glib-2.0/schemas:\\${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\natexit()\n{\n if [ $isEulaAccepted == 1 ] ; then\n if [ $NUMBER_OF_ARGS -eq 0 ] ; then\n exec \"$BIN\"\n else\n exec \"$BIN\" \"\\${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"]}
@@ -0,0 +1,3 @@
1
+ import { AppImageBuilderOptions } from "./appImageUtil";
2
+ export declare function copyIcons(options: AppImageBuilderOptions): Promise<void>;
3
+ export declare function copyMimeTypes(options: AppImageBuilderOptions): Promise<string | null>;
@@ -0,0 +1,91 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.copyIcons = copyIcons;
4
+ exports.copyMimeTypes = copyMimeTypes;
5
+ const path = require("path");
6
+ const fs = require("fs-extra");
7
+ const builder_util_1 = require("builder-util");
8
+ const ICON_DIR_RELATIVE_PATH = "usr/share/icons/hicolor";
9
+ const MIME_TYPE_DIR_RELATIVE_PATH = "usr/share/mime";
10
+ /**
11
+ * Escapes special XML characters to prevent injection
12
+ */
13
+ function xmlEscape(str) {
14
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&apos;");
15
+ }
16
+ async function copyIcons(options) {
17
+ const { stageDir, options: configuration } = options;
18
+ const iconCommonDir = path.join(stageDir, ICON_DIR_RELATIVE_PATH);
19
+ await fs.ensureDir(iconCommonDir);
20
+ const icons = configuration.icons;
21
+ if (!icons || icons.length === 0) {
22
+ throw new Error("At least one icon is required for AppImage");
23
+ }
24
+ const iconExtWithDot = path.extname(icons[0].file);
25
+ const iconFileName = `${configuration.executableName}${iconExtWithDot}`;
26
+ const maxIconIndex = icons.length - 1;
27
+ const iconInfoList = icons.map(icon => {
28
+ if (path.extname(icon.file) !== iconExtWithDot) {
29
+ throw new Error(`All icons must have the same extension: expected ${iconExtWithDot}, but got ${icon.file}`);
30
+ }
31
+ let iconSizeDir;
32
+ if (iconExtWithDot === ".svg") {
33
+ // SVG icons go in scalable/apps directory per freedesktop icon theme spec
34
+ iconSizeDir = "scalable/apps";
35
+ }
36
+ else {
37
+ iconSizeDir = `${icon.size}x${icon.size}/apps`;
38
+ }
39
+ const iconRelativeToStageFile = path.join(ICON_DIR_RELATIVE_PATH, iconSizeDir, iconFileName);
40
+ const iconDir = path.join(iconCommonDir, iconSizeDir);
41
+ const iconFile = path.join(iconDir, iconFileName);
42
+ return { icon, iconDir, iconFile, iconRelativeToStageFile };
43
+ });
44
+ await Promise.all(iconInfoList.map(async ({ icon, iconDir, iconFile }) => {
45
+ await fs.ensureDir(iconDir);
46
+ await (0, builder_util_1.copyOrLinkFile)(icon.file, iconFile);
47
+ }));
48
+ // Create symlinks for the last (largest) icon
49
+ const { iconRelativeToStageFile } = iconInfoList[maxIconIndex];
50
+ await fs.symlink(iconRelativeToStageFile, path.join(stageDir, iconFileName));
51
+ await fs.symlink(iconRelativeToStageFile, path.join(stageDir, ".DirIcon"));
52
+ }
53
+ async function copyMimeTypes(options) {
54
+ const { stageDir, options: { fileAssociations, productName, executableName }, } = options;
55
+ if (!fileAssociations || fileAssociations.length === 0) {
56
+ return null;
57
+ }
58
+ const mimeTypeParts = [];
59
+ for (const fileAssociation of fileAssociations) {
60
+ if (!fileAssociation.mimeType) {
61
+ continue;
62
+ }
63
+ // XML-escape to prevent injection
64
+ mimeTypeParts.push(`<mime-type type="${xmlEscape(fileAssociation.mimeType)}">`);
65
+ mimeTypeParts.push(` <comment>${xmlEscape(productName)} document</comment>`);
66
+ // Handle extension(s)
67
+ const extensions = Array.isArray(fileAssociation.ext) ? fileAssociation.ext : [fileAssociation.ext];
68
+ for (const ext of extensions) {
69
+ // Validate extension doesn't contain dangerous characters
70
+ if (!/^[a-zA-Z0-9_-]+$/.test(ext)) {
71
+ builder_util_1.log.warn({ extension: ext }, `file extension contains unexpected characters and may not be supported`);
72
+ }
73
+ mimeTypeParts.push(` <glob pattern="*.${xmlEscape(ext)}"/>`);
74
+ }
75
+ mimeTypeParts.push(' <generic-icon name="x-office-document"/>');
76
+ mimeTypeParts.push("</mime-type>");
77
+ }
78
+ // If no mime-types were generated, return null
79
+ if (mimeTypeParts.length === 0) {
80
+ return null;
81
+ }
82
+ const mimeTypeDir = path.join(stageDir, MIME_TYPE_DIR_RELATIVE_PATH);
83
+ const fileName = `${executableName}.xml`;
84
+ const mimeTypeFile = path.join(mimeTypeDir, fileName);
85
+ await fs.ensureDir(mimeTypeDir);
86
+ const xmlContent = ['<?xml version="1.0"?>', '<mime-info xmlns="http://www.freedesktop.org/standards/shared-mime-info">', ...mimeTypeParts, "</mime-info>"].join("\n");
87
+ // Use 0o644 (rw-r--r--) instead of 0o666 to avoid world-writable permissions
88
+ await fs.writeFile(mimeTypeFile, xmlContent, { mode: 0o644 });
89
+ return path.join(MIME_TYPE_DIR_RELATIVE_PATH, fileName);
90
+ }
91
+ //# sourceMappingURL=appLauncher.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"appLauncher.js","sourceRoot":"","sources":["../../../src/targets/appimage/appLauncher.ts"],"names":[],"mappings":"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","sourcesContent":["import * as path from \"path\"\nimport * as fs from \"fs-extra\"\nimport { copyOrLinkFile, log } from \"builder-util\"\nimport { AppImageBuilderOptions } from \"./appImageUtil\"\n\nconst ICON_DIR_RELATIVE_PATH = \"usr/share/icons/hicolor\"\nconst MIME_TYPE_DIR_RELATIVE_PATH = \"usr/share/mime\"\n\n/**\n * Escapes special XML characters to prevent injection\n */\nfunction xmlEscape(str: string): string {\n return str.replace(/&/g, \"&amp;\").replace(/</g, \"&lt;\").replace(/>/g, \"&gt;\").replace(/\"/g, \"&quot;\").replace(/'/g, \"&apos;\")\n}\n\nexport async function copyIcons(options: AppImageBuilderOptions): Promise<void> {\n const { stageDir, options: configuration } = options\n const iconCommonDir = path.join(stageDir, ICON_DIR_RELATIVE_PATH)\n\n await fs.ensureDir(iconCommonDir)\n\n const icons = configuration.icons\n if (!icons || icons.length === 0) {\n throw new Error(\"At least one icon is required for AppImage\")\n }\n\n const iconExtWithDot = path.extname(icons[0].file)\n const iconFileName = `${configuration.executableName}${iconExtWithDot}`\n const maxIconIndex = icons.length - 1\n\n const iconInfoList = icons.map(icon => {\n if (path.extname(icon.file) !== iconExtWithDot) {\n throw new Error(`All icons must have the same extension: expected ${iconExtWithDot}, but got ${icon.file}`)\n }\n let iconSizeDir: string\n\n if (iconExtWithDot === \".svg\") {\n // SVG icons go in scalable/apps directory per freedesktop icon theme spec\n iconSizeDir = \"scalable/apps\"\n } else {\n iconSizeDir = `${icon.size}x${icon.size}/apps`\n }\n\n const iconRelativeToStageFile = path.join(ICON_DIR_RELATIVE_PATH, iconSizeDir, iconFileName)\n const iconDir = path.join(iconCommonDir, iconSizeDir)\n const iconFile = path.join(iconDir, iconFileName)\n return { icon, iconDir, iconFile, iconRelativeToStageFile }\n })\n await Promise.all(\n iconInfoList.map(async ({ icon, iconDir, iconFile }) => {\n await fs.ensureDir(iconDir)\n await copyOrLinkFile(icon.file, iconFile)\n })\n )\n // Create symlinks for the last (largest) icon\n const { iconRelativeToStageFile } = iconInfoList[maxIconIndex]\n await fs.symlink(iconRelativeToStageFile, path.join(stageDir, iconFileName))\n await fs.symlink(iconRelativeToStageFile, path.join(stageDir, \".DirIcon\"))\n}\n\nexport async function copyMimeTypes(options: AppImageBuilderOptions): Promise<string | null> {\n const {\n stageDir,\n options: { fileAssociations, productName, executableName },\n } = options\n\n if (!fileAssociations || fileAssociations.length === 0) {\n return null\n }\n\n const mimeTypeParts: string[] = []\n\n for (const fileAssociation of fileAssociations) {\n if (!fileAssociation.mimeType) {\n continue\n }\n\n // XML-escape to prevent injection\n mimeTypeParts.push(`<mime-type type=\"${xmlEscape(fileAssociation.mimeType)}\">`)\n mimeTypeParts.push(` <comment>${xmlEscape(productName)} document</comment>`)\n\n // Handle extension(s)\n const extensions = Array.isArray(fileAssociation.ext) ? fileAssociation.ext : [fileAssociation.ext]\n\n for (const ext of extensions) {\n // Validate extension doesn't contain dangerous characters\n if (!/^[a-zA-Z0-9_-]+$/.test(ext)) {\n log.warn({ extension: ext }, `file extension contains unexpected characters and may not be supported`)\n }\n mimeTypeParts.push(` <glob pattern=\"*.${xmlEscape(ext)}\"/>`)\n }\n\n mimeTypeParts.push(' <generic-icon name=\"x-office-document\"/>')\n mimeTypeParts.push(\"</mime-type>\")\n }\n\n // If no mime-types were generated, return null\n if (mimeTypeParts.length === 0) {\n return null\n }\n\n const mimeTypeDir = path.join(stageDir, MIME_TYPE_DIR_RELATIVE_PATH)\n const fileName = `${executableName}.xml`\n const mimeTypeFile = path.join(mimeTypeDir, fileName)\n\n await fs.ensureDir(mimeTypeDir)\n\n const xmlContent = ['<?xml version=\"1.0\"?>', '<mime-info xmlns=\"http://www.freedesktop.org/standards/shared-mime-info\">', ...mimeTypeParts, \"</mime-info>\"].join(\"\\n\")\n\n // Use 0o644 (rw-r--r--) instead of 0o666 to avoid world-writable permissions\n await fs.writeFile(mimeTypeFile, xmlContent, { mode: 0o644 })\n\n return path.join(MIME_TYPE_DIR_RELATIVE_PATH, fileName)\n}\n"]}
@@ -8,7 +8,7 @@ const builder_util_1 = require("builder-util");
8
8
  const fs_extra_1 = require("fs-extra");
9
9
  const path = require("path");
10
10
  const tar_1 = require("tar");
11
- const tools_1 = require("./tools");
11
+ const linux_1 = require("../toolsets/linux");
12
12
  /** @internal */
13
13
  async function tar(compression, format, outFile, dirToArchive, isMacApp, tempDirManager) {
14
14
  const tarFile = await tempDirManager.getTempFile({ suffix: ".tar" });
@@ -33,7 +33,7 @@ async function tar(compression, format, outFile, dirToArchive, isMacApp, tempDir
33
33
  // noinspection SpellCheckingInspection
34
34
  let lzipPath = "lzip";
35
35
  if (process.platform === "darwin") {
36
- lzipPath = path.join(await (0, tools_1.getLinuxToolsPath)(), "bin", lzipPath);
36
+ lzipPath = path.join(await (0, linux_1.getLinuxToolsPath)(), "bin", lzipPath);
37
37
  }
38
38
  await (0, builder_util_1.exec)(lzipPath, [compression === "store" ? "-1" : "-9", "--keep" /* keep (don't delete) input files */, tarFile]);
39
39
  // bloody lzip creates file in the same dir where input file with postfix `.lz`, option --output doesn't work
@@ -1 +1 @@
1
- {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/targets/archive.ts"],"names":[],"mappings":"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","sourcesContent":["import { debug7z, exec, exists, getPath7za, log, statOrNull, unlinkIfExists } from \"builder-util\"\nimport { move } from \"fs-extra\"\nimport * as path from \"path\"\nimport { create } from \"tar\"\nimport { TmpDir } from \"temp-file\"\nimport { CompressionLevel } from \"../core\"\nimport { getLinuxToolsPath } from \"./tools\"\nimport { TarOptionsWithAliasesAsync } from \"tar/dist/commonjs/options\"\n\n/** @internal */\nexport async function tar(compression: CompressionLevel | any, format: string, outFile: string, dirToArchive: string, isMacApp: boolean, tempDirManager: TmpDir): Promise<void> {\n const tarFile = await tempDirManager.getTempFile({ suffix: \".tar\" })\n const tarArgs: TarOptionsWithAliasesAsync = {\n file: tarFile,\n portable: true,\n cwd: dirToArchive,\n prefix: path.basename(outFile, `.${format}`),\n }\n let tarDirectory = \".\"\n if (isMacApp) {\n delete tarArgs.prefix\n tarArgs.cwd = path.dirname(dirToArchive)\n tarDirectory = path.basename(dirToArchive)\n }\n\n await Promise.all([\n create(tarArgs, [tarDirectory]),\n // remove file before - 7z doesn't overwrite file, but update\n unlinkIfExists(outFile),\n ])\n\n if (format === \"tar.lz\") {\n // noinspection SpellCheckingInspection\n let lzipPath = \"lzip\"\n if (process.platform === \"darwin\") {\n lzipPath = path.join(await getLinuxToolsPath(), \"bin\", lzipPath)\n }\n await exec(lzipPath, [compression === \"store\" ? \"-1\" : \"-9\", \"--keep\" /* keep (don't delete) input files */, tarFile])\n // bloody lzip creates file in the same dir where input file with postfix `.lz`, option --output doesn't work\n await move(`${tarFile}.lz`, outFile)\n return\n }\n\n const args = compute7zCompressArgs(format === \"tar.xz\" ? \"xz\" : format === \"tar.bz2\" ? \"bzip2\" : \"gzip\", {\n isRegularFile: true,\n method: \"DEFAULT\",\n compression,\n })\n args.push(outFile, tarFile)\n await exec(\n await getPath7za(),\n args,\n {\n cwd: path.dirname(dirToArchive),\n },\n debug7z.enabled\n )\n}\n\nexport interface ArchiveOptions {\n compression?: CompressionLevel | null\n\n /**\n * @default false\n */\n withoutDir?: boolean\n\n /**\n * @default true\n */\n solid?: boolean\n\n /**\n * @default true\n */\n isArchiveHeaderCompressed?: boolean\n\n dictSize?: number\n excluded?: Array<string> | null\n\n // DEFAULT allows to disable custom logic and do not pass method switch at all\n method?: \"Copy\" | \"LZMA\" | \"Deflate\" | \"DEFAULT\"\n\n isRegularFile?: boolean\n}\n\nexport function compute7zCompressArgs(format: string, options: ArchiveOptions = {}) {\n let storeOnly = options.compression === \"store\"\n const args = debug7zArgs(\"a\")\n\n let isLevelSet = false\n if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {\n storeOnly = false\n args.push(`-mx=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)\n isLevelSet = true\n }\n\n const isZip = format === \"zip\"\n if (!storeOnly) {\n if (isZip && options.compression === \"maximum\") {\n // http://superuser.com/a/742034\n args.push(\"-mfb=258\", \"-mpass=15\")\n }\n\n if (!isLevelSet) {\n // https://github.com/electron-userland/electron-builder/pull/3032\n args.push(\"-mx=\" + (!isZip || options.compression === \"maximum\" ? \"9\" : \"7\"))\n }\n }\n\n if (options.dictSize != null) {\n args.push(`-md=${options.dictSize}m`)\n }\n\n // https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm#7Z\n // https://stackoverflow.com/questions/27136783/7zip-produces-different-output-from-identical-input\n // tc and ta are off by default, but to be sure, we explicitly set it to off\n // disable \"Stores NTFS timestamps for files: Modification time, Creation time, Last access time.\" to produce the same archive for the same data\n if (!options.isRegularFile) {\n args.push(\"-mtc=off\")\n }\n\n if (format === \"7z\" || format.endsWith(\".7z\")) {\n if (options.solid === false) {\n args.push(\"-ms=off\")\n }\n\n if (options.isArchiveHeaderCompressed === false) {\n args.push(\"-mhc=off\")\n }\n\n // https://www.7-zip.org/7z.html\n // Filters: BCJ, BCJ2, ARM, ARMT, IA64, PPC, SPARC, ...\n if (process.env.ELECTRON_BUILDER_7Z_FILTER) {\n args.push(`-mf=${process.env.ELECTRON_BUILDER_7Z_FILTER}`)\n }\n\n // args valid only for 7z\n // -mtm=off disable \"Stores last Modified timestamps for files.\"\n args.push(\"-mtm=off\", \"-mta=off\")\n }\n\n if (options.method != null) {\n if (options.method !== \"DEFAULT\") {\n args.push(`-mm=${options.method}`)\n }\n } else if (isZip || storeOnly) {\n args.push(`-mm=${storeOnly ? \"Copy\" : \"Deflate\"}`)\n }\n\n if (isZip) {\n // -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols.\n // because default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols.\n // but archive should be the same regardless where produced\n args.push(\"-mcu\")\n }\n return args\n}\n\nexport function computeZipCompressArgs(options: ArchiveOptions = {}) {\n let storeOnly = options.compression === \"store\"\n // do not deref symlinks\n const args = [\"-q\", \"-r\", \"-y\"]\n if (debug7z.enabled) {\n args.push(\"-v\")\n }\n\n if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {\n storeOnly = false\n args.push(`-${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)\n } else if (!storeOnly) {\n // https://github.com/electron-userland/electron-builder/pull/3032\n args.push(\"-\" + (options.compression === \"maximum\" ? \"9\" : \"7\"))\n }\n\n if (options.dictSize != null) {\n log.warn({ distSize: options.dictSize }, `ignoring unsupported option`)\n }\n\n // do not save extra file attributes (Extended Attributes on OS/2, uid/gid and file times on Unix)\n if (!options.isRegularFile) {\n args.push(\"-X\")\n }\n\n if (options.method != null) {\n if (options.method !== \"DEFAULT\") {\n log.warn({ method: options.method }, `ignoring unsupported option`)\n }\n } else {\n args.push(\"-Z\", storeOnly ? \"store\" : \"deflate\")\n }\n return args\n}\n\n// 7z is very fast, so, use ultra compression\n/** @internal */\nexport async function archive(format: string, outFile: string, dirToArchive: string, options: ArchiveOptions = {}): Promise<string> {\n const outFileStat = await statOrNull(outFile)\n const dirStat = await statOrNull(dirToArchive)\n if (outFileStat && dirStat && outFileStat.mtime > dirStat.mtime) {\n log.info({ reason: \"Archive file is up to date\", outFile }, `skipped archiving`)\n return outFile\n }\n let use7z = true\n if (process.platform === \"darwin\" && format === \"zip\" && dirToArchive.normalize(\"NFC\") !== dirToArchive) {\n log.warn({ reason: \"7z doesn't support NFD-normalized filenames\" }, `using zip`)\n use7z = false\n }\n const args = use7z ? compute7zCompressArgs(format, options) : computeZipCompressArgs(options)\n // remove file before - 7z and zip doesn't overwrite file, but update\n await unlinkIfExists(outFile)\n\n args.push(outFile, options.withoutDir ? \".\" : path.basename(dirToArchive))\n if (options.excluded != null) {\n for (const mask of options.excluded) {\n args.push(use7z ? `-xr!${mask}` : `-x${mask}`)\n }\n }\n\n try {\n const binary = use7z ? await getPath7za() : \"zip\"\n await exec(\n binary,\n args,\n {\n cwd: options.withoutDir ? dirToArchive : path.dirname(dirToArchive),\n },\n debug7z.enabled\n )\n } catch (e: any) {\n if (e.code === \"ENOENT\" && !(await exists(dirToArchive))) {\n throw new Error(`Cannot create archive: \"${dirToArchive}\" doesn't exist`)\n } else {\n throw e\n }\n }\n\n return outFile\n}\n\nfunction debug7zArgs(command: \"a\" | \"x\"): Array<string> {\n const args = [command, \"-bd\"]\n if (debug7z.enabled) {\n args.push(\"-bb\")\n }\n return args\n}\n"]}
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/targets/archive.ts"],"names":[],"mappings":"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","sourcesContent":["import { debug7z, exec, exists, getPath7za, log, statOrNull, unlinkIfExists } from \"builder-util\"\nimport { move } from \"fs-extra\"\nimport * as path from \"path\"\nimport { create } from \"tar\"\nimport { TmpDir } from \"temp-file\"\nimport { CompressionLevel } from \"../core\"\nimport { getLinuxToolsPath } from \"../toolsets/linux\"\nimport { TarOptionsWithAliasesAsync } from \"tar/dist/commonjs/options\"\n\n/** @internal */\nexport async function tar(compression: CompressionLevel | any, format: string, outFile: string, dirToArchive: string, isMacApp: boolean, tempDirManager: TmpDir): Promise<void> {\n const tarFile = await tempDirManager.getTempFile({ suffix: \".tar\" })\n const tarArgs: TarOptionsWithAliasesAsync = {\n file: tarFile,\n portable: true,\n cwd: dirToArchive,\n prefix: path.basename(outFile, `.${format}`),\n }\n let tarDirectory = \".\"\n if (isMacApp) {\n delete tarArgs.prefix\n tarArgs.cwd = path.dirname(dirToArchive)\n tarDirectory = path.basename(dirToArchive)\n }\n\n await Promise.all([\n create(tarArgs, [tarDirectory]),\n // remove file before - 7z doesn't overwrite file, but update\n unlinkIfExists(outFile),\n ])\n\n if (format === \"tar.lz\") {\n // noinspection SpellCheckingInspection\n let lzipPath = \"lzip\"\n if (process.platform === \"darwin\") {\n lzipPath = path.join(await getLinuxToolsPath(), \"bin\", lzipPath)\n }\n await exec(lzipPath, [compression === \"store\" ? \"-1\" : \"-9\", \"--keep\" /* keep (don't delete) input files */, tarFile])\n // bloody lzip creates file in the same dir where input file with postfix `.lz`, option --output doesn't work\n await move(`${tarFile}.lz`, outFile)\n return\n }\n\n const args = compute7zCompressArgs(format === \"tar.xz\" ? \"xz\" : format === \"tar.bz2\" ? \"bzip2\" : \"gzip\", {\n isRegularFile: true,\n method: \"DEFAULT\",\n compression,\n })\n args.push(outFile, tarFile)\n await exec(\n await getPath7za(),\n args,\n {\n cwd: path.dirname(dirToArchive),\n },\n debug7z.enabled\n )\n}\n\nexport interface ArchiveOptions {\n compression?: CompressionLevel | null\n\n /**\n * @default false\n */\n withoutDir?: boolean\n\n /**\n * @default true\n */\n solid?: boolean\n\n /**\n * @default true\n */\n isArchiveHeaderCompressed?: boolean\n\n dictSize?: number\n excluded?: Array<string> | null\n\n // DEFAULT allows to disable custom logic and do not pass method switch at all\n method?: \"Copy\" | \"LZMA\" | \"Deflate\" | \"DEFAULT\"\n\n isRegularFile?: boolean\n}\n\nexport function compute7zCompressArgs(format: string, options: ArchiveOptions = {}) {\n let storeOnly = options.compression === \"store\"\n const args = debug7zArgs(\"a\")\n\n let isLevelSet = false\n if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {\n storeOnly = false\n args.push(`-mx=${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)\n isLevelSet = true\n }\n\n const isZip = format === \"zip\"\n if (!storeOnly) {\n if (isZip && options.compression === \"maximum\") {\n // http://superuser.com/a/742034\n args.push(\"-mfb=258\", \"-mpass=15\")\n }\n\n if (!isLevelSet) {\n // https://github.com/electron-userland/electron-builder/pull/3032\n args.push(\"-mx=\" + (!isZip || options.compression === \"maximum\" ? \"9\" : \"7\"))\n }\n }\n\n if (options.dictSize != null) {\n args.push(`-md=${options.dictSize}m`)\n }\n\n // https://sevenzip.osdn.jp/chm/cmdline/switches/method.htm#7Z\n // https://stackoverflow.com/questions/27136783/7zip-produces-different-output-from-identical-input\n // tc and ta are off by default, but to be sure, we explicitly set it to off\n // disable \"Stores NTFS timestamps for files: Modification time, Creation time, Last access time.\" to produce the same archive for the same data\n if (!options.isRegularFile) {\n args.push(\"-mtc=off\")\n }\n\n if (format === \"7z\" || format.endsWith(\".7z\")) {\n if (options.solid === false) {\n args.push(\"-ms=off\")\n }\n\n if (options.isArchiveHeaderCompressed === false) {\n args.push(\"-mhc=off\")\n }\n\n // https://www.7-zip.org/7z.html\n // Filters: BCJ, BCJ2, ARM, ARMT, IA64, PPC, SPARC, ...\n if (process.env.ELECTRON_BUILDER_7Z_FILTER) {\n args.push(`-mf=${process.env.ELECTRON_BUILDER_7Z_FILTER}`)\n }\n\n // args valid only for 7z\n // -mtm=off disable \"Stores last Modified timestamps for files.\"\n args.push(\"-mtm=off\", \"-mta=off\")\n }\n\n if (options.method != null) {\n if (options.method !== \"DEFAULT\") {\n args.push(`-mm=${options.method}`)\n }\n } else if (isZip || storeOnly) {\n args.push(`-mm=${storeOnly ? \"Copy\" : \"Deflate\"}`)\n }\n\n if (isZip) {\n // -mcu switch: 7-Zip uses UTF-8, if there are non-ASCII symbols.\n // because default mode: 7-Zip uses UTF-8, if the local code page doesn't contain required symbols.\n // but archive should be the same regardless where produced\n args.push(\"-mcu\")\n }\n return args\n}\n\nexport function computeZipCompressArgs(options: ArchiveOptions = {}) {\n let storeOnly = options.compression === \"store\"\n // do not deref symlinks\n const args = [\"-q\", \"-r\", \"-y\"]\n if (debug7z.enabled) {\n args.push(\"-v\")\n }\n\n if (process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL != null) {\n storeOnly = false\n args.push(`-${process.env.ELECTRON_BUILDER_COMPRESSION_LEVEL}`)\n } else if (!storeOnly) {\n // https://github.com/electron-userland/electron-builder/pull/3032\n args.push(\"-\" + (options.compression === \"maximum\" ? \"9\" : \"7\"))\n }\n\n if (options.dictSize != null) {\n log.warn({ distSize: options.dictSize }, `ignoring unsupported option`)\n }\n\n // do not save extra file attributes (Extended Attributes on OS/2, uid/gid and file times on Unix)\n if (!options.isRegularFile) {\n args.push(\"-X\")\n }\n\n if (options.method != null) {\n if (options.method !== \"DEFAULT\") {\n log.warn({ method: options.method }, `ignoring unsupported option`)\n }\n } else {\n args.push(\"-Z\", storeOnly ? \"store\" : \"deflate\")\n }\n return args\n}\n\n// 7z is very fast, so, use ultra compression\n/** @internal */\nexport async function archive(format: string, outFile: string, dirToArchive: string, options: ArchiveOptions = {}): Promise<string> {\n const outFileStat = await statOrNull(outFile)\n const dirStat = await statOrNull(dirToArchive)\n if (outFileStat && dirStat && outFileStat.mtime > dirStat.mtime) {\n log.info({ reason: \"Archive file is up to date\", outFile }, `skipped archiving`)\n return outFile\n }\n let use7z = true\n if (process.platform === \"darwin\" && format === \"zip\" && dirToArchive.normalize(\"NFC\") !== dirToArchive) {\n log.warn({ reason: \"7z doesn't support NFD-normalized filenames\" }, `using zip`)\n use7z = false\n }\n const args = use7z ? compute7zCompressArgs(format, options) : computeZipCompressArgs(options)\n // remove file before - 7z and zip doesn't overwrite file, but update\n await unlinkIfExists(outFile)\n\n args.push(outFile, options.withoutDir ? \".\" : path.basename(dirToArchive))\n if (options.excluded != null) {\n for (const mask of options.excluded) {\n args.push(use7z ? `-xr!${mask}` : `-x${mask}`)\n }\n }\n\n try {\n const binary = use7z ? await getPath7za() : \"zip\"\n await exec(\n binary,\n args,\n {\n cwd: options.withoutDir ? dirToArchive : path.dirname(dirToArchive),\n },\n debug7z.enabled\n )\n } catch (e: any) {\n if (e.code === \"ENOENT\" && !(await exists(dirToArchive))) {\n throw new Error(`Cannot create archive: \"${dirToArchive}\" doesn't exist`)\n } else {\n throw e\n }\n }\n\n return outFile\n}\n\nfunction debug7zArgs(command: \"a\" | \"x\"): Array<string> {\n const args = [command, \"-bd\"]\n if (debug7z.enabled) {\n args.push(\"-bb\")\n }\n return args\n}\n"]}
@@ -0,0 +1,9 @@
1
+ import { Arch } from "builder-util";
2
+ export declare function getLinuxToolsPath(): Promise<string>;
3
+ export declare function getFpmPath(): Promise<string>;
4
+ export declare function getAppImageTools(targetArch: Arch): Promise<{
5
+ mksquashfs: string;
6
+ desktopFileValidate: string;
7
+ runtime: string;
8
+ runtimeLibraries: string;
9
+ }>;
@@ -0,0 +1,68 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.getLinuxToolsPath = getLinuxToolsPath;
4
+ exports.getFpmPath = getFpmPath;
5
+ exports.getAppImageTools = getAppImageTools;
6
+ const builder_util_1 = require("builder-util");
7
+ const path = require("path");
8
+ const binDownload_1 = require("../binDownload");
9
+ // It's just easier to copy the map of checksums here rather than adding them to within each if-statement. Also, easy copy-paste from the releases page
10
+ const fpmChecksums = {
11
+ "fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z": "0n3BG/Xz1T5YIsoNNTG1bBege9E8A7rym5e3mfzHSHbiSiTS44v6GIHW4amDQk1Y5dtKtWXVq7FwjdmAf3kmMg==",
12
+ "fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z": "wPX3UheBznIlAXduM22W/d27i+DZVIB/MYnY5eh/qLeEEASZqHJWgN+pIckz3jT0dP37g1SQCikXXfsgxtMSPA==",
13
+ "fpm-1.17.0-ruby-3.4.3-linux-amd64.7z": "7miGWr6dfJSzXDD9ALqkwxvGACp7s7GR50NPcU0YwzbJL825H1SLwGJSGME+v57BxDI2xac47gFEkRZf5u9EtA==",
14
+ "fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z": "moRNjg6Q2iSXpkrm5sGNL2F6KilGNPagbefxhtr3VEqvAUSg2k2pMLr5xXUo0L4rZ4V+uETbwmbDCpeO3pmLyQ==",
15
+ "fpm-1.17.0-ruby-3.4.3-linux-i386.7z": "UPzsXhkW2T7+oHSKgFsZsFUxxmPC9lNZHsQbT+OeoTbIGsb6+qf3m7c6uP0XvRFnJiu3MM3lE1xAWQOctvajWA==",
16
+ };
17
+ function getLinuxToolsPath() {
18
+ return (0, binDownload_1.getBinFromUrl)("linux-tools-mac-10.12.3", "linux-tools-mac-10.12.3.7z", "SQ8fqIRVXuQVWnVgaMTDWyf2TLAJjJYw3tRSqQJECmgF6qdM7Kogfa6KD49RbGzzMYIFca9Uw3MdsxzOPRWcYw==");
19
+ }
20
+ async function getFpmPath() {
21
+ if (process.env.CUSTOM_FPM_PATH != null) {
22
+ return path.resolve(process.env.CUSTOM_FPM_PATH);
23
+ }
24
+ const exec = "fpm";
25
+ if (process.platform === "win32" || process.env.USE_SYSTEM_FPM === "true") {
26
+ return exec;
27
+ }
28
+ const getKey = () => {
29
+ if (process.platform === "linux") {
30
+ if (process.arch == "x64") {
31
+ return "fpm-1.17.0-ruby-3.4.3-linux-amd64.7z";
32
+ }
33
+ else if (process.arch === "arm64") {
34
+ return "fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z";
35
+ }
36
+ return "fpm-1.17.0-ruby-3.4.3-linux-i386.7z";
37
+ }
38
+ // darwin arm64
39
+ if (process.arch === "arm64") {
40
+ return "fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z";
41
+ }
42
+ return "fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z";
43
+ };
44
+ const filename = getKey();
45
+ const fpmPath = await (0, binDownload_1.getBinFromUrl)("fpm@2.1.4", filename, fpmChecksums[filename]);
46
+ return path.join(fpmPath, exec);
47
+ }
48
+ async function getAppImageTools(targetArch) {
49
+ var _a;
50
+ const override = (_a = process.env.APPIMAGE_TOOLS_PATH) === null || _a === void 0 ? void 0 : _a.trim();
51
+ const artifactPath = override ||
52
+ (await (0, binDownload_1.downloadArtifact)({
53
+ releaseName: "appimage@1.0.2",
54
+ filenameWithExt: "appimage-tools-runtime-20251108.tar.gz",
55
+ checksums: {
56
+ "appimage-tools-runtime-20251108.tar.gz": "a784a8c26331ec2e945c23d6bdb14af5c9df27f5939825d84b8709c61dc81eb0",
57
+ },
58
+ githubOrgRepo: "electron-userland/electron-builder-binaries",
59
+ }));
60
+ const runtimeArch = targetArch === builder_util_1.Arch.armv7l ? "arm32" : targetArch === builder_util_1.Arch.arm64 ? "arm64" : targetArch === builder_util_1.Arch.ia32 ? "ia32" : "x64";
61
+ return {
62
+ mksquashfs: path.join(artifactPath, "mksquashfs"),
63
+ desktopFileValidate: path.join(artifactPath, "desktop-file-validate"),
64
+ runtime: path.join(artifactPath, "runtimes", `runtime-${runtimeArch}`),
65
+ runtimeLibraries: path.join(artifactPath, "lib", runtimeArch),
66
+ };
67
+ }
68
+ //# sourceMappingURL=linux.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"linux.js","sourceRoot":"","sources":["../../src/toolsets/linux.ts"],"names":[],"mappings":"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","sourcesContent":["import { Arch } from \"builder-util\"\nimport * as path from \"path\"\nimport { downloadArtifact, getBinFromUrl } from \"../binDownload\"\n\n// It's just easier to copy the map of checksums here rather than adding them to within each if-statement. Also, easy copy-paste from the releases page\nconst fpmChecksums = {\n \"fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z\": \"0n3BG/Xz1T5YIsoNNTG1bBege9E8A7rym5e3mfzHSHbiSiTS44v6GIHW4amDQk1Y5dtKtWXVq7FwjdmAf3kmMg==\",\n \"fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z\": \"wPX3UheBznIlAXduM22W/d27i+DZVIB/MYnY5eh/qLeEEASZqHJWgN+pIckz3jT0dP37g1SQCikXXfsgxtMSPA==\",\n \"fpm-1.17.0-ruby-3.4.3-linux-amd64.7z\": \"7miGWr6dfJSzXDD9ALqkwxvGACp7s7GR50NPcU0YwzbJL825H1SLwGJSGME+v57BxDI2xac47gFEkRZf5u9EtA==\",\n \"fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z\": \"moRNjg6Q2iSXpkrm5sGNL2F6KilGNPagbefxhtr3VEqvAUSg2k2pMLr5xXUo0L4rZ4V+uETbwmbDCpeO3pmLyQ==\",\n \"fpm-1.17.0-ruby-3.4.3-linux-i386.7z\": \"UPzsXhkW2T7+oHSKgFsZsFUxxmPC9lNZHsQbT+OeoTbIGsb6+qf3m7c6uP0XvRFnJiu3MM3lE1xAWQOctvajWA==\",\n} as const\n\nexport function getLinuxToolsPath() {\n return getBinFromUrl(\"linux-tools-mac-10.12.3\", \"linux-tools-mac-10.12.3.7z\", \"SQ8fqIRVXuQVWnVgaMTDWyf2TLAJjJYw3tRSqQJECmgF6qdM7Kogfa6KD49RbGzzMYIFca9Uw3MdsxzOPRWcYw==\")\n}\n\nexport async function getFpmPath() {\n if (process.env.CUSTOM_FPM_PATH != null) {\n return path.resolve(process.env.CUSTOM_FPM_PATH)\n }\n const exec = \"fpm\"\n if (process.platform === \"win32\" || process.env.USE_SYSTEM_FPM === \"true\") {\n return exec\n }\n const getKey = () => {\n if (process.platform === \"linux\") {\n if (process.arch == \"x64\") {\n return \"fpm-1.17.0-ruby-3.4.3-linux-amd64.7z\"\n } else if (process.arch === \"arm64\") {\n return \"fpm-1.17.0-ruby-3.4.3-linux-arm64v8.7z\"\n }\n return \"fpm-1.17.0-ruby-3.4.3-linux-i386.7z\"\n }\n // darwin arm64\n if (process.arch === \"arm64\") {\n return \"fpm-1.17.0-ruby-3.4.3-darwin-arm64.7z\"\n }\n return \"fpm-1.17.0-ruby-3.4.3-darwin-x86_64.7z\"\n }\n\n const filename = getKey()\n const fpmPath = await getBinFromUrl(\"fpm@2.1.4\", filename, fpmChecksums[filename])\n return path.join(fpmPath, exec)\n}\n\nexport async function getAppImageTools(targetArch: Arch) {\n const override = process.env.APPIMAGE_TOOLS_PATH?.trim()\n const artifactPath =\n override ||\n (await downloadArtifact({\n releaseName: \"appimage@1.0.2\",\n filenameWithExt: \"appimage-tools-runtime-20251108.tar.gz\",\n checksums: {\n \"appimage-tools-runtime-20251108.tar.gz\": \"a784a8c26331ec2e945c23d6bdb14af5c9df27f5939825d84b8709c61dc81eb0\",\n },\n githubOrgRepo: \"electron-userland/electron-builder-binaries\",\n }))\n\n const runtimeArch = targetArch === Arch.armv7l ? \"arm32\" : targetArch === Arch.arm64 ? \"arm64\" : targetArch === Arch.ia32 ? \"ia32\" : \"x64\"\n return {\n mksquashfs: path.join(artifactPath, \"mksquashfs\"),\n desktopFileValidate: path.join(artifactPath, \"desktop-file-validate\"),\n runtime: path.join(artifactPath, \"runtimes\", `runtime-${runtimeArch}`),\n runtimeLibraries: path.join(artifactPath, \"lib\", runtimeArch),\n }\n}\n"]}