craft-native 0.0.435 → 0.0.442

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 (39) hide show
  1. package/LICENSE.md +30 -0
  2. package/README.md +35 -0
  3. package/dist/android/src/index.d.ts +8 -0
  4. package/dist/android/src/index.js +17 -2
  5. package/dist/android/templates/CraftHealthServices.kt.template +2 -0
  6. package/dist/android/templates/CraftNativeCapabilities.kt.template +42 -1
  7. package/dist/android/templates/CraftNativeMotion.kt.template +269 -0
  8. package/dist/android/templates/CraftNativeServices.kt.template +6 -1
  9. package/dist/android/templates/CraftPassiveSteps.kt.template +159 -0
  10. package/dist/android/templates/CraftRecordingPressure.kt.template +156 -0
  11. package/dist/android/templates/LocationRecordingService.kt.template +77 -9
  12. package/dist/android/templates/MainActivityNative.kt.template +129 -1
  13. package/dist/cli.js +289 -108
  14. package/dist/components/index.d.ts +25 -0
  15. package/dist/index.cjs +207 -27
  16. package/dist/index.d.cts +2 -2
  17. package/dist/index.d.ts +2 -2
  18. package/dist/index.js +321 -140
  19. package/dist/installer-background.d.ts +2 -0
  20. package/dist/installer-layout.d.ts +1 -0
  21. package/dist/ios/src/index.d.ts +10 -0
  22. package/dist/ios/src/index.js +28 -2
  23. package/dist/ios/templates/CraftApp.swift +14 -0
  24. package/dist/ios/templates/CraftHealth.swift +2 -1
  25. package/dist/ios/templates/CraftHealthBackground.swift +308 -0
  26. package/dist/ios/templates/CraftNativeActions.swift +153 -0
  27. package/dist/ios/templates/CraftNativeMutation.swift +18 -3
  28. package/dist/ios/templates/CraftNativePedometer.swift +181 -0
  29. package/dist/ios/templates/CraftNativeScreen.swift +76 -0
  30. package/dist/ios/templates/testing/DriverTests.swift.template +24 -4
  31. package/dist/macos/src/index.js +1 -1
  32. package/dist/macos/src/toolchain.d.ts +1 -1
  33. package/dist/macos/templates/CraftMacApplication.swift +124 -39
  34. package/dist/macos/templates/CraftMacRenderer.swift +169 -37
  35. package/dist/macos/templates/CraftMacRuntime.swift +298 -77
  36. package/dist/macos/templates/CraftNativeMutation.swift +18 -3
  37. package/dist/package.d.ts +40 -0
  38. package/dist/types.d.ts +26 -0
  39. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -12,10 +12,140 @@ var __esm = (fn, res, err) => () => {
12
12
  return res;
13
13
  };
14
14
 
