seabox 0.1.2 → 0.2.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/.mocharc.json +6 -6
- package/LICENSE.MD +21 -21
- package/README.md +310 -310
- package/bin/seabox-rebuild.mjs +88 -88
- package/bin/seabox.mjs +150 -147
- package/lib/blob.mjs +104 -104
- package/lib/bootstrap.cjs +756 -756
- package/lib/build-cache.mjs +199 -199
- package/lib/build.mjs +77 -77
- package/lib/config.mjs +243 -243
- package/lib/crypto-assets.mjs +125 -125
- package/lib/diagnostics.mjs +203 -203
- package/lib/entry-bundler.mjs +64 -64
- package/lib/fetch-node.mjs +172 -172
- package/lib/index.mjs +26 -26
- package/lib/inject.mjs +106 -106
- package/lib/manifest.mjs +100 -100
- package/lib/multi-target-builder.mjs +697 -697
- package/lib/native-scanner.mjs +203 -203
- package/lib/obfuscate.mjs +51 -51
- package/lib/require-shim.mjs +113 -113
- package/lib/rolldown-bundler.mjs +411 -411
- package/lib/unsign.cjs +197 -169
- package/package.json +61 -61
package/README.md
CHANGED
|
@@ -1,310 +1,310 @@
|
|
|
1
|
-
# seabox
|
|
2
|
-
|
|
3
|
-
A reusable tool for building Node.js Single Executable Applications (SEA) with native-module support and binary extraction.
|
|
4
|
-
|
|
5
|
-
## Features
|
|
6
|
-
|
|
7
|
-
- Bundle Node.js applications into standalone executables
|
|
8
|
-
- **Automatic asset detection** from `path.join(__dirname, ...)` patterns
|
|
9
|
-
- **Automatic native module detection** (.node files) with pattern transforms
|
|
10
|
-
- Platform-specific library extraction (DLLs, shared libraries)
|
|
11
|
-
- Asset encryption with obfuscated keys
|
|
12
|
-
- Multi-platform targeting (Windows, Linux, macOS)
|
|
13
|
-
- V8 snapshot support for faster startup
|
|
14
|
-
- Integrity checking for extracted binaries
|
|
15
|
-
- Automatic code signature removal before injection
|
|
16
|
-
|
|
17
|
-
## Use case
|
|
18
|
-
This tooling was created as an alternative to pkg, which is unfortunatly deprecated, and where forks were running foul of virus checkers. By using node's SEA, the executables are directly downloaded from nodejs's distribution source, and built using node's native Single Executable Application solution. Unfortunatly this does mean native modules embedded within the exe cannot run directly and must be extracted to a location on the disk on first run - This tooling automates that process for you, while providing arbitrary asset embedding. Embedded assets are _not_ extracted and access to them is handled by intercepting require and fs.
|
|
19
|
-
|
|
20
|
-
Note: **V8 snapshot includes and embedds the original source**, this is currently a limitation of Node's SEA tooling as far as I can tell; thus the snapshot is only useful for faster startup. Its possible to get around this by using bytenode's vm.script hack (embed the bytenode code as an asset and run another vm snapshot with the faux script input) and I'll look into supporting it in the future.
|
|
21
|
-
|
|
22
|
-
## Installation
|
|
23
|
-
|
|
24
|
-
```bash
|
|
25
|
-
npm install --save-dev seabox
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
### Optional: Windows Executable Metadata
|
|
29
|
-
|
|
30
|
-
If you want to customize Windows executable metadata (icon, version info), install `rcedit`:
|
|
31
|
-
|
|
32
|
-
```bash
|
|
33
|
-
npm install --save-dev rcedit
|
|
34
|
-
```
|
|
35
|
-
|
|
36
|
-
This is only needed if you use the `rcedit` configuration option.
|
|
37
|
-
|
|
38
|
-
## Configuration
|
|
39
|
-
|
|
40
|
-
Create a `seabox.config.json` file in your project root:
|
|
41
|
-
|
|
42
|
-
```json
|
|
43
|
-
{
|
|
44
|
-
"entry": "./src/index.js",
|
|
45
|
-
"outputs": [
|
|
46
|
-
{
|
|
47
|
-
"path": "./dist/win",
|
|
48
|
-
"target": "node24.11.0-win32-x64",
|
|
49
|
-
"output": "myapp.exe"
|
|
50
|
-
}
|
|
51
|
-
],
|
|
52
|
-
"bundler": {
|
|
53
|
-
"external": []
|
|
54
|
-
},
|
|
55
|
-
"encryptAssets": false,
|
|
56
|
-
"useSnapshot": true,
|
|
57
|
-
"verbose": false
|
|
58
|
-
}
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Configuration Options
|
|
62
|
-
|
|
63
|
-
| Option | Type | Required | Description |
|
|
64
|
-
|--------|------|----------|-------------|
|
|
65
|
-
| `entry` | `string` | Yes | Path to your application's entry point |
|
|
66
|
-
| `outputs` | `array` | Yes | Array of build targets |
|
|
67
|
-
| `outputs[].path` | `string` | Yes | Output directory for this target |
|
|
68
|
-
| `outputs[].target` | `string` | Yes | Build target (format: `nodeX.Y.Z-platform-arch`) |
|
|
69
|
-
| `outputs[].output` | `string` | Yes | Output filename |
|
|
70
|
-
| `outputs[].libraries` | `array` | No | Explicit glob patterns for shared libraries (DLLs/SOs) requiring filesystem extraction. Libraries referenced in code via `, ...)` are automatically detected. |
|
|
71
|
-
| `outputs[].rcedit` | `object` | No | Windows executable metadata (icon, version info) |
|
|
72
|
-
| `assets` | `array` | No | Glob patterns for assets to embed (merged with auto-detected assets) |
|
|
73
|
-
| `bundler` | `object` | No | Rolldown Bundler options |
|
|
74
|
-
| `bundler.external` | `array` | No | Modules to exclude from bundling |
|
|
75
|
-
| `bundler.plugins` | `array` | No | Additional Rolldown plugins |
|
|
76
|
-
| `bundler.minify` | `boolean` | No | Minify bundled code |
|
|
77
|
-
| `bundler.sourcemap` | `boolean` | No | Generate source maps |
|
|
78
|
-
| `encryptAssets` | `boolean` | No | Enable asset encryption (default: false) |
|
|
79
|
-
| `encryptExclude` | `array` | No | Glob patterns to exclude from encryption |
|
|
80
|
-
| `useSnapshot` | `boolean` | No | Enable V8 startup snapshots (default: true) |
|
|
81
|
-
| `useCodeCache` | `boolean` | No | Enable V8 code cache (default: false) |
|
|
82
|
-
| `cacheLocation` | `string` | No | Path for code cache storage |
|
|
83
|
-
| `sign` | `string` | No | Path to custom signing script (.mjs/.cjs) |
|
|
84
|
-
| `verbose` | `boolean` | No | Enable verbose logging (default: false) |
|
|
85
|
-
|
|
86
|
-
## Usage
|
|
87
|
-
|
|
88
|
-
### CLI Commands
|
|
89
|
-
|
|
90
|
-
```bash
|
|
91
|
-
# Build executable(s)
|
|
92
|
-
npx seabox build
|
|
93
|
-
|
|
94
|
-
# Build with verbose output
|
|
95
|
-
npx seabox build --verbose
|
|
96
|
-
|
|
97
|
-
# Specify custom config file
|
|
98
|
-
npx seabox build --config custom-config.json
|
|
99
|
-
|
|
100
|
-
# Initialize a new config file
|
|
101
|
-
npx seabox init
|
|
102
|
-
|
|
103
|
-
# Show help
|
|
104
|
-
npx seabox help
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
### npm Scripts (Recommended)
|
|
108
|
-
|
|
109
|
-
Add to your `package.json`:
|
|
110
|
-
|
|
111
|
-
```json
|
|
112
|
-
{
|
|
113
|
-
"scripts": {
|
|
114
|
-
"build": "seabox build",
|
|
115
|
-
"build:verbose": "seabox build --verbose"
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
```
|
|
119
|
-
|
|
120
|
-
Then run:
|
|
121
|
-
|
|
122
|
-
```bash
|
|
123
|
-
npm run build
|
|
124
|
-
```
|
|
125
|
-
|
|
126
|
-
### Programmatic API
|
|
127
|
-
|
|
128
|
-
```javascript
|
|
129
|
-
import { build } from 'seabox';
|
|
130
|
-
|
|
131
|
-
await build({
|
|
132
|
-
projectRoot: process.cwd(),
|
|
133
|
-
verbose: true
|
|
134
|
-
});
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
## How It Works
|
|
138
|
-
|
|
139
|
-
seabox automates the entire SEA build process:
|
|
140
|
-
|
|
141
|
-
1. **Bundling** - Automatically bundles your app with Rolldown, detecting:
|
|
142
|
-
- Native module patterns (`bindings`, `node-gyp-build`, direct `.node` requires)
|
|
143
|
-
- Asset references via `path.join(__dirname, 'relative/path')`
|
|
144
|
-
- Additional
|
|
145
|
-
|
|
146
|
-
2. **Asset Collection** - Gathers assets from three sources:
|
|
147
|
-
- **Auto-detected**: Files referenced via `path.join(__dirname, ...)` patterns
|
|
148
|
-
- **Config globs**: Patterns specified in `assets` array
|
|
149
|
-
- **Libraries**: Platform-specific shared libraries (DLLs/SOs)
|
|
150
|
-
|
|
151
|
-
3. **Native Module Rebuilding** - Rebuilds native modules for target platform
|
|
152
|
-
|
|
153
|
-
4. **Bootstrap Injection** - Adds runtime code for asset loading and native module extraction
|
|
154
|
-
|
|
155
|
-
5. **SEA Blob Creation** - Packages everything using Node.js SEA tooling
|
|
156
|
-
|
|
157
|
-
6. **Binary Preparation** - Downloads target Node.js binary and removes code signature
|
|
158
|
-
|
|
159
|
-
7. **Injection** - Uses `postject` to inject the blob into the Node.js binary
|
|
160
|
-
|
|
161
|
-
8. **Output** - Produces standalone executable(s) ready for distribution
|
|
162
|
-
|
|
163
|
-
### Automatic Asset Detection
|
|
164
|
-
|
|
165
|
-
**Like pkg**, seabox automatically detects and embeds assets referenced in your code:
|
|
166
|
-
|
|
167
|
-
```javascript
|
|
168
|
-
import path from 'path';
|
|
169
|
-
import { fileURLToPath } from 'url';
|
|
170
|
-
|
|
171
|
-
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
172
|
-
|
|
173
|
-
// This asset will be automatically detected and embedded
|
|
174
|
-
const configPath = path.join(__dirname, '../config/app.json');
|
|
175
|
-
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
**Asset sources (merged and deduplicated):**
|
|
179
|
-
1. **Auto-detected** from code analysis during bundling
|
|
180
|
-
2. **Config globs** from `assets: ["./data/**/*", "./public/**/*"]`
|
|
181
|
-
3. **Platform libraries** from `outputs[].libraries` (e.g., DLLs for Windows)
|
|
182
|
-
|
|
183
|
-
### Native Module Support
|
|
184
|
-
|
|
185
|
-
seabox automatically handles native modules without any configuration:
|
|
186
|
-
|
|
187
|
-
**Supported patterns:**
|
|
188
|
-
- `require('bindings')('module')` - Standard bindings package
|
|
189
|
-
- `require('./build/Release/addon.node')` - Direct requires
|
|
190
|
-
- `require('node-gyp-build')(__dirname)` - Prebuild binaries
|
|
191
|
-
- `require('node-pre-gyp')` patterns - Pre-compiled binaries
|
|
192
|
-
|
|
193
|
-
**At runtime:**
|
|
194
|
-
- Native modules are extracted to a cache directory on first run
|
|
195
|
-
- Modules are integrity-checked with SHA-256 hashes
|
|
196
|
-
- Custom `require()` shim loads modules from cache
|
|
197
|
-
|
|
198
|
-
### Platform-Specific Libraries
|
|
199
|
-
|
|
200
|
-
Libraries that require filesystem access (like DLLs loaded via `dlopen`) can be included in two ways:
|
|
201
|
-
|
|
202
|
-
**1. Automatic Detection (Recommended)**
|
|
203
|
-
|
|
204
|
-
If your code references a DLL using `path.join(__dirname, ...)`, it will be automatically detected and included:
|
|
205
|
-
|
|
206
|
-
```javascript
|
|
207
|
-
// This will be automatically detected during bundling
|
|
208
|
-
const dllPath = path.join(__dirname, './lib/RGDevice.dll');
|
|
209
|
-
```
|
|
210
|
-
|
|
211
|
-
**2. Explicit Glob Patterns**
|
|
212
|
-
|
|
213
|
-
You can also explicitly specify library patterns in your config:
|
|
214
|
-
|
|
215
|
-
```json
|
|
216
|
-
{
|
|
217
|
-
"outputs": [
|
|
218
|
-
{
|
|
219
|
-
"target": "node24.11.0-win32-x64",
|
|
220
|
-
"libraries": ["lib/*.dll"] // Manually specify DLLs to include
|
|
221
|
-
}
|
|
222
|
-
]
|
|
223
|
-
}
|
|
224
|
-
```
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
These files are extracted on first run (like `.node` files) since they need to be loaded from the filesystem.
|
|
228
|
-
|
|
229
|
-
### Code Signature Removal
|
|
230
|
-
If you have sign tools available, the seabox will attempt to unsign the node exe before modifying it. This is to reduce issues afterward when you try to resign it.
|
|
231
|
-
- **Windows**: `signtool.exe` (from Windows SDK)
|
|
232
|
-
- **macOS**: `codesign` (included with Xcode)
|
|
233
|
-
- **Linux**: Not required
|
|
234
|
-
|
|
235
|
-
### Custom Signing
|
|
236
|
-
|
|
237
|
-
You can apply code signing after the build completes by specifying a custom signing script:
|
|
238
|
-
|
|
239
|
-
```json
|
|
240
|
-
{
|
|
241
|
-
"sign": "./scripts/sign.mjs"
|
|
242
|
-
}
|
|
243
|
-
```
|
|
244
|
-
|
|
245
|
-
The signing script must export a default function that receives a config object:
|
|
246
|
-
|
|
247
|
-
```javascript
|
|
248
|
-
// scripts/sign.mjs
|
|
249
|
-
export default async function sign(config) {
|
|
250
|
-
const { exePath, target, platform, arch, nodeVersion, projectRoot } = config;
|
|
251
|
-
|
|
252
|
-
// Example: Windows code signing with signtool
|
|
253
|
-
if (platform === 'win32') {
|
|
254
|
-
execSync(`signtool sign /fd SHA256 /a "${exePath}"`);
|
|
255
|
-
}
|
|
256
|
-
|
|
257
|
-
// Example: macOS code signing
|
|
258
|
-
if (platform === 'darwin') {
|
|
259
|
-
execSync(`codesign --force --sign "Developer ID" "${exePath}"`);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
```
|
|
263
|
-
|
|
264
|
-
**Config parameters:**
|
|
265
|
-
- `exePath` - Absolute path to the built executable
|
|
266
|
-
- `target` - Full target string (e.g., "node24.11.0-win32-x64")
|
|
267
|
-
- `platform` - Platform name (win32, linux, darwin)
|
|
268
|
-
- `arch` - Architecture (x64, arm64)
|
|
269
|
-
- `nodeVersion` - Node.js version
|
|
270
|
-
- `projectRoot` - Absolute path to project root
|
|
271
|
-
|
|
272
|
-
## Asset Encryption
|
|
273
|
-
|
|
274
|
-
seabox supports optional AES-256-GCM encryption of embedded assets to protect your application code and data:
|
|
275
|
-
|
|
276
|
-
```json
|
|
277
|
-
{
|
|
278
|
-
"sea": {
|
|
279
|
-
"encryptAssets": true,
|
|
280
|
-
"encryptExclude": ["*.txt", "public/*"],
|
|
281
|
-
"useSnapshot": true
|
|
282
|
-
}
|
|
283
|
-
}
|
|
284
|
-
```
|
|
285
|
-
|
|
286
|
-
### How Encryption Works
|
|
287
|
-
|
|
288
|
-
1. **Build Time**: A random 256-bit encryption key is generated
|
|
289
|
-
2. **Asset Encryption**: Non-binary assets are encrypted using AES-256-GCM
|
|
290
|
-
3. **Key Embedding**: The encryption key is obfuscated and embedded in the bootstrap code
|
|
291
|
-
4. **Key Obfuscation**: the bootstrap and key code are obfuscated
|
|
292
|
-
5. **Runtime Decryption**: Assets are transparently decrypted when accessed
|
|
293
|
-
|
|
294
|
-
### Considerations
|
|
295
|
-
|
|
296
|
-
- **Binary files** (`.node`, `.dll`, `.so`, `.dylib`) are **never encrypted** as they must be extracted as-is
|
|
297
|
-
- The manifest (`sea-manifest.json`) is **not encrypted** to allow bootstrap initialization
|
|
298
|
-
- **V8 snapshot includes the original source**, this is currently a limitation of Node's SEA tooling.
|
|
299
|
-
- Encryption provides **obfuscation**, not cryptographic security against determined attackers
|
|
300
|
-
- The bootloader code, that includes the encryption key, is obfuscated in the source embedded by Node's SEA
|
|
301
|
-
|
|
302
|
-
## Contributing
|
|
303
|
-
|
|
304
|
-
Contributions welcome! Please open an issue or PR on [GitHub](https://github.com/MeirionHughes/seabox).
|
|
305
|
-
|
|
306
|
-
## License
|
|
307
|
-
|
|
308
|
-
MIT
|
|
309
|
-
|
|
310
|
-
Copyright © 2025 Meirion Hughes
|
|
1
|
+
# seabox
|
|
2
|
+
|
|
3
|
+
A reusable tool for building Node.js Single Executable Applications (SEA) with native-module support and binary extraction.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
- Bundle Node.js applications into standalone executables
|
|
8
|
+
- **Automatic asset detection** from `path.join(__dirname, ...)` patterns
|
|
9
|
+
- **Automatic native module detection** (.node files) with pattern transforms
|
|
10
|
+
- Platform-specific library extraction (DLLs, shared libraries)
|
|
11
|
+
- Asset encryption with obfuscated keys
|
|
12
|
+
- Multi-platform targeting (Windows, Linux, macOS)
|
|
13
|
+
- V8 snapshot support for faster startup
|
|
14
|
+
- Integrity checking for extracted binaries
|
|
15
|
+
- Automatic code signature removal before injection
|
|
16
|
+
|
|
17
|
+
## Use case
|
|
18
|
+
This tooling was created as an alternative to pkg, which is unfortunatly deprecated, and where forks were running foul of virus checkers. By using node's SEA, the executables are directly downloaded from nodejs's distribution source, and built using node's native Single Executable Application solution. Unfortunatly this does mean native modules embedded within the exe cannot run directly and must be extracted to a location on the disk on first run - This tooling automates that process for you, while providing arbitrary asset embedding. Embedded assets are _not_ extracted and access to them is handled by intercepting require and fs.
|
|
19
|
+
|
|
20
|
+
Note: **V8 snapshot includes and embedds the original source**, this is currently a limitation of Node's SEA tooling as far as I can tell; thus the snapshot is only useful for faster startup. Its possible to get around this by using bytenode's vm.script hack (embed the bytenode code as an asset and run another vm snapshot with the faux script input) and I'll look into supporting it in the future.
|
|
21
|
+
|
|
22
|
+
## Installation
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install --save-dev seabox
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### Optional: Windows Executable Metadata
|
|
29
|
+
|
|
30
|
+
If you want to customize Windows executable metadata (icon, version info), install `rcedit`:
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
npm install --save-dev rcedit
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This is only needed if you use the `rcedit` configuration option.
|
|
37
|
+
|
|
38
|
+
## Configuration
|
|
39
|
+
|
|
40
|
+
Create a `seabox.config.json` file in your project root:
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"entry": "./src/index.js",
|
|
45
|
+
"outputs": [
|
|
46
|
+
{
|
|
47
|
+
"path": "./dist/win",
|
|
48
|
+
"target": "node24.11.0-win32-x64",
|
|
49
|
+
"output": "myapp.exe"
|
|
50
|
+
}
|
|
51
|
+
],
|
|
52
|
+
"bundler": {
|
|
53
|
+
"external": []
|
|
54
|
+
},
|
|
55
|
+
"encryptAssets": false,
|
|
56
|
+
"useSnapshot": true,
|
|
57
|
+
"verbose": false
|
|
58
|
+
}
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Configuration Options
|
|
62
|
+
|
|
63
|
+
| Option | Type | Required | Description |
|
|
64
|
+
|--------|------|----------|-------------|
|
|
65
|
+
| `entry` | `string` | Yes | Path to your application's entry point |
|
|
66
|
+
| `outputs` | `array` | Yes | Array of build targets |
|
|
67
|
+
| `outputs[].path` | `string` | Yes | Output directory for this target |
|
|
68
|
+
| `outputs[].target` | `string` | Yes | Build target (format: `nodeX.Y.Z-platform-arch`) |
|
|
69
|
+
| `outputs[].output` | `string` | Yes | Output filename |
|
|
70
|
+
| `outputs[].libraries` | `array` | No | Explicit glob patterns for shared libraries (DLLs/SOs) requiring filesystem extraction. Libraries referenced in code via `, ...)` are automatically detected. |
|
|
71
|
+
| `outputs[].rcedit` | `object` | No | Windows executable metadata (icon, version info) |
|
|
72
|
+
| `assets` | `array` | No | Glob patterns for assets to embed (merged with auto-detected assets) |
|
|
73
|
+
| `bundler` | `object` | No | Rolldown Bundler options |
|
|
74
|
+
| `bundler.external` | `array` | No | Modules to exclude from bundling |
|
|
75
|
+
| `bundler.plugins` | `array` | No | Additional Rolldown plugins |
|
|
76
|
+
| `bundler.minify` | `boolean` | No | Minify bundled code |
|
|
77
|
+
| `bundler.sourcemap` | `boolean` | No | Generate source maps |
|
|
78
|
+
| `encryptAssets` | `boolean` | No | Enable asset encryption (default: false) |
|
|
79
|
+
| `encryptExclude` | `array` | No | Glob patterns to exclude from encryption |
|
|
80
|
+
| `useSnapshot` | `boolean` | No | Enable V8 startup snapshots (default: true) |
|
|
81
|
+
| `useCodeCache` | `boolean` | No | Enable V8 code cache (default: false) |
|
|
82
|
+
| `cacheLocation` | `string` | No | Path for code cache storage |
|
|
83
|
+
| `sign` | `string` | No | Path to custom signing script (.mjs/.cjs) |
|
|
84
|
+
| `verbose` | `boolean` | No | Enable verbose logging (default: false) |
|
|
85
|
+
|
|
86
|
+
## Usage
|
|
87
|
+
|
|
88
|
+
### CLI Commands
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
# Build executable(s)
|
|
92
|
+
npx seabox build
|
|
93
|
+
|
|
94
|
+
# Build with verbose output
|
|
95
|
+
npx seabox build --verbose
|
|
96
|
+
|
|
97
|
+
# Specify custom config file
|
|
98
|
+
npx seabox build --config custom-config.json
|
|
99
|
+
|
|
100
|
+
# Initialize a new config file
|
|
101
|
+
npx seabox init
|
|
102
|
+
|
|
103
|
+
# Show help
|
|
104
|
+
npx seabox help
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
### npm Scripts (Recommended)
|
|
108
|
+
|
|
109
|
+
Add to your `package.json`:
|
|
110
|
+
|
|
111
|
+
```json
|
|
112
|
+
{
|
|
113
|
+
"scripts": {
|
|
114
|
+
"build": "seabox build",
|
|
115
|
+
"build:verbose": "seabox build --verbose"
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
Then run:
|
|
121
|
+
|
|
122
|
+
```bash
|
|
123
|
+
npm run build
|
|
124
|
+
```
|
|
125
|
+
|
|
126
|
+
### Programmatic API
|
|
127
|
+
|
|
128
|
+
```javascript
|
|
129
|
+
import { build } from 'seabox';
|
|
130
|
+
|
|
131
|
+
await build({
|
|
132
|
+
projectRoot: process.cwd(),
|
|
133
|
+
verbose: true
|
|
134
|
+
});
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## How It Works
|
|
138
|
+
|
|
139
|
+
seabox automates the entire SEA build process:
|
|
140
|
+
|
|
141
|
+
1. **Bundling** - Automatically bundles your app with Rolldown, detecting:
|
|
142
|
+
- Native module patterns (`bindings`, `node-gyp-build`, direct `.node` requires)
|
|
143
|
+
- Asset references via `path.join(__dirname, 'relative/path')`
|
|
144
|
+
- Additional
|
|
145
|
+
|
|
146
|
+
2. **Asset Collection** - Gathers assets from three sources:
|
|
147
|
+
- **Auto-detected**: Files referenced via `path.join(__dirname, ...)` patterns
|
|
148
|
+
- **Config globs**: Patterns specified in `assets` array
|
|
149
|
+
- **Libraries**: Platform-specific shared libraries (DLLs/SOs)
|
|
150
|
+
|
|
151
|
+
3. **Native Module Rebuilding** - Rebuilds native modules for target platform
|
|
152
|
+
|
|
153
|
+
4. **Bootstrap Injection** - Adds runtime code for asset loading and native module extraction
|
|
154
|
+
|
|
155
|
+
5. **SEA Blob Creation** - Packages everything using Node.js SEA tooling
|
|
156
|
+
|
|
157
|
+
6. **Binary Preparation** - Downloads target Node.js binary and removes code signature
|
|
158
|
+
|
|
159
|
+
7. **Injection** - Uses `postject` to inject the blob into the Node.js binary
|
|
160
|
+
|
|
161
|
+
8. **Output** - Produces standalone executable(s) ready for distribution
|
|
162
|
+
|
|
163
|
+
### Automatic Asset Detection
|
|
164
|
+
|
|
165
|
+
**Like pkg**, seabox automatically detects and embeds assets referenced in your code:
|
|
166
|
+
|
|
167
|
+
```javascript
|
|
168
|
+
import path from 'path';
|
|
169
|
+
import { fileURLToPath } from 'url';
|
|
170
|
+
|
|
171
|
+
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
172
|
+
|
|
173
|
+
// This asset will be automatically detected and embedded
|
|
174
|
+
const configPath = path.join(__dirname, '../config/app.json');
|
|
175
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
**Asset sources (merged and deduplicated):**
|
|
179
|
+
1. **Auto-detected** from code analysis during bundling
|
|
180
|
+
2. **Config globs** from `assets: ["./data/**/*", "./public/**/*"]`
|
|
181
|
+
3. **Platform libraries** from `outputs[].libraries` (e.g., DLLs for Windows)
|
|
182
|
+
|
|
183
|
+
### Native Module Support
|
|
184
|
+
|
|
185
|
+
seabox automatically handles native modules without any configuration:
|
|
186
|
+
|
|
187
|
+
**Supported patterns:**
|
|
188
|
+
- `require('bindings')('module')` - Standard bindings package
|
|
189
|
+
- `require('./build/Release/addon.node')` - Direct requires
|
|
190
|
+
- `require('node-gyp-build')(__dirname)` - Prebuild binaries
|
|
191
|
+
- `require('node-pre-gyp')` patterns - Pre-compiled binaries
|
|
192
|
+
|
|
193
|
+
**At runtime:**
|
|
194
|
+
- Native modules are extracted to a cache directory on first run
|
|
195
|
+
- Modules are integrity-checked with SHA-256 hashes
|
|
196
|
+
- Custom `require()` shim loads modules from cache
|
|
197
|
+
|
|
198
|
+
### Platform-Specific Libraries
|
|
199
|
+
|
|
200
|
+
Libraries that require filesystem access (like DLLs loaded via `dlopen`) can be included in two ways:
|
|
201
|
+
|
|
202
|
+
**1. Automatic Detection (Recommended)**
|
|
203
|
+
|
|
204
|
+
If your code references a DLL using `path.join(__dirname, ...)`, it will be automatically detected and included:
|
|
205
|
+
|
|
206
|
+
```javascript
|
|
207
|
+
// This will be automatically detected during bundling
|
|
208
|
+
const dllPath = path.join(__dirname, './lib/RGDevice.dll');
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
**2. Explicit Glob Patterns**
|
|
212
|
+
|
|
213
|
+
You can also explicitly specify library patterns in your config:
|
|
214
|
+
|
|
215
|
+
```json
|
|
216
|
+
{
|
|
217
|
+
"outputs": [
|
|
218
|
+
{
|
|
219
|
+
"target": "node24.11.0-win32-x64",
|
|
220
|
+
"libraries": ["lib/*.dll"] // Manually specify DLLs to include
|
|
221
|
+
}
|
|
222
|
+
]
|
|
223
|
+
}
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
|
|
227
|
+
These files are extracted on first run (like `.node` files) since they need to be loaded from the filesystem.
|
|
228
|
+
|
|
229
|
+
### Code Signature Removal
|
|
230
|
+
If you have sign tools available, the seabox will attempt to unsign the node exe before modifying it. This is to reduce issues afterward when you try to resign it.
|
|
231
|
+
- **Windows**: `signtool.exe` (from Windows SDK)
|
|
232
|
+
- **macOS**: `codesign` (included with Xcode)
|
|
233
|
+
- **Linux**: Not required
|
|
234
|
+
|
|
235
|
+
### Custom Signing
|
|
236
|
+
|
|
237
|
+
You can apply code signing after the build completes by specifying a custom signing script:
|
|
238
|
+
|
|
239
|
+
```json
|
|
240
|
+
{
|
|
241
|
+
"sign": "./scripts/sign.mjs"
|
|
242
|
+
}
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
The signing script must export a default function that receives a config object:
|
|
246
|
+
|
|
247
|
+
```javascript
|
|
248
|
+
// scripts/sign.mjs
|
|
249
|
+
export default async function sign(config) {
|
|
250
|
+
const { exePath, target, platform, arch, nodeVersion, projectRoot } = config;
|
|
251
|
+
|
|
252
|
+
// Example: Windows code signing with signtool
|
|
253
|
+
if (platform === 'win32') {
|
|
254
|
+
execSync(`signtool sign /fd SHA256 /a "${exePath}"`);
|
|
255
|
+
}
|
|
256
|
+
|
|
257
|
+
// Example: macOS code signing
|
|
258
|
+
if (platform === 'darwin') {
|
|
259
|
+
execSync(`codesign --force --sign "Developer ID" "${exePath}"`);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
**Config parameters:**
|
|
265
|
+
- `exePath` - Absolute path to the built executable
|
|
266
|
+
- `target` - Full target string (e.g., "node24.11.0-win32-x64")
|
|
267
|
+
- `platform` - Platform name (win32, linux, darwin)
|
|
268
|
+
- `arch` - Architecture (x64, arm64)
|
|
269
|
+
- `nodeVersion` - Node.js version
|
|
270
|
+
- `projectRoot` - Absolute path to project root
|
|
271
|
+
|
|
272
|
+
## Asset Encryption
|
|
273
|
+
|
|
274
|
+
seabox supports optional AES-256-GCM encryption of embedded assets to protect your application code and data:
|
|
275
|
+
|
|
276
|
+
```json
|
|
277
|
+
{
|
|
278
|
+
"sea": {
|
|
279
|
+
"encryptAssets": true,
|
|
280
|
+
"encryptExclude": ["*.txt", "public/*"],
|
|
281
|
+
"useSnapshot": true
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### How Encryption Works
|
|
287
|
+
|
|
288
|
+
1. **Build Time**: A random 256-bit encryption key is generated
|
|
289
|
+
2. **Asset Encryption**: Non-binary assets are encrypted using AES-256-GCM
|
|
290
|
+
3. **Key Embedding**: The encryption key is obfuscated and embedded in the bootstrap code
|
|
291
|
+
4. **Key Obfuscation**: the bootstrap and key code are obfuscated
|
|
292
|
+
5. **Runtime Decryption**: Assets are transparently decrypted when accessed
|
|
293
|
+
|
|
294
|
+
### Considerations
|
|
295
|
+
|
|
296
|
+
- **Binary files** (`.node`, `.dll`, `.so`, `.dylib`) are **never encrypted** as they must be extracted as-is
|
|
297
|
+
- The manifest (`sea-manifest.json`) is **not encrypted** to allow bootstrap initialization
|
|
298
|
+
- **V8 snapshot includes the original source**, this is currently a limitation of Node's SEA tooling.
|
|
299
|
+
- Encryption provides **obfuscation**, not cryptographic security against determined attackers
|
|
300
|
+
- The bootloader code, that includes the encryption key, is obfuscated in the source embedded by Node's SEA
|
|
301
|
+
|
|
302
|
+
## Contributing
|
|
303
|
+
|
|
304
|
+
Contributions welcome! Please open an issue or PR on [GitHub](https://github.com/MeirionHughes/seabox).
|
|
305
|
+
|
|
306
|
+
## License
|
|
307
|
+
|
|
308
|
+
MIT
|
|
309
|
+
|
|
310
|
+
Copyright © 2025 Meirion Hughes
|