craft-native 0.0.37 → 0.0.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/android/src/index.js +268 -0
- package/dist/android/src/index.js.map +10 -0
- package/dist/android/templates/AndroidManifest.xml.template +69 -0
- package/dist/android/templates/CraftBridge.kt.template +3748 -0
- package/dist/android/templates/CraftBridgeExtensions.kt.template +383 -0
- package/dist/android/templates/CraftWidgetProvider.kt.template +246 -0
- package/dist/android/templates/MainActivity.kt.template +109 -0
- package/dist/android/templates/build.gradle.kts.app.template +80 -0
- package/dist/android/templates/build.gradle.kts.project.template +5 -0
- package/dist/android/templates/fastlane/Appfile +25 -0
- package/dist/android/templates/fastlane/Fastfile +192 -0
- package/dist/android/templates/fastlane/Gemfile +7 -0
- package/dist/android/templates/github-workflow-android.yml +248 -0
- package/dist/android/templates/github-workflow-test.yml +329 -0
- package/dist/android/templates/settings.gradle.kts.template +18 -0
- package/dist/android/templates/test-bridges.html +1463 -0
- package/dist/api/window.d.ts +18 -0
- package/dist/api/window.d.ts.map +1 -1
- package/dist/assets/index.d.ts.map +1 -1
- package/dist/bridge/core.d.ts +2 -0
- package/dist/bridge/core.d.ts.map +1 -1
- package/dist/cli.js +4168 -0
- package/dist/components/sidebar.d.ts +5 -1
- package/dist/components/sidebar.d.ts.map +1 -1
- package/dist/dev/devtools.d.ts +1 -1
- package/dist/dev/devtools.d.ts.map +1 -1
- package/dist/dev/hot-reload.d.ts +12 -3
- package/dist/dev/hot-reload.d.ts.map +1 -1
- package/dist/index.cjs +573 -208
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +585 -216
- package/dist/index.js.map +45 -0
- package/dist/ios/src/index.js +186 -0
- package/dist/ios/src/index.js.map +10 -0
- package/dist/ios/templates/CraftApp.swift +4241 -0
- package/dist/ios/templates/CraftAppExtensions.swift +361 -0
- package/dist/ios/templates/CraftWidget.swift +247 -0
- package/dist/ios/templates/Info.plist.template +65 -0
- package/dist/ios/templates/fastlane/Appfile +45 -0
- package/dist/ios/templates/fastlane/Fastfile +189 -0
- package/dist/ios/templates/fastlane/Gemfile +7 -0
- package/dist/ios/templates/fastlane/Matchfile +58 -0
- package/dist/ios/templates/github-workflow-ios.yml +192 -0
- package/dist/ios/templates/github-workflow-release.yml +175 -0
- package/dist/ios/templates/github-workflow-test.yml +272 -0
- package/dist/ios/templates/project.yml.template +25 -0
- package/dist/ios/templates/test-bridges.html +1463 -0
- package/dist/package.d.ts +106 -2
- package/dist/package.d.ts.map +1 -1
- package/dist/package.test.d.ts +2 -0
- package/dist/package.test.d.ts.map +1 -0
- package/dist/styles/sidebar-templates.d.ts.map +1 -1
- package/dist/styles/sidebars.d.ts +12 -8
- package/dist/styles/sidebars.d.ts.map +1 -1
- package/dist/templates/projects/blank/craft.config.ts +19 -0
- package/dist/templates/projects/blank/index.html +27 -0
- package/dist/templates/projects/blank/package.json +19 -0
- package/dist/templates/projects/blank/src/main.ts +26 -0
- package/dist/templates/projects/dashboard/craft.config.ts +42 -0
- package/dist/templates/projects/dashboard/index.html +13 -0
- package/dist/templates/projects/dashboard/package.json +20 -0
- package/dist/templates/projects/dashboard/src/main.ts +163 -0
- package/dist/templates/projects/dashboard/src/styles.css +280 -0
- package/dist/templates/projects/drawer/craft.config.ts +47 -0
- package/dist/templates/projects/drawer/index.html +13 -0
- package/dist/templates/projects/drawer/package.json +21 -0
- package/dist/templates/projects/drawer/src/main.ts +406 -0
- package/dist/templates/projects/drawer/src/styles.css +468 -0
- package/dist/templates/projects/ecommerce/craft.config.ts +32 -0
- package/dist/templates/projects/ecommerce/index.html +13 -0
- package/dist/templates/projects/ecommerce/package.json +19 -0
- package/dist/templates/projects/ecommerce/src/main.ts +194 -0
- package/dist/templates/projects/ecommerce/src/styles.css +169 -0
- package/dist/templates/projects/social/craft.config.ts +32 -0
- package/dist/templates/projects/social/index.html +13 -0
- package/dist/templates/projects/social/package.json +19 -0
- package/dist/templates/projects/social/src/main.ts +270 -0
- package/dist/templates/projects/social/src/styles.css +216 -0
- package/dist/templates/projects/tabs/craft.config.ts +47 -0
- package/dist/templates/projects/tabs/index.html +13 -0
- package/dist/templates/projects/tabs/package.json +21 -0
- package/dist/templates/projects/tabs/src/main.ts +177 -0
- package/dist/templates/projects/tabs/src/styles.css +163 -0
- package/dist/types.d.ts +29 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/updater/index.d.ts +1 -0
- package/dist/updater/index.d.ts.map +1 -1
- package/package.json +5 -12
- package/bin/cli.ts +0 -937
package/dist/index.cjs
CHANGED
|
@@ -177,7 +177,7 @@ __export(exports_src, {
|
|
|
177
177
|
focusFilters: () => focusFilters,
|
|
178
178
|
focus: () => focus,
|
|
179
179
|
exit: () => exit,
|
|
180
|
-
exec: () =>
|
|
180
|
+
exec: () => exec,
|
|
181
181
|
env: () => env,
|
|
182
182
|
dialog: () => dialog,
|
|
183
183
|
device: () => device,
|
|
@@ -290,16 +290,90 @@ function craftBinaryNotFoundMessage(triedPath) {
|
|
|
290
290
|
|
|
291
291
|
// src/package.ts
|
|
292
292
|
var import_child_process = require("child_process");
|
|
293
|
+
var import_crypto = require("crypto");
|
|
293
294
|
var import_fs = require("fs");
|
|
294
295
|
var import_os = require("os");
|
|
295
296
|
var import_path = require("path");
|
|
296
|
-
var
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
297
|
+
var import_zlib = require("zlib");
|
|
298
|
+
var CRC32_TABLE = (() => {
|
|
299
|
+
const table = new Uint32Array(256);
|
|
300
|
+
for (let n = 0;n < 256; n++) {
|
|
301
|
+
let c = n;
|
|
302
|
+
for (let k = 0;k < 8; k++)
|
|
303
|
+
c = c & 1 ? 3988292384 ^ c >>> 1 : c >>> 1;
|
|
304
|
+
table[n] = c >>> 0;
|
|
305
|
+
}
|
|
306
|
+
return table;
|
|
307
|
+
})();
|
|
308
|
+
function crc32(data) {
|
|
309
|
+
let c = 4294967295;
|
|
310
|
+
for (let i = 0;i < data.length; i++)
|
|
311
|
+
c = CRC32_TABLE[(c ^ data[i]) & 255] ^ c >>> 8;
|
|
312
|
+
return (c ^ 4294967295) >>> 0;
|
|
313
|
+
}
|
|
314
|
+
function dosDateTime(d) {
|
|
315
|
+
const time = d.getHours() << 11 | d.getMinutes() << 5 | d.getSeconds() >> 1;
|
|
316
|
+
const date = d.getFullYear() - 1980 << 9 | d.getMonth() + 1 << 5 | d.getDate();
|
|
317
|
+
return { time: time & 65535, date: date & 65535 };
|
|
318
|
+
}
|
|
319
|
+
function buildZip(entries) {
|
|
320
|
+
const { time, date } = dosDateTime(new Date);
|
|
321
|
+
const locals = [];
|
|
322
|
+
const central = [];
|
|
323
|
+
let offset = 0;
|
|
324
|
+
for (const entry of entries) {
|
|
325
|
+
const nameBytes = Buffer.from(entry.name, "utf8");
|
|
326
|
+
const compressed = import_zlib.deflateRawSync(entry.data, { level: 9 });
|
|
327
|
+
const crc = crc32(entry.data);
|
|
328
|
+
const lfh = Buffer.alloc(30);
|
|
329
|
+
lfh.writeUInt32LE(67324752, 0);
|
|
330
|
+
lfh.writeUInt16LE(20, 4);
|
|
331
|
+
lfh.writeUInt16LE(0, 6);
|
|
332
|
+
lfh.writeUInt16LE(8, 8);
|
|
333
|
+
lfh.writeUInt16LE(time, 10);
|
|
334
|
+
lfh.writeUInt16LE(date, 12);
|
|
335
|
+
lfh.writeUInt32LE(crc, 14);
|
|
336
|
+
lfh.writeUInt32LE(compressed.length, 18);
|
|
337
|
+
lfh.writeUInt32LE(entry.data.length, 22);
|
|
338
|
+
lfh.writeUInt16LE(nameBytes.length, 26);
|
|
339
|
+
lfh.writeUInt16LE(0, 28);
|
|
340
|
+
locals.push(lfh, nameBytes, compressed);
|
|
341
|
+
const cdh = Buffer.alloc(46);
|
|
342
|
+
cdh.writeUInt32LE(33639248, 0);
|
|
343
|
+
cdh.writeUInt16LE(20, 4);
|
|
344
|
+
cdh.writeUInt16LE(20, 6);
|
|
345
|
+
cdh.writeUInt16LE(0, 8);
|
|
346
|
+
cdh.writeUInt16LE(8, 10);
|
|
347
|
+
cdh.writeUInt16LE(time, 12);
|
|
348
|
+
cdh.writeUInt16LE(date, 14);
|
|
349
|
+
cdh.writeUInt32LE(crc, 16);
|
|
350
|
+
cdh.writeUInt32LE(compressed.length, 20);
|
|
351
|
+
cdh.writeUInt32LE(entry.data.length, 24);
|
|
352
|
+
cdh.writeUInt16LE(nameBytes.length, 28);
|
|
353
|
+
cdh.writeUInt16LE(0, 30);
|
|
354
|
+
cdh.writeUInt16LE(0, 32);
|
|
355
|
+
cdh.writeUInt16LE(0, 34);
|
|
356
|
+
cdh.writeUInt16LE(0, 36);
|
|
357
|
+
cdh.writeUInt32LE(0, 38);
|
|
358
|
+
cdh.writeUInt32LE(offset, 42);
|
|
359
|
+
central.push(cdh, nameBytes);
|
|
360
|
+
offset += lfh.length + nameBytes.length + compressed.length;
|
|
361
|
+
}
|
|
362
|
+
const centralBuf = Buffer.concat(central);
|
|
363
|
+
const eocd = Buffer.alloc(22);
|
|
364
|
+
eocd.writeUInt32LE(101010256, 0);
|
|
365
|
+
eocd.writeUInt16LE(0, 4);
|
|
366
|
+
eocd.writeUInt16LE(0, 6);
|
|
367
|
+
eocd.writeUInt16LE(entries.length, 8);
|
|
368
|
+
eocd.writeUInt16LE(entries.length, 10);
|
|
369
|
+
eocd.writeUInt32LE(centralBuf.length, 12);
|
|
370
|
+
eocd.writeUInt32LE(offset, 16);
|
|
371
|
+
eocd.writeUInt16LE(0, 20);
|
|
372
|
+
return Buffer.concat([...locals, centralBuf, eocd]);
|
|
373
|
+
}
|
|
374
|
+
function formatPackagingCommandError(tool, code, stdout, stderr) {
|
|
375
|
+
const detail = `${stdout}${stderr}`.trim();
|
|
376
|
+
return `${tool} exited with code ${code}${detail ? `: ${detail}` : ""}`;
|
|
303
377
|
}
|
|
304
378
|
async function packageApp(config) {
|
|
305
379
|
const results = [];
|
|
@@ -330,13 +404,20 @@ async function packageMacOS(config, outDir) {
|
|
|
330
404
|
const results = [];
|
|
331
405
|
const { name, version, bundleId = `com.myapp.${name.toLowerCase()}` } = config;
|
|
332
406
|
const opts = config.macos || {};
|
|
407
|
+
const hardenedRuntime = !opts.appStore;
|
|
333
408
|
const appBundlePath = import_path.join(outDir, `${name}.app`);
|
|
334
409
|
const appBundle = createMacOSAppBundle({
|
|
335
410
|
name,
|
|
336
411
|
version,
|
|
337
412
|
bundleId,
|
|
413
|
+
buildNumber: opts.buildNumber,
|
|
414
|
+
category: opts.category,
|
|
415
|
+
minimumSystemVersion: opts.minimumSystemVersion,
|
|
416
|
+
menuBarOnly: opts.menuBarOnly,
|
|
338
417
|
binaryPath: config.binaryPath,
|
|
339
418
|
iconPath: config.iconPath,
|
|
419
|
+
provisioningProfile: opts.provisioningProfile,
|
|
420
|
+
additionalExecutables: opts.additionalExecutables,
|
|
340
421
|
outputPath: appBundlePath
|
|
341
422
|
});
|
|
342
423
|
if (!appBundle.success) {
|
|
@@ -348,12 +429,30 @@ async function packageMacOS(config, outDir) {
|
|
|
348
429
|
});
|
|
349
430
|
return results;
|
|
350
431
|
}
|
|
351
|
-
if (opts.
|
|
352
|
-
const
|
|
353
|
-
appBundlePath,
|
|
354
|
-
|
|
355
|
-
|
|
432
|
+
if (opts.signIdentity) {
|
|
433
|
+
const signed = await runTool("codesign", codesignArguments({
|
|
434
|
+
path: appBundlePath,
|
|
435
|
+
identity: opts.signIdentity,
|
|
436
|
+
entitlements: opts.entitlements,
|
|
437
|
+
hardenedRuntime
|
|
438
|
+
}));
|
|
439
|
+
if (!signed.success) {
|
|
440
|
+
results.push({ success: false, platform: "macos", format: "app", error: signed.error });
|
|
441
|
+
return results;
|
|
442
|
+
}
|
|
443
|
+
} else if (opts.appStore) {
|
|
444
|
+
results.push({
|
|
445
|
+
success: false,
|
|
446
|
+
platform: "macos",
|
|
447
|
+
format: "pkg",
|
|
448
|
+
error: 'App Store packaging requires macos.signIdentity (a "3rd Party Mac Developer Application" identity)'
|
|
356
449
|
});
|
|
450
|
+
return results;
|
|
451
|
+
}
|
|
452
|
+
results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
|
|
453
|
+
if (opts.dmg !== false) {
|
|
454
|
+
const outputPath = import_path.join(outDir, `${name}-${version}.dmg`);
|
|
455
|
+
const dmgResult = await createDMG({ appBundlePath, outputPath, volumeName: name });
|
|
357
456
|
results.push({
|
|
358
457
|
success: dmgResult.success,
|
|
359
458
|
platform: "macos",
|
|
@@ -361,24 +460,59 @@ async function packageMacOS(config, outDir) {
|
|
|
361
460
|
outputPath: dmgResult.outputPath,
|
|
362
461
|
error: dmgResult.error
|
|
363
462
|
});
|
|
463
|
+
if (dmgResult.success)
|
|
464
|
+
results.push(...await notarizeIfRequested(opts, outputPath, "dmg"));
|
|
364
465
|
}
|
|
365
|
-
if (opts.pkg) {
|
|
466
|
+
if (opts.pkg || opts.appStore) {
|
|
467
|
+
const outputPath = import_path.join(outDir, `${name}-${version}.pkg`);
|
|
366
468
|
const pkgResult = await createPKG({
|
|
367
469
|
appBundlePath,
|
|
368
|
-
outputPath
|
|
470
|
+
outputPath,
|
|
369
471
|
identifier: bundleId,
|
|
370
|
-
version
|
|
472
|
+
version,
|
|
473
|
+
appStore: opts.appStore === true,
|
|
474
|
+
installerIdentity: opts.installerIdentity
|
|
371
475
|
});
|
|
372
476
|
results.push({
|
|
373
477
|
success: pkgResult.success,
|
|
374
478
|
platform: "macos",
|
|
375
|
-
format: "pkg",
|
|
479
|
+
format: opts.appStore ? "pkg (app store)" : "pkg",
|
|
376
480
|
outputPath: pkgResult.outputPath,
|
|
377
481
|
error: pkgResult.error
|
|
378
482
|
});
|
|
483
|
+
if (pkgResult.success && !opts.appStore)
|
|
484
|
+
results.push(...await notarizeIfRequested(opts, outputPath, "pkg"));
|
|
379
485
|
}
|
|
380
486
|
return results;
|
|
381
487
|
}
|
|
488
|
+
async function notarizeIfRequested(opts, artifactPath, format) {
|
|
489
|
+
if (!opts.notarize)
|
|
490
|
+
return [];
|
|
491
|
+
if (!opts.appleId || !opts.applePassword || !opts.teamId) {
|
|
492
|
+
return [{
|
|
493
|
+
success: false,
|
|
494
|
+
platform: "macos",
|
|
495
|
+
format: `${format} (notarize)`,
|
|
496
|
+
error: "Notarization requires macos.appleId, macos.applePassword and macos.teamId"
|
|
497
|
+
}];
|
|
498
|
+
}
|
|
499
|
+
const submitted = await runTool("xcrun", notarytoolArguments({
|
|
500
|
+
artifactPath,
|
|
501
|
+
appleId: opts.appleId,
|
|
502
|
+
applePassword: opts.applePassword,
|
|
503
|
+
teamId: opts.teamId
|
|
504
|
+
}));
|
|
505
|
+
if (!submitted.success)
|
|
506
|
+
return [{ success: false, platform: "macos", format: `${format} (notarize)`, error: submitted.error }];
|
|
507
|
+
const stapled = await runTool("xcrun", ["stapler", "staple", artifactPath]);
|
|
508
|
+
return [{
|
|
509
|
+
success: stapled.success,
|
|
510
|
+
platform: "macos",
|
|
511
|
+
format: `${format} (notarize)`,
|
|
512
|
+
outputPath: stapled.success ? artifactPath : undefined,
|
|
513
|
+
error: stapled.success ? undefined : stapled.error
|
|
514
|
+
}];
|
|
515
|
+
}
|
|
382
516
|
async function packageWindows(config, outDir) {
|
|
383
517
|
const results = [];
|
|
384
518
|
const { name, version } = config;
|
|
@@ -389,7 +523,10 @@ async function packageWindows(config, outDir) {
|
|
|
389
523
|
version,
|
|
390
524
|
binaryPath: config.binaryPath,
|
|
391
525
|
outputPath: import_path.join(outDir, `${name}-${version}.msi`),
|
|
392
|
-
manufacturer: config.author || "Unknown"
|
|
526
|
+
manufacturer: config.author || "Unknown",
|
|
527
|
+
architecture: opts.architecture || windowsArchitecture(process.arch),
|
|
528
|
+
certificatePath: opts.certificatePath,
|
|
529
|
+
certificatePassword: opts.certificatePassword
|
|
393
530
|
});
|
|
394
531
|
results.push({
|
|
395
532
|
success: msiResult.success,
|
|
@@ -473,83 +610,200 @@ async function packageLinux(config, outDir) {
|
|
|
473
610
|
}
|
|
474
611
|
return results;
|
|
475
612
|
}
|
|
476
|
-
function
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
613
|
+
function macOSInfoPlist(metadata) {
|
|
614
|
+
const entries = [
|
|
615
|
+
["CFBundleExecutable", metadata.name],
|
|
616
|
+
["CFBundleIdentifier", metadata.bundleId],
|
|
617
|
+
["CFBundleName", metadata.name],
|
|
618
|
+
["CFBundleShortVersionString", metadata.version],
|
|
619
|
+
["CFBundleVersion", metadata.buildNumber || metadata.version],
|
|
620
|
+
["CFBundlePackageType", "APPL"],
|
|
621
|
+
["NSHighResolutionCapable", true]
|
|
622
|
+
];
|
|
623
|
+
if (metadata.iconName)
|
|
624
|
+
entries.push(["CFBundleIconFile", metadata.iconName]);
|
|
625
|
+
if (metadata.category)
|
|
626
|
+
entries.push(["LSApplicationCategoryType", metadata.category]);
|
|
627
|
+
if (metadata.minimumSystemVersion)
|
|
628
|
+
entries.push(["LSMinimumSystemVersion", metadata.minimumSystemVersion]);
|
|
629
|
+
if (metadata.menuBarOnly)
|
|
630
|
+
entries.push(["LSUIElement", true]);
|
|
631
|
+
const body = entries.map(([key, value]) => ` <key>${xml(key)}</key>
|
|
632
|
+
${value === true ? " <true/>" : ` <string>${xml(value)}</string>`}`).join(`
|
|
633
|
+
`);
|
|
634
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
484
635
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
485
636
|
<plist version="1.0">
|
|
486
637
|
<dict>
|
|
487
|
-
|
|
488
|
-
<string>${name}</string>
|
|
489
|
-
<key>CFBundleIdentifier</key>
|
|
490
|
-
<string>${bundleId}</string>
|
|
491
|
-
<key>CFBundleName</key>
|
|
492
|
-
<string>${name}</string>
|
|
493
|
-
<key>CFBundleShortVersionString</key>
|
|
494
|
-
<string>${version}</string>
|
|
495
|
-
<key>CFBundleVersion</key>
|
|
496
|
-
<string>${version}</string>
|
|
497
|
-
<key>CFBundlePackageType</key>
|
|
498
|
-
<string>APPL</string>
|
|
499
|
-
<key>NSHighResolutionCapable</key>
|
|
500
|
-
<true/>
|
|
638
|
+
${body}
|
|
501
639
|
</dict>
|
|
502
640
|
</plist>`;
|
|
503
|
-
|
|
641
|
+
}
|
|
642
|
+
function codesignArguments(opts) {
|
|
643
|
+
return [
|
|
644
|
+
"--force",
|
|
645
|
+
"--sign",
|
|
646
|
+
opts.identity,
|
|
647
|
+
"--timestamp",
|
|
648
|
+
...opts.hardenedRuntime ? ["--options", "runtime"] : [],
|
|
649
|
+
...opts.entitlements ? ["--entitlements", opts.entitlements] : [],
|
|
650
|
+
"--deep",
|
|
651
|
+
opts.path
|
|
652
|
+
];
|
|
653
|
+
}
|
|
654
|
+
function productbuildArguments(opts) {
|
|
655
|
+
return [
|
|
656
|
+
"--component",
|
|
657
|
+
opts.appBundlePath,
|
|
658
|
+
"/Applications",
|
|
659
|
+
"--sign",
|
|
660
|
+
opts.identity,
|
|
661
|
+
opts.outputPath
|
|
662
|
+
];
|
|
663
|
+
}
|
|
664
|
+
function notarytoolArguments(opts) {
|
|
665
|
+
return [
|
|
666
|
+
"notarytool",
|
|
667
|
+
"submit",
|
|
668
|
+
opts.artifactPath,
|
|
669
|
+
"--apple-id",
|
|
670
|
+
opts.appleId,
|
|
671
|
+
"--password",
|
|
672
|
+
opts.applePassword,
|
|
673
|
+
"--team-id",
|
|
674
|
+
opts.teamId,
|
|
675
|
+
"--wait"
|
|
676
|
+
];
|
|
677
|
+
}
|
|
678
|
+
function createMacOSAppBundle(opts) {
|
|
679
|
+
try {
|
|
680
|
+
const { name, binaryPath, iconPath, provisioningProfile, additionalExecutables, outputPath } = opts;
|
|
681
|
+
const contents = import_path.join(outputPath, "Contents");
|
|
682
|
+
const macOS = import_path.join(contents, "MacOS");
|
|
683
|
+
import_fs.mkdirSync(macOS, { recursive: true });
|
|
684
|
+
import_fs.mkdirSync(import_path.join(contents, "Resources"), { recursive: true });
|
|
685
|
+
import_fs.copyFileSync(binaryPath, import_path.join(macOS, name));
|
|
686
|
+
import_fs.chmodSync(import_path.join(macOS, name), 493);
|
|
687
|
+
for (const executable of additionalExecutables || []) {
|
|
688
|
+
if (!import_fs.existsSync(executable))
|
|
689
|
+
return { success: false, error: `Additional executable not found: ${executable}` };
|
|
690
|
+
const destination = import_path.join(macOS, import_path.basename(executable));
|
|
691
|
+
import_fs.copyFileSync(executable, destination);
|
|
692
|
+
import_fs.chmodSync(destination, 493);
|
|
693
|
+
}
|
|
694
|
+
let iconName;
|
|
695
|
+
if (iconPath) {
|
|
696
|
+
if (!import_fs.existsSync(iconPath))
|
|
697
|
+
return { success: false, error: `Icon not found: ${iconPath}` };
|
|
698
|
+
iconName = import_path.basename(iconPath).replace(/\.icns$/i, "");
|
|
699
|
+
import_fs.copyFileSync(iconPath, import_path.join(contents, "Resources", `${iconName}.icns`));
|
|
700
|
+
}
|
|
701
|
+
if (provisioningProfile) {
|
|
702
|
+
if (!import_fs.existsSync(provisioningProfile))
|
|
703
|
+
return { success: false, error: `Provisioning profile not found: ${provisioningProfile}` };
|
|
704
|
+
import_fs.copyFileSync(provisioningProfile, import_path.join(contents, "embedded.provisionprofile"));
|
|
705
|
+
}
|
|
706
|
+
import_fs.writeFileSync(import_path.join(contents, "Info.plist"), macOSInfoPlist({ ...opts, iconName }));
|
|
504
707
|
return { success: true };
|
|
505
708
|
} catch (error) {
|
|
506
709
|
return { success: false, error: error.message };
|
|
507
710
|
}
|
|
508
711
|
}
|
|
509
|
-
|
|
712
|
+
var MEBIBYTE = 1024 * 1024;
|
|
713
|
+
function pathContentBytes(path) {
|
|
714
|
+
const stat = import_fs.lstatSync(path);
|
|
715
|
+
if (!stat.isDirectory())
|
|
716
|
+
return stat.size;
|
|
717
|
+
return import_fs.readdirSync(path).reduce((total, entry) => total + pathContentBytes(import_path.join(path, entry)), 0);
|
|
718
|
+
}
|
|
719
|
+
function dmgCapacityMegabytes(contentBytes) {
|
|
720
|
+
if (!Number.isSafeInteger(contentBytes) || contentBytes < 0)
|
|
721
|
+
throw new Error(`DMG content size must be a non-negative safe integer: ${contentBytes}`);
|
|
722
|
+
const contentMegabytes = Math.ceil(contentBytes / MEBIBYTE);
|
|
723
|
+
return Math.max(64, Math.ceil(contentMegabytes * 1.25) + 32);
|
|
724
|
+
}
|
|
725
|
+
function dmgCreateArguments(opts, contentBytes) {
|
|
726
|
+
return [
|
|
727
|
+
"create",
|
|
728
|
+
"-volname",
|
|
729
|
+
opts.volumeName,
|
|
730
|
+
"-srcfolder",
|
|
731
|
+
opts.appBundlePath,
|
|
732
|
+
"-size",
|
|
733
|
+
`${dmgCapacityMegabytes(contentBytes)}m`,
|
|
734
|
+
"-ov",
|
|
735
|
+
"-format",
|
|
736
|
+
"UDZO",
|
|
737
|
+
opts.outputPath
|
|
738
|
+
];
|
|
739
|
+
}
|
|
740
|
+
var HDIUTIL_MAX_ATTEMPTS = 3;
|
|
741
|
+
function shouldRetryHdiutil(error, attempt, maxAttempts = HDIUTIL_MAX_ATTEMPTS) {
|
|
742
|
+
if (!Number.isInteger(attempt) || attempt < 1 || !Number.isInteger(maxAttempts) || maxAttempts < 1)
|
|
743
|
+
throw new Error("hdiutil retry attempts must be positive integers");
|
|
744
|
+
return attempt < maxAttempts && /(?:resource busy|resource temporarily unavailable)/i.test(error);
|
|
745
|
+
}
|
|
746
|
+
function runTool(tool, args) {
|
|
510
747
|
return new Promise((resolve) => {
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
"create",
|
|
517
|
-
"-volname",
|
|
518
|
-
opts.volumeName,
|
|
519
|
-
"-srcfolder",
|
|
520
|
-
opts.appBundlePath,
|
|
521
|
-
"-ov",
|
|
522
|
-
"-format",
|
|
523
|
-
"UDZO",
|
|
524
|
-
opts.outputPath
|
|
525
|
-
]);
|
|
526
|
-
proc.on("close", (code) => {
|
|
527
|
-
if (code === 0) {
|
|
528
|
-
resolve({ success: true, outputPath: opts.outputPath });
|
|
529
|
-
} else {
|
|
530
|
-
resolve({ success: false, error: `hdiutil exited with code ${code}` });
|
|
531
|
-
}
|
|
748
|
+
const proc = import_child_process.spawn(tool, args);
|
|
749
|
+
let stdout = "";
|
|
750
|
+
let stderr = "";
|
|
751
|
+
proc.stdout?.on("data", (chunk) => {
|
|
752
|
+
stdout += chunk.toString();
|
|
532
753
|
});
|
|
533
|
-
proc.on("
|
|
534
|
-
|
|
754
|
+
proc.stderr?.on("data", (chunk) => {
|
|
755
|
+
stderr += chunk.toString();
|
|
535
756
|
});
|
|
757
|
+
proc.on("close", (code) => {
|
|
758
|
+
if (code === 0)
|
|
759
|
+
resolve({ success: true });
|
|
760
|
+
else
|
|
761
|
+
resolve({ success: false, error: formatPackagingCommandError(tool, code, stdout, stderr) });
|
|
762
|
+
});
|
|
763
|
+
proc.on("error", (err) => resolve({ success: false, error: err.message }));
|
|
536
764
|
});
|
|
537
765
|
}
|
|
766
|
+
var runHdiutil = (args) => runTool("hdiutil", args);
|
|
767
|
+
async function createDMG(opts) {
|
|
768
|
+
if (!/^[^/:\n]{1,27}$/.test(opts.volumeName))
|
|
769
|
+
return { success: false, error: `Invalid DMG volume name "${opts.volumeName}"; must be 1..27 chars without /, :, or newline` };
|
|
770
|
+
const args = dmgCreateArguments(opts, pathContentBytes(opts.appBundlePath));
|
|
771
|
+
const failures = [];
|
|
772
|
+
for (let attempt = 1;attempt <= HDIUTIL_MAX_ATTEMPTS; attempt++) {
|
|
773
|
+
const result = await runHdiutil(args);
|
|
774
|
+
if (result.success)
|
|
775
|
+
return { success: true, outputPath: opts.outputPath };
|
|
776
|
+
failures.push(`attempt ${attempt}: ${result.error}`);
|
|
777
|
+
if (!shouldRetryHdiutil(result.error, attempt))
|
|
778
|
+
return { success: false, error: failures.join(`
|
|
779
|
+
`) };
|
|
780
|
+
import_fs.rmSync(opts.outputPath, { force: true });
|
|
781
|
+
await new Promise((resolve) => setTimeout(resolve, attempt * 2000));
|
|
782
|
+
}
|
|
783
|
+
return { success: false, error: failures.join(`
|
|
784
|
+
`) };
|
|
785
|
+
}
|
|
538
786
|
async function createPKG(opts) {
|
|
539
|
-
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
if (
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
787
|
+
if (!/^[a-zA-Z0-9._-]+$/.test(opts.identifier) || !opts.identifier.includes("."))
|
|
788
|
+
return { success: false, error: `Invalid pkg identifier "${opts.identifier}"; expected reverse-DNS like com.example.app` };
|
|
789
|
+
if (!/^[A-Za-z0-9._+-]+$/.test(opts.version))
|
|
790
|
+
return { success: false, error: `Invalid pkg version "${opts.version}"` };
|
|
791
|
+
if (opts.appStore) {
|
|
792
|
+
if (!opts.installerIdentity)
|
|
793
|
+
return { success: false, error: 'App Store packaging requires macos.installerIdentity (a "3rd Party Mac Developer Installer" identity)' };
|
|
794
|
+
const built = await runTool("productbuild", productbuildArguments({
|
|
795
|
+
appBundlePath: opts.appBundlePath,
|
|
796
|
+
outputPath: opts.outputPath,
|
|
797
|
+
identity: opts.installerIdentity
|
|
798
|
+
}));
|
|
799
|
+
return built.success ? { success: true, outputPath: opts.outputPath } : { success: false, error: built.error };
|
|
800
|
+
}
|
|
801
|
+
const tempDir = import_fs.mkdtempSync(import_path.join(import_os.tmpdir(), "craft-pkg-"));
|
|
802
|
+
try {
|
|
549
803
|
const appsDir = import_path.join(tempDir, "Applications");
|
|
550
804
|
import_fs.mkdirSync(appsDir, { recursive: true });
|
|
551
805
|
import_fs.cpSync(opts.appBundlePath, import_path.join(appsDir, import_path.basename(opts.appBundlePath)), { recursive: true });
|
|
552
|
-
const
|
|
806
|
+
const built = await runTool("pkgbuild", [
|
|
553
807
|
"--root",
|
|
554
808
|
tempDir,
|
|
555
809
|
"--identifier",
|
|
@@ -558,64 +812,116 @@ async function createPKG(opts) {
|
|
|
558
812
|
opts.version,
|
|
559
813
|
"--install-location",
|
|
560
814
|
"/",
|
|
815
|
+
...opts.installerIdentity ? ["--sign", opts.installerIdentity] : [],
|
|
561
816
|
opts.outputPath
|
|
562
817
|
]);
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
818
|
+
return built.success ? { success: true, outputPath: opts.outputPath } : { success: false, error: built.error };
|
|
819
|
+
} finally {
|
|
820
|
+
import_fs.rmSync(tempDir, { recursive: true, force: true });
|
|
821
|
+
}
|
|
822
|
+
}
|
|
823
|
+
function xml(value) {
|
|
824
|
+
return value.replaceAll("&", "&").replaceAll("<", "<").replaceAll(">", ">").replaceAll('"', """).replaceAll(`'`, "'");
|
|
825
|
+
}
|
|
826
|
+
function wixIdentifier(value) {
|
|
827
|
+
const sanitized = value.replace(/[^A-Za-z0-9_.]/g, "_");
|
|
828
|
+
return /^[A-Za-z_]/.test(sanitized) ? sanitized : `_${sanitized}`;
|
|
829
|
+
}
|
|
830
|
+
function deterministicGuid(value) {
|
|
831
|
+
const digest = import_crypto.createHash("sha256").update(value).digest("hex").slice(0, 32).split("");
|
|
832
|
+
digest[12] = "4";
|
|
833
|
+
digest[16] = (Number.parseInt(digest[16], 16) & 3 | 8).toString(16);
|
|
834
|
+
const hex = digest.join("").toUpperCase();
|
|
835
|
+
return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;
|
|
836
|
+
}
|
|
837
|
+
function windowsArchitecture(architecture) {
|
|
838
|
+
if (architecture === "ia32" || architecture === "x86")
|
|
839
|
+
return "x86";
|
|
840
|
+
if (architecture === "x64" || architecture === "arm64")
|
|
841
|
+
return architecture;
|
|
842
|
+
throw new Error(`Unsupported Windows package architecture: ${architecture}`);
|
|
843
|
+
}
|
|
844
|
+
function renderWixSource(opts, sourceName) {
|
|
845
|
+
if (!/^[0-9]+\.[0-9]+\.[0-9]+(?:\.[0-9]+)?$/.test(opts.version))
|
|
846
|
+
throw new Error(`MSI version must have 3 or 4 numeric parts: ${opts.version}`);
|
|
847
|
+
const id = wixIdentifier(opts.name);
|
|
848
|
+
const manufacturer = opts.manufacturer.trim() || "Unknown";
|
|
849
|
+
const upgradeCode = deterministicGuid(`${manufacturer}/${opts.name}`);
|
|
850
|
+
const programFilesFolder = opts.architecture === "x86" ? "ProgramFilesFolder" : "ProgramFiles64Folder";
|
|
851
|
+
const win64 = opts.architecture === "x86" ? "no" : "yes";
|
|
852
|
+
return `<?xml version="1.0" encoding="UTF-8"?>
|
|
853
|
+
<Wix xmlns="http://schemas.microsoft.com/wix/2006/wi">
|
|
854
|
+
<Product Id="*" Name="${xml(opts.name)}" Language="1033" Version="${opts.version}" Manufacturer="${xml(manufacturer)}" UpgradeCode="${upgradeCode}">
|
|
855
|
+
<Package InstallerVersion="500" Compressed="yes" InstallScope="perMachine" Platform="${opts.architecture}" />
|
|
856
|
+
<MajorUpgrade AllowDowngrades="yes" />
|
|
857
|
+
<MediaTemplate EmbedCab="yes" />
|
|
858
|
+
<Directory Id="TARGETDIR" Name="SourceDir">
|
|
859
|
+
<Directory Id="${programFilesFolder}">
|
|
860
|
+
<Directory Id="INSTALLFOLDER" Name="${xml(opts.name)}">
|
|
861
|
+
<Component Id="${id}Executable" Guid="*" Win64="${win64}">
|
|
862
|
+
<File Id="${id}File" Source="${xml(sourceName)}" KeyPath="yes" />
|
|
863
|
+
</Component>
|
|
864
|
+
</Directory>
|
|
865
|
+
</Directory>
|
|
866
|
+
</Directory>
|
|
867
|
+
<Feature Id="ProductFeature" Title="${xml(opts.name)}" Level="1">
|
|
868
|
+
<ComponentRef Id="${id}Executable" />
|
|
869
|
+
</Feature>
|
|
870
|
+
</Product>
|
|
871
|
+
</Wix>
|
|
872
|
+
`;
|
|
576
873
|
}
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
583
|
-
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
});
|
|
590
|
-
}
|
|
591
|
-
});
|
|
874
|
+
function windowsExecutableName(name) {
|
|
875
|
+
if (name.length === 0 || name.trim() !== name || /[<>:"/\\|?*\u0000-\u001F]/.test(name) || /[. ]$/.test(name))
|
|
876
|
+
throw new Error(`Invalid Windows application name: ${JSON.stringify(name)}`);
|
|
877
|
+
if (/^(?:CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(?:\.|$)/i.test(name))
|
|
878
|
+
throw new Error(`Reserved Windows application name: ${JSON.stringify(name)}`);
|
|
879
|
+
return `${name}.exe`;
|
|
880
|
+
}
|
|
881
|
+
function runCommand(command, args, cwd) {
|
|
882
|
+
return new Promise((resolve, reject) => {
|
|
883
|
+
const child = import_child_process.spawn(command, args, { cwd, stdio: "inherit", windowsHide: true });
|
|
884
|
+
child.once("error", reject);
|
|
885
|
+
child.once("close", (code) => code === 0 ? resolve() : reject(new Error(`${command} exited with code ${code}`)));
|
|
592
886
|
});
|
|
593
887
|
}
|
|
888
|
+
async function createMSI(opts) {
|
|
889
|
+
const tempDir = import_fs.mkdtempSync(import_path.join(import_os.tmpdir(), "craft-msi-"));
|
|
890
|
+
try {
|
|
891
|
+
const binaryName = windowsExecutableName(opts.name);
|
|
892
|
+
const sourcePath = import_path.join(tempDir, binaryName);
|
|
893
|
+
const wxsPath = import_path.join(tempDir, "installer.wxs");
|
|
894
|
+
const wixobjPath = import_path.join(tempDir, "installer.wixobj");
|
|
895
|
+
import_fs.copyFileSync(opts.binaryPath, sourcePath);
|
|
896
|
+
import_fs.writeFileSync(wxsPath, renderWixSource(opts, binaryName));
|
|
897
|
+
await runCommand("candle.exe", ["-nologo", "-out", wixobjPath, wxsPath], tempDir);
|
|
898
|
+
await runCommand("light.exe", ["-nologo", "-sval", "-out", opts.outputPath, wixobjPath], tempDir);
|
|
899
|
+
if (opts.certificatePath) {
|
|
900
|
+
const signArgs = ["sign", "/fd", "sha256", "/tr", "https://timestamp.digicert.com", "/td", "sha256", "/f", opts.certificatePath];
|
|
901
|
+
if (opts.certificatePassword)
|
|
902
|
+
signArgs.push("/p", opts.certificatePassword);
|
|
903
|
+
signArgs.push(opts.outputPath);
|
|
904
|
+
await runCommand("signtool.exe", signArgs);
|
|
905
|
+
await runCommand("signtool.exe", ["verify", "/pa", "/all", opts.outputPath]);
|
|
906
|
+
}
|
|
907
|
+
return { success: true, outputPath: opts.outputPath };
|
|
908
|
+
} catch (error) {
|
|
909
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
910
|
+
const missingTool = /ENOENT|not found/i.test(message);
|
|
911
|
+
return { success: false, error: missingTool ? `WiX Toolset not found: ${message}` : message };
|
|
912
|
+
} finally {
|
|
913
|
+
import_fs.rmSync(tempDir, { recursive: true, force: true });
|
|
914
|
+
}
|
|
915
|
+
}
|
|
594
916
|
async function createZIP(opts) {
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
const
|
|
598
|
-
|
|
599
|
-
|
|
600
|
-
|
|
601
|
-
|
|
602
|
-
|
|
603
|
-
settled = true;
|
|
604
|
-
resolve(r);
|
|
605
|
-
};
|
|
606
|
-
output.on("close", () => {
|
|
607
|
-
settle({ success: true, outputPath: opts.outputPath });
|
|
608
|
-
});
|
|
609
|
-
output.on("error", (err) => {
|
|
610
|
-
settle({ success: false, error: `Failed to write ZIP: ${err.message}` });
|
|
611
|
-
});
|
|
612
|
-
archive.on("error", (err) => {
|
|
613
|
-
settle({ success: false, error: err.message });
|
|
614
|
-
});
|
|
615
|
-
archive.pipe(output);
|
|
616
|
-
archive.file(opts.binaryPath, { name: `${opts.name}.exe` });
|
|
617
|
-
archive.finalize();
|
|
618
|
-
});
|
|
917
|
+
try {
|
|
918
|
+
const data = new Uint8Array(import_fs.readFileSync(opts.binaryPath));
|
|
919
|
+
const zip = buildZip([{ name: `${opts.name}.exe`, data }]);
|
|
920
|
+
import_fs.writeFileSync(opts.outputPath, zip);
|
|
921
|
+
return { success: true, outputPath: opts.outputPath };
|
|
922
|
+
} catch (err) {
|
|
923
|
+
return { success: false, error: `Failed to write ZIP: ${err.message}` };
|
|
924
|
+
}
|
|
619
925
|
}
|
|
620
926
|
async function createDEB(opts) {
|
|
621
927
|
return new Promise((resolve) => {
|
|
@@ -2082,6 +2388,9 @@ class Window {
|
|
|
2082
2388
|
async setPosition(x, y, animate) {
|
|
2083
2389
|
await this._call("setPosition", { x, y, animate });
|
|
2084
2390
|
}
|
|
2391
|
+
async moveBy(dx, dy) {
|
|
2392
|
+
await this._call("moveBy", { dx, dy });
|
|
2393
|
+
}
|
|
2085
2394
|
async getPosition() {
|
|
2086
2395
|
return this._call("getPosition");
|
|
2087
2396
|
}
|
|
@@ -2109,6 +2418,9 @@ class Window {
|
|
|
2109
2418
|
async setMovable(movable) {
|
|
2110
2419
|
await this._call("setMovable", { movable });
|
|
2111
2420
|
}
|
|
2421
|
+
async startDrag() {
|
|
2422
|
+
await this._call("startDrag");
|
|
2423
|
+
}
|
|
2112
2424
|
async isMovable() {
|
|
2113
2425
|
return this._call("isMovable");
|
|
2114
2426
|
}
|
|
@@ -2226,12 +2538,14 @@ class WindowManager {
|
|
|
2226
2538
|
setTitle = (title) => this.current.setTitle(title);
|
|
2227
2539
|
setSize = (width, height, animate) => this.current.setSize(width, height, animate);
|
|
2228
2540
|
setPosition = (x, y, animate) => this.current.setPosition(x, y, animate);
|
|
2541
|
+
moveBy = (dx, dy) => this.current.moveBy(dx, dy);
|
|
2229
2542
|
setBounds = (bounds, animate) => this.current.setBounds(bounds, animate);
|
|
2230
2543
|
setAlwaysOnTop = (alwaysOnTop) => this.current.setAlwaysOnTop(alwaysOnTop);
|
|
2231
2544
|
setOpacity = (opacity) => this.current.setOpacity(opacity);
|
|
2232
2545
|
setBackgroundColor = (color) => this.current.setBackgroundColor(color);
|
|
2233
2546
|
setVibrancy = (vibrancy) => this.current.setVibrancy(vibrancy);
|
|
2234
2547
|
setResizable = (resizable) => this.current.setResizable(resizable);
|
|
2548
|
+
startDrag = () => this.current.startDrag();
|
|
2235
2549
|
getState = () => this.current.getState();
|
|
2236
2550
|
on = (event, handler) => this.current.on(event, handler);
|
|
2237
2551
|
once = (event, handler) => this.current.once(event, handler);
|
|
@@ -3674,8 +3988,8 @@ var crypto = {
|
|
|
3674
3988
|
if (!hasNodeCrypto) {
|
|
3675
3989
|
throw new CraftCryptoError("MD5 is not available in this runtime — WebCrypto does not implement it. " + "Use sha256/sha512, or call this from Node.");
|
|
3676
3990
|
}
|
|
3677
|
-
const { createHash:
|
|
3678
|
-
return
|
|
3991
|
+
const { createHash: createHash3 } = await import("node:crypto");
|
|
3992
|
+
return createHash3("md5").update(data).digest("hex");
|
|
3679
3993
|
}
|
|
3680
3994
|
if (typeof globalThis.crypto !== "undefined" && globalThis.crypto.subtle) {
|
|
3681
3995
|
const encoder = new TextEncoder;
|
|
@@ -3683,8 +3997,8 @@ var crypto = {
|
|
|
3683
3997
|
const hashBuffer = await globalThis.crypto.subtle.digest(algorithm === "sha256" ? "SHA-256" : "SHA-512", dataBuffer);
|
|
3684
3998
|
return bufferToHex(hashBuffer);
|
|
3685
3999
|
}
|
|
3686
|
-
const { createHash } = await import("node:crypto");
|
|
3687
|
-
return
|
|
4000
|
+
const { createHash: createHash2 } = await import("node:crypto");
|
|
4001
|
+
return createHash2(algorithm).update(data).digest("hex");
|
|
3688
4002
|
},
|
|
3689
4003
|
async encrypt(data, key) {
|
|
3690
4004
|
if (typeof window !== "undefined" && window.craft?.crypto) {
|
|
@@ -3999,7 +4313,7 @@ async function getSystemInfo() {
|
|
|
3999
4313
|
uptime: 0
|
|
4000
4314
|
};
|
|
4001
4315
|
}
|
|
4002
|
-
async function
|
|
4316
|
+
async function exec(command, options) {
|
|
4003
4317
|
if (typeof window !== "undefined" && window.craft) {
|
|
4004
4318
|
return callBridge3("process.exec", { command, ...options });
|
|
4005
4319
|
}
|
|
@@ -4179,18 +4493,18 @@ async function open(target) {
|
|
|
4179
4493
|
const platform = getPlatform();
|
|
4180
4494
|
const { execFile } = await import("node:child_process");
|
|
4181
4495
|
const { promisify } = await import("node:util");
|
|
4182
|
-
const
|
|
4496
|
+
const exec2 = promisify(execFile);
|
|
4183
4497
|
switch (platform) {
|
|
4184
4498
|
case "darwin":
|
|
4185
4499
|
case "macos":
|
|
4186
|
-
await
|
|
4500
|
+
await exec2("open", [target]);
|
|
4187
4501
|
return;
|
|
4188
4502
|
case "win32":
|
|
4189
4503
|
case "windows":
|
|
4190
|
-
await
|
|
4504
|
+
await exec2("cmd.exe", ["/c", "start", '""', target]);
|
|
4191
4505
|
return;
|
|
4192
4506
|
case "linux":
|
|
4193
|
-
await
|
|
4507
|
+
await exec2("xdg-open", [target]);
|
|
4194
4508
|
return;
|
|
4195
4509
|
default:
|
|
4196
4510
|
throw new Error(`Unsupported platform: ${platform}`);
|
|
@@ -8169,9 +8483,9 @@ async function buildCSS(options) {
|
|
|
8169
8483
|
console.warn("buildCSS can only be run in Node.js environment");
|
|
8170
8484
|
return;
|
|
8171
8485
|
}
|
|
8172
|
-
const { exec:
|
|
8486
|
+
const { exec: exec2 } = await import("child_process");
|
|
8173
8487
|
const { promisify } = await import("util");
|
|
8174
|
-
const execAsync = promisify(
|
|
8488
|
+
const execAsync = promisify(exec2);
|
|
8175
8489
|
const args = [
|
|
8176
8490
|
"build",
|
|
8177
8491
|
"--content",
|
|
@@ -8192,109 +8506,123 @@ async function buildCSS(options) {
|
|
|
8192
8506
|
// src/styles/sidebars.ts
|
|
8193
8507
|
var tahoeStyles = {
|
|
8194
8508
|
sidebar: `
|
|
8195
|
-
w-
|
|
8196
|
-
bg-white/
|
|
8197
|
-
backdrop-blur-
|
|
8198
|
-
|
|
8509
|
+
w-[250px] h-full flex flex-col
|
|
8510
|
+
bg-white/55 dark:bg-[#1e1e23]/55
|
|
8511
|
+
backdrop-blur-[60px] backdrop-saturate-[1.8]
|
|
8512
|
+
text-black dark:text-white
|
|
8199
8513
|
select-none
|
|
8200
8514
|
`,
|
|
8201
8515
|
content: `
|
|
8202
8516
|
flex-1 overflow-y-auto overflow-x-hidden
|
|
8203
|
-
|
|
8204
|
-
scrollbar-thin scrollbar-thumb-black/10 dark:scrollbar-thumb-white/10
|
|
8517
|
+
px-[10px] pb-[10px]
|
|
8205
8518
|
`,
|
|
8206
8519
|
section: `
|
|
8207
|
-
|
|
8520
|
+
flex flex-col gap-[2px]
|
|
8208
8521
|
`,
|
|
8209
8522
|
sectionHeader: `
|
|
8210
|
-
|
|
8211
|
-
text-[11px] font-semibold
|
|
8212
|
-
text-
|
|
8523
|
+
pl-[8px] pr-[6px] pt-[16px] pb-[5px]
|
|
8524
|
+
text-[11px] font-semibold leading-[13px]
|
|
8525
|
+
text-[#3c3c43]/60 dark:text-[#ebebf5]/60
|
|
8213
8526
|
`,
|
|
8214
8527
|
sectionHeaderCollapsible: `
|
|
8215
|
-
|
|
8216
|
-
|
|
8217
|
-
text-
|
|
8218
|
-
|
|
8219
|
-
|
|
8528
|
+
group flex items-center w-full
|
|
8529
|
+
pl-[8px] pr-[6px] pt-[16px] pb-[5px]
|
|
8530
|
+
text-[11px] font-semibold leading-[13px]
|
|
8531
|
+
text-[#3c3c43]/60 dark:text-[#ebebf5]/60
|
|
8532
|
+
cursor-default
|
|
8220
8533
|
`,
|
|
8221
8534
|
collapseChevron: `
|
|
8222
|
-
|
|
8535
|
+
ml-auto h-[11px] w-[11px]
|
|
8536
|
+
text-[#3c3c43]/45 dark:text-[#ebebf5]/45
|
|
8537
|
+
opacity-0 group-hover:opacity-100
|
|
8538
|
+
transition-all duration-200
|
|
8223
8539
|
`,
|
|
8224
8540
|
item: `
|
|
8225
|
-
flex items-center
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8541
|
+
flex w-full items-center
|
|
8542
|
+
h-[30px] rounded-[9px] pl-[4px] pr-[8px]
|
|
8543
|
+
text-[13px] leading-[16px] text-black dark:text-white
|
|
8544
|
+
cursor-default transition-colors duration-150 ease-out
|
|
8545
|
+
hover:bg-black/4 dark:hover:bg-white/6
|
|
8546
|
+
active:bg-black/10 dark:active:bg-white/18
|
|
8229
8547
|
`,
|
|
8230
8548
|
itemSelected: `
|
|
8231
|
-
flex items-center
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8549
|
+
flex w-full items-center
|
|
8550
|
+
h-[30px] rounded-[9px] pl-[4px] pr-[8px]
|
|
8551
|
+
text-[13px] leading-[16px] text-black dark:text-white
|
|
8552
|
+
cursor-default
|
|
8553
|
+
bg-black/8 dark:bg-white/14
|
|
8554
|
+
`,
|
|
8555
|
+
disclosure: `
|
|
8556
|
+
flex h-[16px] w-[18px] shrink-0 items-center justify-center
|
|
8557
|
+
`,
|
|
8558
|
+
disclosureChevron: `
|
|
8559
|
+
h-[11px] w-[11px]
|
|
8560
|
+
text-[#3c3c43]/55 dark:text-[#ebebf5]/55
|
|
8561
|
+
transition-transform duration-200 ease-out
|
|
8236
8562
|
`,
|
|
8237
8563
|
itemIcon: `
|
|
8238
|
-
|
|
8239
|
-
text-
|
|
8564
|
+
h-[17px] w-[17px] flex-shrink-0
|
|
8565
|
+
text-[#0088ff]
|
|
8240
8566
|
`,
|
|
8241
8567
|
itemIconSelected: `
|
|
8242
|
-
|
|
8243
|
-
text-
|
|
8568
|
+
h-[17px] w-[17px] flex-shrink-0
|
|
8569
|
+
text-[#0088ff]
|
|
8570
|
+
`,
|
|
8571
|
+
itemIconSlot: `
|
|
8572
|
+
flex h-[20px] w-[22px] shrink-0 items-center justify-center mr-[7px]
|
|
8244
8573
|
`,
|
|
8245
8574
|
itemLabel: `
|
|
8246
8575
|
flex-1 truncate
|
|
8247
8576
|
`,
|
|
8248
8577
|
itemBadge: `
|
|
8249
|
-
|
|
8250
|
-
|
|
8251
|
-
text-
|
|
8578
|
+
ml-[8px] shrink-0 tabular-nums
|
|
8579
|
+
text-[13px] leading-[16px]
|
|
8580
|
+
text-[#3c3c43]/60 dark:text-[#ebebf5]/60
|
|
8252
8581
|
`,
|
|
8253
8582
|
itemBadgeSelected: `
|
|
8254
|
-
|
|
8255
|
-
|
|
8583
|
+
ml-[8px] shrink-0 tabular-nums
|
|
8584
|
+
text-[13px] leading-[16px]
|
|
8585
|
+
text-[#3c3c43]/60 dark:text-[#ebebf5]/60
|
|
8256
8586
|
`,
|
|
8257
8587
|
children: `
|
|
8258
|
-
ml-
|
|
8588
|
+
ml-[16px] mt-[2px] flex flex-col gap-[2px]
|
|
8259
8589
|
`,
|
|
8260
8590
|
dragIndicator: `
|
|
8261
|
-
absolute left-0 right-0 h-0.5 bg-
|
|
8591
|
+
absolute left-0 right-0 h-0.5 bg-[#0088ff]
|
|
8262
8592
|
pointer-events-none
|
|
8263
8593
|
`,
|
|
8264
8594
|
searchContainer: `
|
|
8265
|
-
px-
|
|
8595
|
+
px-[10px] pb-[6px]
|
|
8266
8596
|
`,
|
|
8267
8597
|
searchInput: `
|
|
8268
|
-
w-full
|
|
8269
|
-
text-[13px]
|
|
8270
|
-
|
|
8598
|
+
h-[28px] w-full rounded-[8px] px-[8px]
|
|
8599
|
+
text-[13px] text-black dark:text-white
|
|
8600
|
+
placeholder:text-[#3c3c43]/50 dark:placeholder:text-[#ebebf5]/50
|
|
8601
|
+
bg-black/5 dark:bg-white/10
|
|
8271
8602
|
border border-transparent
|
|
8272
|
-
focus:outline-none focus:
|
|
8603
|
+
focus:outline-none focus:ring-2 focus:ring-[#0088ff]/60
|
|
8273
8604
|
transition-all duration-150
|
|
8274
8605
|
`,
|
|
8275
8606
|
header: `
|
|
8276
|
-
|
|
8277
|
-
flex items-center gap-3
|
|
8607
|
+
h-[52px] px-[21px] flex items-center gap-3
|
|
8278
8608
|
`,
|
|
8279
8609
|
headerAvatar: `
|
|
8280
|
-
w-
|
|
8281
|
-
flex items-center justify-center text-
|
|
8610
|
+
w-[30px] h-[30px] rounded-full bg-black/10 dark:bg-white/15
|
|
8611
|
+
flex items-center justify-center text-[13px] font-semibold
|
|
8282
8612
|
`,
|
|
8283
8613
|
headerTitle: `
|
|
8284
|
-
text-[13px] font-medium text-
|
|
8614
|
+
text-[13px] font-medium text-black dark:text-white
|
|
8285
8615
|
`,
|
|
8286
8616
|
headerSubtitle: `
|
|
8287
|
-
text-[11px] text-
|
|
8617
|
+
text-[11px] text-[#3c3c43]/60 dark:text-[#ebebf5]/60
|
|
8288
8618
|
`,
|
|
8289
8619
|
footer: `
|
|
8290
|
-
px-
|
|
8291
|
-
flex items-center gap-2
|
|
8620
|
+
px-[10px] pb-[8px] pt-[4px] flex items-center gap-2
|
|
8292
8621
|
`,
|
|
8293
8622
|
footerButton: `
|
|
8294
|
-
|
|
8295
|
-
text-
|
|
8296
|
-
hover:bg-black/5 dark:hover:bg-white/
|
|
8297
|
-
hover:text-neutral-700 dark:hover:text-neutral-200
|
|
8623
|
+
grid h-[28px] w-[28px] place-items-center rounded-[7px]
|
|
8624
|
+
text-[#3c3c43]/70 dark:text-[#ebebf5]/70
|
|
8625
|
+
hover:bg-black/5 dark:hover:bg-white/10
|
|
8298
8626
|
transition-colors duration-150
|
|
8299
8627
|
`
|
|
8300
8628
|
};
|
|
@@ -8713,19 +9041,21 @@ function renderTahoeSidebar(data) {
|
|
|
8713
9041
|
const itemClass = isSelected ? s.itemSelected : s.item;
|
|
8714
9042
|
const iconClass = isSelected ? s.itemIconSelected : s.itemIcon;
|
|
8715
9043
|
const badgeClass = isSelected ? s.itemBadgeSelected : s.itemBadge;
|
|
9044
|
+
const hasChildren = (item.children?.length ?? 0) > 0;
|
|
9045
|
+
const chevron = hasChildren ? `<span class='${s.disclosureChevron}${item.expanded ? " rotate-90" : ""}'>${icons.chevronRight}</span>` : "";
|
|
9046
|
+
const tint = item.color ? ` style='color: ${item.color}'` : "";
|
|
8716
9047
|
let html = `
|
|
8717
|
-
<div class='${itemClass}' data-id='${item.id}' style='padding-left: ${
|
|
8718
|
-
<span class='${
|
|
9048
|
+
<div class='${itemClass}' data-id='${item.id}'${depth > 0 ? ` style='padding-left: ${4 + depth * 16}px'` : ""}>
|
|
9049
|
+
<span class='${s.disclosure}'>${chevron}</span>
|
|
9050
|
+
<span class='${s.itemIconSlot}'><span class='${iconClass}'${tint}>${getIcon2(item.icon || "document")}</span></span>
|
|
8719
9051
|
<span class='${s.itemLabel}'>${item.label}</span>
|
|
8720
9052
|
${item.badge ? `<span class='${badgeClass}'>${item.badge}</span>` : ""}
|
|
8721
9053
|
</div>
|
|
8722
9054
|
`;
|
|
8723
9055
|
if (item.children && item.expanded) {
|
|
8724
|
-
html += `<div class='${s.children}'>`;
|
|
8725
9056
|
item.children.forEach((child) => {
|
|
8726
9057
|
html += renderItem(child, depth + 1);
|
|
8727
9058
|
});
|
|
8728
|
-
html += `</div>`;
|
|
8729
9059
|
}
|
|
8730
9060
|
return html;
|
|
8731
9061
|
};
|
|
@@ -8734,8 +9064,8 @@ function renderTahoeSidebar(data) {
|
|
|
8734
9064
|
<div class='${s.section}'>
|
|
8735
9065
|
${section.title ? `
|
|
8736
9066
|
<div class="${section.collapsible ? s.sectionHeaderCollapsible : s.sectionHeader}" data-section="${section.id}">
|
|
8737
|
-
|
|
8738
|
-
${section.
|
|
9067
|
+
<span class='truncate'>${section.title}</span>
|
|
9068
|
+
${section.collapsible ? `<span class='${s.collapseChevron}${section.collapsed ? " -rotate-90" : ""}'>${icons.chevronDown}</span>` : ""}
|
|
8739
9069
|
</div>
|
|
8740
9070
|
` : ""}
|
|
8741
9071
|
${!section.collapsed ? section.items.map((item) => renderItem(item)).join("") : ""}
|
|
@@ -9475,7 +9805,7 @@ __export(exports_updater, {
|
|
|
9475
9805
|
var import_fs3 = require("fs");
|
|
9476
9806
|
var import_path2 = require("path");
|
|
9477
9807
|
var import_child_process2 = require("child_process");
|
|
9478
|
-
var
|
|
9808
|
+
var import_crypto3 = require("crypto");
|
|
9479
9809
|
var import_events3 = require("events");
|
|
9480
9810
|
function findFirstByName(root, namePattern, kind) {
|
|
9481
9811
|
const out = import_child_process2.execFileSync("find", [root, "-name", namePattern, "-type", kind, "-print0"]);
|
|
@@ -9492,6 +9822,12 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9492
9822
|
cachedEtag = null;
|
|
9493
9823
|
cachedLastModified = null;
|
|
9494
9824
|
cachedManifest = null;
|
|
9825
|
+
emitError(error) {
|
|
9826
|
+
if (this.listenerCount("error") > 0)
|
|
9827
|
+
this.emit("error", error);
|
|
9828
|
+
else
|
|
9829
|
+
console.error("[Updater]", error);
|
|
9830
|
+
}
|
|
9495
9831
|
constructor(config) {
|
|
9496
9832
|
super();
|
|
9497
9833
|
const url = config.updateUrl;
|
|
@@ -9565,7 +9901,7 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9565
9901
|
return null;
|
|
9566
9902
|
}
|
|
9567
9903
|
} catch (error) {
|
|
9568
|
-
this.
|
|
9904
|
+
this.emitError(error);
|
|
9569
9905
|
return null;
|
|
9570
9906
|
}
|
|
9571
9907
|
}
|
|
@@ -9619,11 +9955,32 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9619
9955
|
this.emit("download-progress", progress);
|
|
9620
9956
|
}
|
|
9621
9957
|
fileStream.end();
|
|
9958
|
+
await new Promise((resolve, reject) => {
|
|
9959
|
+
fileStream.once("finish", resolve);
|
|
9960
|
+
fileStream.once("error", reject);
|
|
9961
|
+
});
|
|
9622
9962
|
const hash = await this.computeFileHash(this.downloadPath);
|
|
9623
9963
|
if (hash !== expectedHash) {
|
|
9624
9964
|
import_fs3.unlinkSync(this.downloadPath);
|
|
9625
9965
|
throw new Error("Download verification failed: hash mismatch");
|
|
9626
9966
|
}
|
|
9967
|
+
if (deltaUpdate) {
|
|
9968
|
+
if (!import_fs3.statSync(this.config.appPath).isFile()) {
|
|
9969
|
+
throw new Error("Delta updates require appPath to point to the installed bundle file");
|
|
9970
|
+
}
|
|
9971
|
+
const patchPath = this.downloadPath;
|
|
9972
|
+
const reconstructedPath = import_path2.join(downloadDir, `reconstructed-${import_path2.basename(platformUpdate.url)}`);
|
|
9973
|
+
await DeltaGenerator.apply(this.config.appPath, patchPath, reconstructedPath);
|
|
9974
|
+
const reconstructedHash = await this.computeFileHash(reconstructedPath);
|
|
9975
|
+
if (reconstructedHash !== platformUpdate.sha256) {
|
|
9976
|
+
try {
|
|
9977
|
+
import_fs3.unlinkSync(reconstructedPath);
|
|
9978
|
+
} catch {}
|
|
9979
|
+
throw new Error("Delta reconstruction failed: full bundle hash mismatch");
|
|
9980
|
+
}
|
|
9981
|
+
import_fs3.unlinkSync(patchPath);
|
|
9982
|
+
this.downloadPath = reconstructedPath;
|
|
9983
|
+
}
|
|
9627
9984
|
if (this.config.publicKeyPem && !platformUpdate.signature) {
|
|
9628
9985
|
import_fs3.unlinkSync(this.downloadPath);
|
|
9629
9986
|
throw new Error("Updater: publicKeyPem is configured but the manifest entry has no signature. " + "Refusing to install unsigned update.");
|
|
@@ -9645,7 +10002,7 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9645
10002
|
}
|
|
9646
10003
|
return this.downloadPath;
|
|
9647
10004
|
} catch (error) {
|
|
9648
|
-
this.
|
|
10005
|
+
this.emitError(error);
|
|
9649
10006
|
return null;
|
|
9650
10007
|
}
|
|
9651
10008
|
}
|
|
@@ -9705,7 +10062,8 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9705
10062
|
}
|
|
9706
10063
|
} catch (error) {
|
|
9707
10064
|
progress.phase = "error";
|
|
9708
|
-
this.
|
|
10065
|
+
this.emitError(error);
|
|
10066
|
+
throw error;
|
|
9709
10067
|
}
|
|
9710
10068
|
}
|
|
9711
10069
|
async installMacOSUpdate() {
|
|
@@ -9824,7 +10182,7 @@ class AutoUpdater extends import_events3.EventEmitter {
|
|
|
9824
10182
|
}
|
|
9825
10183
|
async computeFileHash(filePath) {
|
|
9826
10184
|
return new Promise((resolve, reject) => {
|
|
9827
|
-
const hash =
|
|
10185
|
+
const hash = import_crypto3.createHash("sha256");
|
|
9828
10186
|
const stream = import_fs3.createReadStream(filePath);
|
|
9829
10187
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
9830
10188
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -9896,7 +10254,7 @@ class DeltaGenerator {
|
|
|
9896
10254
|
}
|
|
9897
10255
|
static async computeHash(filePath) {
|
|
9898
10256
|
return new Promise((resolve, reject) => {
|
|
9899
|
-
const hash =
|
|
10257
|
+
const hash = import_crypto3.createHash("sha256");
|
|
9900
10258
|
const stream = import_fs3.createReadStream(filePath);
|
|
9901
10259
|
stream.on("data", (chunk) => hash.update(chunk));
|
|
9902
10260
|
stream.on("end", () => resolve(hash.digest("hex")));
|
|
@@ -9915,7 +10273,7 @@ function generateUpdateManifest(options) {
|
|
|
9915
10273
|
if (!info)
|
|
9916
10274
|
continue;
|
|
9917
10275
|
const bytes = import_fs3.readFileSync(info.path);
|
|
9918
|
-
const hash =
|
|
10276
|
+
const hash = import_crypto3.createHash("sha256").update(bytes).digest("hex");
|
|
9919
10277
|
manifest.platforms[platform] = {
|
|
9920
10278
|
url: info.url,
|
|
9921
10279
|
size: bytes.length,
|
|
@@ -9925,7 +10283,7 @@ function generateUpdateManifest(options) {
|
|
|
9925
10283
|
const platformDeltas = options.deltas?.filter((d) => d.platform === platform) || [];
|
|
9926
10284
|
for (const delta of platformDeltas) {
|
|
9927
10285
|
const deltaBytes = import_fs3.readFileSync(delta.path);
|
|
9928
|
-
const deltaHash =
|
|
10286
|
+
const deltaHash = import_crypto3.createHash("sha256").update(deltaBytes).digest("hex");
|
|
9929
10287
|
manifest.platforms[platform].delta.push({
|
|
9930
10288
|
fromVersion: delta.fromVersion,
|
|
9931
10289
|
url: delta.url,
|
|
@@ -10023,7 +10381,7 @@ var execFileAsync = import_node_util.promisify(import_node_child_process.execFil
|
|
|
10023
10381
|
var versionMismatchWarned = false;
|
|
10024
10382
|
function getSdkVersion() {
|
|
10025
10383
|
try {
|
|
10026
|
-
const pkgPath = import_node_path.join("/
|
|
10384
|
+
const pkgPath = import_node_path.join("/Users/chris/Code/Tools/craft/packages/typescript/src", "..", "package.json");
|
|
10027
10385
|
return JSON.parse(import_node_fs2.readFileSync(pkgPath, "utf-8")).version ?? "unknown";
|
|
10028
10386
|
} catch {
|
|
10029
10387
|
return "unknown";
|
|
@@ -10194,6 +10552,13 @@ class CraftApp {
|
|
|
10194
10552
|
args.push("--menubar-only");
|
|
10195
10553
|
if (window3?.titlebarHidden)
|
|
10196
10554
|
args.push("--titlebar-hidden");
|
|
10555
|
+
if (window3?.webSidebarMaterial) {
|
|
10556
|
+
args.push("--web-sidebar-material");
|
|
10557
|
+
if (window3?.webSidebarWidth)
|
|
10558
|
+
args.push("--web-sidebar-width", String(window3.webSidebarWidth));
|
|
10559
|
+
if (window3?.webSidebarMaterialOpacity !== undefined)
|
|
10560
|
+
args.push("--web-sidebar-material-opacity", String(window3.webSidebarMaterialOpacity));
|
|
10561
|
+
}
|
|
10197
10562
|
if (window3?.icon)
|
|
10198
10563
|
args.push("--icon", window3.icon);
|
|
10199
10564
|
if (window3?.nativeSidebar) {
|
|
@@ -10209,7 +10574,7 @@ class CraftApp {
|
|
|
10209
10574
|
} : undefined;
|
|
10210
10575
|
if (sidebarConfig?.variant === "desktop") {
|
|
10211
10576
|
sidebarConfig.material = sidebarConfig.material ?? "sidebar";
|
|
10212
|
-
sidebarConfig.backgroundEffect = sidebarConfig.backgroundEffect ?? "
|
|
10577
|
+
sidebarConfig.backgroundEffect = sidebarConfig.backgroundEffect ?? "vibrancy";
|
|
10213
10578
|
sidebarConfig.allowsVibrancy = sidebarConfig.allowsVibrancy ?? true;
|
|
10214
10579
|
}
|
|
10215
10580
|
if (sidebarConfig) {
|