15
+ // src/installer-layout.ts
16
+ import { execFileSync } from "child_process";
17
+ import { statSync, writeFileSync as writeFileSync2 } from "fs";
18
+ import { join } from "path";
19
+ function backgroundAlias(mount, volume) {
20
+ const folder = ".background";
21
+ const filename = "installer.png";
22
+ const directory = statSync(join(mount, folder));
23
+ const file = statSync(join(mount, folder, filename));
24
+ const date = (ms) => Math.floor(ms / 1000) + 2082844800;
25
+ const volumeDate = date(statSync(mount).birthtimeMs);
26
+ const fileDate = date(file.birthtimeMs);
27
+ const preciseDate = (value) => {
28
+ const out = Buffer.alloc(8);
29
+ out.writeBigUInt64BE(BigInt(value) * 65536n);
30
+ return out;
31
+ };
32
+ const body = Buffer.concat([
33
+ number(0, 2),
34
+ pascal(volume, 28),
35
+ number(volumeDate),
36
+ Buffer.from("H+"),
37
+ number(0, 2),
38
+ number(directory.ino),
39
+ pascal(filename, 64),
40
+ number(file.ino),
41
+ number(fileDate),
42
+ Buffer.alloc(8),
43
+ number(65535, 2),
44
+ number(65535, 2),
45
+ Buffer.alloc(16),
46
+ tag(0, Buffer.from(folder)),
47
+ tag(16, preciseDate(volumeDate)),
48
+ tag(17, preciseDate(fileDate)),
49
+ tag(1, number(directory.ino)),
50
+ tag(2, Buffer.from(`${volume}:${folder}:\x00${filename}`)),
51
+ tag(14, Buffer.concat([number(filename.length, 2), unicode2(filename)])),
52
+ tag(15, Buffer.concat([number(volume.length, 2), unicode2(volume)])),
53
+ tag(18, Buffer.from(`/${folder}/${filename}`)),
54
+ tag(19, Buffer.from(`/Volumes/${volume}`)),
55
+ number(65535, 2),
56
+ number(0, 2)
57
+ ]);
58
+ return Buffer.concat([Buffer.alloc(4), number(body.length + 8, 2), number(2, 2), body]);
59
+ }
60
+ function plist(values) {
61
+ const escape = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
62
+ const entries = Object.entries(values).map(([key, value]) => {
63
+ const data = Buffer.isBuffer(value) ? `<data>${value.toString("base64")}</data>` : typeof value === "boolean" ? `<${value}/>` : typeof value === "number" ? ["viewOptionsVersion", "backgroundType"].includes(key) ? `<integer>${value}</integer>` : `<real>${value}</real>` : `<string>${escape(value)}</string>`;
64
+ return `<key>${key}</key>${data}`;
65
+ }).join("");
66
+ return execFileSync("plutil", ["-convert", "binary1", "-o", "-", "-"], { input: `<?xml version="1.0"?><plist version="1.0"><dict>${entries}</dict></plist>` });
67
+ }
68
+ function writeInstallerLayout(mount, volume, appName) {
69
+ const records = [];
70
+ const blob = (name, code, data) => records.push({ name, code, type: "blob", data: Buffer.concat([number(data.length), data]) });
71
+ blob(".", "bwsp", plist({ ShowStatusBar: false, ShowToolbar: false, ShowTabView: false, ShowSidebar: false, ContainerShowSidebar: false, ShowPathbar: false, SidebarWidth: 0, PreviewPaneVisibility: false, WindowBounds: "{{100, 100}, {660, 460}}" }));
72
+ blob(".", "icvp", plist({ viewOptionsVersion: 1, backgroundType: 2, backgroundColorRed: 1, backgroundColorGreen: 1, backgroundColorBlue: 1, backgroundImageAlias: backgroundAlias(mount, volume), iconSize: 96, arrangeBy: "none", gridSpacing: 100, gridOffsetX: 0, gridOffsetY: 0, scrollPositionX: 0, scrollPositionY: 0, textSize: 13, labelOnBottom: true, showIconPreview: true, showItemInfo: false }));
73
+ records.push({ name: ".", code: "vSrn", type: "long", data: number(1) });
74
+ records.push({ name: ".", code: "icvl", type: "type", data: Buffer.from("icnv") });
75
+ records.push({ name: ".", code: "vstl", type: "type", data: Buffer.from("icnv") });
76
+ for (const [name, x, y] of [[appName, 160, 190], ["Applications", 500, 190], [".background", 500, 600]])
77
+ blob(name, "Iloc", Buffer.concat([number(x), number(y), Buffer.from("ffffffffffff0000", "hex")]));
78
+ records.sort((a, b) => {
79
+ const left = a.name.normalize("NFD").toLowerCase();
80
+ const right = b.name.normalize("NFD").toLowerCase();
81
+ return left < right ? -1 : left > right ? 1 : a.code < b.code ? -1 : 1;
82
+ });
83
+ const leaf = Buffer.concat([number(0), number(records.length), ...records.map((record) => {
84
+ const name = record.name.normalize("NFD");
85
+ return Buffer.concat([number(name.length), unicode2(name), Buffer.from(record.code + record.type), record.data]);
86
+ })]);
87
+ if (leaf.length > 4096)
88
+ throw new Error("Installer layout exceeds the Finder store leaf capacity");
89
+ const offsets = Buffer.alloc(1024);
90
+ offsets.writeUInt32BE(2048 | 11, 0);
91
+ offsets.writeUInt32BE(32 | 5, 4);
92
+ offsets.writeUInt32BE(4096 | 12, 8);
93
+ const free = Array.from({ length: 32 }, (_, power) => power >= 6 && power <= 10 || power >= 13 && power <= 30 ? Buffer.concat([number(1), number(2 ** power)]) : number(0));
94
+ const root = Buffer.concat([number(3), number(0), offsets, number(1), Buffer.from([4]), Buffer.from("DSDB"), number(1), ...free]);
95
+ const out = Buffer.alloc(8196);
96
+ Buffer.concat([number(1), Buffer.from("Bud1"), number(2048), number(root.length), number(2048), Buffer.alloc(16)]).copy(out);
97
+ Buffer.concat([number(2), number(0), number(records.length), number(1), number(4096)]).copy(out, 36);
98
+ root.copy(out, 2052);
99
+ leaf.copy(out, 4100);
100
+ writeFileSync2(join(mount, ".DS_Store"), out);
101
+ }
102
+ var number = (value, bytes = 4) => {
103
+ const out = Buffer.alloc(bytes);
104
+ out.writeUIntBE(value, 0, bytes);
105
+ return out;
106
+ }, unicode2 = (value) => Buffer.from(value, "utf16le").swap16(), pascal = (value, size) => {
107
+ const out = Buffer.alloc(size);
108
+ const bytes = Buffer.from(value).subarray(0, size - 1);
109
+ out[0] = bytes.length;
110
+ bytes.copy(out, 1);
111
+ return out;
112
+ }, tag = (id, data) => Buffer.concat([number(id, 2), number(data.length, 2), data, Buffer.alloc(data.length % 2)]);
113
+ var init_installer_layout = __esm(() => {
114
+ /*!
115
+ * Format implementation adapted from MIT-licensed references:
116
+ * Copyright (c) 2020 Kenty Gwend
117
+ * Copyright (c) 2026 John Campion Jr
118
+ * Copyright (c) 2014 Alastair Houghton
119
+ * Copyright (c) 2022 Russell Keith-Magee
120
+ *
121
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
122
+ * of this software and associated documentation files (the "Software"), to deal
123
+ * in the Software without restriction, including without limitation the rights
124
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
125
+ * copies of the Software, and to permit persons to whom the Software is
126
+ * furnished to do so, subject to the following conditions:
127
+ * The above copyright notice and this permission notice shall be included in
128
+ * all copies or substantial portions of the Software.
129
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
130
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
131
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
132
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
133
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
134
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
135
+ * SOFTWARE.
136
+ */
137
+ });
138
+
139
+ // src/installer-background.ts
140
+ var installerBackground;
141
+ var init_installer_background = __esm(() => {
142
+ installerBackground = Buffer.from("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vpDh4twyyyyT7S6//PKDdsOXbt/xkT2miF0Kvq200kqZDVsFuI4P6667buZw9913p5deeilnMWGz3nrr5euIqtEURBYCiPFjn20ASyyxRO4TW1wPYQkXGLz44ovZD67hB8v0d955Z3rllVeyYAs/iEnZD2wg5LDx+OOPp9dffz33AcsNN9wwLb744pnpaHwn0/3GG29k34kpMV5yySXTWmutlV+won/en3zyyfTCCy/ksWIbP5577rnclnHgcxT8wxbbF2DL+JZaaqlsk72v2IQZBdvcp9ShEKsVV1xx8F58880309JLL53jsvLKK4/5/ZI79R8JSGDMCSgoxxypBiUwPgT+4z/+I++vZLI+7LDD8uT9v//7v1l4cA6BxaR/zDHH5Ad5YkJHXCFK/u///i/NmjUrixrEAAVxggA44ogj0he+8IUsAv7xH/8x70ukTgjRc889N51//vlp2sADNFynHYIDMYHda6+9dj677INEeH7xi19MhxxyyKAA7ZYUfSJQ/vu//zuPhTEeeOCB6fd///fT7Nmz01/+5V/m6wjaP/7jP07w4fx7772XRSSiZ9ddd00nnHBCFjVwG64gnB544IFBO4gzxCNMEUGbb755OvbYY9P06dOzEKL+jTfemLcLYBcRiG//8z//k+65557sB+IMUfe5z30u/eqv/moW9REreLN/8Qc/+EG68MILs4B9//33Mz9ELAL2q1/9am6L77AYqmALGz/60Y/ylwj2qVLof4UVVsgcyPQi8Fjiht2jjz6a+6ct5aSTTsovxsfyN+Om/R133JHjzpgQ0PiCeMUu2xF+5Vd+JY8L/+j3r//6r7Mwhd3v/u7v5rrf/e53s4BlfGRF+YL05S9/Od8v9D3c2LhukYAEektAQdlb/vYugY4JkBlj4mdSv+KKK7JIJLvDZ15MwGSCeEocIcPeQiZwMkN/9Vd/la666qo8kSNeED7UZzJHRCAWOEaoIprIpCF6EHAURAHXEWq0Q3CQJeQp7VtvvTXbw274gRglE8o+TAQHomssCwIx9vlF5os+OUfhOEQMPuEv74zjvPPOy6LpL/7iL/L4hhIuCKRbbrkl/emf/mkW7Qip4hgZF0L63nvvzXUQqvBCEOIHx/CHPSzCD3zBjx//+MeZ5R/90R9ln6P+3//932chSH36o198ZMxkW//sz/4sx+jQQw/NfeXG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6gzXR1zrxA7jHS7u2B5NnfCh3XsnfrWz4zkJSKA3BOZf/+mND/YqAQlIQAINIsCXCwQqr5HEdoOwOFQJ1JqAGcpah0/nJSABCdSHAFlM9nEeddRR+WeMEJM8BER20iIBCdSbgHso6x0/vZeABCRQOwI8xBN7QclWKihrF0IdlsCnCJih/BQST0hAAhKQQJUE4in4KvvQtgQkML4E3EM5vrztTQISkIAEJCABCUw4AgrKCRdSByQBCUhAAhKQgATGl4CCcnx525sEJCABCUhAAhKYcAQUlBMupA5IAhKQgAQkIAEJjC8BBeX48rY3CUhAAhKQgAQkMOEIKCgnXEgdkAQkIAEJSEACEhhfAgrK8eVtbxKQgAQkIAEJSGDCEVBQTriQOiAJSEACEpCABCQwvgQUlOPL294kIAEJSEACEpDAhCOgoJxwIXVAEpCABCQgAQlIYHwJKCjHl7e9SUACEpCABCQggQlHQEE54ULqgCTQGwKTJk1KkydPTrxbekOgyH+hhRbK8ajSk/Hoo0r/tS0BCYwdAQXl2LHUkgQqIYBAY+IuvhAOU6ZM6al4w58Qj7zPmTMnPfvss+mDDz6ohMN4Gy2Obyz6jviNha12Nj788MPM/7333stxeemll/LndnU7ORf3YbTl84svvjimfYRt3yUggfoRmFI/l/VYAs0hgHB86KGH0u23355Fwrx583LWaamllkprr712Wn/99bOw/Pjjj8cVCv29/vrrabHFFkuLLrpo9umJJ55IF1xwQTriiCOybx999NG4+jSWneE741t88cXTIosskuDeTYHXFVdckebOnZv22muvHLNu7JXbIlZfffXV9MMf/jDtu+++afPNN0/nnXdeeuONN9Lxxx+fx9HNGBCPCNX3338/ce9xXzKWc889N73zzjvpG9/4Rr4XuumjPCY/S0AC9SJghrJe8dLbhhFAKLz88svprrvuSm+99Vae0N9888105513ptNPPz395Cc/Se++++58mUImf0o5w8Z5hADn25XydT6HrWJ9bCBeTjnllHTvvfemqVOn5suIJrKTvIetdu2pHNeH8qXY33D1sRM2hrI5mjrF/hjfK6+8kk4++eT0wAMPDI4v6hT74Xikgr3nn38+3XzzzemWW25JzzzzzKcEJXbCFuPhFZ/D/kjjRMzBHzFMn5tttlmaMWNGWnjhhQcFMTaH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SEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJSEACEpCABCRQHQEFZXVstSwBCUhAAhKQgAQaQUBB2YgwO0gJ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", "base64");
143
+ });
144
+
15
145
  // src/temp-dir.ts
