craft-native 0.0.278 → 0.0.293
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/README.md +16 -0
- package/dist/android/src/emulator.d.ts +4 -0
- package/dist/android/src/index.d.ts +1 -1
- package/dist/android/src/index.js +17 -6
- package/dist/android/templates/CraftNativeHealth.kt.template +77 -1
- package/dist/android/templates/CraftNativeShell.kt.template +12 -5
- package/dist/android/templates/CraftSnapshotFile.kt.template +26 -0
- package/dist/android/templates/MainActivityNative.kt.template +16 -0
- package/dist/api/mobile.d.ts +48 -4
- package/dist/browser/storage.d.ts +5 -3
- package/dist/browser.d.ts +1 -0
- package/dist/browser.js +31 -7
- package/dist/cli.js +103 -23
- package/dist/index.cjs +100 -23
- package/dist/index.d.cts +1 -1
- package/dist/index.d.ts +1 -1
- package/dist/index.js +103 -23
- package/dist/ios/templates/CraftApp.swift +64 -5
- package/dist/ios/templates/CraftHealth.swift +76 -0
- package/dist/ios/templates/CraftHybrid.swift +21 -0
- package/dist/ios/templates/CraftNativeScreen.swift +116 -8
- package/dist/mobile.js +6 -0
- package/dist/package.d.ts +10 -0
- package/dist/types.d.ts +13 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -130,12 +130,15 @@ import { spawn } from "child_process";
|
|
|
130
130
|
import { createHash } from "crypto";
|
|
131
131
|
import {
|
|
132
132
|
chmodSync,
|
|
133
|
+
closeSync,
|
|
133
134
|
copyFileSync,
|
|
134
135
|
cpSync,
|
|
135
136
|
existsSync as existsSync4,
|
|
136
137
|
lstatSync,
|
|
137
138
|
mkdirSync,
|
|
139
|
+
openSync,
|
|
138
140
|
readFileSync as readFileSync2,
|
|
141
|
+
readSync,
|
|
139
142
|
readdirSync as readdirSync2,
|
|
140
143
|
rmSync as rmSync2,
|
|
141
144
|
writeFileSync as writeFileSync3
|
|
@@ -243,6 +246,8 @@ async function packageMacOS(config, outDir) {
|
|
|
243
246
|
const { name, version, bundleId = `com.myapp.${name.toLowerCase()}` } = config;
|
|
244
247
|
const opts = config.macos || {};
|
|
245
248
|
const hardenedRuntime = !opts.appStore;
|
|
249
|
+
if (opts.appStore && (!opts.entitlements || !opts.provisioningProfile))
|
|
250
|
+
return [{ success: false, platform: "macos", format: "app", error: "App Store packaging requires macos.entitlements and macos.provisioningProfile" }];
|
|
246
251
|
const appBundlePath = join2(outDir, `${name}.app`);
|
|
247
252
|
const appBundle = opts.appBundlePath ? copyMacOSAppBundle(opts.appBundlePath, appBundlePath) : createMacOSAppBundle({
|
|
248
253
|
name,
|
|
@@ -268,25 +273,42 @@ async function packageMacOS(config, outDir) {
|
|
|
268
273
|
});
|
|
269
274
|
return results;
|
|
270
275
|
}
|
|
271
|
-
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
}
|
|
278
|
-
if (
|
|
279
|
-
|
|
280
|
-
|
|
276
|
+
try {
|
|
277
|
+
const contents = join2(appBundlePath, "Contents");
|
|
278
|
+
if (opts.provisioningProfile) {
|
|
279
|
+
const profile = join2(contents, "embedded.provisionprofile");
|
|
280
|
+
copyFileSync(opts.provisioningProfile, profile);
|
|
281
|
+
chmodSync(profile, 420);
|
|
282
|
+
}
|
|
283
|
+
if (opts.privacyManifest)
|
|
284
|
+
copyFileSync(opts.privacyManifest, join2(contents, "Resources", "PrivacyInfo.xcprivacy"));
|
|
285
|
+
if (opts.appBundlePath) {
|
|
286
|
+
const metadata = {
|
|
287
|
+
CFBundleVersion: opts.buildNumber,
|
|
288
|
+
LSApplicationCategoryType: opts.category,
|
|
289
|
+
LSMinimumSystemVersion: opts.minimumSystemVersion,
|
|
290
|
+
LSUIElement: opts.menuBarOnly
|
|
291
|
+
};
|
|
292
|
+
if (config.iconPath) {
|
|
293
|
+
const icon = basename(config.iconPath);
|
|
294
|
+
copyFileSync(config.iconPath, join2(contents, "Resources", icon));
|
|
295
|
+
metadata.CFBundleIconFile = icon;
|
|
296
|
+
}
|
|
297
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
298
|
+
if (value === undefined)
|
|
299
|
+
continue;
|
|
300
|
+
const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join2(contents, "Info.plist")]);
|
|
301
|
+
if (!result.success)
|
|
302
|
+
throw new Error(result.error);
|
|
303
|
+
}
|
|
281
304
|
}
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
}
|
|
289
|
-
return results;
|
|
305
|
+
if (opts.signIdentity) {
|
|
306
|
+
await signMacOSAppBundle(appBundlePath, bundleId, opts, hardenedRuntime);
|
|
307
|
+
} else if (opts.appStore) {
|
|
308
|
+
throw new Error('App Store packaging requires macos.signIdentity (a "3rd Party Mac Developer Application" identity)');
|
|
309
|
+
}
|
|
310
|
+
} catch (error) {
|
|
311
|
+
return [{ success: false, platform: "macos", format: "app", error: error.message }];
|
|
290
312
|
}
|
|
291
313
|
results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
|
|
292
314
|
if (opts.dmg !== false) {
|
|
@@ -310,7 +332,8 @@ async function packageMacOS(config, outDir) {
|
|
|
310
332
|
identifier: bundleId,
|
|
311
333
|
version,
|
|
312
334
|
appStore: opts.appStore === true,
|
|
313
|
-
installerIdentity: opts.installerIdentity
|
|
335
|
+
installerIdentity: opts.installerIdentity,
|
|
336
|
+
signingKeychain: opts.signingKeychain
|
|
314
337
|
});
|
|
315
338
|
results.push({
|
|
316
339
|
success: pkgResult.success,
|
|
@@ -550,6 +573,59 @@ ${body}
|
|
|
550
573
|
</dict>
|
|
551
574
|
</plist>`;
|
|
552
575
|
}
|
|
576
|
+
async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
|
|
577
|
+
const scratch = createTempDir("craft-sign-");
|
|
578
|
+
try {
|
|
579
|
+
let helperEntitlements = opts.helperEntitlements;
|
|
580
|
+
if (opts.appStore && !helperEntitlements) {
|
|
581
|
+
helperEntitlements = join2(scratch, "inherit.plist");
|
|
582
|
+
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>');
|
|
583
|
+
}
|
|
584
|
+
const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join2(app, "Contents", "Info.plist")]);
|
|
585
|
+
if (!extracted.success)
|
|
586
|
+
throw new Error(extracted.error);
|
|
587
|
+
const main = join2(app, "Contents", "MacOS", extracted.stdout.trim());
|
|
588
|
+
const sign = async (path, entitlements, identifier) => {
|
|
589
|
+
const signed = await runTool("codesign", codesignArguments({ path, identity: opts.signIdentity, entitlements, hardenedRuntime, identifier, keychain: opts.signingKeychain, deep: false }));
|
|
590
|
+
if (!signed.success)
|
|
591
|
+
throw new Error(signed.error);
|
|
592
|
+
};
|
|
593
|
+
const walk = async (directory) => {
|
|
594
|
+
for (const entry of readdirSync2(directory)) {
|
|
595
|
+
const path = join2(directory, entry);
|
|
596
|
+
const stat = lstatSync(path);
|
|
597
|
+
if (stat.isSymbolicLink())
|
|
598
|
+
continue;
|
|
599
|
+
if (stat.isDirectory()) {
|
|
600
|
+
await walk(path);
|
|
601
|
+
if (/\.(?:app|framework|xpc|appex|bundle)$/.test(entry))
|
|
602
|
+
await sign(path, /\.(?:app|xpc|appex)$/.test(entry) ? helperEntitlements : undefined);
|
|
603
|
+
} else if (path !== main && stat.isFile() && isMachO(path)) {
|
|
604
|
+
const executable = (stat.mode & 73) !== 0 && !/\.(?:dylib|so)$/.test(entry);
|
|
605
|
+
await sign(path, executable ? helperEntitlements : undefined, `${bundleId}.${entry}`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
};
|
|
609
|
+
await walk(join2(app, "Contents"));
|
|
610
|
+
await sign(app, opts.entitlements);
|
|
611
|
+
const verified = await runTool("codesign", ["--verify", "--deep", "--strict", app]);
|
|
612
|
+
if (!verified.success)
|
|
613
|
+
throw new Error(verified.error);
|
|
614
|
+
} finally {
|
|
615
|
+
removeTempDir(scratch);
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
function isMachO(path) {
|
|
619
|
+
const fd = openSync(path, "r");
|
|
620
|
+
try {
|
|
621
|
+
const magic = Buffer.alloc(4);
|
|
622
|
+
if (readSync(fd, magic, 0, 4, 0) !== 4)
|
|
623
|
+
return false;
|
|
624
|
+
return [4277009102, 3472551422, 4277009103, 3489328638, 3405691582, 3199925962, 3405691583, 3216703178].includes(magic.readUInt32BE());
|
|
625
|
+
} finally {
|
|
626
|
+
closeSync(fd);
|
|
627
|
+
}
|
|
628
|
+
}
|
|
553
629
|
function codesignArguments(opts) {
|
|
554
630
|
return [
|
|
555
631
|
"--force",
|
|
@@ -558,7 +634,9 @@ function codesignArguments(opts) {
|
|
|
558
634
|
...opts.identity === "-" ? [] : ["--timestamp"],
|
|
559
635
|
...opts.hardenedRuntime ? ["--options", "runtime"] : [],
|
|
560
636
|
...opts.entitlements ? ["--entitlements", opts.entitlements] : [],
|
|
561
|
-
"--
|
|
637
|
+
...opts.identifier ? ["--identifier", opts.identifier] : [],
|
|
638
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
639
|
+
...opts.deep === false ? [] : ["--deep"],
|
|
562
640
|
opts.path
|
|
563
641
|
];
|
|
564
642
|
}
|
|
@@ -569,6 +647,7 @@ function productbuildArguments(opts) {
|
|
|
569
647
|
"/Applications",
|
|
570
648
|
"--sign",
|
|
571
649
|
opts.identity,
|
|
650
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
572
651
|
opts.outputPath
|
|
573
652
|
];
|
|
574
653
|
}
|
|
@@ -686,7 +765,7 @@ function runTool(tool, args) {
|
|
|
686
765
|
});
|
|
687
766
|
proc.on("close", (code) => {
|
|
688
767
|
if (code === 0)
|
|
689
|
-
resolve({ success: true });
|
|
768
|
+
resolve({ success: true, stdout });
|
|
690
769
|
else
|
|
691
770
|
resolve({ success: false, error: formatPackagingCommandError(tool, code, stdout, stderr) });
|
|
692
771
|
});
|
|
@@ -760,7 +839,8 @@ async function createPKG(opts) {
|
|
|
760
839
|
const built = await runTool("productbuild", productbuildArguments({
|
|
761
840
|
appBundlePath: opts.appBundlePath,
|
|
762
841
|
outputPath: opts.outputPath,
|
|
763
|
-
identity: opts.installerIdentity
|
|
842
|
+
identity: opts.installerIdentity,
|
|
843
|
+
keychain: opts.signingKeychain
|
|
764
844
|
}));
|
|
765
845
|
return built.success ? { success: true, outputPath: opts.outputPath } : { success: false, error: built.error };
|
|
766
846
|
}
|
|
@@ -2865,7 +2945,7 @@ function pinCraftNativeDependency(packagePath, craftVersion) {
|
|
|
2865
2945
|
`);
|
|
2866
2946
|
}
|
|
2867
2947
|
// package.json
|
|
2868
|
-
var version = "0.0.
|
|
2948
|
+
var version = "0.0.293";
|
|
2869
2949
|
|
|
2870
2950
|
// bin/cli.ts
|
|
2871
2951
|
var spawnedFrom = process6.env[CRAFT_CLI_SPAWN_MARKER];
|
package/dist/index.cjs
CHANGED
|
@@ -374,7 +374,7 @@ function craftBinaryNotFoundMessage(triedPath) {
|
|
|
374
374
|
`);
|
|
375
375
|
}
|
|
376
376
|
// package.json
|
|
377
|
-
var version = "0.0.
|
|
377
|
+
var version = "0.0.293";
|
|
378
378
|
|
|
379
379
|
// src/sdk-version.ts
|
|
380
380
|
var SDK_VERSION = version;
|
|
@@ -611,6 +611,8 @@ async function packageMacOS(config, outDir) {
|
|
|
611
611
|
const { name, version, bundleId = `com.myapp.${name.toLowerCase()}` } = config;
|
|
612
612
|
const opts = config.macos || {};
|
|
613
613
|
const hardenedRuntime = !opts.appStore;
|
|
614
|
+
if (opts.appStore && (!opts.entitlements || !opts.provisioningProfile))
|
|
615
|
+
return [{ success: false, platform: "macos", format: "app", error: "App Store packaging requires macos.entitlements and macos.provisioningProfile" }];
|
|
614
616
|
const appBundlePath = import_path.join(outDir, `${name}.app`);
|
|
615
617
|
const appBundle = opts.appBundlePath ? copyMacOSAppBundle(opts.appBundlePath, appBundlePath) : createMacOSAppBundle({
|
|
616
618
|
name,
|
|
@@ -636,25 +638,42 @@ async function packageMacOS(config, outDir) {
|
|
|
636
638
|
});
|
|
637
639
|
return results;
|
|
638
640
|
}
|
|
639
|
-
|
|
640
|
-
const
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
}
|
|
646
|
-
if (
|
|
647
|
-
|
|
648
|
-
|
|
641
|
+
try {
|
|
642
|
+
const contents = import_path.join(appBundlePath, "Contents");
|
|
643
|
+
if (opts.provisioningProfile) {
|
|
644
|
+
const profile = import_path.join(contents, "embedded.provisionprofile");
|
|
645
|
+
import_fs.copyFileSync(opts.provisioningProfile, profile);
|
|
646
|
+
import_fs.chmodSync(profile, 420);
|
|
647
|
+
}
|
|
648
|
+
if (opts.privacyManifest)
|
|
649
|
+
import_fs.copyFileSync(opts.privacyManifest, import_path.join(contents, "Resources", "PrivacyInfo.xcprivacy"));
|
|
650
|
+
if (opts.appBundlePath) {
|
|
651
|
+
const metadata = {
|
|
652
|
+
CFBundleVersion: opts.buildNumber,
|
|
653
|
+
LSApplicationCategoryType: opts.category,
|
|
654
|
+
LSMinimumSystemVersion: opts.minimumSystemVersion,
|
|
655
|
+
LSUIElement: opts.menuBarOnly
|
|
656
|
+
};
|
|
657
|
+
if (config.iconPath) {
|
|
658
|
+
const icon = import_path.basename(config.iconPath);
|
|
659
|
+
import_fs.copyFileSync(config.iconPath, import_path.join(contents, "Resources", icon));
|
|
660
|
+
metadata.CFBundleIconFile = icon;
|
|
661
|
+
}
|
|
662
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
663
|
+
if (value === undefined)
|
|
664
|
+
continue;
|
|
665
|
+
const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), import_path.join(contents, "Info.plist")]);
|
|
666
|
+
if (!result.success)
|
|
667
|
+
throw new Error(result.error);
|
|
668
|
+
}
|
|
649
669
|
}
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
654
|
-
|
|
655
|
-
|
|
656
|
-
}
|
|
657
|
-
return results;
|
|
670
|
+
if (opts.signIdentity) {
|
|
671
|
+
await signMacOSAppBundle(appBundlePath, bundleId, opts, hardenedRuntime);
|
|
672
|
+
} else if (opts.appStore) {
|
|
673
|
+
throw new Error('App Store packaging requires macos.signIdentity (a "3rd Party Mac Developer Application" identity)');
|
|
674
|
+
}
|
|
675
|
+
} catch (error) {
|
|
676
|
+
return [{ success: false, platform: "macos", format: "app", error: error.message }];
|
|
658
677
|
}
|
|
659
678
|
results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
|
|
660
679
|
if (opts.dmg !== false) {
|
|
@@ -678,7 +697,8 @@ async function packageMacOS(config, outDir) {
|
|
|
678
697
|
identifier: bundleId,
|
|
679
698
|
version,
|
|
680
699
|
appStore: opts.appStore === true,
|
|
681
|
-
installerIdentity: opts.installerIdentity
|
|
700
|
+
installerIdentity: opts.installerIdentity,
|
|
701
|
+
signingKeychain: opts.signingKeychain
|
|
682
702
|
});
|
|
683
703
|
results.push({
|
|
684
704
|
success: pkgResult.success,
|
|
@@ -919,6 +939,59 @@ ${body}
|
|
|
919
939
|
</dict>
|
|
920
940
|
</plist>`;
|
|
921
941
|
}
|
|
942
|
+
async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
|
|
943
|
+
const scratch = createTempDir("craft-sign-");
|
|
944
|
+
try {
|
|
945
|
+
let helperEntitlements = opts.helperEntitlements;
|
|
946
|
+
if (opts.appStore && !helperEntitlements) {
|
|
947
|
+
helperEntitlements = import_path.join(scratch, "inherit.plist");
|
|
948
|
+
import_fs.writeFileSync(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>');
|
|
949
|
+
}
|
|
950
|
+
const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", import_path.join(app, "Contents", "Info.plist")]);
|
|
951
|
+
if (!extracted.success)
|
|
952
|
+
throw new Error(extracted.error);
|
|
953
|
+
const main = import_path.join(app, "Contents", "MacOS", extracted.stdout.trim());
|
|
954
|
+
const sign = async (path, entitlements, identifier) => {
|
|
955
|
+
const signed = await runTool("codesign", codesignArguments({ path, identity: opts.signIdentity, entitlements, hardenedRuntime, identifier, keychain: opts.signingKeychain, deep: false }));
|
|
956
|
+
if (!signed.success)
|
|
957
|
+
throw new Error(signed.error);
|
|
958
|
+
};
|
|
959
|
+
const walk = async (directory) => {
|
|
960
|
+
for (const entry of import_fs.readdirSync(directory)) {
|
|
961
|
+
const path = import_path.join(directory, entry);
|
|
962
|
+
const stat = import_fs.lstatSync(path);
|
|
963
|
+
if (stat.isSymbolicLink())
|
|
964
|
+
continue;
|
|
965
|
+
if (stat.isDirectory()) {
|
|
966
|
+
await walk(path);
|
|
967
|
+
if (/\.(?:app|framework|xpc|appex|bundle)$/.test(entry))
|
|
968
|
+
await sign(path, /\.(?:app|xpc|appex)$/.test(entry) ? helperEntitlements : undefined);
|
|
969
|
+
} else if (path !== main && stat.isFile() && isMachO(path)) {
|
|
970
|
+
const executable = (stat.mode & 73) !== 0 && !/\.(?:dylib|so)$/.test(entry);
|
|
971
|
+
await sign(path, executable ? helperEntitlements : undefined, `${bundleId}.${entry}`);
|
|
972
|
+
}
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
await walk(import_path.join(app, "Contents"));
|
|
976
|
+
await sign(app, opts.entitlements);
|
|
977
|
+
const verified = await runTool("codesign", ["--verify", "--deep", "--strict", app]);
|
|
978
|
+
if (!verified.success)
|
|
979
|
+
throw new Error(verified.error);
|
|
980
|
+
} finally {
|
|
981
|
+
removeTempDir(scratch);
|
|
982
|
+
}
|
|
983
|
+
}
|
|
984
|
+
function isMachO(path) {
|
|
985
|
+
const fd = import_fs.openSync(path, "r");
|
|
986
|
+
try {
|
|
987
|
+
const magic = Buffer.alloc(4);
|
|
988
|
+
if (import_fs.readSync(fd, magic, 0, 4, 0) !== 4)
|
|
989
|
+
return false;
|
|
990
|
+
return [4277009102, 3472551422, 4277009103, 3489328638, 3405691582, 3199925962, 3405691583, 3216703178].includes(magic.readUInt32BE());
|
|
991
|
+
} finally {
|
|
992
|
+
import_fs.closeSync(fd);
|
|
993
|
+
}
|
|
994
|
+
}
|
|
922
995
|
function codesignArguments(opts) {
|
|
923
996
|
return [
|
|
924
997
|
"--force",
|
|
@@ -927,7 +1000,9 @@ function codesignArguments(opts) {
|
|
|
927
1000
|
...opts.identity === "-" ? [] : ["--timestamp"],
|
|
928
1001
|
...opts.hardenedRuntime ? ["--options", "runtime"] : [],
|
|
929
1002
|
...opts.entitlements ? ["--entitlements", opts.entitlements] : [],
|
|
930
|
-
"--
|
|
1003
|
+
...opts.identifier ? ["--identifier", opts.identifier] : [],
|
|
1004
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
1005
|
+
...opts.deep === false ? [] : ["--deep"],
|
|
931
1006
|
opts.path
|
|
932
1007
|
];
|
|
933
1008
|
}
|
|
@@ -938,6 +1013,7 @@ function productbuildArguments(opts) {
|
|
|
938
1013
|
"/Applications",
|
|
939
1014
|
"--sign",
|
|
940
1015
|
opts.identity,
|
|
1016
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
941
1017
|
opts.outputPath
|
|
942
1018
|
];
|
|
943
1019
|
}
|
|
@@ -1057,7 +1133,7 @@ function runTool(tool, args) {
|
|
|
1057
1133
|
});
|
|
1058
1134
|
proc.on("close", (code) => {
|
|
1059
1135
|
if (code === 0)
|
|
1060
|
-
resolve({ success: true });
|
|
1136
|
+
resolve({ success: true, stdout });
|
|
1061
1137
|
else
|
|
1062
1138
|
resolve({ success: false, error: formatPackagingCommandError(tool, code, stdout, stderr) });
|
|
1063
1139
|
});
|
|
@@ -1132,7 +1208,8 @@ async function createPKG(opts) {
|
|
|
1132
1208
|
const built = await runTool("productbuild", productbuildArguments({
|
|
1133
1209
|
appBundlePath: opts.appBundlePath,
|
|
1134
1210
|
outputPath: opts.outputPath,
|
|
1135
|
-
identity: opts.installerIdentity
|
|
1211
|
+
identity: opts.installerIdentity,
|
|
1212
|
+
keychain: opts.signingKeychain
|
|
1136
1213
|
}));
|
|
1137
1214
|
return built.success ? { success: true, outputPath: opts.outputPath } : { success: false, error: built.error };
|
|
1138
1215
|
}
|
package/dist/index.d.cts
CHANGED
|
@@ -85,4 +85,4 @@ export declare function show(html: string, options?: WindowOptions): Promise<voi
|
|
|
85
85
|
* Quick helper to load a URL
|
|
86
86
|
*/
|
|
87
87
|
export declare function loadURL(url: string, options?: WindowOptions): Promise<void>;
|
|
88
|
-
export type { WindowOptions, CraftSidebarAPI, CraftNativeUIAPI, CraftContextMenuItem, CraftContextMenuResult, AppConfig, CraftTrayAPI, CraftWindowAPI, CraftAppAPI, CraftBridgeAPI, Permission, HapticType, CraftHapticsAPI, CameraOptions, PhotoPickerOptions, CraftMobileAPI, CraftFileSystemAPI, CraftFsWatchEvent, CraftFsWatchHandle, CraftDatabaseAPI, CraftHttpAPI, CraftCryptoAPI, CraftCapabilities, CapabilityNamespace, CapabilityNamespaceStatus, CapabilityAction, CraftPreferencesAPI, CraftPreferencesInfo, CraftSettingsAPI, PreferenceValue, CraftEventType, CraftEventMap, CraftEventHandler, CraftEventEmitter, IOSConfig, AndroidConfig, MacOSConfig, WindowsConfig, LinuxConfig, CraftAppConfig, } from './types.js';
|
|
88
|
+
export type { WindowOptions, CraftSidebarAPI, CraftNativeUIAPI, CraftContextMenuItem, CraftContextMenuResult, AppConfig, CraftTrayAPI, CraftWindowAPI, CraftAppAPI, CraftBridgeAPI, CraftTimersAPI, Permission, HapticType, CraftHapticsAPI, CameraOptions, PhotoPickerOptions, CraftMobileAPI, CraftFileSystemAPI, CraftFsWatchEvent, CraftFsWatchHandle, CraftDatabaseAPI, CraftHttpAPI, CraftCryptoAPI, CraftCapabilities, CapabilityNamespace, CapabilityNamespaceStatus, CapabilityAction, CraftPreferencesAPI, CraftPreferencesInfo, CraftSettingsAPI, PreferenceValue, CraftEventType, CraftEventMap, CraftEventHandler, CraftEventEmitter, IOSConfig, AndroidConfig, MacOSConfig, WindowsConfig, LinuxConfig, CraftAppConfig, } from './types.js';
|
package/dist/index.d.ts
CHANGED
|
@@ -85,4 +85,4 @@ export declare function show(html: string, options?: WindowOptions): Promise<voi
|
|
|
85
85
|
* Quick helper to load a URL
|
|
86
86
|
*/
|
|
87
87
|
export declare function loadURL(url: string, options?: WindowOptions): Promise<void>;
|
|
88
|
-
export type { WindowOptions, CraftSidebarAPI, CraftNativeUIAPI, CraftContextMenuItem, CraftContextMenuResult, AppConfig, CraftTrayAPI, CraftWindowAPI, CraftAppAPI, CraftBridgeAPI, Permission, HapticType, CraftHapticsAPI, CameraOptions, PhotoPickerOptions, CraftMobileAPI, CraftFileSystemAPI, CraftFsWatchEvent, CraftFsWatchHandle, CraftDatabaseAPI, CraftHttpAPI, CraftCryptoAPI, CraftCapabilities, CapabilityNamespace, CapabilityNamespaceStatus, CapabilityAction, CraftPreferencesAPI, CraftPreferencesInfo, CraftSettingsAPI, PreferenceValue, CraftEventType, CraftEventMap, CraftEventHandler, CraftEventEmitter, IOSConfig, AndroidConfig, MacOSConfig, WindowsConfig, LinuxConfig, CraftAppConfig, } from './types.js';
|
|
88
|
+
export type { WindowOptions, CraftSidebarAPI, CraftNativeUIAPI, CraftContextMenuItem, CraftContextMenuResult, AppConfig, CraftTrayAPI, CraftWindowAPI, CraftAppAPI, CraftBridgeAPI, CraftTimersAPI, Permission, HapticType, CraftHapticsAPI, CameraOptions, PhotoPickerOptions, CraftMobileAPI, CraftFileSystemAPI, CraftFsWatchEvent, CraftFsWatchHandle, CraftDatabaseAPI, CraftHttpAPI, CraftCryptoAPI, CraftCapabilities, CapabilityNamespace, CapabilityNamespaceStatus, CapabilityAction, CraftPreferencesAPI, CraftPreferencesInfo, CraftSettingsAPI, PreferenceValue, CraftEventType, CraftEventMap, CraftEventHandler, CraftEventEmitter, IOSConfig, AndroidConfig, MacOSConfig, WindowsConfig, LinuxConfig, CraftAppConfig, } from './types.js';
|
package/dist/index.js
CHANGED
|
@@ -117,7 +117,7 @@ function craftBinaryNotFoundMessage(triedPath) {
|
|
|
117
117
|
`);
|
|
118
118
|
}
|
|
119
119
|
// package.json
|
|
120
|
-
var version = "0.0.
|
|
120
|
+
var version = "0.0.293";
|
|
121
121
|
|
|
122
122
|
// src/sdk-version.ts
|
|
123
123
|
var SDK_VERSION = version;
|
|
@@ -241,12 +241,15 @@ import { spawn } from "child_process";
|
|
|
241
241
|
import { createHash } from "crypto";
|
|
242
242
|
import {
|
|
243
243
|
chmodSync,
|
|
244
|
+
closeSync,
|
|
244
245
|
copyFileSync,
|
|
245
246
|
cpSync,
|
|
246
247
|
existsSync as existsSync3,
|
|
247
248
|
lstatSync,
|
|
248
249
|
mkdirSync,
|
|
250
|
+
openSync,
|
|
249
251
|
readFileSync,
|
|
252
|
+
readSync,
|
|
250
253
|
readdirSync as readdirSync2,
|
|
251
254
|
rmSync as rmSync2,
|
|
252
255
|
writeFileSync as writeFileSync2
|
|
@@ -365,6 +368,8 @@ async function packageMacOS(config, outDir) {
|
|
|
365
368
|
const { name, version, bundleId = `com.myapp.${name.toLowerCase()}` } = config;
|
|
366
369
|
const opts = config.macos || {};
|
|
367
370
|
const hardenedRuntime = !opts.appStore;
|
|
371
|
+
if (opts.appStore && (!opts.entitlements || !opts.provisioningProfile))
|
|
372
|
+
return [{ success: false, platform: "macos", format: "app", error: "App Store packaging requires macos.entitlements and macos.provisioningProfile" }];
|
|
368
373
|
const appBundlePath = join2(outDir, `${name}.app`);
|
|
369
374
|
const appBundle = opts.appBundlePath ? copyMacOSAppBundle(opts.appBundlePath, appBundlePath) : createMacOSAppBundle({
|
|
370
375
|
name,
|
|
@@ -390,25 +395,42 @@ async function packageMacOS(config, outDir) {
|
|
|
390
395
|
});
|
|
391
396
|
return results;
|
|
392
397
|
}
|
|
393
|
-
|
|
394
|
-
const
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
}
|
|
400
|
-
if (
|
|
401
|
-
|
|
402
|
-
|
|
398
|
+
try {
|
|
399
|
+
const contents = join2(appBundlePath, "Contents");
|
|
400
|
+
if (opts.provisioningProfile) {
|
|
401
|
+
const profile = join2(contents, "embedded.provisionprofile");
|
|
402
|
+
copyFileSync(opts.provisioningProfile, profile);
|
|
403
|
+
chmodSync(profile, 420);
|
|
404
|
+
}
|
|
405
|
+
if (opts.privacyManifest)
|
|
406
|
+
copyFileSync(opts.privacyManifest, join2(contents, "Resources", "PrivacyInfo.xcprivacy"));
|
|
407
|
+
if (opts.appBundlePath) {
|
|
408
|
+
const metadata = {
|
|
409
|
+
CFBundleVersion: opts.buildNumber,
|
|
410
|
+
LSApplicationCategoryType: opts.category,
|
|
411
|
+
LSMinimumSystemVersion: opts.minimumSystemVersion,
|
|
412
|
+
LSUIElement: opts.menuBarOnly
|
|
413
|
+
};
|
|
414
|
+
if (config.iconPath) {
|
|
415
|
+
const icon = basename(config.iconPath);
|
|
416
|
+
copyFileSync(config.iconPath, join2(contents, "Resources", icon));
|
|
417
|
+
metadata.CFBundleIconFile = icon;
|
|
418
|
+
}
|
|
419
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
420
|
+
if (value === undefined)
|
|
421
|
+
continue;
|
|
422
|
+
const result = await runTool("plutil", ["-replace", key, typeof value === "boolean" ? "-bool" : "-string", String(value), join2(contents, "Info.plist")]);
|
|
423
|
+
if (!result.success)
|
|
424
|
+
throw new Error(result.error);
|
|
425
|
+
}
|
|
403
426
|
}
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
}
|
|
411
|
-
return results;
|
|
427
|
+
if (opts.signIdentity) {
|
|
428
|
+
await signMacOSAppBundle(appBundlePath, bundleId, opts, hardenedRuntime);
|
|
429
|
+
} else if (opts.appStore) {
|
|
430
|
+
throw new Error('App Store packaging requires macos.signIdentity (a "3rd Party Mac Developer Application" identity)');
|
|
431
|
+
}
|
|
432
|
+
} catch (error) {
|
|
433
|
+
return [{ success: false, platform: "macos", format: "app", error: error.message }];
|
|
412
434
|
}
|
|
413
435
|
results.push({ success: true, platform: "macos", format: "app", outputPath: appBundlePath });
|
|
414
436
|
if (opts.dmg !== false) {
|
|
@@ -432,7 +454,8 @@ async function packageMacOS(config, outDir) {
|
|
|
432
454
|
identifier: bundleId,
|
|
433
455
|
version,
|
|
434
456
|
appStore: opts.appStore === true,
|
|
435
|
-
installerIdentity: opts.installerIdentity
|
|
457
|
+
installerIdentity: opts.installerIdentity,
|
|
458
|
+
signingKeychain: opts.signingKeychain
|
|
436
459
|
});
|
|
437
460
|
results.push({
|
|
438
461
|
success: pkgResult.success,
|
|
@@ -673,6 +696,59 @@ ${body}
|
|
|
673
696
|
</dict>
|
|
674
697
|
</plist>`;
|
|
675
698
|
}
|
|
699
|
+
async function signMacOSAppBundle(app, bundleId, opts, hardenedRuntime) {
|
|
700
|
+
const scratch = createTempDir("craft-sign-");
|
|
701
|
+
try {
|
|
702
|
+
let helperEntitlements = opts.helperEntitlements;
|
|
703
|
+
if (opts.appStore && !helperEntitlements) {
|
|
704
|
+
helperEntitlements = join2(scratch, "inherit.plist");
|
|
705
|
+
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>');
|
|
706
|
+
}
|
|
707
|
+
const extracted = await runTool("plutil", ["-extract", "CFBundleExecutable", "raw", "-o", "-", join2(app, "Contents", "Info.plist")]);
|
|
708
|
+
if (!extracted.success)
|
|
709
|
+
throw new Error(extracted.error);
|
|
710
|
+
const main = join2(app, "Contents", "MacOS", extracted.stdout.trim());
|
|
711
|
+
const sign = async (path, entitlements, identifier) => {
|
|
712
|
+
const signed = await runTool("codesign", codesignArguments({ path, identity: opts.signIdentity, entitlements, hardenedRuntime, identifier, keychain: opts.signingKeychain, deep: false }));
|
|
713
|
+
if (!signed.success)
|
|
714
|
+
throw new Error(signed.error);
|
|
715
|
+
};
|
|
716
|
+
const walk = async (directory) => {
|
|
717
|
+
for (const entry of readdirSync2(directory)) {
|
|
718
|
+
const path = join2(directory, entry);
|
|
719
|
+
const stat = lstatSync(path);
|
|
720
|
+
if (stat.isSymbolicLink())
|
|
721
|
+
continue;
|
|
722
|
+
if (stat.isDirectory()) {
|
|
723
|
+
await walk(path);
|
|
724
|
+
if (/\.(?:app|framework|xpc|appex|bundle)$/.test(entry))
|
|
725
|
+
await sign(path, /\.(?:app|xpc|appex)$/.test(entry) ? helperEntitlements : undefined);
|
|
726
|
+
} else if (path !== main && stat.isFile() && isMachO(path)) {
|
|
727
|
+
const executable = (stat.mode & 73) !== 0 && !/\.(?:dylib|so)$/.test(entry);
|
|
728
|
+
await sign(path, executable ? helperEntitlements : undefined, `${bundleId}.${entry}`);
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
await walk(join2(app, "Contents"));
|
|
733
|
+
await sign(app, opts.entitlements);
|
|
734
|
+
const verified = await runTool("codesign", ["--verify", "--deep", "--strict", app]);
|
|
735
|
+
if (!verified.success)
|
|
736
|
+
throw new Error(verified.error);
|
|
737
|
+
} finally {
|
|
738
|
+
removeTempDir(scratch);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
function isMachO(path) {
|
|
742
|
+
const fd = openSync(path, "r");
|
|
743
|
+
try {
|
|
744
|
+
const magic = Buffer.alloc(4);
|
|
745
|
+
if (readSync(fd, magic, 0, 4, 0) !== 4)
|
|
746
|
+
return false;
|
|
747
|
+
return [4277009102, 3472551422, 4277009103, 3489328638, 3405691582, 3199925962, 3405691583, 3216703178].includes(magic.readUInt32BE());
|
|
748
|
+
} finally {
|
|
749
|
+
closeSync(fd);
|
|
750
|
+
}
|
|
751
|
+
}
|
|
676
752
|
function codesignArguments(opts) {
|
|
677
753
|
return [
|
|
678
754
|
"--force",
|
|
@@ -681,7 +757,9 @@ function codesignArguments(opts) {
|
|
|
681
757
|
...opts.identity === "-" ? [] : ["--timestamp"],
|
|
682
758
|
...opts.hardenedRuntime ? ["--options", "runtime"] : [],
|
|
683
759
|
...opts.entitlements ? ["--entitlements", opts.entitlements] : [],
|
|
684
|
-
"--
|
|
760
|
+
...opts.identifier ? ["--identifier", opts.identifier] : [],
|
|
761
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
762
|
+
...opts.deep === false ? [] : ["--deep"],
|
|
685
763
|
opts.path
|
|
686
764
|
];
|
|
687
765
|
}
|
|
@@ -692,6 +770,7 @@ function productbuildArguments(opts) {
|
|
|
692
770
|
"/Applications",
|
|
693
771
|
"--sign",
|
|
694
772
|
opts.identity,
|
|
773
|
+
...opts.keychain ? ["--keychain", opts.keychain] : [],
|
|
695
774
|
opts.outputPath
|
|
696
775
|
];
|
|
697
776
|
}
|
|
@@ -811,7 +890,7 @@ function runTool(tool, args) {
|
|
|
811
890
|
});
|
|
812
891
|
proc.on("close", (code) => {
|
|
813
892
|
if (code === 0)
|
|
814
|
-
resolve({ success: true });
|
|
893
|
+
resolve({ success: true, stdout });
|
|
815
894
|
else
|
|
816
895
|
resolve({ success: false, error: formatPackagingCommandError(tool, code, stdout, stderr) });
|
|
817
896
|
});
|
|
@@ -886,7 +965,8 @@ async function createPKG(opts) {
|
|
|
886
965
|
const built = await runTool("productbuild", productbuildArguments({
|
|
887
966
|
appBundlePath: opts.appBundlePath,
|
|
888
967
|
outputPath: opts.outputPath,
|
|
889
|
-
identity: opts.installerIdentity
|
|
968
|
+
identity: opts.installerIdentity,
|
|
969
|
+
keychain: opts.signingKeychain
|
|
890
970
|
}));
|
|
891
971
|
return built.success ? { success: true, outputPath: opts.outputPath } : { success: false, error: built.error };
|
|
892
972
|
}
|