craft-native 0.0.436 → 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 (36) 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/CraftNativePedometer.swift +181 -0
  28. package/dist/ios/templates/CraftNativeScreen.swift +76 -0
  29. package/dist/macos/src/index.js +1 -1
  30. package/dist/macos/src/toolchain.d.ts +1 -1
  31. package/dist/macos/templates/CraftMacApplication.swift +124 -39
  32. package/dist/macos/templates/CraftMacRenderer.swift +111 -33
  33. package/dist/macos/templates/CraftMacRuntime.swift +270 -81
  34. package/dist/package.d.ts +40 -0
  35. package/dist/types.d.ts +26 -0
  36. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -77,8 +77,8 @@ __export(exports_updater, {
77
77
 
78
78
  // src/index.ts
79
79
  import { execFile as execFile2, spawn as spawn4 } from "child_process";
80
- import { writeFileSync as writeFileSync4 } from "fs";
81
- import { join as join5 } from "path";
80
+ import { writeFileSync as writeFileSync5 } from "fs";
81
+ import { join as join6 } from "path";
82
82
  import { promisify as promisify2 } from "util";
83
83
 
84
84
  // src/binary-resolver.ts
@@ -117,7 +117,7 @@ function craftBinaryNotFoundMessage(triedPath) {
117
117
  `);
118
118
  }
119
119
  // package.json
120
- var version = "0.0.436";
120
+ var version = "0.0.442";
121
121
 
122
122
  // src/sdk-version.ts
123
123
  var SDK_VERSION = version;
@@ -236,6 +236,134 @@ function removeTempDir(dir) {
236
236
  unhook();
237
237
  }
238
238
 
239
+ // src/installer-layout.ts
240
+ import { execFileSync } from "child_process";
241
+ import { statSync as statSync2, writeFileSync as writeFileSync2 } from "fs";
242
+ import { join as join2 } from "path";
243
+ /*!
244
+ * Format implementation adapted from MIT-licensed references:
245
+ * Copyright (c) 2020 Kenty Gwend
246
+ * Copyright (c) 2026 John Campion Jr
247
+ * Copyright (c) 2014 Alastair Houghton
248
+ * Copyright (c) 2022 Russell Keith-Magee
249
+ *
250
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
251
+ * of this software and associated documentation files (the "Software"), to deal
252
+ * in the Software without restriction, including without limitation the rights
253
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
254
+ * copies of the Software, and to permit persons to whom the Software is
255
+ * furnished to do so, subject to the following conditions:
256
+ * The above copyright notice and this permission notice shall be included in
257
+ * all copies or substantial portions of the Software.
258
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
259
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
260
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
261
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
262
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
263
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
264
+ * SOFTWARE.
265
+ */
266
+ var number = (value, bytes = 4) => {
267
+ const out = Buffer.alloc(bytes);
268
+ out.writeUIntBE(value, 0, bytes);
269
+ return out;
270
+ };
271
+ var unicode = (value) => Buffer.from(value, "utf16le").swap16();
272
+ var pascal = (value, size) => {
273
+ const out = Buffer.alloc(size);
274
+ const bytes = Buffer.from(value).subarray(0, size - 1);
275
+ out[0] = bytes.length;
276
+ bytes.copy(out, 1);
277
+ return out;
278
+ };
279
+ var tag = (id, data) => Buffer.concat([number(id, 2), number(data.length, 2), data, Buffer.alloc(data.length % 2)]);
280
+ function backgroundAlias(mount, volume) {
281
+ const folder = ".background";
282
+ const filename = "installer.png";
283
+ const directory = statSync2(join2(mount, folder));
284
+ const file = statSync2(join2(mount, folder, filename));
285
+ const date = (ms) => Math.floor(ms / 1000) + 2082844800;
286
+ const volumeDate = date(statSync2(mount).birthtimeMs);
287
+ const fileDate = date(file.birthtimeMs);
288
+ const preciseDate = (value) => {
289
+ const out = Buffer.alloc(8);
290
+ out.writeBigUInt64BE(BigInt(value) * 65536n);
291
+ return out;
292
+ };
293
+ const body = Buffer.concat([
294
+ number(0, 2),
295
+ pascal(volume, 28),
296
+ number(volumeDate),
297
+ Buffer.from("H+"),
298
+ number(0, 2),
299
+ number(directory.ino),
300
+ pascal(filename, 64),
301
+ number(file.ino),
302
+ number(fileDate),
303
+ Buffer.alloc(8),
304
+ number(65535, 2),
305
+ number(65535, 2),
306
+ Buffer.alloc(16),
307
+ tag(0, Buffer.from(folder)),
308
+ tag(16, preciseDate(volumeDate)),
309
+ tag(17, preciseDate(fileDate)),
310
+ tag(1, number(directory.ino)),
311
+ tag(2, Buffer.from(`${volume}:${folder}:\x00${filename}`)),
312
+ tag(14, Buffer.concat([number(filename.length, 2), unicode(filename)])),
313
+ tag(15, Buffer.concat([number(volume.length, 2), unicode(volume)])),
314
+ tag(18, Buffer.from(`/${folder}/${filename}`)),
315
+ tag(19, Buffer.from(`/Volumes/${volume}`)),
316
+ number(65535, 2),
317
+ number(0, 2)
318
+ ]);
319
+ return Buffer.concat([Buffer.alloc(4), number(body.length + 8, 2), number(2, 2), body]);
320
+ }
321
+ function plist(values) {
322
+ const escape = (value) => value.replaceAll("&", "&amp;").replaceAll("<", "&lt;").replaceAll(">", "&gt;");
323
+ const entries = Object.entries(values).map(([key, value]) => {
324
+ 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>`;
325
+ return `<key>${key}</key>${data}`;
326
+ }).join("");
327
+ return execFileSync("plutil", ["-convert", "binary1", "-o", "-", "-"], { input: `<?xml version="1.0"?><plist version="1.0"><dict>${entries}</dict></plist>` });
328
+ }
329
+ function writeInstallerLayout(mount, volume, appName) {
330
+ const records = [];
331
+ const blob = (name, code, data) => records.push({ name, code, type: "blob", data: Buffer.concat([number(data.length), data]) });
332
+ blob(".", "bwsp", plist({ ShowStatusBar: false, ShowToolbar: false, ShowTabView: false, ShowSidebar: false, ContainerShowSidebar: false, ShowPathbar: false, SidebarWidth: 0, PreviewPaneVisibility: false, WindowBounds: "{{100, 100}, {660, 460}}" }));
333
+ 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 }));
334
+ records.push({ name: ".", code: "vSrn", type: "long", data: number(1) });
335
+ records.push({ name: ".", code: "icvl", type: "type", data: Buffer.from("icnv") });
336
+ records.push({ name: ".", code: "vstl", type: "type", data: Buffer.from("icnv") });
337
+ for (const [name, x, y] of [[appName, 160, 190], ["Applications", 500, 190], [".background", 500, 600]])
338
+ blob(name, "Iloc", Buffer.concat([number(x), number(y), Buffer.from("ffffffffffff0000", "hex")]));
339
+ records.sort((a, b) => {
340
+ const left = a.name.normalize("NFD").toLowerCase();
341
+ const right = b.name.normalize("NFD").toLowerCase();
342
+ return left < right ? -1 : left > right ? 1 : a.code < b.code ? -1 : 1;
343
+ });
344
+ const leaf = Buffer.concat([number(0), number(records.length), ...records.map((record) => {
345
+ const name = record.name.normalize("NFD");
346
+ return Buffer.concat([number(name.length), unicode(name), Buffer.from(record.code + record.type), record.data]);
347
+ })]);
348
+ if (leaf.length > 4096)
349
+ throw new Error("Installer layout exceeds the Finder store leaf capacity");
350
+ const offsets = Buffer.alloc(1024);
351
+ offsets.writeUInt32BE(2048 | 11, 0);
352
+ offsets.writeUInt32BE(32 | 5, 4);
353
+ offsets.writeUInt32BE(4096 | 12, 8);
354
+ const free = Array.from({ length: 32 }, (_, power) => power >= 6 && power <= 10 || power >= 13 && power <= 30 ? Buffer.concat([number(1), number(2 ** power)]) : number(0));
355
+ const root = Buffer.concat([number(3), number(0), offsets, number(1), Buffer.from([4]), Buffer.from("DSDB"), number(1), ...free]);
356
+ const out = Buffer.alloc(8196);
357
+ Buffer.concat([number(1), Buffer.from("Bud1"), number(2048), number(root.length), number(2048), Buffer.alloc(16)]).copy(out);
358
+ Buffer.concat([number(2), number(0), number(records.length), number(1), number(4096)]).copy(out, 36);
359
+ root.copy(out, 2052);
360
+ leaf.copy(out, 4100);
361
+ writeFileSync2(join2(mount, ".DS_Store"), out);
362
+ }
363
+
364
+ // src/installer-background.ts
365
+ var 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");
366
+
239
367
  // src/package.ts
