nodejs-sea 1.0.1 → 1.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/README.md +2 -0
- package/lib/cli.js +74 -50
- package/lib/cli.mjs +57 -22
- package/lib/node-utils.d.ts +1 -1
- package/package.json +30 -26
package/README.md
CHANGED
|
@@ -67,7 +67,9 @@ Options:
|
|
|
67
67
|
-s, --sea-config Path of the sea config file [string] [default: "sea/config.json"]
|
|
68
68
|
-n, --node-version Node.js version [string] [default: "*"]
|
|
69
69
|
-c, --clean Remove generated files [boolean] [default: true]
|
|
70
|
+
-p, --platform Target platform (linux, darwin, win32) [string] [default: current platform]
|
|
70
71
|
--help Show help [boolean]
|
|
72
|
+
-e, --env-file Path to .env file [string] [default: .env]
|
|
71
73
|
```
|
|
72
74
|
|
|
73
75
|
## Example
|
package/lib/cli.js
CHANGED
|
@@ -5,6 +5,7 @@ var child_process = require('child_process');
|
|
|
5
5
|
var fs = require('fs');
|
|
6
6
|
var path = require('path');
|
|
7
7
|
var clipanion = require('clipanion');
|
|
8
|
+
var dotenv = require('dotenv');
|
|
8
9
|
var rimraf = require('rimraf');
|
|
9
10
|
var chalk = require('chalk');
|
|
10
11
|
var cliProgress = require('cli-progress');
|
|
@@ -16,17 +17,6 @@ var nv = require('@pkgjs/nv');
|
|
|
16
17
|
var tar = require('tar');
|
|
17
18
|
var undici = require('undici');
|
|
18
19
|
|
|
19
|
-
function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
|
|
20
|
-
|
|
21
|
-
var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
|
|
22
|
-
var path__default = /*#__PURE__*/_interopDefaultLegacy(path);
|
|
23
|
-
var chalk__default = /*#__PURE__*/_interopDefaultLegacy(chalk);
|
|
24
|
-
var cliProgress__default = /*#__PURE__*/_interopDefaultLegacy(cliProgress);
|
|
25
|
-
var crypto__default = /*#__PURE__*/_interopDefaultLegacy(crypto);
|
|
26
|
-
var zlib__default = /*#__PURE__*/_interopDefaultLegacy(zlib);
|
|
27
|
-
var nv__default = /*#__PURE__*/_interopDefaultLegacy(nv);
|
|
28
|
-
var tar__default = /*#__PURE__*/_interopDefaultLegacy(tar);
|
|
29
|
-
|
|
30
20
|
class LoggerImpl {
|
|
31
21
|
constructor() {
|
|
32
22
|
this.currentStep = "";
|
|
@@ -37,7 +27,7 @@ class LoggerImpl {
|
|
|
37
27
|
this.stepCompleted();
|
|
38
28
|
}
|
|
39
29
|
this.currentStep = info;
|
|
40
|
-
console.warn(`${
|
|
30
|
+
console.warn(`${chalk.yellow("→")} ${info} ...`);
|
|
41
31
|
}
|
|
42
32
|
_stepDone() {
|
|
43
33
|
this.currentStep = "";
|
|
@@ -49,14 +39,14 @@ class LoggerImpl {
|
|
|
49
39
|
stepCompleted() {
|
|
50
40
|
const doneText = this.currentStep;
|
|
51
41
|
this._stepDone();
|
|
52
|
-
console.warn(
|
|
42
|
+
console.warn(chalk.green(` ✓ Completed: ${doneText}`));
|
|
53
43
|
}
|
|
54
44
|
stepFailed(err) {
|
|
55
45
|
this._stepDone();
|
|
56
|
-
console.warn(
|
|
46
|
+
console.warn(chalk.red(` ✖ Failed: ${err.message}`));
|
|
57
47
|
}
|
|
58
48
|
startProgress(maximum) {
|
|
59
|
-
this.cliProgress = new
|
|
49
|
+
this.cliProgress = new cliProgress.SingleBar({}, cliProgress.Presets.shades_classic);
|
|
60
50
|
this.cliProgress.start(maximum, 0);
|
|
61
51
|
}
|
|
62
52
|
doProgress(current) {
|
|
@@ -68,7 +58,7 @@ class LoggerImpl {
|
|
|
68
58
|
|
|
69
59
|
class NodeUtils {
|
|
70
60
|
// Download and unpack a tarball containing the code for a specific Node.js version.
|
|
71
|
-
async getNodeSourceForVersion(range, dir, logger, retries = 2) {
|
|
61
|
+
async getNodeSourceForVersion(range, dir, logger, platform = "linux", retries = 2) {
|
|
72
62
|
var _a, _b;
|
|
73
63
|
logger.stepStarting(`Looking for Node.js version matching ${JSON.stringify(range)}`);
|
|
74
64
|
let inputIsFileUrl = false;
|
|
@@ -80,17 +70,17 @@ class NodeUtils {
|
|
|
80
70
|
}
|
|
81
71
|
if (inputIsFileUrl) {
|
|
82
72
|
logger.stepStarting(`Extracting tarball from ${range} to ${dir}`);
|
|
83
|
-
|
|
84
|
-
await promises.pipeline(fs.createReadStream(url.fileURLToPath(range)),
|
|
73
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
74
|
+
await promises.pipeline(fs.createReadStream(url.fileURLToPath(range)), zlib.createGunzip(), tar.x({
|
|
85
75
|
cwd: dir,
|
|
86
76
|
}));
|
|
87
77
|
logger.stepCompleted();
|
|
88
|
-
const filesInDir =
|
|
78
|
+
const filesInDir = fs.readdirSync(dir, { withFileTypes: true });
|
|
89
79
|
const dirsInDir = filesInDir.filter((f) => f.isDirectory());
|
|
90
80
|
if (dirsInDir.length !== 1) {
|
|
91
81
|
throw new Error("Node.js tarballs should contain exactly one directory");
|
|
92
82
|
}
|
|
93
|
-
return
|
|
83
|
+
return path.join(dir, dirsInDir[0].name);
|
|
94
84
|
}
|
|
95
85
|
let releaseBaseUrl;
|
|
96
86
|
let version;
|
|
@@ -99,20 +89,23 @@ class NodeUtils {
|
|
|
99
89
|
releaseBaseUrl = `https://nodejs.org/download/nightly/${version}`;
|
|
100
90
|
}
|
|
101
91
|
else {
|
|
102
|
-
const ver = (await
|
|
92
|
+
const ver = (await nv(range)).pop();
|
|
103
93
|
if (!ver) {
|
|
104
94
|
throw new Error(`No node version found for ${range}`);
|
|
105
95
|
}
|
|
106
96
|
version = `v${ver.version}`;
|
|
107
97
|
releaseBaseUrl = `https://nodejs.org/download/release/${version}`;
|
|
108
98
|
}
|
|
109
|
-
const
|
|
110
|
-
const
|
|
111
|
-
const
|
|
112
|
-
const
|
|
99
|
+
const nodePlatform = platform === "win32" ? "win" : platform;
|
|
100
|
+
const arch = "x64";
|
|
101
|
+
const ext = platform === "win32" ? "zip" : "tar.gz";
|
|
102
|
+
const cachedName = `node-${version}-${nodePlatform}-${arch}`;
|
|
103
|
+
const tarballName = `${cachedName}.${ext}`;
|
|
104
|
+
const cachedTarballPath = path.join(dir, tarballName);
|
|
105
|
+
const cachedNodePath = path.join(dir, cachedName, platform === "win32" ? "node.exe" : path.join("bin", "node"));
|
|
113
106
|
let hasCachedTarball = false;
|
|
114
107
|
try {
|
|
115
|
-
hasCachedTarball =
|
|
108
|
+
hasCachedTarball = fs.statSync(cachedTarballPath).size > 0;
|
|
116
109
|
}
|
|
117
110
|
catch { }
|
|
118
111
|
if (hasCachedTarball) {
|
|
@@ -136,7 +129,7 @@ class NodeUtils {
|
|
|
136
129
|
return null;
|
|
137
130
|
})(),
|
|
138
131
|
(async () => {
|
|
139
|
-
const hash =
|
|
132
|
+
const hash = crypto.createHash("sha256");
|
|
140
133
|
await promises.pipeline(fs.createReadStream(cachedTarballPath), hash);
|
|
141
134
|
return hash.digest("hex");
|
|
142
135
|
})(),
|
|
@@ -152,7 +145,7 @@ class NodeUtils {
|
|
|
152
145
|
let tarballStream;
|
|
153
146
|
let tarballWritePromise;
|
|
154
147
|
if (hasCachedTarball) {
|
|
155
|
-
const hasNodePath =
|
|
148
|
+
const hasNodePath = fs.statSync(cachedNodePath).size > 0;
|
|
156
149
|
if (hasNodePath) {
|
|
157
150
|
return cachedNodePath;
|
|
158
151
|
}
|
|
@@ -166,7 +159,7 @@ class NodeUtils {
|
|
|
166
159
|
throw new Error(`Could not download Node.js source tarball: ${tarball.statusCode}`);
|
|
167
160
|
}
|
|
168
161
|
logger.stepStarting(`Unpacking tarball to ${dir}`);
|
|
169
|
-
|
|
162
|
+
fs.mkdirSync(dir, { recursive: true });
|
|
170
163
|
const contentLength = +((_a = tarball.headers["content-length"]) !== null && _a !== void 0 ? _a : 0);
|
|
171
164
|
if (contentLength) {
|
|
172
165
|
logger.startProgress(contentLength);
|
|
@@ -181,21 +174,28 @@ class NodeUtils {
|
|
|
181
174
|
// unpack below in order not to lose any data.
|
|
182
175
|
tarballWritePromise = promises.pipeline(tarballStream, fs.createWriteStream(cachedTarballPath));
|
|
183
176
|
}
|
|
184
|
-
// Streaming unpack
|
|
185
|
-
// with the Node.js source tarball contents in it.
|
|
177
|
+
// Streaming unpack or unzip.
|
|
186
178
|
try {
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
})
|
|
191
|
-
|
|
192
|
-
|
|
179
|
+
if (ext === "zip") {
|
|
180
|
+
if (tarballWritePromise)
|
|
181
|
+
await tarballWritePromise;
|
|
182
|
+
logger.stepStarting(`Unzipping to ${dir}`);
|
|
183
|
+
child_process.execSync(`unzip -q -o "${cachedTarballPath}" -d "${dir}"`);
|
|
184
|
+
}
|
|
185
|
+
else {
|
|
186
|
+
await Promise.all([
|
|
187
|
+
promises.pipeline(tarballStream, zlib.createGunzip(), tar.x({
|
|
188
|
+
cwd: dir,
|
|
189
|
+
})),
|
|
190
|
+
tarballWritePromise,
|
|
191
|
+
]);
|
|
192
|
+
}
|
|
193
193
|
}
|
|
194
194
|
catch (err) {
|
|
195
195
|
if (retries > 0) {
|
|
196
196
|
logger.stepFailed(err);
|
|
197
197
|
logger.stepStarting("Re-trying");
|
|
198
|
-
return await this.getNodeSourceForVersion(range, dir, logger, retries - 1);
|
|
198
|
+
return await this.getNodeSourceForVersion(range, dir, logger, platform, retries - 1);
|
|
199
199
|
}
|
|
200
200
|
throw err;
|
|
201
201
|
}
|
|
@@ -212,12 +212,18 @@ class PackCommand extends clipanion.Command {
|
|
|
212
212
|
this.input = clipanion.Option.String(`-s,--sea-config`, {
|
|
213
213
|
description: `Path of the sea config file. Default is sea/config.json`,
|
|
214
214
|
});
|
|
215
|
+
this.envFile = clipanion.Option.String(`-e,--env-file`, {
|
|
216
|
+
description: `Path to .env file. Default is .env`,
|
|
217
|
+
});
|
|
215
218
|
this.nodeVersion = clipanion.Option.String(`-n,--node-version`, {
|
|
216
219
|
description: `Node.js version. Default is 22.11.0`,
|
|
217
220
|
});
|
|
218
221
|
this.clean = clipanion.Option.String(`-c,--clean`, {
|
|
219
222
|
description: `Remove generated files. Default is true`,
|
|
220
223
|
});
|
|
224
|
+
this.platform = clipanion.Option.String(`-p,--platform`, {
|
|
225
|
+
description: `Target platform (linux, darwin, win32). Default is current platform`,
|
|
226
|
+
});
|
|
221
227
|
}
|
|
222
228
|
/**
|
|
223
229
|
* run command
|
|
@@ -238,12 +244,12 @@ class PackCommand extends clipanion.Command {
|
|
|
238
244
|
throw new clipanion.UsageError(`Command failed`);
|
|
239
245
|
}
|
|
240
246
|
async execute() {
|
|
241
|
-
var _a, _b, _c, _d;
|
|
247
|
+
var _a, _b, _c, _d, _e, _f;
|
|
242
248
|
const logger = new LoggerImpl();
|
|
243
249
|
const nodeUtils = new NodeUtils();
|
|
244
|
-
const tmpdir =
|
|
250
|
+
const tmpdir = path.join(currentWorkingDirectory, "node_modules/.cache/nodejs-sea");
|
|
245
251
|
const configFilePath = (_a = this.input) !== null && _a !== void 0 ? _a : "sea/config.json";
|
|
246
|
-
const configContent =
|
|
252
|
+
const configContent = fs.readFileSync(configFilePath).toString();
|
|
247
253
|
const nodeVersion = (_b = this.nodeVersion) !== null && _b !== void 0 ? _b : "22.11.0";
|
|
248
254
|
let config;
|
|
249
255
|
try {
|
|
@@ -256,11 +262,13 @@ class PackCommand extends clipanion.Command {
|
|
|
256
262
|
const outputPath = config.output.split("/").slice(0, -1).join("/");
|
|
257
263
|
const copyFiles = (_c = config.copyFiles) !== null && _c !== void 0 ? _c : [];
|
|
258
264
|
const esbuildConfig = config.esbuild;
|
|
259
|
-
const
|
|
260
|
-
const
|
|
265
|
+
const platform = (_d = this.platform) !== null && _d !== void 0 ? _d : process.platform;
|
|
266
|
+
const nodeSourcePath = await nodeUtils.getNodeSourceForVersion(nodeVersion, tmpdir, logger, platform);
|
|
267
|
+
const executableName = platform === "win32" ? "app.exe" : "app";
|
|
268
|
+
const appPath = path.join(outputPath, executableName);
|
|
261
269
|
logger.stepStarting("Cleaning dist directory");
|
|
262
270
|
await rimraf.rimraf(outputPath, { glob: false });
|
|
263
|
-
|
|
271
|
+
fs.mkdirSync(outputPath, { recursive: true });
|
|
264
272
|
logger.stepCompleted();
|
|
265
273
|
if (Array.isArray(copyFiles) && copyFiles.length > 0) {
|
|
266
274
|
logger.stepStarting("Copy files");
|
|
@@ -270,29 +278,45 @@ class PackCommand extends clipanion.Command {
|
|
|
270
278
|
logger.stepCompleted();
|
|
271
279
|
}
|
|
272
280
|
if (esbuildConfig) {
|
|
273
|
-
|
|
281
|
+
// Load env file
|
|
282
|
+
const envFile = (_e = this.envFile) !== null && _e !== void 0 ? _e : ".env";
|
|
283
|
+
const envPath = path.resolve(currentWorkingDirectory, envFile);
|
|
284
|
+
if (fs.existsSync(envPath)) {
|
|
285
|
+
logger.stepStarting("Run esbuild - with env");
|
|
286
|
+
dotenv.config({ path: envPath });
|
|
287
|
+
esbuildConfig.define = {
|
|
288
|
+
...esbuildConfig.define,
|
|
289
|
+
...Object.fromEntries(Object.entries(process.env).map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)])),
|
|
290
|
+
};
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
logger.stepStarting("Run esbuild - without env");
|
|
294
|
+
}
|
|
274
295
|
await esbuild.build(esbuildConfig);
|
|
275
296
|
logger.stepCompleted();
|
|
276
297
|
}
|
|
277
298
|
logger.stepStarting("Inject to NodeJS Single Execute Application");
|
|
278
299
|
await this.execCommand("node", ["--experimental-sea-config", configFilePath]);
|
|
279
300
|
await this.execCommand("cp", [nodeSourcePath, appPath]);
|
|
280
|
-
|
|
281
|
-
"postject",
|
|
301
|
+
const postjectCommand = [
|
|
282
302
|
appPath,
|
|
283
303
|
"NODE_SEA_BLOB",
|
|
284
304
|
config.output,
|
|
285
305
|
"--sentinel-fuse",
|
|
286
306
|
"NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2",
|
|
287
|
-
]
|
|
307
|
+
];
|
|
308
|
+
if (platform === "darwin") {
|
|
309
|
+
postjectCommand.push("--macho-segment-name", "NODE_SEA");
|
|
310
|
+
}
|
|
311
|
+
await this.execCommand("postject", postjectCommand);
|
|
288
312
|
logger.stepCompleted();
|
|
289
313
|
// clear temp file
|
|
290
|
-
const clean = (
|
|
314
|
+
const clean = (_f = this.clean) !== null && _f !== void 0 ? _f : true;
|
|
291
315
|
if (clean) {
|
|
292
316
|
logger.stepStarting("Remove generated files");
|
|
293
317
|
const cleanFiles = [config.output];
|
|
294
318
|
if (esbuildConfig === null || esbuildConfig === void 0 ? void 0 : esbuildConfig.outfile) {
|
|
295
|
-
cleanFiles.push(
|
|
319
|
+
cleanFiles.push(path.resolve(currentWorkingDirectory, esbuildConfig.outfile));
|
|
296
320
|
}
|
|
297
321
|
await this.execCommand("rm", cleanFiles);
|
|
298
322
|
logger.stepCompleted();
|
package/lib/cli.mjs
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { spawn } from 'child_process';
|
|
2
|
+
import { execSync, spawn } from 'child_process';
|
|
3
3
|
import fs, { createReadStream, createWriteStream } from 'fs';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import { runExit, Command, Option, UsageError } from 'clipanion';
|
|
6
|
+
import dotenv from 'dotenv';
|
|
6
7
|
import { rimraf } from 'rimraf';
|
|
7
8
|
import chalk from 'chalk';
|
|
8
9
|
import cliProgress from 'cli-progress';
|
|
@@ -55,7 +56,7 @@ class LoggerImpl {
|
|
|
55
56
|
|
|
56
57
|
class NodeUtils {
|
|
57
58
|
// Download and unpack a tarball containing the code for a specific Node.js version.
|
|
58
|
-
async getNodeSourceForVersion(range, dir, logger, retries = 2) {
|
|
59
|
+
async getNodeSourceForVersion(range, dir, logger, platform = "linux", retries = 2) {
|
|
59
60
|
var _a, _b;
|
|
60
61
|
logger.stepStarting(`Looking for Node.js version matching ${JSON.stringify(range)}`);
|
|
61
62
|
let inputIsFileUrl = false;
|
|
@@ -93,10 +94,13 @@ class NodeUtils {
|
|
|
93
94
|
version = `v${ver.version}`;
|
|
94
95
|
releaseBaseUrl = `https://nodejs.org/download/release/${version}`;
|
|
95
96
|
}
|
|
96
|
-
const
|
|
97
|
-
const
|
|
97
|
+
const nodePlatform = platform === "win32" ? "win" : platform;
|
|
98
|
+
const arch = "x64";
|
|
99
|
+
const ext = platform === "win32" ? "zip" : "tar.gz";
|
|
100
|
+
const cachedName = `node-${version}-${nodePlatform}-${arch}`;
|
|
101
|
+
const tarballName = `${cachedName}.${ext}`;
|
|
98
102
|
const cachedTarballPath = path.join(dir, tarballName);
|
|
99
|
-
const cachedNodePath = path.join(dir, cachedName, "bin", "node");
|
|
103
|
+
const cachedNodePath = path.join(dir, cachedName, platform === "win32" ? "node.exe" : path.join("bin", "node"));
|
|
100
104
|
let hasCachedTarball = false;
|
|
101
105
|
try {
|
|
102
106
|
hasCachedTarball = fs.statSync(cachedTarballPath).size > 0;
|
|
@@ -168,21 +172,28 @@ class NodeUtils {
|
|
|
168
172
|
// unpack below in order not to lose any data.
|
|
169
173
|
tarballWritePromise = pipeline(tarballStream, createWriteStream(cachedTarballPath));
|
|
170
174
|
}
|
|
171
|
-
// Streaming unpack
|
|
172
|
-
// with the Node.js source tarball contents in it.
|
|
175
|
+
// Streaming unpack or unzip.
|
|
173
176
|
try {
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
})
|
|
178
|
-
|
|
179
|
-
|
|
177
|
+
if (ext === "zip") {
|
|
178
|
+
if (tarballWritePromise)
|
|
179
|
+
await tarballWritePromise;
|
|
180
|
+
logger.stepStarting(`Unzipping to ${dir}`);
|
|
181
|
+
execSync(`unzip -q -o "${cachedTarballPath}" -d "${dir}"`);
|
|
182
|
+
}
|
|
183
|
+
else {
|
|
184
|
+
await Promise.all([
|
|
185
|
+
pipeline(tarballStream, zlib.createGunzip(), tar.x({
|
|
186
|
+
cwd: dir,
|
|
187
|
+
})),
|
|
188
|
+
tarballWritePromise,
|
|
189
|
+
]);
|
|
190
|
+
}
|
|
180
191
|
}
|
|
181
192
|
catch (err) {
|
|
182
193
|
if (retries > 0) {
|
|
183
194
|
logger.stepFailed(err);
|
|
184
195
|
logger.stepStarting("Re-trying");
|
|
185
|
-
return await this.getNodeSourceForVersion(range, dir, logger, retries - 1);
|
|
196
|
+
return await this.getNodeSourceForVersion(range, dir, logger, platform, retries - 1);
|
|
186
197
|
}
|
|
187
198
|
throw err;
|
|
188
199
|
}
|
|
@@ -199,12 +210,18 @@ class PackCommand extends Command {
|
|
|
199
210
|
this.input = Option.String(`-s,--sea-config`, {
|
|
200
211
|
description: `Path of the sea config file. Default is sea/config.json`,
|
|
201
212
|
});
|
|
213
|
+
this.envFile = Option.String(`-e,--env-file`, {
|
|
214
|
+
description: `Path to .env file. Default is .env`,
|
|
215
|
+
});
|
|
202
216
|
this.nodeVersion = Option.String(`-n,--node-version`, {
|
|
203
217
|
description: `Node.js version. Default is 22.11.0`,
|
|
204
218
|
});
|
|
205
219
|
this.clean = Option.String(`-c,--clean`, {
|
|
206
220
|
description: `Remove generated files. Default is true`,
|
|
207
221
|
});
|
|
222
|
+
this.platform = Option.String(`-p,--platform`, {
|
|
223
|
+
description: `Target platform (linux, darwin, win32). Default is current platform`,
|
|
224
|
+
});
|
|
208
225
|
}
|
|
209
226
|
/**
|
|
210
227
|
* run command
|
|
@@ -225,7 +242,7 @@ class PackCommand extends Command {
|
|
|
225
242
|
throw new UsageError(`Command failed`);
|
|
226
243
|
}
|
|
227
244
|
async execute() {
|
|
228
|
-
var _a, _b, _c, _d;
|
|
245
|
+
var _a, _b, _c, _d, _e, _f;
|
|
229
246
|
const logger = new LoggerImpl();
|
|
230
247
|
const nodeUtils = new NodeUtils();
|
|
231
248
|
const tmpdir = path.join(currentWorkingDirectory, "node_modules/.cache/nodejs-sea");
|
|
@@ -243,8 +260,10 @@ class PackCommand extends Command {
|
|
|
243
260
|
const outputPath = config.output.split("/").slice(0, -1).join("/");
|
|
244
261
|
const copyFiles = (_c = config.copyFiles) !== null && _c !== void 0 ? _c : [];
|
|
245
262
|
const esbuildConfig = config.esbuild;
|
|
246
|
-
const
|
|
247
|
-
const
|
|
263
|
+
const platform = (_d = this.platform) !== null && _d !== void 0 ? _d : process.platform;
|
|
264
|
+
const nodeSourcePath = await nodeUtils.getNodeSourceForVersion(nodeVersion, tmpdir, logger, platform);
|
|
265
|
+
const executableName = platform === "win32" ? "app.exe" : "app";
|
|
266
|
+
const appPath = path.join(outputPath, executableName);
|
|
248
267
|
logger.stepStarting("Cleaning dist directory");
|
|
249
268
|
await rimraf(outputPath, { glob: false });
|
|
250
269
|
fs.mkdirSync(outputPath, { recursive: true });
|
|
@@ -257,24 +276,40 @@ class PackCommand extends Command {
|
|
|
257
276
|
logger.stepCompleted();
|
|
258
277
|
}
|
|
259
278
|
if (esbuildConfig) {
|
|
260
|
-
|
|
279
|
+
// Load env file
|
|
280
|
+
const envFile = (_e = this.envFile) !== null && _e !== void 0 ? _e : ".env";
|
|
281
|
+
const envPath = path.resolve(currentWorkingDirectory, envFile);
|
|
282
|
+
if (fs.existsSync(envPath)) {
|
|
283
|
+
logger.stepStarting("Run esbuild - with env");
|
|
284
|
+
dotenv.config({ path: envPath });
|
|
285
|
+
esbuildConfig.define = {
|
|
286
|
+
...esbuildConfig.define,
|
|
287
|
+
...Object.fromEntries(Object.entries(process.env).map(([key, value]) => [`process.env.${key}`, JSON.stringify(value)])),
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
else {
|
|
291
|
+
logger.stepStarting("Run esbuild - without env");
|
|
292
|
+
}
|
|
261
293
|
await esbuild.build(esbuildConfig);
|
|
262
294
|
logger.stepCompleted();
|
|
263
295
|
}
|
|
264
296
|
logger.stepStarting("Inject to NodeJS Single Execute Application");
|
|
265
297
|
await this.execCommand("node", ["--experimental-sea-config", configFilePath]);
|
|
266
298
|
await this.execCommand("cp", [nodeSourcePath, appPath]);
|
|
267
|
-
|
|
268
|
-
"postject",
|
|
299
|
+
const postjectCommand = [
|
|
269
300
|
appPath,
|
|
270
301
|
"NODE_SEA_BLOB",
|
|
271
302
|
config.output,
|
|
272
303
|
"--sentinel-fuse",
|
|
273
304
|
"NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2",
|
|
274
|
-
]
|
|
305
|
+
];
|
|
306
|
+
if (platform === "darwin") {
|
|
307
|
+
postjectCommand.push("--macho-segment-name", "NODE_SEA");
|
|
308
|
+
}
|
|
309
|
+
await this.execCommand("postject", postjectCommand);
|
|
275
310
|
logger.stepCompleted();
|
|
276
311
|
// clear temp file
|
|
277
|
-
const clean = (
|
|
312
|
+
const clean = (_f = this.clean) !== null && _f !== void 0 ? _f : true;
|
|
278
313
|
if (clean) {
|
|
279
314
|
logger.stepStarting("Remove generated files");
|
|
280
315
|
const cleanFiles = [config.output];
|
package/lib/node-utils.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
import { Logger } from "./logger";
|
|
2
2
|
export declare class NodeUtils {
|
|
3
|
-
getNodeSourceForVersion(range: string, dir: string, logger: Logger, retries?: number): Promise<string>;
|
|
3
|
+
getNodeSourceForVersion(range: string, dir: string, logger: Logger, platform?: string, retries?: number): Promise<string>;
|
|
4
4
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nodejs-sea",
|
|
3
|
-
"version": "1.0
|
|
3
|
+
"version": "1.2.0",
|
|
4
4
|
"description": "A powerful package for NodeJS single executable applications (SEA), support good for NestJS framework",
|
|
5
5
|
"main": "lib/index.js",
|
|
6
6
|
"license": "MIT",
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
"precommit": "lint-staged",
|
|
19
19
|
"prepare": "husky",
|
|
20
20
|
"prepack": "rm -rf lib && rollup -c",
|
|
21
|
-
"test": "
|
|
21
|
+
"build:test": "node lib/cli.js -s test/sea/config.json -e test/.env",
|
|
22
22
|
"standard-version": "standard-version",
|
|
23
23
|
"build": "rollup -c"
|
|
24
24
|
},
|
|
@@ -26,42 +26,46 @@
|
|
|
26
26
|
"node": ">=18"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
|
-
"@rollup/plugin-commonjs": "^
|
|
30
|
-
"@rollup/plugin-node-resolve": "^
|
|
31
|
-
"@rollup/plugin-typescript": "^
|
|
29
|
+
"@rollup/plugin-commonjs": "^29.0.0",
|
|
30
|
+
"@rollup/plugin-node-resolve": "^16.0.3",
|
|
31
|
+
"@rollup/plugin-typescript": "^12.3.0",
|
|
32
|
+
"@types/adm-zip": "^0.5.7",
|
|
32
33
|
"@types/cli-progress": "^3.11.6",
|
|
33
|
-
"@types/node": "^
|
|
34
|
-
"@types/tar": "^
|
|
35
|
-
"@typescript-eslint/eslint-plugin": "^
|
|
36
|
-
"@typescript-eslint/parser": "^
|
|
37
|
-
"@yarnpkg/eslint-config": "^1.0
|
|
38
|
-
"eslint": "^
|
|
39
|
-
"eslint-config-prettier": "^
|
|
34
|
+
"@types/node": "^25.3.2",
|
|
35
|
+
"@types/tar": "^7.0.87",
|
|
36
|
+
"@typescript-eslint/eslint-plugin": "^8.56.1",
|
|
37
|
+
"@typescript-eslint/parser": "^8.56.1",
|
|
38
|
+
"@yarnpkg/eslint-config": "^3.1.0",
|
|
39
|
+
"eslint": "^10.0.2",
|
|
40
|
+
"eslint-config-prettier": "^10.1.8",
|
|
40
41
|
"eslint-plugin-eslint-comments": "^3.2.0",
|
|
41
42
|
"eslint-plugin-import": "^2.29.1",
|
|
42
|
-
"eslint-plugin-prettier": "^
|
|
43
|
-
"eslint-plugin-promise": "^
|
|
43
|
+
"eslint-plugin-prettier": "^5.5.5",
|
|
44
|
+
"eslint-plugin-promise": "^7.2.1",
|
|
44
45
|
"husky": "^9.1.7",
|
|
45
|
-
"lint-staged": "^
|
|
46
|
-
"prettier": "
|
|
47
|
-
"rollup": "^
|
|
48
|
-
"rollup-plugin-multi-input": "^1.
|
|
46
|
+
"lint-staged": "^16.2.7",
|
|
47
|
+
"prettier": "3.8.1",
|
|
48
|
+
"rollup": "^4.59.0",
|
|
49
|
+
"rollup-plugin-multi-input": "^1.7.0",
|
|
49
50
|
"rollup-plugin-preserve-shebang": "^1.0.1",
|
|
50
51
|
"rollup-plugin-terser": "^7.0.2",
|
|
51
52
|
"standard-version": "^9.5.0",
|
|
52
|
-
"terser": "^5.
|
|
53
|
+
"terser": "^5.46.0",
|
|
53
54
|
"ts-node": "^10.9.1",
|
|
54
|
-
"typescript": "^
|
|
55
|
+
"typescript": "^5.9.3"
|
|
55
56
|
},
|
|
56
57
|
"dependencies": {
|
|
57
|
-
"@pkgjs/nv": "^0.
|
|
58
|
+
"@pkgjs/nv": "^0.3.0",
|
|
59
|
+
"adm-zip": "^0.5.16",
|
|
60
|
+
"chalk": "^4.1.2",
|
|
58
61
|
"cli-progress": "^3.12.0",
|
|
59
|
-
"clipanion": "
|
|
60
|
-
"
|
|
62
|
+
"clipanion": "4.0.0-rc.4",
|
|
63
|
+
"dotenv": "^17.3.1",
|
|
64
|
+
"esbuild": "^0.27.3",
|
|
61
65
|
"postject": "^1.0.0-alpha.6",
|
|
62
|
-
"rimraf": "^6.
|
|
63
|
-
"tar": "^7.
|
|
64
|
-
"undici": "^7.
|
|
66
|
+
"rimraf": "^6.1.3",
|
|
67
|
+
"tar": "^7.5.9",
|
|
68
|
+
"undici": "^7.22.0"
|
|
65
69
|
},
|
|
66
70
|
"publishConfig": {
|
|
67
71
|
"main": "lib/index"
|