@bitmagic/cli 0.1.83-dev.0 → 0.1.83-dev.2
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 +70 -1
- package/assets/skills/publishing-to-steam/SKILL.md +218 -0
- package/dist/assets/vxl-summary.d.ts +6 -20
- package/dist/assets/vxl-summary.js +9 -100
- package/dist/assets/vxl-summary.js.map +1 -1
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +2 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/check.js +5 -0
- package/dist/commands/check.js.map +1 -1
- package/dist/commands/forge.js +1 -1
- package/dist/commands/forge.js.map +1 -1
- package/dist/commands/import.js +2 -4
- package/dist/commands/import.js.map +1 -1
- package/dist/commands/init.js +0 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/ios.js +88 -136
- package/dist/commands/ios.js.map +1 -1
- package/dist/commands/promote.js +2 -4
- package/dist/commands/promote.js.map +1 -1
- package/dist/commands/publish.js +0 -1
- package/dist/commands/publish.js.map +1 -1
- package/dist/commands/steam-build.d.ts +67 -0
- package/dist/commands/steam-build.js +286 -0
- package/dist/commands/steam-build.js.map +1 -0
- package/dist/commands/steam-portal.d.ts +1 -0
- package/dist/commands/steam-portal.js +319 -0
- package/dist/commands/steam-portal.js.map +1 -0
- package/dist/commands/steam-upload.d.ts +37 -0
- package/dist/commands/steam-upload.js +172 -0
- package/dist/commands/steam-upload.js.map +1 -0
- package/dist/commands/steam.d.ts +1 -0
- package/dist/commands/steam.js +502 -0
- package/dist/commands/steam.js.map +1 -0
- package/dist/commands/verify.js +6 -0
- package/dist/commands/verify.js.map +1 -1
- package/dist/editor/asset-viewer.js +5 -4
- package/dist/editor/asset-viewer.js.map +1 -1
- package/dist/editor/game-info-panel.d.ts +2 -2
- package/dist/editor/game-info-panel.js +1 -2
- package/dist/editor/game-info-panel.js.map +1 -1
- package/dist/editor/game-info.d.ts +1 -3
- package/dist/editor/game-info.js +1 -2
- package/dist/editor/game-info.js.map +1 -1
- package/dist/editor/server.js +2 -3
- package/dist/editor/server.js.map +1 -1
- package/dist/editor/shell-page.js +9 -7
- package/dist/editor/shell-page.js.map +1 -1
- package/dist/forge/browser-host.d.ts +6 -12
- package/dist/forge/browser-host.js +5 -11
- package/dist/forge/browser-host.js.map +1 -1
- package/dist/ios/native-overrides.d.ts +27 -0
- package/dist/ios/native-overrides.js +87 -0
- package/dist/ios/native-overrides.js.map +1 -0
- package/dist/ios/record-validate.d.ts +1 -33
- package/dist/ios/record-validate.js +2 -100
- package/dist/ios/record-validate.js.map +1 -1
- package/dist/ios/store-bridge.d.ts +26 -0
- package/dist/ios/store-bridge.js +224 -0
- package/dist/ios/store-bridge.js.map +1 -0
- package/dist/ios/storekit-config.d.ts +15 -0
- package/dist/ios/storekit-config.js +106 -0
- package/dist/ios/storekit-config.js.map +1 -0
- package/dist/ios/xcode-template.d.ts +12 -3
- package/dist/ios/xcode-template.js +158 -27
- package/dist/ios/xcode-template.js.map +1 -1
- package/dist/package/collect-urls.d.ts +1 -1
- package/dist/package/collect-urls.js +10 -2
- package/dist/package/collect-urls.js.map +1 -1
- package/dist/package/offline-payload.d.ts +35 -0
- package/dist/package/offline-payload.js +142 -0
- package/dist/package/offline-payload.js.map +1 -0
- package/dist/package/packaged-check.d.ts +39 -0
- package/dist/package/packaged-check.js +104 -0
- package/dist/package/packaged-check.js.map +1 -0
- package/dist/package/transform.d.ts +4 -4
- package/dist/package/transform.js +3 -3
- package/dist/project/context.d.ts +7 -2
- package/dist/project/context.js +1 -2
- package/dist/project/context.js.map +1 -1
- package/dist/project/published-three.d.ts +14 -0
- package/dist/project/published-three.js +93 -0
- package/dist/project/published-three.js.map +1 -0
- package/dist/publish/bundle.d.ts +1 -1
- package/dist/publish/bundle.js +8 -3
- package/dist/publish/bundle.js.map +1 -1
- package/dist/publish/platform.d.ts +1 -1
- package/dist/publish/platform.js +1 -1
- package/dist/publish/source-zip.d.ts +0 -1
- package/dist/publish/source-zip.js +1 -2
- package/dist/publish/source-zip.js.map +1 -1
- package/dist/scaffold/aliases.js +8 -5
- package/dist/scaffold/aliases.js.map +1 -1
- package/dist/scaffold/engine-download.d.ts +1 -1
- package/dist/scaffold/engine-download.js +1 -1
- package/dist/scaffold/export-zip.d.ts +0 -1
- package/dist/scaffold/export-zip.js +3 -6
- package/dist/scaffold/export-zip.js.map +1 -1
- package/dist/scaffold/import-project.js +1 -1
- package/dist/scaffold/project-export.js +0 -1
- package/dist/scaffold/project-export.js.map +1 -1
- package/dist/scaffold/project-files.d.ts +0 -1
- package/dist/scaffold/project-files.js +8 -5
- package/dist/scaffold/project-files.js.map +1 -1
- package/dist/scaffold/project.d.ts +15 -4
- package/dist/scaffold/project.js +30 -13
- package/dist/scaffold/project.js.map +1 -1
- package/dist/scaffold/skill-files.js +3 -1
- package/dist/scaffold/skill-files.js.map +1 -1
- package/dist/scaffold/steam-skill-files.d.ts +2 -0
- package/dist/scaffold/steam-skill-files.js +7 -0
- package/dist/scaffold/steam-skill-files.js.map +1 -0
- package/dist/scaffold/suggest-template.js +0 -1
- package/dist/scaffold/suggest-template.js.map +1 -1
- package/dist/scaffold/unity-skill-files.js +1 -1
- package/dist/steam/art-generate.d.ts +55 -0
- package/dist/steam/art-generate.js +173 -0
- package/dist/steam/art-generate.js.map +1 -0
- package/dist/steam/art-render.d.ts +25 -0
- package/dist/steam/art-render.js +157 -0
- package/dist/steam/art-render.js.map +1 -0
- package/dist/steam/art-use.d.ts +20 -0
- package/dist/steam/art-use.js +84 -0
- package/dist/steam/art-use.js.map +1 -0
- package/dist/steam/art.d.ts +98 -0
- package/dist/steam/art.js +243 -0
- package/dist/steam/art.js.map +1 -0
- package/dist/steam/check.d.ts +21 -0
- package/dist/steam/check.js +113 -0
- package/dist/steam/check.js.map +1 -0
- package/dist/steam/config.d.ts +57 -0
- package/dist/steam/config.js +145 -0
- package/dist/steam/config.js.map +1 -0
- package/dist/steam/electron-cache.d.ts +11 -0
- package/dist/steam/electron-cache.js +105 -0
- package/dist/steam/electron-cache.js.map +1 -0
- package/dist/steam/fuses.d.ts +16 -0
- package/dist/steam/fuses.js +75 -0
- package/dist/steam/fuses.js.map +1 -0
- package/dist/steam/icon-files.d.ts +16 -0
- package/dist/steam/icon-files.js +70 -0
- package/dist/steam/icon-files.js.map +1 -0
- package/dist/steam/image-info.d.ts +16 -0
- package/dist/steam/image-info.js +89 -0
- package/dist/steam/image-info.js.map +1 -0
- package/dist/steam/launch-check.d.ts +12 -0
- package/dist/steam/launch-check.js +101 -0
- package/dist/steam/launch-check.js.map +1 -0
- package/dist/steam/media.d.ts +48 -0
- package/dist/steam/media.js +151 -0
- package/dist/steam/media.js.map +1 -0
- package/dist/steam/package-macos.d.ts +52 -0
- package/dist/steam/package-macos.js +268 -0
- package/dist/steam/package-macos.js.map +1 -0
- package/dist/steam/package-windows.d.ts +24 -0
- package/dist/steam/package-windows.js +84 -0
- package/dist/steam/package-windows.js.map +1 -0
- package/dist/steam/paths.d.ts +37 -0
- package/dist/steam/paths.js +45 -0
- package/dist/steam/paths.js.map +1 -0
- package/dist/steam/playtest-shots.d.ts +18 -0
- package/dist/steam/playtest-shots.js +83 -0
- package/dist/steam/playtest-shots.js.map +1 -0
- package/dist/steam/portal-recipes.d.ts +25 -0
- package/dist/steam/portal-recipes.js +61 -0
- package/dist/steam/portal-recipes.js.map +1 -0
- package/dist/steam/portal.d.ts +58 -0
- package/dist/steam/portal.js +340 -0
- package/dist/steam/portal.js.map +1 -0
- package/dist/steam/raster.d.ts +59 -0
- package/dist/steam/raster.js +285 -0
- package/dist/steam/raster.js.map +1 -0
- package/dist/steam/shell-files.d.ts +17 -0
- package/dist/steam/shell-files.js +268 -0
- package/dist/steam/shell-files.js.map +1 -0
- package/dist/steam/specs.d.ts +61 -0
- package/dist/steam/specs.js +103 -0
- package/dist/steam/specs.js.map +1 -0
- package/dist/steam/steampipe.d.ts +46 -0
- package/dist/steam/steampipe.js +170 -0
- package/dist/steam/steampipe.js.map +1 -0
- package/dist/steam/store-copy.d.ts +89 -0
- package/dist/steam/store-copy.js +221 -0
- package/dist/steam/store-copy.js.map +1 -0
- package/dist/steam/tags.d.ts +9 -0
- package/dist/steam/tags.js +49 -0
- package/dist/steam/tags.js.map +1 -0
- package/dist/steam/trailer.d.ts +34 -0
- package/dist/steam/trailer.js +141 -0
- package/dist/steam/trailer.js.map +1 -0
- package/dist/verify/browser.d.ts +11 -0
- package/dist/verify/browser.js +195 -152
- package/dist/verify/browser.js.map +1 -1
- package/dist/verify/classify.d.ts +11 -2
- package/dist/verify/classify.js +16 -4
- package/dist/verify/classify.js.map +1 -1
- package/dist/verify/mobile-parity.d.ts +1 -1
- package/dist/verify/mobile-parity.js +1 -1
- package/package.json +5 -4
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The video side of the store kit: what a trailer file actually is (Steam has rules about frame
|
|
3
|
+
* size, frame rate and bit rate), where its shots cut, and stills pulled from it as screenshots.
|
|
4
|
+
* All through ffmpeg/ffprobe, the same tools the trailer lane already requires.
|
|
5
|
+
*/
|
|
6
|
+
import { captureFfmpegTool, ensureFfmpeg, runFfmpeg } from '@bitmagic/asset-core/trailer';
|
|
7
|
+
import { CliError } from '../errors.js';
|
|
8
|
+
function parseRate(rate) {
|
|
9
|
+
if (typeof rate !== 'string')
|
|
10
|
+
return 0;
|
|
11
|
+
const [num, den] = rate.split('/').map(Number);
|
|
12
|
+
if (!Number.isFinite(num) || !Number.isFinite(den) || den === 0)
|
|
13
|
+
return 0;
|
|
14
|
+
return Math.round((num / den) * 100) / 100;
|
|
15
|
+
}
|
|
16
|
+
/** Pure, so the parsing is testable without ffprobe. */
|
|
17
|
+
export function parseVideoProbe(json, file) {
|
|
18
|
+
let parsed;
|
|
19
|
+
try {
|
|
20
|
+
parsed = JSON.parse(json);
|
|
21
|
+
}
|
|
22
|
+
catch {
|
|
23
|
+
throw new CliError(`ffprobe answered in a shape this CLI cannot read for ${file}.`);
|
|
24
|
+
}
|
|
25
|
+
const root = (typeof parsed === 'object' && parsed !== null ? parsed : {});
|
|
26
|
+
const streams = Array.isArray(root.streams) ? root.streams : [];
|
|
27
|
+
const video = streams.find((stream) => stream.codec_type === 'video');
|
|
28
|
+
if (!video || typeof video.width !== 'number' || typeof video.height !== 'number') {
|
|
29
|
+
throw new CliError(`${file} has no video stream ffprobe can read.`);
|
|
30
|
+
}
|
|
31
|
+
const audio = streams.find((stream) => stream.codec_type === 'audio');
|
|
32
|
+
const duration = Number(root.format?.duration);
|
|
33
|
+
const bitrate = Number(root.format?.bit_rate);
|
|
34
|
+
return {
|
|
35
|
+
width: video.width,
|
|
36
|
+
height: video.height,
|
|
37
|
+
fps: parseRate(video.avg_frame_rate) || parseRate(video.r_frame_rate),
|
|
38
|
+
durationSec: Number.isFinite(duration) ? duration : 0,
|
|
39
|
+
bitrateKbps: Number.isFinite(bitrate) ? Math.round(bitrate / 1000) : 0,
|
|
40
|
+
videoCodec: typeof video.codec_name === 'string' ? video.codec_name : '',
|
|
41
|
+
audioCodec: audio !== undefined && typeof audio.codec_name === 'string' ? audio.codec_name : null,
|
|
42
|
+
container: typeof root.format?.format_name === 'string' ? root.format.format_name : '',
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
export async function probeVideo(file) {
|
|
46
|
+
ensureFfmpeg(['ffmpeg', 'ffprobe']);
|
|
47
|
+
const stdout = await captureFfmpegTool('ffprobe', ['-v', 'error', '-print_format', 'json', '-show_streams', '-show_format', file]);
|
|
48
|
+
return parseVideoProbe(stdout.toString('utf-8'), file);
|
|
49
|
+
}
|
|
50
|
+
/** The times (seconds) at which the picture cuts, from ffmpeg's scene-change score. */
|
|
51
|
+
export async function detectCuts(file, threshold = 0.3) {
|
|
52
|
+
ensureFfmpeg(['ffmpeg']);
|
|
53
|
+
const stdout = await captureFfmpegTool('ffmpeg', [
|
|
54
|
+
'-hide_banner', '-nostats', '-i', file,
|
|
55
|
+
'-filter:v', `select='gt(scene,${threshold})',metadata=print:file=-`,
|
|
56
|
+
'-an', '-f', 'null', '-',
|
|
57
|
+
]);
|
|
58
|
+
return parseCutTimes(stdout.toString('utf-8'));
|
|
59
|
+
}
|
|
60
|
+
export function parseCutTimes(output) {
|
|
61
|
+
const times = [];
|
|
62
|
+
for (const match of output.matchAll(/pts_time:([0-9.]+)/g)) {
|
|
63
|
+
const t = Number(match[1]);
|
|
64
|
+
if (Number.isFinite(t))
|
|
65
|
+
times.push(t);
|
|
66
|
+
}
|
|
67
|
+
return times.sort((a, b) => a - b);
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Up to `count` shots worth a screenshot: the longest ones, so every pick is a different moment
|
|
71
|
+
* and none sits on a transition. `trimEndSec` skips the tail, where trailers put their end card.
|
|
72
|
+
* Returned in time order. Pure.
|
|
73
|
+
*/
|
|
74
|
+
export function pickScreenshotShots(options) {
|
|
75
|
+
const start = options.trimStartSec ?? 0;
|
|
76
|
+
const end = Math.max(start, options.durationSec - (options.trimEndSec ?? 0));
|
|
77
|
+
const bounds = [start, ...options.cuts.filter((t) => t > start && t < end), end];
|
|
78
|
+
const shots = [];
|
|
79
|
+
for (let i = 0; i + 1 < bounds.length; i++) {
|
|
80
|
+
if (bounds[i + 1] - bounds[i] >= 0.5)
|
|
81
|
+
shots.push({ from: bounds[i], to: bounds[i + 1] });
|
|
82
|
+
}
|
|
83
|
+
return shots
|
|
84
|
+
.sort((a, b) => (b.to - b.from) - (a.to - a.from))
|
|
85
|
+
.slice(0, options.count)
|
|
86
|
+
.sort((a, b) => a.from - b.from);
|
|
87
|
+
}
|
|
88
|
+
/** ffmpeg's blurdetect score for the frame at `atSec` — higher is blurrier. */
|
|
89
|
+
export async function blurScore(file, atSec) {
|
|
90
|
+
const stdout = await captureFfmpegTool('ffmpeg', [
|
|
91
|
+
'-hide_banner', '-nostats', '-ss', atSec.toFixed(3), '-i', file,
|
|
92
|
+
'-frames:v', '1', '-vf', 'blurdetect,metadata=print:file=-', '-f', 'null', '-',
|
|
93
|
+
]);
|
|
94
|
+
const match = /lavfi\.blur=([0-9.]+)/.exec(stdout.toString('utf-8'));
|
|
95
|
+
return match ? Number(match[1]) : Number.POSITIVE_INFINITY;
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* The sharpest of `samples` frames across the middle of a shot. Gameplay footage carries motion
|
|
99
|
+
* blur on fast moments, and the middle frame of a shot is as likely as any to be the smeared one;
|
|
100
|
+
* a screenshot is looked at still, so it should be the crispest frame the shot has.
|
|
101
|
+
*/
|
|
102
|
+
export async function sharpestMoment(file, shot, samples = 5) {
|
|
103
|
+
const span = shot.to - shot.from;
|
|
104
|
+
const times = Array.from({ length: samples }, (_, i) => shot.from + span * (0.2 + (0.6 * i) / Math.max(1, samples - 1)));
|
|
105
|
+
let best = times[Math.floor(times.length / 2)];
|
|
106
|
+
let bestScore = Number.POSITIVE_INFINITY;
|
|
107
|
+
for (const t of times) {
|
|
108
|
+
const score = await blurScore(file, t);
|
|
109
|
+
if (score < bestScore) {
|
|
110
|
+
bestScore = score;
|
|
111
|
+
best = t;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return Math.round(best * 100) / 100;
|
|
115
|
+
}
|
|
116
|
+
/** One frame at `atSec`, scaled to cover `width`x`height` and centre-cropped to it, as PNG. */
|
|
117
|
+
export async function extractFrame(file, atSec, out, width, height) {
|
|
118
|
+
await runFfmpeg([
|
|
119
|
+
'-hide_banner', '-loglevel', 'error', '-y',
|
|
120
|
+
'-ss', atSec.toFixed(3), '-i', file,
|
|
121
|
+
'-frames:v', '1',
|
|
122
|
+
'-vf', `scale=${width}:${height}:force_original_aspect_ratio=increase:flags=lanczos,crop=${width}:${height}`,
|
|
123
|
+
out,
|
|
124
|
+
]);
|
|
125
|
+
}
|
|
126
|
+
/** Normalise any still to `width`x`height` PNG the same way. */
|
|
127
|
+
export async function normaliseStill(file, out, width, height) {
|
|
128
|
+
await runFfmpeg([
|
|
129
|
+
'-hide_banner', '-loglevel', 'error', '-y', '-i', file,
|
|
130
|
+
'-frames:v', '1',
|
|
131
|
+
'-vf', `scale=${width}:${height}:force_original_aspect_ratio=increase:flags=lanczos,crop=${width}:${height}`,
|
|
132
|
+
out,
|
|
133
|
+
]);
|
|
134
|
+
}
|
|
135
|
+
/** A grid of the stills, for the agent to look at in one image instead of eight. */
|
|
136
|
+
export async function contactSheet(files, out) {
|
|
137
|
+
if (files.length === 0)
|
|
138
|
+
return;
|
|
139
|
+
const columns = Math.min(4, files.length);
|
|
140
|
+
const inputs = files.flatMap((file) => ['-i', file]);
|
|
141
|
+
const scaled = files.map((_, i) => `[${i}:v]scale=480:270[s${i}]`).join(';');
|
|
142
|
+
const layout = files.map((_, i) => `${(i % columns) * 480}_${Math.floor(i / columns) * 270}`).join('|');
|
|
143
|
+
const stack = files.length === 1
|
|
144
|
+
? `${scaled};[s0]copy[out]`
|
|
145
|
+
: `${scaled};${files.map((_, i) => `[s${i}]`).join('')}xstack=inputs=${files.length}:layout=${layout}:fill=black[out]`;
|
|
146
|
+
await runFfmpeg([
|
|
147
|
+
'-hide_banner', '-loglevel', 'error', '-y', ...inputs,
|
|
148
|
+
'-filter_complex', stack, '-map', '[out]', '-frames:v', '1', '-q:v', '3', out,
|
|
149
|
+
]);
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=media.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"media.js","sourceRoot":"","sources":["../../src/steam/media.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import type { ShellIdentity } from './shell-files.js';
|
|
2
|
+
/**
|
|
3
|
+
* Hardened-runtime exceptions every Electron process needs: V8 compiles JavaScript to machine code
|
|
4
|
+
* at run time. Nothing else — no library-validation or DYLD exceptions, which only the Steam
|
|
5
|
+
* overlay's injection would need, and this shell does not host it.
|
|
6
|
+
*/
|
|
7
|
+
export declare const ENTITLEMENTS_PLIST = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<!DOCTYPE plist PUBLIC \"-//Apple//DTD PLIST 1.0//EN\" \"http://www.apple.com/DTDs/PropertyList-1.0.dtd\">\n<plist version=\"1.0\">\n<dict>\n <key>com.apple.security.cs.allow-jit</key>\n <true/>\n <key>com.apple.security.cs.allow-unsigned-executable-memory</key>\n <true/>\n</dict>\n</plist>\n";
|
|
8
|
+
export interface MacStampOptions {
|
|
9
|
+
/** The extracted Electron release directory (holds Electron.app). */
|
|
10
|
+
shellDir: string;
|
|
11
|
+
/** Where the stamped single-arch app goes (the directory that will hold `<Product>.app`). */
|
|
12
|
+
outDir: string;
|
|
13
|
+
productName: string;
|
|
14
|
+
bundleId: string;
|
|
15
|
+
version: string;
|
|
16
|
+
buildNumber: string;
|
|
17
|
+
copyrightHolder: string;
|
|
18
|
+
identity: ShellIdentity;
|
|
19
|
+
payloadDir: string;
|
|
20
|
+
icns: Buffer | null;
|
|
21
|
+
}
|
|
22
|
+
/** One architecture's app, fully stamped but unsigned. Returns the .app path. */
|
|
23
|
+
export declare function stampMacApp(options: MacStampOptions): string;
|
|
24
|
+
export declare function isMachO(file: string): boolean;
|
|
25
|
+
/**
|
|
26
|
+
* Merge two single-architecture apps into a universal one: Mach-O files that differ are joined
|
|
27
|
+
* with lipo, identical files are copied, symlinks are recreated as symlinks, and a file only one
|
|
28
|
+
* side has (each architecture's V8 snapshot) is kept — the same rules as @electron/universal for
|
|
29
|
+
* an app with no asar and no native modules, which is what the shell is.
|
|
30
|
+
*/
|
|
31
|
+
export declare function mergeUniversal(arm64App: string, x64App: string, outApp: string): void;
|
|
32
|
+
/** Every Developer ID Application identity in the keychain, as codesign names them. */
|
|
33
|
+
export declare function findDeveloperIdIdentities(): string[];
|
|
34
|
+
export declare function signMacApp(app: string, identity: string, log: (message: string) => void): void;
|
|
35
|
+
/** How notarytool authenticates: a stored keychain profile, or an App Store Connect API key. */
|
|
36
|
+
export type NotaryCredentials = {
|
|
37
|
+
kind: 'profile';
|
|
38
|
+
profile: string;
|
|
39
|
+
} | {
|
|
40
|
+
kind: 'key';
|
|
41
|
+
keyPath: string;
|
|
42
|
+
keyId: string;
|
|
43
|
+
issuerId: string;
|
|
44
|
+
};
|
|
45
|
+
export interface NotarizeResult {
|
|
46
|
+
submissionId: string;
|
|
47
|
+
status: string;
|
|
48
|
+
}
|
|
49
|
+
/** Submit, wait, staple. On a rejection, Apple's log is fetched and its issues quoted. */
|
|
50
|
+
export declare function notarizeMacApp(app: string, credentials: NotaryCredentials, log: (message: string) => void): NotarizeResult;
|
|
51
|
+
/** What Gatekeeper says about the app, e.g. "accepted, source=Notarized Developer ID". */
|
|
52
|
+
export declare function gatekeeperAssessment(app: string): string;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The macOS depot: one universal `<Game>.app` (Apple Silicon and Intel), stamped from Electron's
|
|
3
|
+
* two darwin releases, signed with the creator's Developer ID and notarized — Steam requires new
|
|
4
|
+
* macOS apps to be notarized (partner.steamgames.com/doc/store/application/platforms).
|
|
5
|
+
*
|
|
6
|
+
* Mac-only, by necessity: ditto keeps the frameworks' symlinks, lipo merges the architectures,
|
|
7
|
+
* codesign/notarytool/stapler sign and notarize, plutil edits the plists. Every one of them ships
|
|
8
|
+
* with macOS or the Xcode command-line tools, so the lane adds no dependency to get them.
|
|
9
|
+
*
|
|
10
|
+
* The stamping follows what electron-packager does, so the app is indistinguishable from a
|
|
11
|
+
* hand-packaged Electron game: the executable and the four helper apps carry the game's name
|
|
12
|
+
* (Electron finds its helpers as "<CFBundleName> Helper (…).app"), the plists carry its identity,
|
|
13
|
+
* the demo app is removed, the developer fuses are off.
|
|
14
|
+
*/
|
|
15
|
+
import { spawnSync } from 'child_process';
|
|
16
|
+
import * as fs from 'fs';
|
|
17
|
+
import * as os from 'os';
|
|
18
|
+
import * as path from 'path';
|
|
19
|
+
import { CliError } from '../errors.js';
|
|
20
|
+
import { flipFusesInFile } from './fuses.js';
|
|
21
|
+
import { writeShellApp } from './package-windows.js';
|
|
22
|
+
const HELPER_SUFFIXES = ['', ' (GPU)', ' (Renderer)', ' (Plugin)'];
|
|
23
|
+
const HELPER_ID_SUFFIXES = {
|
|
24
|
+
'': '',
|
|
25
|
+
' (GPU)': '.GPU',
|
|
26
|
+
' (Renderer)': '.Renderer',
|
|
27
|
+
' (Plugin)': '.Plugin',
|
|
28
|
+
};
|
|
29
|
+
/**
|
|
30
|
+
* Hardened-runtime exceptions every Electron process needs: V8 compiles JavaScript to machine code
|
|
31
|
+
* at run time. Nothing else — no library-validation or DYLD exceptions, which only the Steam
|
|
32
|
+
* overlay's injection would need, and this shell does not host it.
|
|
33
|
+
*/
|
|
34
|
+
export const ENTITLEMENTS_PLIST = `<?xml version="1.0" encoding="UTF-8"?>
|
|
35
|
+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
|
36
|
+
<plist version="1.0">
|
|
37
|
+
<dict>
|
|
38
|
+
<key>com.apple.security.cs.allow-jit</key>
|
|
39
|
+
<true/>
|
|
40
|
+
<key>com.apple.security.cs.allow-unsigned-executable-memory</key>
|
|
41
|
+
<true/>
|
|
42
|
+
</dict>
|
|
43
|
+
</plist>
|
|
44
|
+
`;
|
|
45
|
+
function run(command, args, what) {
|
|
46
|
+
const result = spawnSync(command, args, { encoding: 'utf-8', maxBuffer: 64 * 1024 * 1024 });
|
|
47
|
+
if (result.error !== undefined) {
|
|
48
|
+
throw new CliError(`${what}: could not run ${command} (${result.error.message}). Install the Xcode command-line tools: xcode-select --install`, 3);
|
|
49
|
+
}
|
|
50
|
+
if (result.status !== 0) {
|
|
51
|
+
throw new CliError(`${what} failed:\n${(result.stderr || result.stdout).trim().split('\n').slice(-20).join('\n')}`);
|
|
52
|
+
}
|
|
53
|
+
return result;
|
|
54
|
+
}
|
|
55
|
+
function plistSet(plist, key, value) {
|
|
56
|
+
// -replace adds the key when it is missing and overwrites it when present.
|
|
57
|
+
run('plutil', ['-replace', key, '-string', value, plist], `Writing ${key} into ${path.basename(path.dirname(path.dirname(plist)))}`);
|
|
58
|
+
}
|
|
59
|
+
/** One architecture's app, fully stamped but unsigned. Returns the .app path. */
|
|
60
|
+
export function stampMacApp(options) {
|
|
61
|
+
const template = path.join(options.shellDir, 'Electron.app');
|
|
62
|
+
if (!fs.existsSync(template))
|
|
63
|
+
throw new CliError(`The Electron release at ${options.shellDir} has no Electron.app.`);
|
|
64
|
+
const app = path.join(options.outDir, `${options.productName}.app`);
|
|
65
|
+
fs.rmSync(options.outDir, { recursive: true, force: true });
|
|
66
|
+
fs.mkdirSync(options.outDir, { recursive: true });
|
|
67
|
+
run('ditto', [template, app], 'Copying the Electron app');
|
|
68
|
+
const contents = path.join(app, 'Contents');
|
|
69
|
+
fs.rmSync(path.join(contents, 'Resources', 'default_app.asar'), { force: true });
|
|
70
|
+
fs.renameSync(path.join(contents, 'MacOS', 'Electron'), path.join(contents, 'MacOS', options.productName));
|
|
71
|
+
const frameworks = path.join(contents, 'Frameworks');
|
|
72
|
+
for (const suffix of HELPER_SUFFIXES) {
|
|
73
|
+
const oldApp = path.join(frameworks, `Electron Helper${suffix}.app`);
|
|
74
|
+
if (!fs.existsSync(oldApp))
|
|
75
|
+
continue;
|
|
76
|
+
const name = `${options.productName} Helper${suffix}`;
|
|
77
|
+
const newApp = path.join(frameworks, `${name}.app`);
|
|
78
|
+
fs.renameSync(oldApp, newApp);
|
|
79
|
+
fs.renameSync(path.join(newApp, 'Contents', 'MacOS', `Electron Helper${suffix}`), path.join(newApp, 'Contents', 'MacOS', name));
|
|
80
|
+
const plist = path.join(newApp, 'Contents', 'Info.plist');
|
|
81
|
+
plistSet(plist, 'CFBundleExecutable', name);
|
|
82
|
+
plistSet(plist, 'CFBundleName', name);
|
|
83
|
+
plistSet(plist, 'CFBundleDisplayName', name);
|
|
84
|
+
plistSet(plist, 'CFBundleIdentifier', `${options.bundleId}.helper${HELPER_ID_SUFFIXES[suffix]}`);
|
|
85
|
+
}
|
|
86
|
+
const plist = path.join(contents, 'Info.plist');
|
|
87
|
+
plistSet(plist, 'CFBundleExecutable', options.productName);
|
|
88
|
+
// Electron finds its helpers by this name, so it must match the helpers' prefix exactly.
|
|
89
|
+
plistSet(plist, 'CFBundleName', options.productName);
|
|
90
|
+
plistSet(plist, 'CFBundleDisplayName', options.identity.displayName);
|
|
91
|
+
plistSet(plist, 'CFBundleIdentifier', options.bundleId);
|
|
92
|
+
plistSet(plist, 'CFBundleShortVersionString', options.version);
|
|
93
|
+
plistSet(plist, 'CFBundleVersion', options.buildNumber);
|
|
94
|
+
plistSet(plist, 'LSApplicationCategoryType', 'public.app-category.games');
|
|
95
|
+
plistSet(plist, 'NSHumanReadableCopyright', `© ${options.copyrightHolder}. Built with the Bitmagic engine.`);
|
|
96
|
+
if (options.icns !== null) {
|
|
97
|
+
// CFBundleIconFile already names electron.icns; replacing the file keeps the plist valid.
|
|
98
|
+
fs.writeFileSync(path.join(contents, 'Resources', 'electron.icns'), options.icns);
|
|
99
|
+
}
|
|
100
|
+
flipFusesInFile(path.join(frameworks, 'Electron Framework.framework', 'Versions', 'A', 'Electron Framework'));
|
|
101
|
+
writeShellApp(path.join(contents, 'Resources', 'app'), options.identity, options.payloadDir);
|
|
102
|
+
return app;
|
|
103
|
+
}
|
|
104
|
+
const MACHO_MAGICS = new Set([0xfeedface, 0xfeedfacf, 0xcefaedfe, 0xcffaedfe, 0xcafebabe, 0xbebafeca]);
|
|
105
|
+
export function isMachO(file) {
|
|
106
|
+
const fd = fs.openSync(file, 'r');
|
|
107
|
+
try {
|
|
108
|
+
const head = Buffer.alloc(4);
|
|
109
|
+
if (fs.readSync(fd, head, 0, 4, 0) < 4)
|
|
110
|
+
return false;
|
|
111
|
+
return MACHO_MAGICS.has(head.readUInt32BE(0));
|
|
112
|
+
}
|
|
113
|
+
finally {
|
|
114
|
+
fs.closeSync(fd);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
function sameBytes(a, b) {
|
|
118
|
+
const sa = fs.statSync(a);
|
|
119
|
+
const sb = fs.statSync(b);
|
|
120
|
+
if (sa.size !== sb.size)
|
|
121
|
+
return false;
|
|
122
|
+
return fs.readFileSync(a).equals(fs.readFileSync(b));
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Merge two single-architecture apps into a universal one: Mach-O files that differ are joined
|
|
126
|
+
* with lipo, identical files are copied, symlinks are recreated as symlinks, and a file only one
|
|
127
|
+
* side has (each architecture's V8 snapshot) is kept — the same rules as @electron/universal for
|
|
128
|
+
* an app with no asar and no native modules, which is what the shell is.
|
|
129
|
+
*/
|
|
130
|
+
export function mergeUniversal(arm64App, x64App, outApp) {
|
|
131
|
+
fs.rmSync(outApp, { recursive: true, force: true });
|
|
132
|
+
const walk = (rel) => {
|
|
133
|
+
const a = path.join(arm64App, rel);
|
|
134
|
+
const x = path.join(x64App, rel);
|
|
135
|
+
const out = path.join(outApp, rel);
|
|
136
|
+
const aStat = fs.existsSync(a) ? fs.lstatSync(a) : null;
|
|
137
|
+
const xStat = fs.existsSync(x) ? fs.lstatSync(x) : null;
|
|
138
|
+
const stat = aStat ?? xStat;
|
|
139
|
+
if (stat === null)
|
|
140
|
+
return;
|
|
141
|
+
if (stat.isSymbolicLink()) {
|
|
142
|
+
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
143
|
+
fs.symlinkSync(fs.readlinkSync(aStat ? a : x), out);
|
|
144
|
+
return;
|
|
145
|
+
}
|
|
146
|
+
if (stat.isDirectory()) {
|
|
147
|
+
fs.mkdirSync(out, { recursive: true });
|
|
148
|
+
const names = new Set([
|
|
149
|
+
...(aStat?.isDirectory() ? fs.readdirSync(a) : []),
|
|
150
|
+
...(xStat?.isDirectory() ? fs.readdirSync(x) : []),
|
|
151
|
+
]);
|
|
152
|
+
for (const name of names)
|
|
153
|
+
walk(path.join(rel, name));
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
fs.mkdirSync(path.dirname(out), { recursive: true });
|
|
157
|
+
if (aStat !== null && xStat !== null && !sameBytes(a, x)) {
|
|
158
|
+
if (!isMachO(a) || !isMachO(x)) {
|
|
159
|
+
throw new CliError(`The two architectures differ in ${rel}, which is not a binary lipo can merge.`);
|
|
160
|
+
}
|
|
161
|
+
run('lipo', ['-create', a, x, '-output', out], `Merging ${rel}`);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
fs.copyFileSync(aStat ? a : x, out);
|
|
165
|
+
}
|
|
166
|
+
fs.chmodSync(out, stat.mode & 0o7777);
|
|
167
|
+
};
|
|
168
|
+
walk('');
|
|
169
|
+
}
|
|
170
|
+
/** Every Developer ID Application identity in the keychain, as codesign names them. */
|
|
171
|
+
export function findDeveloperIdIdentities() {
|
|
172
|
+
const result = spawnSync('security', ['find-identity', '-v', '-p', 'codesigning'], { encoding: 'utf-8' });
|
|
173
|
+
if (result.status !== 0)
|
|
174
|
+
return [];
|
|
175
|
+
return [...result.stdout.matchAll(/"(Developer ID Application: [^"]+)"/g)].map((match) => match[1]);
|
|
176
|
+
}
|
|
177
|
+
/** Bundles and loose Mach-O files under `app`, deepest first: the order codesign needs. */
|
|
178
|
+
function signingOrder(app) {
|
|
179
|
+
const items = [];
|
|
180
|
+
const walk = (dir, depth) => {
|
|
181
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
182
|
+
const full = path.join(dir, entry.name);
|
|
183
|
+
if (entry.isSymbolicLink())
|
|
184
|
+
continue;
|
|
185
|
+
if (entry.isDirectory()) {
|
|
186
|
+
walk(full, depth + 1);
|
|
187
|
+
if (entry.name.endsWith('.app') || entry.name.endsWith('.framework'))
|
|
188
|
+
items.push({ path: full, bundle: true, depth });
|
|
189
|
+
}
|
|
190
|
+
else if (entry.isFile() && isMachO(full)) {
|
|
191
|
+
// A bundle's main executable is signed with its bundle, not on its own.
|
|
192
|
+
const parent = path.basename(path.dirname(full));
|
|
193
|
+
const inBundleMacOS = parent === 'MacOS' && path.basename(path.dirname(path.dirname(full))) === 'Contents';
|
|
194
|
+
const frameworkMain = /\.framework\/Versions\/[^/]+$/.test(path.dirname(full)) && !full.endsWith('.dylib');
|
|
195
|
+
if (!inBundleMacOS && !frameworkMain)
|
|
196
|
+
items.push({ path: full, bundle: false, depth: depth + 1 });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
walk(app, 0);
|
|
201
|
+
items.sort((a, b) => b.depth - a.depth);
|
|
202
|
+
return [...items.map(({ path: p, bundle }) => ({ path: p, bundle })), { path: app, bundle: true }];
|
|
203
|
+
}
|
|
204
|
+
export function signMacApp(app, identity, log) {
|
|
205
|
+
const entitlements = path.join(os.tmpdir(), `bitmagic-entitlements-${process.pid}.plist`);
|
|
206
|
+
fs.writeFileSync(entitlements, ENTITLEMENTS_PLIST);
|
|
207
|
+
try {
|
|
208
|
+
const order = signingOrder(app);
|
|
209
|
+
log(`Signing ${order.length} items with ${identity}…`);
|
|
210
|
+
for (const item of order) {
|
|
211
|
+
const executableBundle = item.bundle && item.path.endsWith('.app');
|
|
212
|
+
run('codesign', [
|
|
213
|
+
'--force', '--timestamp', '--options', 'runtime',
|
|
214
|
+
...(executableBundle ? ['--entitlements', entitlements] : []),
|
|
215
|
+
'--sign', identity, item.path,
|
|
216
|
+
], `Signing ${path.relative(path.dirname(app), item.path)}`);
|
|
217
|
+
}
|
|
218
|
+
run('codesign', ['--verify', '--deep', '--strict', '--verbose=2', app], 'Verifying the signature');
|
|
219
|
+
}
|
|
220
|
+
finally {
|
|
221
|
+
fs.rmSync(entitlements, { force: true });
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
function notaryAuthArgs(credentials) {
|
|
225
|
+
return credentials.kind === 'profile'
|
|
226
|
+
? ['--keychain-profile', credentials.profile]
|
|
227
|
+
: ['--key', credentials.keyPath, '--key-id', credentials.keyId, '--issuer', credentials.issuerId];
|
|
228
|
+
}
|
|
229
|
+
/** Submit, wait, staple. On a rejection, Apple's log is fetched and its issues quoted. */
|
|
230
|
+
export function notarizeMacApp(app, credentials, log) {
|
|
231
|
+
const zip = path.join(os.tmpdir(), `bitmagic-notarize-${process.pid}.zip`);
|
|
232
|
+
try {
|
|
233
|
+
run('ditto', ['-c', '-k', '--keepParent', app, zip], 'Zipping the app for notarization');
|
|
234
|
+
log('Submitting to Apple\'s notary service and waiting (usually a few minutes)…');
|
|
235
|
+
const submitted = spawnSync('xcrun', ['notarytool', 'submit', zip, ...notaryAuthArgs(credentials), '--wait', '--output-format', 'json'], {
|
|
236
|
+
encoding: 'utf-8',
|
|
237
|
+
maxBuffer: 16 * 1024 * 1024,
|
|
238
|
+
});
|
|
239
|
+
let parsed = {};
|
|
240
|
+
try {
|
|
241
|
+
parsed = JSON.parse(submitted.stdout);
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
throw new CliError(`notarytool did not answer: ${(submitted.stderr || submitted.stdout).trim().slice(0, 2000)}`);
|
|
245
|
+
}
|
|
246
|
+
const submissionId = parsed.id ?? '';
|
|
247
|
+
const status = parsed.status ?? 'unknown';
|
|
248
|
+
if (status !== 'Accepted') {
|
|
249
|
+
let issues = '';
|
|
250
|
+
if (submissionId !== '') {
|
|
251
|
+
const logged = spawnSync('xcrun', ['notarytool', 'log', submissionId, ...notaryAuthArgs(credentials)], { encoding: 'utf-8' });
|
|
252
|
+
issues = logged.stdout.slice(0, 4000);
|
|
253
|
+
}
|
|
254
|
+
throw new CliError(`Apple did not notarize the app (status: ${status}). ${parsed.message ?? ''}\n${issues}`);
|
|
255
|
+
}
|
|
256
|
+
run('xcrun', ['stapler', 'staple', app], 'Stapling the notarization ticket');
|
|
257
|
+
return { submissionId, status };
|
|
258
|
+
}
|
|
259
|
+
finally {
|
|
260
|
+
fs.rmSync(zip, { force: true });
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
/** What Gatekeeper says about the app, e.g. "accepted, source=Notarized Developer ID". */
|
|
264
|
+
export function gatekeeperAssessment(app) {
|
|
265
|
+
const result = spawnSync('spctl', ['-a', '-vvv', '-t', 'exec', app], { encoding: 'utf-8' });
|
|
266
|
+
return `${result.stderr}${result.stdout}`.trim();
|
|
267
|
+
}
|
|
268
|
+
//# sourceMappingURL=package-macos.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-macos.js","sourceRoot":"","sources":["../../src/steam/package-macos.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ShellIdentity } from './shell-files.js';
|
|
2
|
+
export interface WindowsPackageOptions {
|
|
3
|
+
/** The extracted electron-v*-win32-x64 release. */
|
|
4
|
+
shellDir: string;
|
|
5
|
+
/** The depot content root; emptied and refilled. */
|
|
6
|
+
outDir: string;
|
|
7
|
+
productName: string;
|
|
8
|
+
identity: ShellIdentity;
|
|
9
|
+
/** `x.y.z` as the version resource wants it. */
|
|
10
|
+
version: string;
|
|
11
|
+
/** Who the copyright line names — the creator owns the game, Bitmagic only made the engine. */
|
|
12
|
+
copyrightHolder: string;
|
|
13
|
+
payloadDir: string;
|
|
14
|
+
/** Multi-size .ico, or null to keep Electron's. */
|
|
15
|
+
ico: Buffer | null;
|
|
16
|
+
}
|
|
17
|
+
export interface WindowsPackageResult {
|
|
18
|
+
exePath: string;
|
|
19
|
+
bytes: number;
|
|
20
|
+
}
|
|
21
|
+
export declare function writeShellApp(appDir: string, identity: ShellIdentity, payloadDir: string): void;
|
|
22
|
+
declare function directoryBytes(dir: string): number;
|
|
23
|
+
export declare function packageWindows(options: WindowsPackageOptions): Promise<WindowsPackageResult>;
|
|
24
|
+
export { directoryBytes };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The Windows depot: the Electron win32-x64 release stamped into `<Game>.exe` — the game's icon
|
|
3
|
+
* and version resource patched in with resedit (pure JS, so this builds on any OS), the developer
|
|
4
|
+
* fuses off, Electron's demo app removed, the shell and the payload in `resources/app/`.
|
|
5
|
+
*
|
|
6
|
+
* Unsigned is fine on Steam: Steam-installed files carry no mark-of-the-web, so SmartScreen never
|
|
7
|
+
* sees them. Valve's DRM wrapper must NOT be applied — it breaks Chromium.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { CliError } from '../errors.js';
|
|
12
|
+
import { flipFusesInFile } from './fuses.js';
|
|
13
|
+
import { SHELL_PRELOAD_JS, buildShellMainJs, buildShellPackageJson } from './shell-files.js';
|
|
14
|
+
function numericVersion(version) {
|
|
15
|
+
const parts = version.split(/[.-]/).map((part) => Number.parseInt(part, 10)).filter((n) => Number.isFinite(n));
|
|
16
|
+
return [parts[0] ?? 1, parts[1] ?? 0, parts[2] ?? 0, parts[3] ?? 0];
|
|
17
|
+
}
|
|
18
|
+
async function patchExe(exePath, options) {
|
|
19
|
+
const ResEdit = await import('resedit');
|
|
20
|
+
const executable = ResEdit.NtExecutable.from(fs.readFileSync(exePath), { ignoreCert: true });
|
|
21
|
+
const resource = ResEdit.NtExecutableResource.from(executable);
|
|
22
|
+
if (options.ico !== null) {
|
|
23
|
+
const iconFile = ResEdit.Data.IconFile.from(options.ico);
|
|
24
|
+
// Electron's main icon group is id 1, language en-US.
|
|
25
|
+
ResEdit.Resource.IconGroupEntry.replaceIconsForResource(resource.entries, 1, 1033, iconFile.icons.map((icon) => icon.data));
|
|
26
|
+
}
|
|
27
|
+
const [major, minor, patch, build] = numericVersion(options.version);
|
|
28
|
+
const versionInfo = ResEdit.Resource.VersionInfo.fromEntries(resource.entries)[0] ?? ResEdit.Resource.VersionInfo.createEmpty();
|
|
29
|
+
versionInfo.setFileVersion(major, minor, patch, build, 1033);
|
|
30
|
+
versionInfo.setProductVersion(major, minor, patch, build, 1033);
|
|
31
|
+
versionInfo.setStringValues({ lang: 1033, codepage: 1200 }, {
|
|
32
|
+
ProductName: options.identity.displayName,
|
|
33
|
+
FileDescription: options.identity.displayName,
|
|
34
|
+
CompanyName: options.copyrightHolder,
|
|
35
|
+
InternalName: options.productName,
|
|
36
|
+
OriginalFilename: `${options.productName}.exe`,
|
|
37
|
+
ProductVersion: options.version,
|
|
38
|
+
FileVersion: options.version,
|
|
39
|
+
LegalCopyright: `© ${options.copyrightHolder}. Built with the Bitmagic engine.`,
|
|
40
|
+
});
|
|
41
|
+
// Electron's marker for the Squirrel.Windows updater, which a Steam game never runs: Steam
|
|
42
|
+
// updates through its depots.
|
|
43
|
+
versionInfo.removeStringValue({ lang: 1033, codepage: 1200 }, 'SquirrelAwareVersion');
|
|
44
|
+
versionInfo.outputToResourceEntries(resource.entries);
|
|
45
|
+
resource.outputResource(executable);
|
|
46
|
+
fs.writeFileSync(exePath, Buffer.from(executable.generate()));
|
|
47
|
+
}
|
|
48
|
+
export function writeShellApp(appDir, identity, payloadDir) {
|
|
49
|
+
fs.rmSync(appDir, { recursive: true, force: true });
|
|
50
|
+
fs.mkdirSync(appDir, { recursive: true });
|
|
51
|
+
fs.writeFileSync(path.join(appDir, 'package.json'), buildShellPackageJson(identity));
|
|
52
|
+
fs.writeFileSync(path.join(appDir, 'main.js'), buildShellMainJs(identity));
|
|
53
|
+
fs.writeFileSync(path.join(appDir, 'preload.js'), SHELL_PRELOAD_JS);
|
|
54
|
+
fs.cpSync(payloadDir, path.join(appDir, 'game'), { recursive: true });
|
|
55
|
+
}
|
|
56
|
+
function directoryBytes(dir) {
|
|
57
|
+
let total = 0;
|
|
58
|
+
for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {
|
|
59
|
+
const full = path.join(dir, entry.name);
|
|
60
|
+
if (entry.isDirectory())
|
|
61
|
+
total += directoryBytes(full);
|
|
62
|
+
else if (entry.isFile())
|
|
63
|
+
total += fs.statSync(full).size;
|
|
64
|
+
}
|
|
65
|
+
return total;
|
|
66
|
+
}
|
|
67
|
+
export async function packageWindows(options) {
|
|
68
|
+
const source = path.join(options.shellDir, 'electron.exe');
|
|
69
|
+
if (!fs.existsSync(source))
|
|
70
|
+
throw new CliError(`The Electron release at ${options.shellDir} has no electron.exe.`);
|
|
71
|
+
fs.rmSync(options.outDir, { recursive: true, force: true });
|
|
72
|
+
fs.cpSync(options.shellDir, options.outDir, { recursive: true });
|
|
73
|
+
fs.rmSync(path.join(options.outDir, '.extracted'), { force: true });
|
|
74
|
+
// Electron's own demo app; with resources/app present it is never loaded, so it is only weight.
|
|
75
|
+
fs.rmSync(path.join(options.outDir, 'resources', 'default_app.asar'), { force: true });
|
|
76
|
+
const exePath = path.join(options.outDir, `${options.productName}.exe`);
|
|
77
|
+
fs.renameSync(path.join(options.outDir, 'electron.exe'), exePath);
|
|
78
|
+
await patchExe(exePath, options);
|
|
79
|
+
flipFusesInFile(exePath);
|
|
80
|
+
writeShellApp(path.join(options.outDir, 'resources', 'app'), options.identity, options.payloadDir);
|
|
81
|
+
return { exePath, bytes: directoryBytes(options.outDir) };
|
|
82
|
+
}
|
|
83
|
+
export { directoryBytes };
|
|
84
|
+
//# sourceMappingURL=package-windows.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"package-windows.js","sourceRoot":"","sources":["../../src/steam/package-windows.ts"],"names":[],"mappings":"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"}
|