240
368
  import { spawn, spawnSync } from "child_process";
241
369
  import { createHash } from "crypto";
@@ -252,10 +380,11 @@ import {
252
380
  readSync,
253
381
  readdirSync as readdirSync2,
254
382
  rmSync as rmSync2,
255
- writeFileSync as writeFileSync2
383
+ symlinkSync,
384
+ writeFileSync as writeFileSync3
256
385
  } from "fs";
257
386
  import { homedir } from "os";
258
- import { basename, dirname, join as join2, resolve } from "path";
387
+ import { basename, dirname, join as join3, resolve } from "path";
259
388
  import { deflateRawSync } from "zlib";
260
389
  var DEFAULT_DEB_DEPENDENCIES = ["libgtk-3-0", "libwebkit2gtk-4.1-37", "libnotify-bin"];
261
390
  var CRC32_TABLE = (() => {
@@ -344,7 +473,7 @@ async function packageApp(config) {
344
473
  throw new Error(`Binary not found: ${config.binaryPath}`);
345
474
  }
346
475
  const platforms = config.platforms || [detectPlatform()];
347
- const outDir = config.outDir || join2(process.cwd(), "dist");
476
+ const outDir = config.outDir || join3(process.cwd(), "dist");
348
477
  if (!existsSync3(outDir)) {
349
478
  mkdirSync(outDir, { recursive: true });
350
479
  }
@@ -366,7 +495,7 @@ async function packageApp(config) {
366
495
  function macOSAppStoreRuntimePath(providerPath) {
367
496
  const providerName = basename(providerPath);
368
497
  const storeName = providerName.startsWith("craft-webview") ? "craft-webview-app-store" : "craft-app-store";
369
- const runtime = providerName === storeName ? providerPath : join2(dirname(providerPath), storeName);
498
+ const runtime = providerName === storeName ? providerPath : join3(dirname(providerPath), storeName);
370
499
  if (!existsSync3(runtime))
371
500
  throw new Error("App Store packaging requires Pantry\u2019s craft-app-store runtime. Upgrade Craft with Pantry before building.");
372
501
  const bytes = readFileSync(runtime);
@@ -393,7 +522,7 @@ async function packageMacOS(config, outDir) {
393
522
  return [{ success: false, platform: "macos", format: "app", error: error.message }];
394
523
  }
395
524
  }
396
- const appBundlePath = join2(outDir, `${name}.app`);
525
+ const appBundlePath = join3(outDir, `${name}.app`);
397
526
  const appBundle = opts.appBundlePath ? copyMacOSAppBundle(opts.appBundlePath, appBundlePath) : createMacOSAppBundle({
398
527
  name,
399
528
  version,
@@ -422,25 +551,25 @@ async function packageMacOS(config, outDir) {
422
551
  return results;
423
552
  }
424
553
  try {
425
- const contents = join2(appBundlePath, "Contents");
426
- if (opts.appStore && opts.appBundlePath && existsSync3(join2(contents, "Resources", "craft.json"))) {
554
+ const contents = join3(appBundlePath, "Contents");
555
+ if (opts.appStore && opts.appBundlePath && existsSync3(join3(contents, "Resources", "craft.json"))) {
427
556
  if (!nativeRuntimePath)
428
557
  throw new Error("App Store packaging of a prebuilt Craft bundle requires macos.nativeRuntimePath from Pantry.");
429
- const plist = join2(contents, "Info.plist");
558
+ const plist = join3(contents, "Info.plist");
430
559
  const executable = spawnSync("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", plist], { encoding: "utf8" });
431
560
  const name = executable.stdout.trim();
432
561
  if (executable.status !== 0 || !name || basename(name) !== name || name === "." || name === "..")
433
562
  throw new Error("Prebuilt Craft bundle has an invalid CFBundleExecutable");
434
- copyFileSync(nativeRuntimePath, join2(contents, "MacOS", name));
435
- chmodSync(join2(contents, "MacOS", name), 493);
563
+ copyFileSync(nativeRuntimePath, join3(contents, "MacOS", name));
564
+ chmodSync(join3(contents, "MacOS", name), 493);
436
565
  }
437
566
  if (opts.provisioningProfile) {
438
- const profile = join2(contents, "embedded.provisionprofile");
567
+ const profile = join3(contents, "embedded.provisionprofile");
439
568
  copyFileSync(opts.provisioningProfile, profile);
440
569
  chmodSync(profile, 420);
441
570
  }
442
571
  if (opts.privacyManifest)
443
- copyFileSync(opts.privacyManifest, join2(contents, "Resources", "PrivacyInfo.xcprivacy"));
572
+ copyFileSync(opts.privacyManifest, join3(contents, "Resources", "PrivacyInfo.xcprivacy"));
444
573
  if (opts.appBundlePath) {
445
574
  const metadata = {
446
575
  CFBundleVersion: opts.buildNumber,
@@ -450,13 +579,13 @@ async function packageMacOS(config, outDir) {
450
579
  };
451
580
  if (config.iconPath) {
452
581
  const icon = basename(config.iconPath);
453
- copyFileSync(config.iconPath, join2(contents, "Resources", icon));
582
+ copyFileSync(config.iconPath, join3(contents, "Resources", icon));
454
583
  metadata.CFBundleIconFile = icon;
455
584
  }
456
585
  for (const [key, value] of Object.entries(metadata)) {
457
586
  if (value === undefined)
458
587
  continue;
459
- const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join2(contents, "Info.plist")]);
588
+ const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join3(contents, "Info.plist")]);
460
589
  if (!result.success)
461
590
  throw new Error(result.error);
462
591
  }
@@ -477,8 +606,8 @@ async function packageMacOS(config, outDir) {
477
606
  }
478
607
  results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
479
608
  if (opts.dmg !== false) {
480
- const outputPath = join2(outDir, `${name}-${version}.dmg`);
481
- let dmgResult = await createDMG({ appBundlePath, outputPath, volumeName: name });
609
+ const outputPath = join3(outDir, `${name}-${version}.dmg`);
610
+ let dmgResult = await createDiskImage({ appBundlePath, outputPath, volumeName: name });
482
611
  if (dmgResult.success && opts.signIdentity) {
483
612
  const signed = await runTool("codesign", codesignArguments({
484
613
  path: outputPath,
@@ -502,7 +631,7 @@ async function packageMacOS(config, outDir) {
502
631
  results.push(...await notarizeIfRequested(opts, outputPath, "dmg"));
503
632
  }
504
633
  if (opts.pkg || opts.appStore) {
505
- const outputPath = join2(outDir, `${name}-${version}.pkg`);
634
+ const outputPath = join3(outDir, `${name}-${version}.pkg`);
506
635
  const pkgResult = await createPKG({
507
636
  appBundlePath,
508
637
  outputPath,
@@ -537,7 +666,7 @@ async function notarizeIfRequested(opts, artifactPath, format) {
537
666
  }
538
667
  const scratch = format === "app" ? createTempDir("craft-notarize-") : undefined;
539
668
  try {
540
- const submission = scratch ? join2(scratch, "app.zip") : artifactPath;
669
+ const submission = scratch ? join3(scratch, "app.zip") : artifactPath;
541
670
  if (scratch) {
542
671
  const zipped = await runTool("ditto", ["-c", "-k", "--keepParent", artifactPath, submission]);
543
672
  if (!zipped.success)
@@ -575,7 +704,7 @@ async function packageWindows(config, outDir) {
575
704
  name,
576
705
  version,
577
706
  binaryPath: config.binaryPath,
578
- outputPath: join2(outDir, `${name}-${version}.msi`),
707
+ outputPath: join3(outDir, `${name}-${version}.msi`),
579
708
  manufacturer: config.author || "Unknown",
580
709
  architecture: opts.architecture || windowsArchitecture(process.arch),
581
710
  additionalFiles: opts.additionalFiles,
@@ -599,7 +728,7 @@ async function packageWindows(config, outDir) {
599
728
  manufacturer: config.author || "Unknown",
600
729
  binaryPath: config.binaryPath,
601
730
  additionalFiles: opts.additionalFiles,
602
- outputPath: join2(outDir, `${name}-${version}-windows.zip`)
731
+ outputPath: join3(outDir, `${name}-${version}-windows.zip`)
603
732
  });
604
733
  results.push({
605
734
  success: zipResult.success,
@@ -620,7 +749,7 @@ async function packageLinux(config, outDir) {
620
749
  name,
621
750
  version,
622
751
  binaryPath: config.binaryPath,
623
- outputPath: join2(outDir, `${name}_${version}_amd64.deb`),
752
+ outputPath: join3(outDir, `${name}_${version}_amd64.deb`),
624
753
  description: config.description || "",
625
754
  maintainer: config.author || "Unknown",
626
755
  dependencies: opts.debDependencies || [...DEFAULT_DEB_DEPENDENCIES],
@@ -640,7 +769,7 @@ async function packageLinux(config, outDir) {
640
769
  name,
641
770
  version,
642
771
  binaryPath: config.binaryPath,
643
- outputPath: join2(outDir, `${name}-${version}-1.x86_64.rpm`),
772
+ outputPath: join3(outDir, `${name}-${version}-1.x86_64.rpm`),
644
773
  description: config.description || "",
645
774
  requires: opts.rpmDependencies || ["gtk3", "webkit2gtk3"]
646
775
  });
@@ -657,7 +786,7 @@ async function packageLinux(config, outDir) {
657
786
  name,
658
787
  version,
659
788
  binaryPath: config.binaryPath,
660
- outputPath: join2(outDir, `${name}-${version}-x86_64.AppImage`),
789
+ outputPath: join3(outDir, `${name}-${version}-x86_64.AppImage`),
661
790
  iconPath: config.iconPath
662
791
  });
663
792
  results.push({
@@ -768,13 +897,13 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
768
897
  try {
769
898
  let helperEntitlements = opts.helperEntitlements;
770
899
  if (opts.appStore && !helperEntitlements) {
771
- helperEntitlements = join2(scratch, "inherit.plist");
772
- writeFileSync2(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>');
900
+ helperEntitlements = join3(scratch, "inherit.plist");
901
+ 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>');
773
902
  }
774
- const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join2(app, "Contents", "Info.plist")]);
903
+ const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join3(app, "Contents", "Info.plist")]);
775
904
  if (!extracted.success)
776
905
  throw new Error(extracted.error);
777
- const main = join2(app, "Contents", "MacOS", extracted.stdout.trim());
906
+ const main = join3(app, "Contents", "MacOS", extracted.stdout.trim());
778
907
  const sign = async (path, entitlements, identifier) => {
779
908
  const signed = await runTool("codesign", codesignArguments({ path, identity: opts.signIdentity, entitlements, hardenedRuntime, identifier, keychain: opts.signingKeychain, deep: false }));
780
909
  if (!signed.success)
@@ -782,7 +911,7 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
782
911
  };
783
912
  const walk = async (directory) => {
784
913
  for (const entry of readdirSync2(directory)) {
785
- const path = join2(directory, entry);
914
+ const path = join3(directory, entry);
786
915
  const stat = lstatSync(path);
787
916
  if (stat.isSymbolicLink())
788
917
  continue;
@@ -796,7 +925,7 @@ async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
796
925
  }
797
926
  }
798
927
  };
799
- await walk(join2(app, "Contents"));
928
+ await walk(join3(app, "Contents"));
800
929
  await sign(app, opts.entitlements);
801
930
  const verified = await runTool("codesign", ["--verify", "--deep", "--strict", app]);
802
931
  if (!verified.success)
@@ -864,8 +993,8 @@ function notarytoolArguments(opts) {
864
993
  }
865
994
  function copyMacOSAppBundle(source, destination) {
866
995
  try {
867
- const info = join2(source, "Contents", "Info.plist");
868
- if (!existsSync3(info) || !existsSync3(join2(source, "Contents", "MacOS")))
996
+ const info = join3(source, "Contents", "Info.plist");
997
+ if (!existsSync3(info) || !existsSync3(join3(source, "Contents", "MacOS")))
869
998
  throw new Error(`Invalid prebuilt macOS application: ${source}`);
870
999
  if (resolve(source) !== resolve(destination)) {
871
1000
  rmSync2(destination, { recursive: true, force: true });
@@ -877,29 +1006,29 @@ function copyMacOSAppBundle(source, destination) {
877
1006
  }
878
1007
  }
879
1008
  function macOSRuntimeExecutablePath(appBundlePath) {
880
- return join2(appBundlePath, "Contents", "Helpers", "CraftRuntime.app", "Contents", "MacOS", "craft");
1009
+ return join3(appBundlePath, "Contents", "Helpers", "CraftRuntime.app", "Contents", "MacOS", "craft");
881
1010
  }
882
1011
  function createMacOSAppBundle(opts) {
883
1012
  try {
884
1013
  const { name, binaryPath, iconPath, provisioningProfile, additionalExecutables, outputPath } = opts;
885
- const contents = join2(outputPath, "Contents");
886
- const macOS = join2(contents, "MacOS");
1014
+ const contents = join3(outputPath, "Contents");
1015
+ const macOS = join3(contents, "MacOS");
887
1016
  mkdirSync(macOS, { recursive: true });
888
- mkdirSync(join2(contents, "Resources"), { recursive: true });
889
- copyFileSync(opts.nativeHost ? opts.nativeRuntimePath : binaryPath, join2(macOS, name));
890
- chmodSync(join2(macOS, name), 493);
1017
+ mkdirSync(join3(contents, "Resources"), { recursive: true });
1018
+ copyFileSync(opts.nativeHost ? opts.nativeRuntimePath : binaryPath, join3(macOS, name));
1019
+ chmodSync(join3(macOS, name), 493);
891
1020
  for (const executable of additionalExecutables || []) {
892
1021
  if (!existsSync3(executable))
893
1022
  return { success: false, error: `Additional executable not found: ${executable}` };
894
- const destination = join2(macOS, basename(executable));
1023
+ const destination = join3(macOS, basename(executable));
895
1024
  copyFileSync(executable, destination);
896
1025
  chmodSync(destination, 493);
897
1026
  }
898
1027
  if (opts.nativeHost) {
899
- const backend = join2(macOS, "craft-backend");
1028
+ const backend = join3(macOS, "craft-backend");
900
1029
  copyFileSync(binaryPath, backend);
901
1030
  chmodSync(backend, 493);
902
- writeFileSync2(join2(contents, "Resources", "craft.json"), `${JSON.stringify({
1031
+ writeFileSync3(join3(contents, "Resources", "craft.json"), `${JSON.stringify({
903
1032
  title: name,
904
1033
  appName: name,
905
1034
  ...opts.nativeWindow,
@@ -909,14 +1038,14 @@ function createMacOSAppBundle(opts) {
909
1038
  } else if (opts.nativeRuntimePath) {
910
1039
  const helper = macOSRuntimeExecutablePath(outputPath);
911
1040
  const helperContents = resolve(helper, "..", "..");
912
- mkdirSync(join2(helperContents, "MacOS"), { recursive: true });
1041
+ mkdirSync(join3(helperContents, "MacOS"), { recursive: true });
913
1042
  copyFileSync(opts.nativeRuntimePath, helper);
914
1043
  chmodSync(helper, 493);
915
1044
  if (iconPath) {
916
- mkdirSync(join2(helperContents, "Resources"), { recursive: true });
917
- copyFileSync(iconPath, join2(helperContents, "Resources", "icon.icns"));
1045
+ mkdirSync(join3(helperContents, "Resources"), { recursive: true });
1046
+ copyFileSync(iconPath, join3(helperContents, "Resources", "icon.icns"));
918
1047
  }
919
- writeFileSync2(join2(helperContents, "Info.plist"), macOSInfoPlist({
1048
+ writeFileSync3(join3(helperContents, "Info.plist"), macOSInfoPlist({
920
1049
  name,
921
1050
  executableName: "craft",
922
1051
  version: opts.version,
@@ -932,14 +1061,14 @@ function createMacOSAppBundle(opts) {
932
1061
  if (!existsSync3(iconPath))
933
1062
  return { success: false, error: `Icon not found: ${iconPath}` };
934
1063
  iconName = basename(iconPath).replace(/\.icns$/i, "");
935
- copyFileSync(iconPath, join2(contents, "Resources", `${iconName}.icns`));
1064
+ copyFileSync(iconPath, join3(contents, "Resources", `${iconName}.icns`));
936
1065
  }
937
1066
  if (provisioningProfile) {
938
1067
  if (!existsSync3(provisioningProfile))
939
1068
  return { success: false, error: `Provisioning profile not found: ${provisioningProfile}` };
940
- copyFileSync(provisioningProfile, join2(contents, "embedded.provisionprofile"));
1069
+ copyFileSync(provisioningProfile, join3(contents, "embedded.provisionprofile"));
941
1070
  }
942
- writeFileSync2(join2(contents, "Info.plist"), macOSInfoPlist({ ...opts, iconName }));
1071
+ writeFileSync3(join3(contents, "Info.plist"), macOSInfoPlist({ ...opts, iconName }));
943
1072
  return { success: true };
944
1073
  } catch (error) {
945
1074
  return { success: false, error: error.message };
@@ -950,7 +1079,7 @@ function pathContentBytes(path) {
950
1079
  const stat = lstatSync(path);
951
1080
  if (!stat.isDirectory())
952
1081
  return stat.size;
953
- return readdirSync2(path).reduce((total, entry) => total + pathContentBytes(join2(path, entry)), 0);
1082
+ return readdirSync2(path).reduce((total, entry) => total + pathContentBytes(join3(path, entry)), 0);
954
1083
  }
955
1084
  function dmgCapacityMegabytes(contentBytes) {
956
1085
  if (!Number.isSafeInteger(contentBytes) || contentBytes < 0)
@@ -965,6 +1094,8 @@ function dmgCreateArguments(opts, contentBytes) {
965
1094
  opts.volumeName,
966
1095
  "-srcfolder",
967
1096
  opts.appBundlePath,
1097
+ "-fs",
1098
+ "HFS+",
968
1099
  "-size",
969
1100
  `${dmgCapacityMegabytes(contentBytes)}m`,
970
1101
  "-ov",
@@ -1000,24 +1131,70 @@ function runTool(tool, args) {
1000
1131
  });
1001
1132
  }
1002
1133
  var runHdiutil = (args) => runTool("hdiutil", args);
1003
- async function createDMG(opts) {
1004
- if (!/^[^/:\n]{1,27}$/.test(opts.volumeName))
1005
- return { success: false, error: `Invalid DMG volume name "${opts.volumeName}"; must be 1..27 chars without /, :, or newline` };
1006
- const args = dmgCreateArguments(opts, pathContentBytes(opts.appBundlePath));
1007
- const failures = [];
1008
- for (let attempt = 1;attempt <= HDIUTIL_MAX_ATTEMPTS; attempt++) {
1009
- const result = await runHdiutil(args);
1134
+ async function detachDiskImage(mount, options = {}) {
1135
+ const run = options.run ?? runHdiutil;
1136
+ const wait = options.wait ?? ((ms) => new Promise((resolve) => {
1137
+ setTimeout(resolve, ms);
1138
+ }));
1139
+ for (let attempt = 1;; attempt++) {
1140
+ const forced = attempt >= HDIUTIL_MAX_ATTEMPTS;
1141
+ const result = await run(forced ? ["detach", mount, "-force"] : ["detach", mount]);
1010
1142
  if (result.success)
1011
- return { success: true, outputPath: opts.outputPath };
1012
- failures.push(`attempt ${attempt}: ${result.error}`);
1143
+ return { success: true };
1013
1144
  if (!shouldRetryHdiutil(result.error, attempt))
1014
- return { success: false, error: failures.join(`
1015
- `) };
1016
- rmSync2(opts.outputPath, { force: true });
1017
- await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
1145
+ return { success: false, error: result.error };
1146
+ await wait(attempt * 2000);
1147
+ }
1148
+ }
1149
+ async function createDiskImage(opts) {
1150
+ if (!/^[^/:\n]{1,27}$/.test(opts.volumeName))
1151
+ return { success: false, error: `Invalid DMG volume name "${opts.volumeName}"; must be 1..27 chars without /, :, or newline` };
1152
+ const scratch = createTempDir("craft-installer-");
1153
+ const payload = join3(scratch, "payload");
1154
+ const mount = join3(scratch, "mount");
1155
+ const writable = join3(scratch, "installer.dmg");
1156
+ let mounted = false;
1157
+ const run = async (tool, args) => {
1158
+ const result = await runTool(tool, args);
1159
+ if (!result.success)
1160
+ throw new Error(result.error);
1161
+ return result;
1162
+ };
1163
+ try {
1164
+ mkdirSync(payload);
1165
+ mkdirSync(mount);
1166
+ const bundleName = basename(opts.appBundlePath);
1167
+ await run("ditto", [opts.appBundlePath, join3(payload, bundleName)]);
1168
+ symlinkSync("/Applications", join3(payload, "Applications"));
1169
+ mkdirSync(join3(payload, ".background"));
1170
+ writeFileSync3(join3(payload, ".background", "installer.png"), installerBackground);
1171
+ const args = dmgCreateArguments({ ...opts, appBundlePath: payload, outputPath: writable }, pathContentBytes(payload));
1172
+ args[args.indexOf("ULMO")] = "UDRW";
1173
+ for (let attempt = 1;; attempt++) {
1174
+ const result = await runHdiutil(args);
1175
+ if (result.success)
1176
+ break;
1177
+ if (!shouldRetryHdiutil(result.error, attempt))
1178
+ throw new Error(result.error);
1179
+ rmSync2(writable, { force: true });
1180
+ await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
1181
+ }
1182
+ await run("hdiutil", ["attach", writable, "-nobrowse", "-mountpoint", mount]);
1183
+ mounted = true;
1184
+ writeInstallerLayout(mount, opts.volumeName, bundleName);
1185
+ const detached = await detachDiskImage(mount);
1186
+ if (!detached.success)
1187
+ throw new Error(detached.error);
1188
+ mounted = false;
1189
+ await run("hdiutil", ["convert", writable, "-format", "ULMO", "-ov", "-o", opts.outputPath]);
1190
+ return { success: true, outputPath: opts.outputPath };
1191
+ } catch (error) {
1192
+ return { success: false, error: error instanceof Error ? error.message : String(error) };
1193
+ } finally {
1194
+ if (mounted)
1195
+ await runTool("hdiutil", ["detach", mount, "-force"]);
1196
+ removeTempDir(scratch);
1018
1197
  }
1019
- return { success: false, error: failures.join(`
1020
- `) };
1021
1198
  }
1022
1199
  function pkgbuildComponentPlist(rootRelativeBundlePath) {
1023
1200
  return `<?xml version="1.0" encoding="UTF-8"?>
@@ -1074,14 +1251,14 @@ async function createPKG(opts) {
1074
1251
  }
1075
1252
  const tempDir = createTempDir("craft-pkg-");
1076
1253
  try {
1077
- const root = join2(tempDir, "root");
1078
- const appsDir = join2(root, "Applications");
1254
+ const root = join3(tempDir, "root");
1255
+ const appsDir = join3(root, "Applications");
1079
1256
  mkdirSync(appsDir, { recursive: true, mode: 493 });
1080
1257
  chmodSync(root, 493);
1081
1258
  const bundleName = basename(opts.appBundlePath);
1082
- cpSync(opts.appBundlePath, join2(appsDir, bundleName), { recursive: true });
1083
- const componentPlistPath = join2(tempDir, "component.plist");
1084
- writeFileSync2(componentPlistPath, pkgbuildComponentPlist(`Applications/${bundleName}`));
1259
+ cpSync(opts.appBundlePath, join3(appsDir, bundleName), { recursive: true });
1260
+ const componentPlistPath = join3(tempDir, "component.plist");
1261
+ writeFileSync3(componentPlistPath, pkgbuildComponentPlist(`Applications/${bundleName}`));
1085
1262
  const built = await runTool("pkgbuild", pkgbuildArguments({
1086
1263
  root,
1087
1264
  componentPlistPath,
@@ -1216,14 +1393,14 @@ async function createMSI(opts) {
1216
1393
  try {
1217
1394
  const binaryName = windowsExecutableName(opts.name);
1218
1395
  const additionalFiles = windowsCompanionFiles(opts.additionalFiles, binaryName);
1219
- const sourcePath = join2(tempDir, binaryName);
1220
- const wxsPath = join2(tempDir, "installer.wxs");
1221
- const wixobjPath = join2(tempDir, "installer.wixobj");
1396
+ const sourcePath = join3(tempDir, binaryName);
1397
+ const wxsPath = join3(tempDir, "installer.wxs");
1398
+ const wixobjPath = join3(tempDir, "installer.wixobj");
1222
1399
  copyFileSync(opts.binaryPath, sourcePath);
1223
- writeFileSync2(join2(tempDir, WINDOWS_NOTIFICATION_ID_FILE), windowsNotificationAppId(opts.name, opts.manufacturer));
1400
+ writeFileSync3(join3(tempDir, WINDOWS_NOTIFICATION_ID_FILE), windowsNotificationAppId(opts.name, opts.manufacturer));
1224
1401
  for (const file of additionalFiles)
1225
- copyFileSync(file.path, join2(tempDir, file.name));
1226
- writeFileSync2(wxsPath, renderWixSource(opts, binaryName, additionalFiles.map((file) => file.name)));
1402
+ copyFileSync(file.path, join3(tempDir, file.name));
1403
+ writeFileSync3(wxsPath, renderWixSource(opts, binaryName, additionalFiles.map((file) => file.name)));
1227
1404
  await runCommand("candle.exe", candleArguments(opts.architecture, wixobjPath, wxsPath), tempDir);
1228
1405
  await runCommand("light.exe", ["-nologo", "-sval", "-out", opts.outputPath, wixobjPath], tempDir);
1229
1406
  if (opts.certificatePath) {
@@ -1252,7 +1429,7 @@ async function createZIP(opts) {
1252
1429
  for (const file of additionalFiles)
1253
1430
  entries.push({ name: file.name, data: new Uint8Array(readFileSync(file.path)) });
1254
1431
  const zip = buildZip(entries);
1255
- writeFileSync2(opts.outputPath, zip);
1432
+ writeFileSync3(opts.outputPath, zip);
1256
1433
  return { success: true, outputPath: opts.outputPath };
1257
1434
  } catch (err) {
1258
1435
  return { success: false, error: `Failed to write ZIP: ${err.message}` };
@@ -1285,15 +1462,15 @@ async function createDEB(opts) {
1285
1462
  const desktopContent = linuxDesktopEntry(opts.name, sanitizedName, opts.urlSchemes, opts.launchUrl);
1286
1463
  const tempDir = createTempDir("craft-deb-");
1287
1464
  staging = tempDir;
1288
- const debianDir = join2(tempDir, "DEBIAN");
1289
- const binDir = join2(tempDir, "usr", "bin");
1290
- const applicationsDir = join2(tempDir, "usr", "share", "applications");
1465
+ const debianDir = join3(tempDir, "DEBIAN");
1466
+ const binDir = join3(tempDir, "usr", "bin");
1467
+ const applicationsDir = join3(tempDir, "usr", "share", "applications");
1291
1468
  mkdirSync(debianDir, { recursive: true });
1292
1469
  mkdirSync(binDir, { recursive: true });
1293
1470
  mkdirSync(applicationsDir, { recursive: true });
1294
1471
  const binaryName = sanitizedName;
1295
- copyFileSync(opts.binaryPath, join2(binDir, binaryName));
1296
- chmodSync(join2(binDir, binaryName), 493);
1472
+ copyFileSync(opts.binaryPath, join3(binDir, binaryName));
1473
+ chmodSync(join3(binDir, binaryName), 493);
1297
1474
  const controlContent = `Package: ${sanitizedName}
1298
1475
  Version: ${opts.version}
1299
1476
  Section: utils
@@ -1303,8 +1480,8 @@ Depends: ${opts.dependencies.join(", ")}
1303
1480
  Maintainer: ${maintainer}
1304
1481
  Description: ${description || opts.name}
1305
1482
  `;
1306
- writeFileSync2(join2(debianDir, "control"), controlContent);
1307
- writeFileSync2(join2(applicationsDir, `${binaryName}.desktop`), desktopContent);
1483
+ writeFileSync3(join3(debianDir, "control"), controlContent);
1484
+ writeFileSync3(join3(applicationsDir, `${binaryName}.desktop`), desktopContent);
1308
1485
  const proc = spawn("dpkg-deb", ["--build", tempDir, opts.outputPath]);
1309
1486
  proc.on("close", (code) => {
1310
1487
  removeTempDir(tempDir);
@@ -1328,11 +1505,11 @@ Description: ${description || opts.name}
1328
1505
  async function createRPM(opts) {
1329
1506
  return new Promise((resolve) => {
1330
1507
  try {
1331
- const buildRoot = join2(homedir(), "rpmbuild");
1332
- const specDir = join2(buildRoot, "SPECS");
1333
- const sourcesDir = join2(buildRoot, "SOURCES");
1334
- const buildDir = join2(buildRoot, "BUILD");
1335
- const rpmsDir = join2(buildRoot, "RPMS");
1508
+ const buildRoot = join3(homedir(), "rpmbuild");
1509
+ const specDir = join3(buildRoot, "SPECS");
1510
+ const sourcesDir = join3(buildRoot, "SOURCES");
1511
+ const buildDir = join3(buildRoot, "BUILD");
1512
+ const rpmsDir = join3(buildRoot, "RPMS");
1336
1513
  mkdirSync(specDir, { recursive: true });
1337
1514
  mkdirSync(sourcesDir, { recursive: true });
1338
1515
  mkdirSync(buildDir, { recursive: true });
@@ -1356,7 +1533,7 @@ async function createRPM(opts) {
1356
1533
  }
1357
1534
  return r;
1358
1535
  }).join(", ");
1359
- copyFileSync(opts.binaryPath, join2(sourcesDir, sanitizedName));
1536
+ copyFileSync(opts.binaryPath, join3(sourcesDir, sanitizedName));
1360
1537
  const specContent = `Name: ${sanitizedName}
1361
1538
  Version: ${opts.version}
1362
1539
  Release: 1%{?dist}
@@ -1374,13 +1551,13 @@ install -m 755 %{SOURCE0} %{buildroot}/usr/bin/${sanitizedName}
1374
1551
  %files
1375
1552
  /usr/bin/${sanitizedName}
1376
1553
  `;
1377
- const specPath = join2(specDir, `${opts.name.toLowerCase()}.spec`);
1378
- writeFileSync2(specPath, specContent);
1554
+ const specPath = join3(specDir, `${opts.name.toLowerCase()}.spec`);
1555
+ writeFileSync3(specPath, specContent);
1379
1556
  const proc = spawn("rpmbuild", ["-bb", specPath]);
1380
1557
  proc.on("close", (code) => {
1381
1558
  if (code === 0) {
1382
1559
  const rpmName = `${opts.name.toLowerCase()}-${opts.version}-1.x86_64.rpm`;
1383
- const builtRpmPath = join2(rpmsDir, "x86_64", rpmName);
1560
+ const builtRpmPath = join3(rpmsDir, "x86_64", rpmName);
1384
1561
  try {
1385
1562
  copyFileSync(builtRpmPath, opts.outputPath);
1386
1563
  resolve({ success: true, outputPath: opts.outputPath });
@@ -1405,22 +1582,22 @@ async function createAppImage(opts) {
1405
1582
  try {
1406
1583
  const appDir = createTempDir("craft-appimage-");
1407
1584
  staging = appDir;
1408
- const appDirPath = join2(appDir, `${opts.name}.AppDir`);
1409
- const binDir = join2(appDirPath, "usr", "bin");
1410
- const shareDir = join2(appDirPath, "usr", "share");
1585
+ const appDirPath = join3(appDir, `${opts.name}.AppDir`);
1586
+ const binDir = join3(appDirPath, "usr", "bin");
1587
+ const shareDir = join3(appDirPath, "usr", "share");
1411
1588
  mkdirSync(binDir, { recursive: true });
1412
1589
  mkdirSync(shareDir, { recursive: true });
1413
1590
  const binaryName = opts.name.toLowerCase();
1414
- copyFileSync(opts.binaryPath, join2(binDir, binaryName));
1415
- chmodSync(join2(binDir, binaryName), 493);
1591
+ copyFileSync(opts.binaryPath, join3(binDir, binaryName));
1592
+ chmodSync(join3(binDir, binaryName), 493);
1416
1593
  const appRunContent = `#!/bin/bash
1417
1594
  SELF=$(readlink -f "$0")
1418
1595
  HERE=\${SELF%/*}
1419
1596
  export PATH="\${HERE}/usr/bin/:\${PATH}"
1420
1597
  exec "\${HERE}/usr/bin/${binaryName}" "$@"
1421
1598
  `;
1422
- writeFileSync2(join2(appDirPath, "AppRun"), appRunContent);
1423
- chmodSync(join2(appDirPath, "AppRun"), 493);
1599
+ writeFileSync3(join3(appDirPath, "AppRun"), appRunContent);
1600
+ chmodSync(join3(appDirPath, "AppRun"), 493);
1424
1601
  const desktopContent = `[Desktop Entry]
1425
1602
  Type=Application
1426
1603
  Name=${opts.name}
@@ -1429,9 +1606,9 @@ Terminal=false
1429
1606
  Categories=Utility;
1430
1607
  Icon=${binaryName}
1431
1608
  `;
1432
- writeFileSync2(join2(appDirPath, `${binaryName}.desktop`), desktopContent);
1609
+ writeFileSync3(join3(appDirPath, `${binaryName}.desktop`), desktopContent);
1433
1610
  if (opts.iconPath && existsSync3(opts.iconPath)) {
1434
- copyFileSync(opts.iconPath, join2(appDirPath, `${binaryName}.png`));
1611
+ copyFileSync(opts.iconPath, join3(appDirPath, `${binaryName}.png`));
1435
1612
  } else {
1436
1613
  const placeholderPng = Buffer.from([
1437
1614
  137,
@@ -1504,7 +1681,7 @@ Icon=${binaryName}
1504
1681
  96,
1505
1682
  130
1506
1683
  ]);
1507
- writeFileSync2(join2(appDirPath, `${binaryName}.png`), placeholderPng);
1684
+ writeFileSync3(join3(appDirPath, `${binaryName}.png`), placeholderPng);
1508
1685
  }
1509
1686
  const proc = spawn("appimagetool", [appDirPath, opts.outputPath], {
1510
1687
  env: { ...process.env, ARCH: "x86_64" }
@@ -10492,17 +10669,17 @@ var commonOptimizations = {
10492
10669
  }
10493
10670
  };
10494
10671
  // src/updater/index.ts
10495
- import { createReadStream, createWriteStream, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmdirSync, statSync as statSync3, unlinkSync, writeFileSync as writeFileSync3 } from "fs";
10496
- import { join as join4, basename as basename3, dirname as dirname3 } from "path";
10672
+ import { createReadStream, createWriteStream, existsSync as existsSync5, mkdirSync as mkdirSync2, readFileSync as readFileSync2, rmdirSync, statSync as statSync4, unlinkSync, writeFileSync as writeFileSync4 } from "fs";
10673
+ import { join as join5, basename as basename3, dirname as dirname3 } from "path";
10497
10674
  import { tmpdir as tmpdir2 } from "os";
10498
- import { execFileSync as execFileSync2, spawn as spawn3 } from "child_process";
10675
+ import { execFileSync as execFileSync3, spawn as spawn3 } from "child_process";
10499
10676
  import { createHash as createHash2 } from "crypto";
10500
10677
  import { EventEmitter as EventEmitter3 } from "events";
10501
10678
 
10502
10679
  // src/updater/macos-bundle.ts
10503
- import { execFile, execFileSync } from "child_process";
10504
- import { accessSync, constants, existsSync as existsSync4, renameSync, rmSync as rmSync3, statSync as statSync2 } from "fs";
10505
- import { basename as basename2, dirname as dirname2, join as join3 } from "path";
10680
+ import { execFile, execFileSync as execFileSync2 } from "child_process";
10681
+ import { accessSync, constants, existsSync as existsSync4, renameSync, readdirSync as readdirSync3, rmSync as rmSync3, statSync as statSync3 } from "fs";
10682
+ import { basename as basename2, dirname as dirname2, join as join4 } from "path";
10506
10683
  import { promisify } from "util";
10507
10684
  var execFileAsync = promisify(execFile);
10508
10685
  function isMacOS() {
@@ -10608,7 +10785,7 @@ async function dittoBundle(source, destination) {
10608
10785
  await execFileAsync("ditto", [source, destination]);
10609
10786
  }
10610
10787
  function findTopLevelApp(root) {
10611
- const out = execFileSync("find", [root, "-maxdepth", "2", "-name", "*.app", "-type", "d", "-print0"]);
10788
+ const out = execFileSync2("find", [root, "-maxdepth", "2", "-name", "*.app", "-type", "d", "-print0"]);
10612
10789
  const parts = out.toString("utf-8").split("\x00").filter((s) => s.length > 0);
10613
10790
  parts.sort((a, b) => a.split("/").length - b.split("/").length);
10614
10791
  return parts[0] ?? null;
@@ -10624,7 +10801,7 @@ async function extractBundleFromDmg(dmgPath, stagingDir) {
10624
10801
  const source = findTopLevelApp(mountPoint);
10625
10802
  if (!source)
10626
10803
  throw new Error(`No .app found in disk image: ${dmgPath}`);
10627
- const appPath = join3(staging, basename2(source));
10804
+ const appPath = join4(staging, basename2(source));
10628
10805
  await dittoBundle(source, appPath);
10629
10806
  staged = true;
10630
10807
  return { appPath, stagingDir: staging };
@@ -10641,13 +10818,16 @@ async function extractBundleFromDmg(dmgPath, stagingDir) {
10641
10818
  }
10642
10819
  async function extractBundleFromZip(zipPath, stagingDir) {
10643
10820
  const staging = stagingDir ?? createTempDir("craft-update-");
10644
- const unpacked = join3(staging, "payload");
10821
+ const unpacked = join4(staging, "payload");
10645
10822
  try {
10646
10823
  await execFileAsync("ditto", ["-x", "-k", zipPath, unpacked]);
10647
10824
  const source = findTopLevelApp(unpacked);
10648
- if (!source)
10649
- throw new Error(`No .app found in archive: ${zipPath}`);
10650
- return { appPath: source, stagingDir: staging };
10825
+ if (source)
10826
+ return { appPath: source, stagingDir: staging };
10827
+ const images = readdirSync3(unpacked, { withFileTypes: true }).filter((entry) => entry.isFile() && entry.name.endsWith(".dmg"));
10828
+ if (images.length !== 1)
10829
+ throw new Error(`Archive must contain one .app or one disk image: ${zipPath}`);
10830
+ return await extractBundleFromDmg(join4(unpacked, images[0].name), staging);
10651
10831
  } catch (error) {
10652
10832
  if (!stagingDir)
10653
10833
  removeTempDir(staging);
@@ -10666,8 +10846,8 @@ async function swapBundle(stagedPath, installedPath) {
10666
10846
  throw new Error(`Staged bundle is missing: ${stagedPath}`);
10667
10847
  const parent = dirname2(installedPath);
10668
10848
  const stamp = `${Date.now()}.${process.pid}`;
10669
- const incoming = join3(parent, `.${basename2(installedPath)}.${stamp}.incoming`);
10670
- const retired = join3(parent, `.${basename2(installedPath)}.${stamp}.retired`);
10849
+ const incoming = join4(parent, `.${basename2(installedPath)}.${stamp}.incoming`);
10850
+ const retired = join4(parent, `.${basename2(installedPath)}.${stamp}.retired`);
10671
10851
  try {
10672
10852
  renameSync(stagedPath, incoming);
10673
10853
  } catch {
@@ -10708,7 +10888,7 @@ function canReplaceBundle(installedPath) {
10708
10888
  const parent = dirname2(installedPath);
10709
10889
  accessSync(parent, constants.W_OK);
10710
10890
  if (existsSync4(installedPath))
10711
- statSync2(installedPath);
10891
+ statSync3(installedPath);
10712
10892
  return true;
10713
10893
  } catch {
10714
10894
  return false;
@@ -10747,7 +10927,7 @@ class AutoUpdater extends EventEmitter3 {
10747
10927
  downloadDir() {
10748
10928
  if (this.config.downloadDir)
10749
10929
  return this.config.downloadDir;
10750
- return join4(tmpdir2(), "craft-updates", basename3(this.config.appPath) || "app");
10930
+ return join5(tmpdir2(), "craft-updates", basename3(this.config.appPath) || "app");
10751
10931
  }
10752
10932
  getLastError() {
10753
10933
  return this.lastError;
@@ -10852,7 +11032,7 @@ class AutoUpdater extends EventEmitter3 {
10852
11032
  const downloadDir = this.downloadDir();
10853
11033
  mkdirSync2(downloadDir, { recursive: true });
10854
11034
  const fileName = basename3(url);
10855
- this.downloadPath = join4(downloadDir, fileName);
11035
+ this.downloadPath = join5(downloadDir, fileName);
10856
11036
  try {
10857
11037
  const response = await fetch(url);
10858
11038
  if (!response.ok) {
@@ -10915,11 +11095,11 @@ class AutoUpdater extends EventEmitter3 {
10915
11095
  throw new Error("Download verification failed: hash mismatch");
10916
11096
  }
10917
11097
  if (deltaUpdate) {
10918
- if (!statSync3(this.config.appPath).isFile()) {
11098
+ if (!statSync4(this.config.appPath).isFile()) {
10919
11099
  throw new Error("Delta updates require appPath to point to the installed bundle file");
10920
11100
  }
10921
11101
  const patchPath = this.downloadPath;
10922
- const reconstructedPath = join4(downloadDir, `reconstructed-${basename3(platformUpdate.url)}`);
11102
+ const reconstructedPath = join5(downloadDir, `reconstructed-${basename3(platformUpdate.url)}`);
10923
11103
  await DeltaGenerator.apply(this.config.appPath, patchPath, reconstructedPath);
10924
11104
  const reconstructedHash = await this.computeFileHash(reconstructedPath);
10925
11105
  if (reconstructedHash !== platformUpdate.sha256) {
@@ -11054,11 +11234,11 @@ class AutoUpdater extends EventEmitter3 {
11054
11234
  }
11055
11235
  async installMacOSPackage(downloadPath) {
11056
11236
  try {
11057
- execFileSync2("pkgutil", ["--check-signature", downloadPath], { stdio: "pipe" });
11237
+ execFileSync3("pkgutil", ["--check-signature", downloadPath], { stdio: "pipe" });
11058
11238
  } catch (e) {
11059
11239
  throw new Error(`Refusing to install ${downloadPath}: pkgutil --check-signature failed. ` + "The .pkg is not signed by a trusted Apple certificate chain. " + `Underlying error: ${e.message}`);
11060
11240
  }
11061
- execFileSync2("sudo", ["installer", "-pkg", downloadPath, "-target", "/"]);
11241
+ execFileSync3("sudo", ["installer", "-pkg", downloadPath, "-target", "/"]);
11062
11242
  }
11063
11243
  async installWindowsUpdate() {
11064
11244
  const downloadPath = this.downloadPath;
@@ -11074,7 +11254,7 @@ class AutoUpdater extends EventEmitter3 {
11074
11254
  });
11075
11255
  } else if (downloadPath.endsWith(".zip")) {
11076
11256
  const appDir = dirname3(this.config.appPath);
11077
- execFileSync2("powershell", [
11257
+ execFileSync3("powershell", [
11078
11258
  "-NoProfile",
11079
11259
  "-NonInteractive",
11080
11260
  "-Command",
@@ -11087,16 +11267,16 @@ class AutoUpdater extends EventEmitter3 {
11087
11267
  async installLinuxUpdate() {
11088
11268
  const downloadPath = this.downloadPath;
11089
11269
  if (downloadPath.endsWith(".AppImage")) {
11090
- execFileSync2("chmod", ["+x", downloadPath]);
11270
+ execFileSync3("chmod", ["+x", downloadPath]);
11091
11271
  const { renameSync } = await import("fs");
11092
11272
  renameSync(downloadPath, this.config.appPath);
11093
11273
  } else if (downloadPath.endsWith(".deb")) {
11094
- execFileSync2("sudo", ["dpkg", "-i", downloadPath]);
11274
+ execFileSync3("sudo", ["dpkg", "-i", downloadPath]);
11095
11275
  } else if (downloadPath.endsWith(".rpm")) {
11096
- execFileSync2("sudo", ["rpm", "-U", downloadPath]);
11276
+ execFileSync3("sudo", ["rpm", "-U", downloadPath]);
11097
11277
  } else if (downloadPath.endsWith(".tar.gz")) {
11098
11278
  const appDir = dirname3(this.config.appPath);
11099
- execFileSync2("tar", ["-xzf", downloadPath, "-C", appDir]);
11279
+ execFileSync3("tar", ["-xzf", downloadPath, "-C", appDir]);
11100
11280
  }
11101
11281
  }
11102
11282
  async restartApp() {
@@ -11191,7 +11371,7 @@ class DeltaGenerator {
11191
11371
  return DeltaGenerator.supported;
11192
11372
  DeltaGenerator.supported = ["bspatch", "xdelta3"].some((tool) => {
11193
11373
  try {
11194
- execFileSync2("command", ["-v", tool], { stdio: "ignore", shell: true });
11374
+ execFileSync3("command", ["-v", tool], { stdio: "ignore", shell: true });
11195
11375
  return true;
11196
11376
  } catch {
11197
11377
  return false;
@@ -11201,16 +11381,16 @@ class DeltaGenerator {
11201
11381
  }
11202
11382
  static async generate(oldPath, newPath, outputPath) {
11203
11383
  try {
11204
- execFileSync2("bsdiff", [oldPath, newPath, outputPath]);
11205
- const stats = statSync3(outputPath);
11384
+ execFileSync3("bsdiff", [oldPath, newPath, outputPath]);
11385
+ const stats = statSync4(outputPath);
11206
11386
  const hash = await DeltaGenerator.computeHash(outputPath);
11207
11387
  return {
11208
11388
  size: stats.size,
11209
11389
  sha256: hash
11210
11390
  };
11211
11391
  } catch {
11212
- execFileSync2("xdelta3", ["-e", "-s", oldPath, newPath, outputPath]);
11213
- const stats = statSync3(outputPath);
11392
+ execFileSync3("xdelta3", ["-e", "-s", oldPath, newPath, outputPath]);
11393
+ const stats = statSync4(outputPath);
11214
11394
  const hash = await DeltaGenerator.computeHash(outputPath);
11215
11395
  return {
11216
11396
  size: stats.size,
@@ -11220,9 +11400,9 @@ class DeltaGenerator {
11220
11400
  }
11221
11401
  static async apply(basePath, deltaPath, outputPath) {
11222
11402
  try {
11223
- execFileSync2("bspatch", [basePath, outputPath, deltaPath]);
11403
+ execFileSync3("bspatch", [basePath, outputPath, deltaPath]);
11224
11404
  } catch {
11225
- execFileSync2("xdelta3", ["-d", "-s", basePath, deltaPath, outputPath]);
11405
+ execFileSync3("xdelta3", ["-d", "-s", basePath, deltaPath, outputPath]);
11226
11406
  }
11227
11407
  }
11228
11408
  static async computeHash(filePath) {
@@ -11324,7 +11504,7 @@ ${update.releaseNotes}`);
11324
11504
  releaseDate: new Date().toISOString(),
11325
11505
  platforms: {}
11326
11506
  };
11327
- writeFileSync3(outputPath, JSON.stringify(manifest, null, 2));
11507
+ writeFileSync4(outputPath, JSON.stringify(manifest, null, 2));
11328
11508
  console.log(`Manifest generated: ${outputPath}`);
11329
11509
  console.log("Edit the file to add platform-specific update URLs");
11330
11510
  break;
@@ -11612,8 +11792,8 @@ class CraftApp {
11612
11792
  } else {
11613
11793
  const dir = createTempDir("craft-sidebar-");
11614
11794
  this.sidebarConfigDir = dir;
11615
- const path = join5(dir, "sidebar-config.json");
11616
- writeFileSync4(path, json, "utf-8");
11795
+ const path = join6(dir, "sidebar-config.json");
11796
+ writeFileSync5(path, json, "utf-8");
11617
11797
  args.push("--sidebar-config-file", path);
11618
11798
  }
11619
11799
  }
@@ -11690,6 +11870,7 @@ export {
11690
11870
  createApp,
11691
11871
  createArcSidebar,
11692
11872
  createClient,
11873
+ createDiskImage,
11693
11874
  createFileBrowser,
11694
11875
  createFileSidebar,
11695
11876
  createMenubarApp,