16
- import { existsSync as existsSync3, mkdtempSync, readdirSync, rmSync, statSync, writeFileSync as writeFileSync2 } from "fs";
146
+ import { existsSync as existsSync3, mkdtempSync, readdirSync, rmSync, statSync as statSync2, writeFileSync as writeFileSync3 } from "fs";
17
147
  import { constants as osConstants, tmpdir } from "os";
18
- import { join } from "path";
148
+ import { join as join2 } from "path";
19
149
  function removeQuietly(dir) {
20
150
  try {
21
151
  rmSync(dir, { recursive: true, force: true });
@@ -83,11 +213,11 @@ function sweepOrphanedTempDirs(options = {}) {
83
213
  const pid = Number(match[1]);
84
214
  if (pid === process.pid || isAlive(pid))
85
215
  continue;
86
- const path = join(root, name);
216
+ const path = join2(root, name);
87
217
  try {
88
- if (now - statSync(path).mtimeMs < minAge)
218
+ if (now - statSync2(path).mtimeMs < minAge)
89
219
  continue;
90
- if (existsSync3(join(path, KEEP_MARKER)))
220
+ if (existsSync3(join2(path, KEEP_MARKER)))
91
221
  continue;
92
222
  } catch {
93
223
  continue;
@@ -107,7 +237,7 @@ function createTempDir(label, root = tmpdir()) {
107
237
  sweepOrphanedTempDirs({ root });
108
238
  }
109
239
  hook();
110
- const dir = mkdtempSync(join(root, tempDirPrefix(label)));
240
+ const dir = mkdtempSync(join2(root, tempDirPrefix(label)));
111
241
  live.add(dir);
112
242
  return dir;
113
243
  }
@@ -141,10 +271,11 @@ import {
141
271
  readSync,
142
272
  readdirSync as readdirSync2,
143
273
  rmSync as rmSync2,
144
- writeFileSync as writeFileSync3
274
+ symlinkSync,
275
+ writeFileSync as writeFileSync4
145
276
  } from "fs";
146
277
  import { homedir } from "os";
147
- import { basename, dirname, join as join2, resolve } from "path";
278
+ import { basename, dirname, join as join3, resolve } from "path";
148
279
  import { deflateRawSync } from "zlib";
149
280
  function crc32(data) {
150
281
  let c = 4294967295;
@@ -222,7 +353,7 @@ async function packageApp(config) {
222
353
  throw new Error(`Binary not found: ${config.binaryPath}`);
223
354
  }
224
355
  const platforms = config.platforms || [detectPlatform()];
225
- const outDir = config.outDir || join2(process.cwd(), "dist");
356
+ const outDir = config.outDir || join3(process.cwd(), "dist");
226
357
  if (!existsSync4(outDir)) {
227
358
  mkdirSync(outDir, { recursive: true });
228
359
  }
@@ -244,7 +375,7 @@ async function packageApp(config) {
244
375
  function macOSAppStoreRuntimePath(providerPath) {
245
376
  const providerName = basename(providerPath);
246
377
  const storeName = providerName.startsWith("craft-webview") ? "craft-webview-app-store" : "craft-app-store";
247
- const runtime = providerName === storeName ? providerPath : join2(dirname(providerPath), storeName);
378
+ const runtime = providerName === storeName ? providerPath : join3(dirname(providerPath), storeName);
248
379
  if (!existsSync4(runtime))
249
380
  throw new Error("App Store packaging requires Pantry\u2019s craft-app-store runtime. Upgrade Craft with Pantry before building.");
250
381
  const bytes = readFileSync2(runtime);
@@ -271,7 +402,7 @@ async function packageMacOS(config, outDir) {
271
402
  return [{ success: false, platform: "macos", format: "app", error: error.message }];
272
403
  }
273
404
  }
274
- const appBundlePath = join2(outDir, `${name}.app`);
405
+ const appBundlePath = join3(outDir, `${name}.app`);
275
406
  const appBundle = opts.appBundlePath ? copyMacOSAppBundle(opts.appBundlePath, appBundlePath) : createMacOSAppBundle({
276
407
  name,
277
408
  version,
@@ -300,25 +431,25 @@ async function packageMacOS(config, outDir) {
300
431
  return results;
301
432
  }
302
433
  try {
303
- const contents = join2(appBundlePath, "Contents");
304
- if (opts.appStore && opts.appBundlePath && existsSync4(join2(contents, "Resources", "craft.json"))) {
434
+ const contents = join3(appBundlePath, "Contents");
435
+ if (opts.appStore && opts.appBundlePath && existsSync4(join3(contents, "Resources", "craft.json"))) {
305
436
  if (!nativeRuntimePath)
306
437
  throw new Error("App Store packaging of a prebuilt Craft bundle requires macos.nativeRuntimePath from Pantry.");
307
- const plist = join2(contents, "Info.plist");
438
+ const plist = join3(contents, "Info.plist");
308
439
  const executable = spawnSync("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", plist], { encoding: "utf8" });
309
440
  const name = executable.stdout.trim();
310
441
  if (executable.status !== 0 || !name || basename(name) !== name || name === "." || name === "..")
311
442
  throw new Error("Prebuilt Craft bundle has an invalid CFBundleExecutable");
312
- copyFileSync(nativeRuntimePath, join2(contents, "MacOS", name));
313
- chmodSync(join2(contents, "MacOS", name), 493);
443
+ copyFileSync(nativeRuntimePath, join3(contents, "MacOS", name));
444
+ chmodSync(join3(contents, "MacOS", name), 493);
314
445
  }
315
446
  if (opts.provisioningProfile) {
316
- const profile = join2(contents, "embedded.provisionprofile");
447
+ const profile = join3(contents, "embedded.provisionprofile");
317
448
  copyFileSync(opts.provisioningProfile, profile);
318
449
  chmodSync(profile, 420);
319
450
  }
320
451
  if (opts.privacyManifest)
321
- copyFileSync(opts.privacyManifest, join2(contents, "Resources", "PrivacyInfo.xcprivacy"));
452
+ copyFileSync(opts.privacyManifest, join3(contents, "Resources", "PrivacyInfo.xcprivacy"));
322
453
  if (opts.appBundlePath) {
323
454
  const metadata = {
324
455
  CFBundleVersion: opts.buildNumber,
@@ -328,13 +459,13 @@ async function packageMacOS(config, outDir) {
328
459
  };
329
460
  if (config.iconPath) {
330
461
  const icon = basename(config.iconPath);
331
- copyFileSync(config.iconPath, join2(contents, "Resources", icon));
462
+ copyFileSync(config.iconPath, join3(contents, "Resources", icon));
332
463
  metadata.CFBundleIconFile = icon;
333
464
  }
334
465
  for (const [key, value] of Object.entries(metadata)) {
335
466
  if (value === undefined)
336
467
  continue;
337
- const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join2(contents, "Info.plist")]);
468
+ const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join3(contents, "Info.plist")]);
338
469
  if (!result.success)
339
470
  throw new Error(result.error);
340
471
  }
@@ -355,8 +486,8 @@ async function packageMacOS(config, outDir) {
355
486
  }
356
487
  results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
357
488
  if (opts.dmg !== false) {
358
- const outputPath = join2(outDir, `${name}-${version}.dmg`);
359
- let dmgResult = await createDMG({ appBundlePath, outputPath, volumeName: name });
489
+ const outputPath = join3(outDir, `${name}-${version}.dmg`);
490
+ let dmgResult = await createDiskImage({ appBundlePath, outputPath, volumeName: name });
360
491
  if (dmgResult.success && opts.signIdentity) {
361
492
  const signed = await runTool("codesign", codesignArguments({
362
493
  path: outputPath,
@@ -380,7 +511,7 @@ async function packageMacOS(config, outDir) {
380
511
  results.push(...await notarizeIfRequested(opts, outputPath, "dmg"));
381
512
  }
382
513
  if (opts.pkg || opts.appStore) {
383
- const outputPath = join2(outDir, `${name}-${version}.pkg`);
514
+ const outputPath = join3(outDir, `${name}-${version}.pkg`);
384
515
  const pkgResult = await createPKG({
385
516
  appBundlePath,
386
517
  outputPath,
@@ -415,7 +546,7 @@ async function notarizeIfRequested(opts, artifactPath, format) {
415
546
  }
416
547
  const scratch = format === "app" ? createTempDir("craft-notarize-") : undefined;
417
548
  try {
418
- const submission = scratch ? join2(scratch, "app.zip") : artifactPath;
549
+ const submission = scratch ? join3(scratch, "app.zip") : artifactPath;
419
550
  if (scratch) {
420
551
  const zipped = await runTool("ditto", ["-c", "-k", "--keepParent", artifactPath, submission]);
421
552
  if (!zipped.success)
@@ -453,7 +584,7 @@ async function packageWindows(config, outDir) {
453
584
  name,
454
585
  version,
455
586
  binaryPath: config.binaryPath,
456
- outputPath: join2(outDir, `${name}-${version}.msi`),
587
+ outputPath: join3(outDir, `${name}-${version}.msi`),
457
588
  manufacturer: config.author || "Unknown",
458
589
  architecture: opts.architecture || windowsArchitecture(process.arch),
459
590
  additionalFiles: opts.additionalFiles,
@@ -477,7 +608,7 @@ async function packageWindows(config, outDir) {
477
608
  manufacturer: config.author || "Unknown",
478
609
  binaryPath: config.binaryPath,
479
610
  additionalFiles: opts.additionalFiles,
480
- outputPath: join2(outDir, `${name}-${version}-windows.zip`)
611
+ outputPath: join3(outDir, `${name}-${version}-windows.zip`)
481
612
  });
482
613
  results.push({
483
614
  success: zipResult.success,
@@ -498,7 +629,7 @@ async function packageLinux(config, outDir) {
498
629
  name,
499
630
  version,
500
631
  binaryPath: config.binaryPath,
501
- outputPath: join2(outDir, `${name}_${version}_amd64.deb`),
632
+ outputPath: join3(outDir, `${name}_${version}_amd64.deb`),
502
633
  description: config.description || "",
503
634
  maintainer: config.author || "Unknown",
504
635
  dependencies: opts.debDependencies || [...DEFAULT_DEB_DEPENDENCIES],
@@ -518,7 +649,7 @@ async function packageLinux(config, outDir) {
518
649
  name,
519
650
  version,
520
651
  binaryPath: config.binaryPath,
521
- outputPath: join2(outDir, `${name}-${version}-1.x86_64.rpm`),
652
+ outputPath: join3(outDir, `${name}-${version}-1.x86_64.rpm`),
522
653
  description: config.description || "",
523
654
  requires: opts.rpmDependencies || ["gtk3", "webkit2gtk3"]
524
655
  });
@@ -535,7 +666,7 @@ async function packageLinux(config, outDir) {
535
666
  name,
536
667
  version,
537
668
  binaryPath: config.binaryPath,
538
- outputPath: join2(outDir, `${name}-${version}-x86_64.AppImage`),
669
+ outputPath: join3(outDir, `${name}-${version}-x86_64.AppImage`),
539
670
  iconPath: config.iconPath
540
671
  });
541
672
  results.push({
@@ -645,13 +776,13 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
645
776
  try {
646
777
  let helperEntitlements = opts.helperEntitlements;
647
778
  if (opts.appStore && !helperEntitlements) {
648
- helperEntitlements = join2(scratch, "inherit.plist");
649
- writeFileSync3(helperEntitlements, '<?xml version="1.0"?><plist version="1.0"><dict><key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.inherit</key><true/></dict></plist>');
779
+ helperEntitlements = join3(scratch, "inherit.plist");
780
+ writeFileSync4(helperEntitlements, '<?xml version="1.0"?><plist version="1.0"><dict><key>com.apple.security.app-sandbox</key><true/><key>com.apple.security.inherit</key><true/></dict></plist>');
650
781
  }
651
- const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join2(app, "Contents", "Info.plist")]);
782
+ const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join3(app, "Contents", "Info.plist")]);
652
783
  if (!extracted.success)
653
784
  throw new Error(extracted.error);
654
- const main = join2(app, "Contents", "MacOS", extracted.stdout.trim());
785
+ const main = join3(app, "Contents", "MacOS", extracted.stdout.trim());
655
786
  const sign = async (path, entitlements, identifier) => {
656
787
  const signed = await runTool("codesign", codesignArguments({ path, identity: opts.signIdentity, entitlements, hardenedRuntime, identifier, keychain: opts.signingKeychain, deep: false }));
657
788
  if (!signed.success)
@@ -659,7 +790,7 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
659
790
  };
660
791
  const walk = async (directory) => {
661
792
  for (const entry of readdirSync2(directory)) {
662
- const path = join2(directory, entry);
793
+ const path = join3(directory, entry);
663
794
  const stat = lstatSync(path);
664
795
  if (stat.isSymbolicLink())
665
796
  continue;
@@ -673,7 +804,7 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
673
804
  }
674
805
  }
675
806
  };
676
- await walk(join2(app, "Contents"));
807
+ await walk(join3(app, "Contents"));
677
808
  await sign(app, opts.entitlements);
678
809
  const verified = await runTool("codesign", ["--verify", "--deep", "--strict", app]);
679
810
  if (!verified.success)
@@ -741,8 +872,8 @@ function notarytoolArguments(opts) {
741
872
  }
742
873
  function copyMacOSAppBundle(source, destination) {
743
874
  try {
744
- const info = join2(source, "Contents", "Info.plist");
745
- if (!existsSync4(info) || !existsSync4(join2(source, "Contents", "MacOS")))
875
+ const info = join3(source, "Contents", "Info.plist");
876
+ if (!existsSync4(info) || !existsSync4(join3(source, "Contents", "MacOS")))
746
877
  throw new Error(`Invalid prebuilt macOS application: ${source}`);
747
878
  if (resolve(source) !== resolve(destination)) {
748
879
  rmSync2(destination, { recursive: true, force: true });
@@ -754,29 +885,29 @@ function copyMacOSAppBundle(source, destination) {
754
885
  }
755
886
  }
756
887
  function macOSRuntimeExecutablePath(appBundlePath) {
757
- return join2(appBundlePath, "Contents", "Helpers", "CraftRuntime.app", "Contents", "MacOS", "craft");
888
+ return join3(appBundlePath, "Contents", "Helpers", "CraftRuntime.app", "Contents", "MacOS", "craft");
758
889
  }
759
890
  function createMacOSAppBundle(opts) {
760
891
  try {
761
892
  const { name, binaryPath, iconPath, provisioningProfile, additionalExecutables, outputPath } = opts;
762
- const contents = join2(outputPath, "Contents");
763
- const macOS = join2(contents, "MacOS");
893
+ const contents = join3(outputPath, "Contents");
894
+ const macOS = join3(contents, "MacOS");
764
895
  mkdirSync(macOS, { recursive: true });
765
- mkdirSync(join2(contents, "Resources"), { recursive: true });
766
- copyFileSync(opts.nativeHost ? opts.nativeRuntimePath : binaryPath, join2(macOS, name));
767
- chmodSync(join2(macOS, name), 493);
896
+ mkdirSync(join3(contents, "Resources"), { recursive: true });
897
+ copyFileSync(opts.nativeHost ? opts.nativeRuntimePath : binaryPath, join3(macOS, name));
898
+ chmodSync(join3(macOS, name), 493);
768
899
  for (const executable of additionalExecutables || []) {
769
900
  if (!existsSync4(executable))
770
901
  return { success: false, error: `Additional executable not found: ${executable}` };
771
- const destination = join2(macOS, basename(executable));
902
+ const destination = join3(macOS, basename(executable));
772
903
  copyFileSync(executable, destination);
773
904
  chmodSync(destination, 493);
774
905
  }
775
906
  if (opts.nativeHost) {
776
- const backend = join2(macOS, "craft-backend");
907
+ const backend = join3(macOS, "craft-backend");
777
908
  copyFileSync(binaryPath, backend);
778
909
  chmodSync(backend, 493);
779
- writeFileSync3(join2(contents, "Resources", "craft.json"), `${JSON.stringify({
910
+ writeFileSync4(join3(contents, "Resources", "craft.json"), `${JSON.stringify({
780
911
  title: name,
781
912
  appName: name,
782
913
  ...opts.nativeWindow,
@@ -786,14 +917,14 @@ function createMacOSAppBundle(opts) {
786
917
  } else if (opts.nativeRuntimePath) {
787
918
  const helper = macOSRuntimeExecutablePath(outputPath);
788
919
  const helperContents = resolve(helper, "..", "..");
789
- mkdirSync(join2(helperContents, "MacOS"), { recursive: true });
920
+ mkdirSync(join3(helperContents, "MacOS"), { recursive: true });
790
921
  copyFileSync(opts.nativeRuntimePath, helper);
791
922
  chmodSync(helper, 493);
792
923
  if (iconPath) {
793
- mkdirSync(join2(helperContents, "Resources"), { recursive: true });
794
- copyFileSync(iconPath, join2(helperContents, "Resources", "icon.icns"));
924
+ mkdirSync(join3(helperContents, "Resources"), { recursive: true });
925
+ copyFileSync(iconPath, join3(helperContents, "Resources", "icon.icns"));
795
926
  }
796
- writeFileSync3(join2(helperContents, "Info.plist"), macOSInfoPlist({
927
+ writeFileSync4(join3(helperContents, "Info.plist"), macOSInfoPlist({
797
928
  name,
798
929
  executableName: "craft",
799
930
  version: opts.version,
@@ -809,14 +940,14 @@ function createMacOSAppBundle(opts) {
809
940
  if (!existsSync4(iconPath))
810
941
  return { success: false, error: `Icon not found: ${iconPath}` };
811
942
  iconName = basename(iconPath).replace(/\.icns$/i, "");
812
- copyFileSync(iconPath, join2(contents, "Resources", `${iconName}.icns`));
943
+ copyFileSync(iconPath, join3(contents, "Resources", `${iconName}.icns`));
813
944
  }
814
945
  if (provisioningProfile) {
815
946
  if (!existsSync4(provisioningProfile))
816
947
  return { success: false, error: `Provisioning profile not found: ${provisioningProfile}` };
817
- copyFileSync(provisioningProfile, join2(contents, "embedded.provisionprofile"));
948
+ copyFileSync(provisioningProfile, join3(contents, "embedded.provisionprofile"));
818
949
  }
819
- writeFileSync3(join2(contents, "Info.plist"), macOSInfoPlist({ ...opts, iconName }));
950
+ writeFileSync4(join3(contents, "Info.plist"), macOSInfoPlist({ ...opts, iconName }));
820
951
  return { success: true };
821
952
  } catch (error) {
822
953
  return { success: false, error: error.message };
@@ -826,7 +957,7 @@ function pathContentBytes(path) {
826
957
  const stat = lstatSync(path);
827
958
  if (!stat.isDirectory())
828
959
  return stat.size;
829
- return readdirSync2(path).reduce((total, entry) => total + pathContentBytes(join2(path, entry)), 0);
960
+ return readdirSync2(path).reduce((total, entry) => total + pathContentBytes(join3(path, entry)), 0);
830
961
  }
831
962
  function dmgCapacityMegabytes(contentBytes) {
832
963
  if (!Number.isSafeInteger(contentBytes) || contentBytes < 0)
@@ -841,6 +972,8 @@ function dmgCreateArguments(opts, contentBytes) {
841
972
  opts.volumeName,
842
973
  "-srcfolder",
843
974
  opts.appBundlePath,
975
+ "-fs",
976
+ "HFS+",
844
977
  "-size",
845
978
  `${dmgCapacityMegabytes(contentBytes)}m`,
846
979
  "-ov",
@@ -874,24 +1007,70 @@ function runTool(tool, args) {
874
1007
  proc.on("error", (err) => resolve({ success: false, error: err.message }));
875
1008
  });
876
1009
  }
877
- async function createDMG(opts) {
878
- if (!/^[^/:\n]{1,27}$/.test(opts.volumeName))
879
- return { success: false, error: `Invalid DMG volume name "${opts.volumeName}"; must be 1..27 chars without /, :, or newline` };
880
- const args = dmgCreateArguments(opts, pathContentBytes(opts.appBundlePath));
881
- const failures = [];
882
- for (let attempt = 1;attempt <= HDIUTIL_MAX_ATTEMPTS; attempt++) {
883
- const result = await runHdiutil(args);
1010
+ async function detachDiskImage(mount, options = {}) {
1011
+ const run = options.run ?? runHdiutil;
1012
+ const wait = options.wait ?? ((ms) => new Promise((resolve) => {
1013
+ setTimeout(resolve, ms);
1014
+ }));
1015
+ for (let attempt = 1;; attempt++) {
1016
+ const forced = attempt >= HDIUTIL_MAX_ATTEMPTS;
1017
+ const result = await run(forced ? ["detach", mount, "-force"] : ["detach", mount]);
884
1018
  if (result.success)
885
- return { success: true, outputPath: opts.outputPath };
886
- failures.push(`attempt ${attempt}: ${result.error}`);
1019
+ return { success: true };
887
1020
  if (!shouldRetryHdiutil(result.error, attempt))
888
- return { success: false, error: failures.join(`
889
- `) };
890
- rmSync2(opts.outputPath, { force: true });
891
- await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
1021
+ return { success: false, error: result.error };
1022
+ await wait(attempt * 2000);
1023
+ }
1024
+ }
1025
+ async function createDiskImage(opts) {
1026
+ if (!/^[^/:\n]{1,27}$/.test(opts.volumeName))
1027
+ return { success: false, error: `Invalid DMG volume name "${opts.volumeName}"; must be 1..27 chars without /, :, or newline` };
1028
+ const scratch = createTempDir("craft-installer-");
1029
+ const payload = join3(scratch, "payload");
1030
+ const mount = join3(scratch, "mount");
1031
+ const writable = join3(scratch, "installer.dmg");
1032
+ let mounted = false;
1033
+ const run = async (tool, args) => {
1034
+ const result = await runTool(tool, args);
1035
+ if (!result.success)
1036
+ throw new Error(result.error);
1037
+ return result;
1038
+ };
1039
+ try {
1040
+ mkdirSync(payload);
1041
+ mkdirSync(mount);
1042
+ const bundleName = basename(opts.appBundlePath);
1043
+ await run("ditto", [opts.appBundlePath, join3(payload, bundleName)]);
1044
+ symlinkSync("/Applications", join3(payload, "Applications"));
1045
+ mkdirSync(join3(payload, ".background"));
1046
+ writeFileSync4(join3(payload, ".background", "installer.png"), installerBackground);
1047
+ const args = dmgCreateArguments({ ...opts, appBundlePath: payload, outputPath: writable }, pathContentBytes(payload));
1048
+ args[args.indexOf("ULMO")] = "UDRW";
1049
+ for (let attempt = 1;; attempt++) {
1050
+ const result = await runHdiutil(args);
1051
+ if (result.success)
1052
+ break;
1053
+ if (!shouldRetryHdiutil(result.error, attempt))
1054
+ throw new Error(result.error);
1055
+ rmSync2(writable, { force: true });
1056
+ await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
1057
+ }
1058
+ await run("hdiutil", ["attach", writable, "-nobrowse", "-mountpoint", mount]);
1059
+ mounted = true;
1060
+ writeInstallerLayout(mount, opts.volumeName, bundleName);
1061
+ const detached = await detachDiskImage(mount);
1062
+ if (!detached.success)
1063
+ throw new Error(detached.error);
1064
+ mounted = false;
1065
+ await run("hdiutil", ["convert", writable, "-format", "ULMO", "-ov", "-o", opts.outputPath]);
1066
+ return { success: true, outputPath: opts.outputPath };
1067
+ } catch (error) {
1068
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1069
+ } finally {
1070
+ if (mounted)
1071
+ await runTool("hdiutil", ["detach", mount, "-force"]);
1072
+ removeTempDir(scratch);
892
1073
  }
893
- return { success: false, error: failures.join(`
894
- `) };
895
1074
  }
896
1075
  function pkgbuildComponentPlist(rootRelativeBundlePath) {
897
1076
  return `<?xml version="1.0" encoding="UTF-8"?>
@@ -948,14 +1127,14 @@ async function createPKG(opts) {
948
1127
  }
949
1128
  const tempDir = createTempDir("craft-pkg-");
950
1129
  try {
951
- const root = join2(tempDir, "root");
952
- const appsDir = join2(root, "Applications");
1130
+ const root = join3(tempDir, "root");
1131
+ const appsDir = join3(root, "Applications");
953
1132
  mkdirSync(appsDir, { recursive: true, mode: 493 });
954
1133
  chmodSync(root, 493);
955
1134
  const bundleName = basename(opts.appBundlePath);
956
- cpSync(opts.appBundlePath, join2(appsDir, bundleName), { recursive: true });
957
- const componentPlistPath = join2(tempDir, "component.plist");
958
- writeFileSync3(componentPlistPath, pkgbuildComponentPlist(`Applications/${bundleName}`));
1135
+ cpSync(opts.appBundlePath, join3(appsDir, bundleName), { recursive: true });
1136
+ const componentPlistPath = join3(tempDir, "component.plist");
1137
+ writeFileSync4(componentPlistPath, pkgbuildComponentPlist(`Applications/${bundleName}`));
959
1138
  const built = await runTool("pkgbuild", pkgbuildArguments({
960
1139
  root,
961
1140
  componentPlistPath,
@@ -1089,14 +1268,14 @@ async function createMSI(opts) {
1089
1268
  try {
1090
1269
  const binaryName = windowsExecutableName(opts.name);
1091
1270
  const additionalFiles = windowsCompanionFiles(opts.additionalFiles, binaryName);
1092
- const sourcePath = join2(tempDir, binaryName);
1093
- const wxsPath = join2(tempDir, "installer.wxs");
1094
- const wixobjPath = join2(tempDir, "installer.wixobj");
1271
+ const sourcePath = join3(tempDir, binaryName);
1272
+ const wxsPath = join3(tempDir, "installer.wxs");
1273
+ const wixobjPath = join3(tempDir, "installer.wixobj");
1095
1274
  copyFileSync(opts.binaryPath, sourcePath);
1096
- writeFileSync3(join2(tempDir, WINDOWS_NOTIFICATION_ID_FILE), windowsNotificationAppId(opts.name, opts.manufacturer));
1275
+ writeFileSync4(join3(tempDir, WINDOWS_NOTIFICATION_ID_FILE), windowsNotificationAppId(opts.name, opts.manufacturer));
1097
1276
  for (const file of additionalFiles)
1098
- copyFileSync(file.path, join2(tempDir, file.name));
1099
- writeFileSync3(wxsPath, renderWixSource(opts, binaryName, additionalFiles.map((file) => file.name)));
1277
+ copyFileSync(file.path, join3(tempDir, file.name));
1278
+ writeFileSync4(wxsPath, renderWixSource(opts, binaryName, additionalFiles.map((file) => file.name)));
1100
1279
  await runCommand("candle.exe", candleArguments(opts.architecture, wixobjPath, wxsPath), tempDir);
1101
1280
  await runCommand("light.exe", ["-nologo", "-sval", "-out", opts.outputPath, wixobjPath], tempDir);
1102
1281
  if (opts.certificatePath) {
@@ -1125,7 +1304,7 @@ async function createZIP(opts) {
1125
1304
  for (const file of additionalFiles)
1126
1305
  entries.push({ name: file.name, data: new Uint8Array(readFileSync2(file.path)) });
1127
1306
  const zip = buildZip(entries);
1128
- writeFileSync3(opts.outputPath, zip);
1307
+ writeFileSync4(opts.outputPath, zip);
1129
1308
  return { success: true, outputPath: opts.outputPath };
1130
1309
  } catch (err) {
1131
1310
  return { success: false, error: `Failed to write ZIP: ${err.message}` };
@@ -1158,15 +1337,15 @@ async function createDEB(opts) {
1158
1337
  const desktopContent = linuxDesktopEntry(opts.name, sanitizedName, opts.urlSchemes, opts.launchUrl);
1159
1338
  const tempDir = createTempDir("craft-deb-");
1160
1339
  staging = tempDir;
1161
- const debianDir = join2(tempDir, "DEBIAN");
1162
- const binDir = join2(tempDir, "usr", "bin");
1163
- const applicationsDir = join2(tempDir, "usr", "share", "applications");
1340
+ const debianDir = join3(tempDir, "DEBIAN");
1341
+ const binDir = join3(tempDir, "usr", "bin");
1342
+ const applicationsDir = join3(tempDir, "usr", "share", "applications");
1164
1343
  mkdirSync(debianDir, { recursive: true });
1165
1344
  mkdirSync(binDir, { recursive: true });
1166
1345
  mkdirSync(applicationsDir, { recursive: true });
1167
1346
  const binaryName = sanitizedName;
1168
- copyFileSync(opts.binaryPath, join2(binDir, binaryName));
1169
- chmodSync(join2(binDir, binaryName), 493);
1347
+ copyFileSync(opts.binaryPath, join3(binDir, binaryName));
1348
+ chmodSync(join3(binDir, binaryName), 493);
1170
1349
  const controlContent = `Package: ${sanitizedName}
1171
1350
  Version: ${opts.version}
1172
1351
  Section: utils
@@ -1176,8 +1355,8 @@ Depends: ${opts.dependencies.join(", ")}
1176
1355
  Maintainer: ${maintainer}
1177
1356
  Description: ${description || opts.name}
1178
1357
  `;
1179
- writeFileSync3(join2(debianDir, "control"), controlContent);
1180
- writeFileSync3(join2(applicationsDir, `${binaryName}.desktop`), desktopContent);
1358
+ writeFileSync4(join3(debianDir, "control"), controlContent);
1359
+ writeFileSync4(join3(applicationsDir, `${binaryName}.desktop`), desktopContent);
1181
1360
  const proc = spawn("dpkg-deb", ["--build", tempDir, opts.outputPath]);
1182
1361
  proc.on("close", (code) => {
1183
1362
  removeTempDir(tempDir);
@@ -1201,11 +1380,11 @@ Description: ${description || opts.name}
1201
1380
  async function createRPM(opts) {
1202
1381
  return new Promise((resolve) => {
1203
1382
  try {
1204
- const buildRoot = join2(homedir(), "rpmbuild");
1205
- const specDir = join2(buildRoot, "SPECS");
1206
- const sourcesDir = join2(buildRoot, "SOURCES");
1207
- const buildDir = join2(buildRoot, "BUILD");
1208
- const rpmsDir = join2(buildRoot, "RPMS");
1383
+ const buildRoot = join3(homedir(), "rpmbuild");
1384
+ const specDir = join3(buildRoot, "SPECS");
1385
+ const sourcesDir = join3(buildRoot, "SOURCES");
1386
+ const buildDir = join3(buildRoot, "BUILD");
1387
+ const rpmsDir = join3(buildRoot, "RPMS");
1209
1388
  mkdirSync(specDir, { recursive: true });
1210
1389
  mkdirSync(sourcesDir, { recursive: true });
1211
1390
  mkdirSync(buildDir, { recursive: true });
@@ -1229,7 +1408,7 @@ async function createRPM(opts) {
1229
1408
  }
1230
1409
  return r;
1231
1410
  }).join(", ");
1232
- copyFileSync(opts.binaryPath, join2(sourcesDir, sanitizedName));
1411
+ copyFileSync(opts.binaryPath, join3(sourcesDir, sanitizedName));
1233
1412
  const specContent = `Name: ${sanitizedName}
1234
1413
  Version: ${opts.version}
1235
1414
  Release: 1%{?dist}
@@ -1247,13 +1426,13 @@ install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
1247
1426
  %files
1248
1427
  /usr/bin/${sanitizedName}
1249
1428
  `;
1250
- const specPath = join2(specDir, `${opts.name.toLowerCase()}.spec`);
1251
- writeFileSync3(specPath, specContent);
1429
+ const specPath = join3(specDir, `${opts.name.toLowerCase()}.spec`);
1430
+ writeFileSync4(specPath, specContent);
1252
1431
  const proc = spawn("rpmbuild", ["-bb", specPath]);
1253
1432
  proc.on("close", (code) => {
1254
1433
  if (code === 0) {
1255
1434
  const rpmName = `${opts.name.toLowerCase()}-${opts.version}-1.x86_64.rpm`;
1256
- const builtRpmPath = join2(rpmsDir, "x86_64", rpmName);
1435
+ const builtRpmPath = join3(rpmsDir, "x86_64", rpmName);
1257
1436
  try {
1258
1437
  copyFileSync(builtRpmPath, opts.outputPath);
1259
1438
  resolve({ success: true, outputPath: opts.outputPath });
@@ -1278,22 +1457,22 @@ async function createAppImage(opts) {
1278
1457
  try {
1279
1458
  const appDir = createTempDir("craft-appimage-");
1280
1459
  staging = appDir;
1281
- const appDirPath = join2(appDir, `${opts.name}.AppDir`);
1282
- const binDir = join2(appDirPath, "usr", "bin");
1283
- const shareDir = join2(appDirPath, "usr", "share");
1460
+ const appDirPath = join3(appDir, `${opts.name}.AppDir`);
1461
+ const binDir = join3(appDirPath, "usr", "bin");
1462
+ const shareDir = join3(appDirPath, "usr", "share");
1284
1463
  mkdirSync(binDir, { recursive: true });
1285
1464
  mkdirSync(shareDir, { recursive: true });
1286
1465
  const binaryName = opts.name.toLowerCase();
1287
- copyFileSync(opts.binaryPath, join2(binDir, binaryName));
1288
- chmodSync(join2(binDir, binaryName), 493);
1466
+ copyFileSync(opts.binaryPath, join3(binDir, binaryName));
1467
+ chmodSync(join3(binDir, binaryName), 493);
1289
1468
  const appRunContent = `#!/bin/bash
1290
1469
  SELF=$(readlink -f "$0")
1291
1470
  HERE=\${SELF%/*}
1292
1471
  export PATH="\${HERE}/usr/bin/:\${PATH}"
1293
1472
  exec "\${HERE}/usr/bin/${binaryName}" "$@"
1294
1473
  `;
1295
- writeFileSync3(join2(appDirPath, "AppRun"), appRunContent);
1296
- chmodSync(join2(appDirPath, "AppRun"), 493);
1474
+ writeFileSync4(join3(appDirPath, "AppRun"), appRunContent);
1475
+ chmodSync(join3(appDirPath, "AppRun"), 493);
1297
1476
  const desktopContent = `[Desktop Entry]
1298
1477
  Type=Application
1299
1478
  Name=${opts.name}
@@ -1302,9 +1481,9 @@ Terminal=false
1302
1481
  Categories=Utility;
1303
1482
  Icon=${binaryName}
1304
1483
  `;
1305
- writeFileSync3(join2(appDirPath, `${binaryName}.desktop`), desktopContent);
1484
+ writeFileSync4(join3(appDirPath, `${binaryName}.desktop`), desktopContent);
1306
1485
  if (opts.iconPath && existsSync4(opts.iconPath)) {
1307
- copyFileSync(opts.iconPath, join2(appDirPath, `${binaryName}.png`));
1486
+ copyFileSync(opts.iconPath, join3(appDirPath, `${binaryName}.png`));
1308
1487
  } else {
1309
1488
  const placeholderPng = Buffer.from([
1310
1489
  137,
@@ -1377,7 +1556,7 @@ Icon=${binaryName}
1377
1556
  96,
1378
1557
  130
1379
1558
  ]);
1380
- writeFileSync3(join2(appDirPath, `${binaryName}.png`), placeholderPng);
1559
+ writeFileSync4(join3(appDirPath, `${binaryName}.png`), placeholderPng);
1381
1560
  }
1382
1561
  const proc = spawn("appimagetool", [appDirPath, opts.outputPath], {
1383
1562
  env: { ...process.env, ARCH: "x86_64" }
@@ -1414,6 +1593,8 @@ function detectPlatform() {
1414
1593
  }
1415
1594
  var DEFAULT_DEB_DEPENDENCIES, CRC32_TABLE, URL_SCHEME, MEBIBYTE, HDIUTIL_MAX_ATTEMPTS = 3, runHdiutil = (args) => runTool("hdiutil", args), WINDOWS_NOTIFICATION_ID_FILE = "craft-notification-id.txt";
1416
1595
  var init_package = __esm(() => {
1596
+ init_installer_layout();
1597
+ init_installer_background();
1417
1598
  init_temp_dir();
1418
1599
  DEFAULT_DEB_DEPENDENCIES = ["libgtk-3-0", "libwebkit2gtk-4.1-37", "libnotify-bin"];
1419
1600
  CRC32_TABLE = (() => {
@@ -3047,7 +3228,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
3047
3228
  `);
3048
3229
  }
3049
3230
  // package.json
3050
- var version = "0.0.435";
3231
+ var version = "0.0.442";
3051
3232
 
3052
3233
  // bin/cli.ts
3053
3234
  var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];