seabox 0.1.0-beta.3 → 0.1.0
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 +177 -154
- package/bin/seabox-rebuild.mjs +88 -0
- package/bin/seabox.mjs +147 -0
- package/lib/{blob.js → blob.mjs} +14 -19
- package/lib/bootstrap.cjs +753 -0
- package/lib/build-cache.mjs +199 -0
- package/lib/build.mjs +77 -0
- package/lib/config.mjs +243 -0
- package/lib/{crypto-assets.js → crypto-assets.mjs} +12 -47
- package/lib/diagnostics.mjs +203 -0
- package/lib/entry-bundler.mjs +64 -0
- package/lib/{fetch-node.js → fetch-node.mjs} +15 -20
- package/lib/index.mjs +26 -0
- package/lib/inject.mjs +95 -0
- package/lib/{manifest.js → manifest.mjs} +5 -11
- package/lib/multi-target-builder.mjs +705 -0
- package/lib/native-scanner.mjs +203 -0
- package/lib/{obfuscate.js → obfuscate.mjs} +9 -31
- package/lib/require-shim.mjs +113 -0
- package/lib/rolldown-bundler.mjs +411 -0
- package/lib/{unsign.js → unsign.cjs} +31 -46
- package/package.json +10 -5
- package/bin/seabox-rebuild.js +0 -395
- package/bin/seabox.js +0 -81
- package/lib/bindings.js +0 -31
- package/lib/bootstrap.js +0 -697
- package/lib/build.js +0 -283
- package/lib/bytenode-hack.js +0 -56
- package/lib/config.js +0 -119
- package/lib/index.js +0 -27
- package/lib/inject.js +0 -114
- package/lib/scanner.js +0 -153
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* diagnostics.mjs
|
|
3
|
+
* Centralized console output formatting for CLI tooling.
|
|
4
|
+
* Provides consistent formatting, indentation, and styling.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Output levels
|
|
9
|
+
*/
|
|
10
|
+
export const Level = {
|
|
11
|
+
ERROR: 'error',
|
|
12
|
+
WARN: 'warn',
|
|
13
|
+
INFO: 'info',
|
|
14
|
+
SUCCESS: 'success',
|
|
15
|
+
VERBOSE: 'verbose'
|
|
16
|
+
};
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Formatting utilities
|
|
20
|
+
*/
|
|
21
|
+
const colors = {
|
|
22
|
+
reset: '\x1b[0m',
|
|
23
|
+
red: '\x1b[31m',
|
|
24
|
+
green: '\x1b[32m',
|
|
25
|
+
yellow: '\x1b[33m',
|
|
26
|
+
blue: '\x1b[34m',
|
|
27
|
+
gray: '\x1b[90m'
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
function withColor(text, color) {
|
|
31
|
+
return `${color}${text}${colors.reset}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Global verbose flag
|
|
36
|
+
*/
|
|
37
|
+
let verboseEnabled = false;
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Enable or disable verbose output
|
|
41
|
+
* @param {boolean} enabled
|
|
42
|
+
*/
|
|
43
|
+
export function setVerbose(enabled) {
|
|
44
|
+
verboseEnabled = enabled;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Core logging function
|
|
49
|
+
* @param {string} message
|
|
50
|
+
* @param {string} prefix
|
|
51
|
+
* @param {number} indent
|
|
52
|
+
*/
|
|
53
|
+
function log(message, prefix = '', indent = 0) {
|
|
54
|
+
const indentation = ' '.repeat(indent);
|
|
55
|
+
console.log(`${indentation}${prefix}${message}`);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Print section header
|
|
60
|
+
* @param {string} title
|
|
61
|
+
*/
|
|
62
|
+
export function header(title) {
|
|
63
|
+
console.log(`\n${title}`);
|
|
64
|
+
console.log('='.repeat(40));
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Print sub-header
|
|
69
|
+
* @param {string} title
|
|
70
|
+
*/
|
|
71
|
+
export function subheader(title) {
|
|
72
|
+
console.log(`\n${title}`);
|
|
73
|
+
console.log('-'.repeat(40));
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Print step with number
|
|
78
|
+
* @param {number} step
|
|
79
|
+
* @param {number} total
|
|
80
|
+
* @param {string} message
|
|
81
|
+
*/
|
|
82
|
+
export function step(step, total, message) {
|
|
83
|
+
log(`[${step}/${total}] ${message}`);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* Print build step
|
|
88
|
+
* @param {number} buildNum
|
|
89
|
+
* @param {number} stepNum
|
|
90
|
+
* @param {string} message
|
|
91
|
+
*/
|
|
92
|
+
export function buildStep(buildNum, stepNum, message) {
|
|
93
|
+
log(`[${buildNum}.${stepNum}] ${message}`, '', 1);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Print success message
|
|
98
|
+
* @param {string} message
|
|
99
|
+
* @param {number} indent
|
|
100
|
+
*/
|
|
101
|
+
export function success(message, indent = 1) {
|
|
102
|
+
log(withColor(`[✓] ${message}`, colors.green), '', indent);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* Print info message
|
|
107
|
+
* @param {string} message
|
|
108
|
+
* @param {number} indent
|
|
109
|
+
*/
|
|
110
|
+
export function info(message, indent = 0) {
|
|
111
|
+
log(message, '', indent);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Print warning
|
|
116
|
+
* @param {string} message
|
|
117
|
+
* @param {number} indent
|
|
118
|
+
*/
|
|
119
|
+
export function warn(message, indent = 1) {
|
|
120
|
+
log(withColor(`[!] ${message}`, colors.yellow), '', indent);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Print error
|
|
125
|
+
* @param {string} message
|
|
126
|
+
* @param {number} indent
|
|
127
|
+
*/
|
|
128
|
+
export function error(message, indent = 0) {
|
|
129
|
+
console.error(`${' '.repeat(indent)}${withColor(`[X] ${message}`, colors.red)}`);
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* Print verbose message (only if verbose enabled)
|
|
134
|
+
* @param {string} message
|
|
135
|
+
* @param {number} indent
|
|
136
|
+
*/
|
|
137
|
+
export function verbose(message, indent = 2) {
|
|
138
|
+
if (verboseEnabled) {
|
|
139
|
+
log(withColor(message, colors.gray), '', indent);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Print list item
|
|
145
|
+
* @param {string} message
|
|
146
|
+
* @param {number} indent
|
|
147
|
+
*/
|
|
148
|
+
export function listItem(message, indent = 1) {
|
|
149
|
+
log(`- ${message}`, '', indent);
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Print numbered list item
|
|
154
|
+
* @param {number} num
|
|
155
|
+
* @param {string} message
|
|
156
|
+
* @param {number} indent
|
|
157
|
+
*/
|
|
158
|
+
export function numberedItem(num, message, indent = 1) {
|
|
159
|
+
log(`${num}. ${message}`, '', indent);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Print section separator
|
|
164
|
+
*/
|
|
165
|
+
export function separator() {
|
|
166
|
+
console.log('');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Print final summary
|
|
171
|
+
* @param {string} message
|
|
172
|
+
*/
|
|
173
|
+
export function summary(message) {
|
|
174
|
+
console.log('');
|
|
175
|
+
console.log('='.repeat(40));
|
|
176
|
+
log(withColor(message, colors.green));
|
|
177
|
+
console.log('='.repeat(40));
|
|
178
|
+
console.log('');
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Format file size in human-readable format
|
|
183
|
+
* @param {number} bytes
|
|
184
|
+
* @returns {string}
|
|
185
|
+
*/
|
|
186
|
+
export function formatSize(bytes) {
|
|
187
|
+
const mb = bytes / 1024 / 1024;
|
|
188
|
+
if (mb >= 1) {
|
|
189
|
+
return `${mb.toFixed(2)} MB`;
|
|
190
|
+
}
|
|
191
|
+
const kb = bytes / 1024;
|
|
192
|
+
return `${kb.toFixed(2)} KB`;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Format target string
|
|
197
|
+
* @param {string} platform
|
|
198
|
+
* @param {string} arch
|
|
199
|
+
* @returns {string}
|
|
200
|
+
*/
|
|
201
|
+
export function formatTarget(platform, arch) {
|
|
202
|
+
return `${platform}-${arch}`;
|
|
203
|
+
}
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* entry-bundler.mjs
|
|
3
|
+
* Bundles the entry file with bootstrap and require shim
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import Module from 'module';
|
|
7
|
+
import { fileURLToPath } from 'url';
|
|
8
|
+
|
|
9
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
10
|
+
const require = Module.createRequire(import.meta.url);
|
|
11
|
+
|
|
12
|
+
const { generateRequireShim, replaceRequireCalls } = require('./require-shim.mjs');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Bundle the entry file for SEA
|
|
16
|
+
* @param {string} entryContent - The entry file content
|
|
17
|
+
* @param {string} augmentedBootstrap - The bootstrap code
|
|
18
|
+
* @param {boolean} useSnapshot - Whether to use snapshot mode
|
|
19
|
+
* @param {boolean} verbose - Enable verbose logging
|
|
20
|
+
* @returns {string} - The bundled entry content
|
|
21
|
+
*/
|
|
22
|
+
export function bundleEntry(entryContent, augmentedBootstrap, useSnapshot, verbose) {
|
|
23
|
+
// Generate the require shim and replace require() calls
|
|
24
|
+
const requireSeaboxShim = generateRequireShim();
|
|
25
|
+
const transformed = replaceRequireCalls(entryContent, verbose);
|
|
26
|
+
const transformedContent = transformed.code;
|
|
27
|
+
|
|
28
|
+
let bundledEntry;
|
|
29
|
+
|
|
30
|
+
if (useSnapshot) {
|
|
31
|
+
// Snapshot mode
|
|
32
|
+
const parts = [
|
|
33
|
+
augmentedBootstrap,
|
|
34
|
+
'\n\n',
|
|
35
|
+
requireSeaboxShim,
|
|
36
|
+
'\n\n',
|
|
37
|
+
'// Application entry - will be wrapped by bootstrap\'s setDeserializeMainFunction interceptor\n',
|
|
38
|
+
'(function() {\n',
|
|
39
|
+
' const v8 = __originalRequire(\'v8\');\n',
|
|
40
|
+
' if (v8.startupSnapshot && v8.startupSnapshot.isBuildingSnapshot()) {\n',
|
|
41
|
+
' v8.startupSnapshot.setDeserializeMainFunction(() => {\n',
|
|
42
|
+
' if (typeof exports === \'undefined\') {\n',
|
|
43
|
+
' var exports = {};\n',
|
|
44
|
+
' var module = { exports: exports };\n',
|
|
45
|
+
' }\n',
|
|
46
|
+
' // Run the application code\n',
|
|
47
|
+
transformedContent,
|
|
48
|
+
'\n',
|
|
49
|
+
' });\n',
|
|
50
|
+
' } else {\n',
|
|
51
|
+
' // Not building snapshot, run normally\n',
|
|
52
|
+
transformedContent,
|
|
53
|
+
'\n',
|
|
54
|
+
' }\n',
|
|
55
|
+
'})();\n'
|
|
56
|
+
];
|
|
57
|
+
bundledEntry = parts.join('');
|
|
58
|
+
} else {
|
|
59
|
+
// Non-snapshot mode
|
|
60
|
+
bundledEntry = augmentedBootstrap + '\n\n' + requireSeaboxShim + '\n' + transformedContent;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
return bundledEntry;
|
|
64
|
+
}
|
|
@@ -1,13 +1,16 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* fetch-node.
|
|
2
|
+
* fetch-node.mjs
|
|
3
3
|
* Download target Node.js binary for SEA injection.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import https from 'https';
|
|
9
|
+
import { pipeline } from 'stream';
|
|
10
|
+
import { promisify } from 'util';
|
|
11
|
+
import AdmZip from 'adm-zip';
|
|
12
|
+
import tar from 'tar';
|
|
13
|
+
import * as diag from './diagnostics.mjs';
|
|
11
14
|
|
|
12
15
|
const pipelineAsync = promisify(pipeline);
|
|
13
16
|
|
|
@@ -78,9 +81,6 @@ async function downloadFile(url, outputPath) {
|
|
|
78
81
|
* @returns {Promise<string>} - Path to extracted node binary
|
|
79
82
|
*/
|
|
80
83
|
async function extractNodeBinary(archivePath, outputDir, platform) {
|
|
81
|
-
const AdmZip = require('adm-zip');
|
|
82
|
-
const tar = require('tar');
|
|
83
|
-
|
|
84
84
|
if (platform === 'win32') {
|
|
85
85
|
// Extract from ZIP
|
|
86
86
|
const zip = new AdmZip(archivePath);
|
|
@@ -135,7 +135,7 @@ async function extractNodeBinary(archivePath, outputDir, platform) {
|
|
|
135
135
|
* @param {string} cacheDir - Directory to cache downloads
|
|
136
136
|
* @returns {Promise<string>} - Path to the node binary
|
|
137
137
|
*/
|
|
138
|
-
async function fetchNodeBinary(nodeVersion, platform, arch, cacheDir) {
|
|
138
|
+
export async function fetchNodeBinary(nodeVersion, platform, arch, cacheDir) {
|
|
139
139
|
if (!fs.existsSync(cacheDir)) {
|
|
140
140
|
fs.mkdirSync(cacheDir, { recursive: true });
|
|
141
141
|
}
|
|
@@ -145,23 +145,23 @@ async function fetchNodeBinary(nodeVersion, platform, arch, cacheDir) {
|
|
|
145
145
|
|
|
146
146
|
// Check cache
|
|
147
147
|
if (fs.existsSync(cachedBinary)) {
|
|
148
|
-
|
|
148
|
+
diag.verbose(`Using cached Node binary: ${cachedBinary}`, 1);
|
|
149
149
|
return cachedBinary;
|
|
150
150
|
}
|
|
151
151
|
|
|
152
|
-
|
|
152
|
+
diag.verbose(`Downloading Node.js v${nodeVersion} for ${platform}-${arch}...`, 1);
|
|
153
153
|
const url = getNodeDownloadUrl(nodeVersion, platform, arch);
|
|
154
154
|
const archiveName = path.basename(url);
|
|
155
155
|
const archivePath = path.join(cacheDir, archiveName);
|
|
156
156
|
|
|
157
157
|
await downloadFile(url, archivePath);
|
|
158
|
-
|
|
158
|
+
diag.verbose(`Downloaded: ${archivePath}`, 1);
|
|
159
159
|
|
|
160
160
|
const extractDir = path.join(cacheDir, `${nodeVersion}-${platform}-${arch}`);
|
|
161
161
|
fs.mkdirSync(extractDir, { recursive: true });
|
|
162
162
|
|
|
163
163
|
const binaryPath = await extractNodeBinary(archivePath, extractDir, platform);
|
|
164
|
-
|
|
164
|
+
diag.verbose(`Extracted Node binary: ${binaryPath}`, 1);
|
|
165
165
|
|
|
166
166
|
// Clean up archive
|
|
167
167
|
fs.unlinkSync(archivePath);
|
|
@@ -169,9 +169,4 @@ async function fetchNodeBinary(nodeVersion, platform, arch, cacheDir) {
|
|
|
169
169
|
return binaryPath;
|
|
170
170
|
}
|
|
171
171
|
|
|
172
|
-
|
|
173
|
-
getNodeDownloadUrl,
|
|
174
|
-
downloadFile,
|
|
175
|
-
extractNodeBinary,
|
|
176
|
-
fetchNodeBinary
|
|
177
|
-
};
|
|
172
|
+
export { getNodeDownloadUrl, downloadFile, extractNodeBinary };
|
package/lib/index.mjs
ADDED
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* index.mjs
|
|
3
|
+
* Main entry point for Seabox v2 library.
|
|
4
|
+
* Exports all public APIs.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
export { build } from './build.mjs';
|
|
8
|
+
export {
|
|
9
|
+
loadConfig,
|
|
10
|
+
validateConfig,
|
|
11
|
+
parseTarget,
|
|
12
|
+
generateDefaultConfig,
|
|
13
|
+
normalizeConfig,
|
|
14
|
+
getDefaultLibraryPatterns
|
|
15
|
+
} from './config.mjs';
|
|
16
|
+
export { MultiTargetBuilder } from './multi-target-builder.mjs';
|
|
17
|
+
export { bundleWithRollup, NativeModuleDetectorPlugin } from './rolldown-bundler.mjs';
|
|
18
|
+
export { scanDependenciesForNativeModules, findNativeModuleBuildPath } from './native-scanner.mjs';
|
|
19
|
+
export { BuildCache } from './build-cache.mjs';
|
|
20
|
+
export { generateManifest, serializeManifest } from './manifest.mjs';
|
|
21
|
+
export { createSeaConfig, writeSeaConfigJson, generateBlob } from './blob.mjs';
|
|
22
|
+
export { fetchNodeBinary } from './fetch-node.mjs';
|
|
23
|
+
export { injectBlob } from './inject.mjs';
|
|
24
|
+
export { generateEncryptionKey, encryptAsset, decryptAsset, encryptAssets, keyToObfuscatedCode } from './crypto-assets.mjs';
|
|
25
|
+
export { obfuscateBootstrap } from './obfuscate.mjs';
|
|
26
|
+
export { bundleEntry } from './entry-bundler.mjs';
|
package/lib/inject.mjs
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* inject.mjs
|
|
3
|
+
* Inject SEA blob into Node binary using postject.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import fs from 'fs';
|
|
7
|
+
import path from 'path';
|
|
8
|
+
import Module from 'module';
|
|
9
|
+
import { fileURLToPath } from 'url';
|
|
10
|
+
import * as diag from './diagnostics.mjs';
|
|
11
|
+
|
|
12
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
13
|
+
const __dirname = path.dirname(__filename);
|
|
14
|
+
|
|
15
|
+
// Import unsign using require since it's CommonJS
|
|
16
|
+
const require = Module.createRequire(import.meta.url);
|
|
17
|
+
const { removeSignature, setVerbose: setUnsignVerbose } = require('./unsign.cjs');
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Inject a SEA blob into a Node.js binary using postject.
|
|
21
|
+
* @param {string} nodeBinaryPath - Path to the source Node binary
|
|
22
|
+
* @param {string} blobPath - Path to the SEA blob file
|
|
23
|
+
* @param {string} outputPath - Path for the output executable
|
|
24
|
+
* @param {string} platform - Target platform (win32, linux, darwin)
|
|
25
|
+
* @param {boolean} verbose - Enable verbose logging
|
|
26
|
+
* @param {Object} [rceditOptions] - Optional rcedit configuration for Windows executables
|
|
27
|
+
* @returns {Promise<void>}
|
|
28
|
+
*/
|
|
29
|
+
export async function injectBlob(nodeBinaryPath, blobPath, outputPath, platform, verbose, rceditOptions) {
|
|
30
|
+
// Ensure output directory exists
|
|
31
|
+
const outputDir = path.dirname(outputPath);
|
|
32
|
+
if (!fs.existsSync(outputDir)) {
|
|
33
|
+
fs.mkdirSync(outputDir, { recursive: true });
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Copy node binary to output location
|
|
37
|
+
fs.copyFileSync(nodeBinaryPath, outputPath);
|
|
38
|
+
|
|
39
|
+
// Remove existing signature before postject injection
|
|
40
|
+
setUnsignVerbose(verbose);
|
|
41
|
+
await removeSignature(outputPath, platform);
|
|
42
|
+
|
|
43
|
+
// Apply rcedit changes (Windows only, before postject)
|
|
44
|
+
if (platform === 'win32' && rceditOptions && typeof rceditOptions === 'object') {
|
|
45
|
+
await applyRcedit(outputPath, rceditOptions, verbose);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Prepare postject command
|
|
49
|
+
const sentinel = 'NODE_SEA_BLOB';
|
|
50
|
+
const sentinelFuse = 'NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2';
|
|
51
|
+
|
|
52
|
+
diag.verbose(`Injecting SEA blob into: ${outputPath}`, 1);
|
|
53
|
+
|
|
54
|
+
// Use postject programmatically
|
|
55
|
+
const postject = (await import('postject')).default;
|
|
56
|
+
|
|
57
|
+
// Read blob data as buffer
|
|
58
|
+
const blobData = fs.readFileSync(blobPath);
|
|
59
|
+
|
|
60
|
+
const injectOptions = {
|
|
61
|
+
sentinelFuse,
|
|
62
|
+
machoSegmentName: platform === 'darwin' ? 'NODE_SEA' : undefined
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
await postject.inject(outputPath, sentinel, blobData, injectOptions);
|
|
67
|
+
diag.verbose('SEA blob injected successfully', 2);
|
|
68
|
+
} catch (error) {
|
|
69
|
+
throw new Error(`Postject injection failed: ${error.message}`);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Apply rcedit to modify Windows executable resources.
|
|
75
|
+
* @param {string} exePath - Path to the executable
|
|
76
|
+
* @param {Object} options - rcedit options (icon, version-string, file-version, product-version, etc.)
|
|
77
|
+
* @param {boolean} verbose - Enable verbose logging
|
|
78
|
+
* @returns {Promise<void>}
|
|
79
|
+
*/
|
|
80
|
+
async function applyRcedit(exePath, options, verbose) {
|
|
81
|
+
diag.verbose('Applying rcedit to modify executable resources...', 2);
|
|
82
|
+
diag.verbose(`Options: ${JSON.stringify(options, null, 2)}`, 2);
|
|
83
|
+
|
|
84
|
+
// Dynamic import for rcedit (it's CommonJS)
|
|
85
|
+
const rcedit = (await import('rcedit')).default;
|
|
86
|
+
|
|
87
|
+
try {
|
|
88
|
+
await rcedit(exePath, options);
|
|
89
|
+
diag.verbose('rcedit applied successfully', 2);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw new Error(`rcedit failed: ${error.message}`);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { applyRcedit };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* manifest.
|
|
2
|
+
* manifest.mjs
|
|
3
3
|
* Generate runtime manifest with asset metadata and extraction rules.
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
|
|
6
|
+
import path from 'path';
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
9
|
* @typedef {Object} BinaryManifestEntry
|
|
@@ -28,13 +28,13 @@ const path = require('path');
|
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
30
|
* Generate a runtime manifest from scanned assets.
|
|
31
|
-
* @param {
|
|
31
|
+
* @param {Array} assets - All scanned assets
|
|
32
32
|
* @param {Object} config - SEA configuration
|
|
33
33
|
* @param {string} targetPlatform - Target platform (win32, linux, darwin)
|
|
34
34
|
* @param {string} targetArch - Target architecture (x64, arm64)
|
|
35
35
|
* @returns {RuntimeManifest}
|
|
36
36
|
*/
|
|
37
|
-
function generateManifest(assets, config, targetPlatform, targetArch) {
|
|
37
|
+
export function generateManifest(assets, config, targetPlatform, targetArch) {
|
|
38
38
|
const binaries = assets
|
|
39
39
|
.filter(a => a.isBinary)
|
|
40
40
|
.map((asset, index) => {
|
|
@@ -95,12 +95,6 @@ function inferExtractionOrder(fileName, fallbackIndex) {
|
|
|
95
95
|
* @param {RuntimeManifest} manifest
|
|
96
96
|
* @returns {string}
|
|
97
97
|
*/
|
|
98
|
-
function serializeManifest(manifest) {
|
|
98
|
+
export function serializeManifest(manifest) {
|
|
99
99
|
return JSON.stringify(manifest, null, 2);
|
|
100
100
|
}
|
|
101
|
-
|
|
102
|
-
module.exports = {
|
|
103
|
-
generateManifest,
|
|
104
|
-
inferExtractionOrder,
|
|
105
|
-
serializeManifest
|
|
106
|
-
};
|