@interopio/gateway-server 0.23.1 → 0.24.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/bin/gateway-server.cjs +289 -118
- package/changelog.md +7 -0
- package/dist/tools.cjs +15 -1
- package/dist/tools.cjs.map +4 -4
- package/dist/tools.js +15 -1
- package/dist/tools.js.map +4 -4
- package/package.json +3 -3
- package/types/build.d.ts +63 -0
- package/types/tools.d.ts +1 -0
package/bin/gateway-server.cjs
CHANGED
|
@@ -8,90 +8,216 @@ const { configure } = require('@interopio/gateway/logging/core');
|
|
|
8
8
|
// import { GatewayServer } from './src/index.ts';
|
|
9
9
|
// import { mkcert, argon2, manage } from './src/tools/index.ts';
|
|
10
10
|
|
|
11
|
-
const { mkcert, argon2, manage } = require('@interopio/gateway-server/tools');
|
|
11
|
+
const { mkcert, argon2, manage, build } = require('@interopio/gateway-server/tools');
|
|
12
12
|
const { GatewayServer } = require('@interopio/gateway-server');
|
|
13
13
|
|
|
14
|
+
// ---------------------------------------------------------------------------
|
|
15
|
+
// Declarative command registry — drives both help text and parseArgs calls
|
|
16
|
+
// ---------------------------------------------------------------------------
|
|
17
|
+
|
|
18
|
+
const commands = {
|
|
19
|
+
run: {
|
|
20
|
+
description: 'Start the gateway server',
|
|
21
|
+
options: {
|
|
22
|
+
port: { type: 'string', short: 'p', help: 'Port or port range (default: 0 i.e. random)', example: '8385, 8000-8100, 3000,4000-4050' },
|
|
23
|
+
host: { type: 'string', short: 'H', help: 'Network address to bind to', example: 'localhost, 127.0.0.1, 0.0.0.0, ::1' },
|
|
24
|
+
user: { type: 'string', short: 'u', help: 'Enable basic auth and set admin username' },
|
|
25
|
+
auth: { type: 'boolean', help: 'Enable/disable authentication (--no-auth overrides config)' },
|
|
26
|
+
ssl: { type: 'boolean', short: 'S', help: 'Enable HTTPS (auto-generates certs if needed)' },
|
|
27
|
+
tls: { type: 'boolean', help: 'Alias for --ssl' },
|
|
28
|
+
cert: { type: 'string', help: 'SSL/TLS certificate file (default: ./gateway-server.crt)' },
|
|
29
|
+
key: { type: 'string', help: 'SSL/TLS private key file (default: ./gateway-server.key)' },
|
|
30
|
+
ca: { type: 'string', help: 'CA certificate file (default: ./gateway-ca.crt)' },
|
|
31
|
+
'ca-key': { type: 'string', help: 'CA private key file (default: ./gateway-ca.key)' },
|
|
32
|
+
gateway: { type: 'boolean', short: 'g', help: 'Enable/disable gateway endpoint (--no-gateway)' },
|
|
33
|
+
static: { type: 'string', short: 's', multiple: true, help: 'Serve static files from location' },
|
|
34
|
+
config: { type: 'string', short: 'c', help: 'Server configuration file (JSON)' },
|
|
35
|
+
debug: { type: 'boolean', help: 'Enable debug logging (default: info)' },
|
|
36
|
+
},
|
|
37
|
+
allowNegative: true,
|
|
38
|
+
examples: [
|
|
39
|
+
'gateway-server run -p 3000',
|
|
40
|
+
'gateway-server run -u admin --port 8385,8388 --debug',
|
|
41
|
+
'gateway-server run -p 8443 --ssl --user admin --gateway',
|
|
42
|
+
'gateway-server run --port 42443 --tls --ca-key ./ssl/ca.key --host example.com --gateway',
|
|
43
|
+
'gateway-server run -p 3000 --static ./public --config ./server-config.json',
|
|
44
|
+
'gateway-server run --config ./server-config.json --no-gateway --no-ssl --no-auth',
|
|
45
|
+
],
|
|
46
|
+
},
|
|
47
|
+
build: {
|
|
48
|
+
description: 'Build a Single Executable Application (SEA)',
|
|
49
|
+
positionals: '[entryPoints...]',
|
|
50
|
+
options: {
|
|
51
|
+
'app-name': { type: 'string', help: 'Base name for the executable (default: package.json name)' },
|
|
52
|
+
'app-version': { type: 'string', help: 'App version in output dir name (default: package.json version)' },
|
|
53
|
+
executable: { type: 'string', help: 'Path to the Node.js binary (default: current node)' },
|
|
54
|
+
outdir: { type: 'string', short: 'o', help: 'Output directory for build artifacts (default: ./build)' },
|
|
55
|
+
},
|
|
56
|
+
examples: [
|
|
57
|
+
'gateway-server build',
|
|
58
|
+
'gateway-server build --app-version 1.2.3',
|
|
59
|
+
'gateway-server build ./src/main.cjs --app-name io-bridge --executable /usr/local/bin/node22 --app-version 2.0.0',
|
|
60
|
+
],
|
|
61
|
+
},
|
|
62
|
+
manage: {
|
|
63
|
+
description: 'Send management commands to a running gateway server',
|
|
64
|
+
positionals: '<command> [key=value... or json]',
|
|
65
|
+
options: {
|
|
66
|
+
path: { type: 'string', help: 'Gateway control socket (named pipe / Unix socket)', example: '\\\\\\\\.\\\\pipe\\\\glue42-gateway-xxx, /tmp/gateway.sock' },
|
|
67
|
+
port: { type: 'string', short: 'p', help: 'TCP port of the management server' },
|
|
68
|
+
timeout: { type: 'string', help: 'Connection timeout in ms (default: 5000)' },
|
|
69
|
+
},
|
|
70
|
+
examples: [
|
|
71
|
+
'gateway-server manage --path \\\\.\\pipe\\glue42-gateway-xxx info',
|
|
72
|
+
'gateway-server manage --path \\\\.\\pipe\\glue42-gateway-xxx shutdown',
|
|
73
|
+
'gateway-server manage --path \\\\.\\pipe\\glue42-gateway-xxx custom-cmd key1=value1 count=42',
|
|
74
|
+
'gateway-server manage --path \\\\.\\pipe\\glue42-gateway-xxx \'{"command":"update-auth","type":"basic"}\'',
|
|
75
|
+
],
|
|
76
|
+
},
|
|
77
|
+
passwd: {
|
|
78
|
+
description: 'Generate password hash (default: Argon2)',
|
|
79
|
+
options: {
|
|
80
|
+
stdin: { type: 'boolean', help: 'Read password from stdin (for piping)' },
|
|
81
|
+
},
|
|
82
|
+
examples: [
|
|
83
|
+
'gateway-server passwd',
|
|
84
|
+
'echo "mySecret123" | gateway-server passwd --stdin',
|
|
85
|
+
],
|
|
86
|
+
},
|
|
87
|
+
mkcert: {
|
|
88
|
+
description: 'Generate client/server certificate signed by Dev CA',
|
|
89
|
+
positionals: '[name...]',
|
|
90
|
+
options: {
|
|
91
|
+
client: { type: 'boolean', help: 'Generate client certificate (default: server)' },
|
|
92
|
+
user: { type: 'string', short: 'u', help: 'Common Name (default: dev-user, --client only)' },
|
|
93
|
+
ca: { type: 'string', help: 'CA certificate file (default: ./gateway-ca.crt)' },
|
|
94
|
+
'ca-key': { type: 'string', help: 'CA private key file (default: ./gateway-ca.key)' },
|
|
95
|
+
key: { type: 'string', help: 'Output private key file' },
|
|
96
|
+
cert: { type: 'string', help: 'Output certificate file' },
|
|
97
|
+
},
|
|
98
|
+
examples: [
|
|
99
|
+
'gateway-server mkcert',
|
|
100
|
+
'gateway-server mkcert localhost 127.0.0.1 IP:192.168.1.100',
|
|
101
|
+
'gateway-server mkcert --client EMAIL:john.doe@example.com',
|
|
102
|
+
'gateway-server mkcert example.com *.example.com --key ./gateway-server.key --cert ./gateway-server.crt',
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
};
|
|
106
|
+
|
|
107
|
+
// ---------------------------------------------------------------------------
|
|
108
|
+
// Help text generator
|
|
109
|
+
// ---------------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
function formatOption(name, opt, negatable, col) {
|
|
112
|
+
const shortFlag = opt.short ? `-${opt.short}, ` : ' ';
|
|
113
|
+
const flag = (opt.type === 'boolean' && negatable) ? `--[no-]${name}` : `--${name}`;
|
|
114
|
+
const argHint = opt.type === 'string' ? ` <${name.replace(/-/g, '_')}>` : '';
|
|
115
|
+
const left = ` ${shortFlag}${flag}${argHint}`;
|
|
116
|
+
const pad = Math.max(2, col - left.length);
|
|
117
|
+
let line = left + ' '.repeat(pad) + (opt.help || '');
|
|
118
|
+
if (opt.example) {
|
|
119
|
+
line += `\n${' '.repeat(col)}examples: ${opt.example}`;
|
|
120
|
+
}
|
|
121
|
+
return line;
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/** Compute column width from a set of options. */
|
|
125
|
+
function optionColumnWidth(options, negatable) {
|
|
126
|
+
let max = 0;
|
|
127
|
+
for (const [name, opt] of Object.entries(options)) {
|
|
128
|
+
const shortFlag = opt.short ? `-X, ` : ' ';
|
|
129
|
+
const flag = (opt.type === 'boolean' && negatable) ? `--[no-]${name}` : `--${name}`;
|
|
130
|
+
const argHint = opt.type === 'string' ? ` <${name.replace(/-/g, '_')}>` : '';
|
|
131
|
+
max = Math.max(max, ` ${shortFlag}${flag}${argHint}`.length);
|
|
132
|
+
}
|
|
133
|
+
return max + 2; // 2 chars minimum padding
|
|
134
|
+
}
|
|
135
|
+
|
|
14
136
|
function showHelp() {
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
-
|
|
42
|
-
--
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
`);
|
|
137
|
+
const lines = [
|
|
138
|
+
'',
|
|
139
|
+
'Usage: gateway-server <command> [options]',
|
|
140
|
+
'',
|
|
141
|
+
'Commands:',
|
|
142
|
+
];
|
|
143
|
+
|
|
144
|
+
// Command list
|
|
145
|
+
for (const [name, cmd] of Object.entries(commands)) {
|
|
146
|
+
lines.push(` ${name.padEnd(24)} ${cmd.description}`);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
// Per-command options
|
|
150
|
+
for (const [name, cmd] of Object.entries(commands)) {
|
|
151
|
+
lines.push('');
|
|
152
|
+
const positionals = cmd.positionals ? ` ${cmd.positionals}` : '';
|
|
153
|
+
lines.push(`${name}${positionals} options:`);
|
|
154
|
+
const col = optionColumnWidth(cmd.options, cmd.allowNegative);
|
|
155
|
+
for (const [optName, opt] of Object.entries(cmd.options)) {
|
|
156
|
+
lines.push(formatOption(optName, opt, cmd.allowNegative, col));
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
// Global options
|
|
161
|
+
lines.push('');
|
|
162
|
+
lines.push('Global options:');
|
|
163
|
+
lines.push(' -v, --version Show version information and exit');
|
|
164
|
+
lines.push(' -h, --help Show this help message and exit');
|
|
165
|
+
|
|
166
|
+
// Examples
|
|
167
|
+
lines.push('');
|
|
168
|
+
lines.push('Examples:');
|
|
169
|
+
for (const cmd of Object.values(commands)) {
|
|
170
|
+
for (const ex of (cmd.examples || [])) {
|
|
171
|
+
lines.push(` ${ex}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
console.log(lines.join('\n'));
|
|
176
|
+
process.exit(0);
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
/** Extract parseArgs-compatible options from a command definition (strips help/example). */
|
|
180
|
+
function argsOptions(name) {
|
|
181
|
+
const cmd = commands[name];
|
|
182
|
+
const opts = { help: { type: 'boolean', short: 'h' } };
|
|
183
|
+
for (const [k, v] of Object.entries(cmd.options)) {
|
|
184
|
+
const o = { type: v.type };
|
|
185
|
+
if (v.short) o.short = v.short;
|
|
186
|
+
if (v.multiple) o.multiple = true;
|
|
187
|
+
opts[k] = o;
|
|
188
|
+
}
|
|
189
|
+
return opts;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
/** Show help for a single command and exit. */
|
|
193
|
+
function showCommandHelp(name) {
|
|
194
|
+
const cmd = commands[name];
|
|
195
|
+
const positionals = cmd.positionals ? ` ${cmd.positionals}` : '';
|
|
196
|
+
const lines = [
|
|
197
|
+
'',
|
|
198
|
+
`Usage: gateway-server ${name}${positionals} [options]`,
|
|
199
|
+
'',
|
|
200
|
+
cmd.description,
|
|
201
|
+
'',
|
|
202
|
+
'Options:',
|
|
203
|
+
];
|
|
204
|
+
|
|
205
|
+
const col = optionColumnWidth(cmd.options, cmd.allowNegative);
|
|
206
|
+
for (const [optName, opt] of Object.entries(cmd.options)) {
|
|
207
|
+
lines.push(formatOption(optName, opt, cmd.allowNegative, col));
|
|
208
|
+
}
|
|
209
|
+
const helpLeft = ' -h, --help';
|
|
210
|
+
lines.push(helpLeft + ' '.repeat(Math.max(2, col - helpLeft.length)) + 'Show this help message');
|
|
211
|
+
|
|
212
|
+
if (cmd.examples && cmd.examples.length > 0) {
|
|
213
|
+
lines.push('');
|
|
214
|
+
lines.push('Examples:');
|
|
215
|
+
for (const ex of cmd.examples) {
|
|
216
|
+
lines.push(` ${ex}`);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
console.log(lines.join('\n'));
|
|
95
221
|
process.exit(0);
|
|
96
222
|
}
|
|
97
223
|
|
|
@@ -100,6 +226,22 @@ function showVersion() {
|
|
|
100
226
|
process.exit(0);
|
|
101
227
|
}
|
|
102
228
|
|
|
229
|
+
/** Read the nearest package.json starting from cwd, walking up. */
|
|
230
|
+
function readPackageJson() {
|
|
231
|
+
const { readFileSync } = require('node:fs');
|
|
232
|
+
const { join, dirname } = require('node:path');
|
|
233
|
+
let dir = process.cwd();
|
|
234
|
+
while (true) {
|
|
235
|
+
try {
|
|
236
|
+
return JSON.parse(readFileSync(join(dir, 'package.json'), 'utf8'));
|
|
237
|
+
} catch {
|
|
238
|
+
const parent = dirname(dir);
|
|
239
|
+
if (parent === dir) return {};
|
|
240
|
+
dir = parent;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
103
245
|
// Parse command-line arguments
|
|
104
246
|
const { values: globalValues, positionals } = parseArgs({
|
|
105
247
|
args: process.argv.slice(2),
|
|
@@ -115,7 +257,7 @@ const { values: globalValues, positionals } = parseArgs({
|
|
|
115
257
|
if (globalValues.version) {
|
|
116
258
|
showVersion();
|
|
117
259
|
}
|
|
118
|
-
if (globalValues.help) {
|
|
260
|
+
if (globalValues.help && positionals.length === 0) {
|
|
119
261
|
showHelp();
|
|
120
262
|
}
|
|
121
263
|
|
|
@@ -133,6 +275,9 @@ switch (command) {
|
|
|
133
275
|
case 'run':
|
|
134
276
|
runServer().catch(e => {console.error(e); process.exit(1);});
|
|
135
277
|
break;
|
|
278
|
+
case 'build':
|
|
279
|
+
buildCommand().catch(e => {console.error(e); process.exit(1);});
|
|
280
|
+
break;
|
|
136
281
|
case 'manage':
|
|
137
282
|
manageCommand().catch(e => {console.error(e); process.exit(1);});
|
|
138
283
|
break;
|
|
@@ -148,18 +293,65 @@ switch (command) {
|
|
|
148
293
|
process.exit(1);
|
|
149
294
|
}
|
|
150
295
|
|
|
296
|
+
// Command: build - Build a Single Executable Application (SEA)
|
|
297
|
+
async function buildCommand() {
|
|
298
|
+
const { values, positionals } = parseArgs({
|
|
299
|
+
args: process.argv.slice(3),
|
|
300
|
+
options: argsOptions('build'),
|
|
301
|
+
strict: true,
|
|
302
|
+
allowPositionals: true,
|
|
303
|
+
});
|
|
304
|
+
if (values.help) showCommandHelp('build');
|
|
305
|
+
|
|
306
|
+
// Default app-name and app-version from the nearest package.json
|
|
307
|
+
const pkg = readPackageJson();
|
|
308
|
+
const name = values['app-name'] || (pkg.name ? pkg.name.replace(/^@.*\//, '') : 'gateway-server');
|
|
309
|
+
const entryPoints = positionals.length > 0 ? positionals : [`./bin/${name}.cjs`];
|
|
310
|
+
const executable = values.executable;
|
|
311
|
+
|
|
312
|
+
if (!executable) {
|
|
313
|
+
try {
|
|
314
|
+
if (require('node:sea').isSea()) {
|
|
315
|
+
console.error('Error: --executable is required when running from a single executable application.');
|
|
316
|
+
console.error('Provide the path to a Node.js binary, e.g. --executable /usr/local/bin/node');
|
|
317
|
+
process.exit(1);
|
|
318
|
+
}
|
|
319
|
+
} catch {
|
|
320
|
+
// not a SEA build
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
const targetPath = await build.buildSea(name, {
|
|
325
|
+
version: values['app-version'] || pkg.version,
|
|
326
|
+
outDir: values.outdir,
|
|
327
|
+
esbuild: {
|
|
328
|
+
entryPoints,
|
|
329
|
+
define: {
|
|
330
|
+
'process.env.NODE_ENV': '"production"',
|
|
331
|
+
'process.env.WS_NO_UTF_8_VALIDATE': 'true',
|
|
332
|
+
'process.env.WS_NO_BUFFER_UTIL': 'true'
|
|
333
|
+
},
|
|
334
|
+
},
|
|
335
|
+
config: {
|
|
336
|
+
executable,
|
|
337
|
+
execArgv: ['--experimental-websocket'],
|
|
338
|
+
execArgvExtension: 'cli',
|
|
339
|
+
},
|
|
340
|
+
});
|
|
341
|
+
|
|
342
|
+
console.log(`SEA executable built: ${targetPath}`);
|
|
343
|
+
process.exit(0);
|
|
344
|
+
}
|
|
345
|
+
|
|
151
346
|
// Command: manage - Send management commands to a running gateway server
|
|
152
347
|
async function manageCommand() {
|
|
153
348
|
const { values, positionals } = parseArgs({
|
|
154
|
-
args: process.argv.slice(3),
|
|
155
|
-
options:
|
|
156
|
-
path: { type: 'string' },
|
|
157
|
-
port: { type: 'string', short: 'p' },
|
|
158
|
-
timeout: { type: 'string' },
|
|
159
|
-
},
|
|
349
|
+
args: process.argv.slice(3),
|
|
350
|
+
options: argsOptions('manage'),
|
|
160
351
|
strict: true,
|
|
161
352
|
allowPositionals: true,
|
|
162
353
|
});
|
|
354
|
+
if (values.help) showCommandHelp('manage');
|
|
163
355
|
|
|
164
356
|
const socketPath = values.path;
|
|
165
357
|
const port = values.port ? parseInt(values.port, 10) : undefined;
|
|
@@ -241,13 +433,12 @@ async function manageCommand() {
|
|
|
241
433
|
// Command: passwd - Generate password hash
|
|
242
434
|
async function passwdCommand() {
|
|
243
435
|
const { values } = parseArgs({
|
|
244
|
-
args: process.argv.slice(3),
|
|
245
|
-
options:
|
|
246
|
-
stdin: { type: 'boolean' },
|
|
247
|
-
},
|
|
436
|
+
args: process.argv.slice(3),
|
|
437
|
+
options: argsOptions('passwd'),
|
|
248
438
|
strict: true,
|
|
249
439
|
allowPositionals: false,
|
|
250
440
|
});
|
|
441
|
+
if (values.help) showCommandHelp('passwd');
|
|
251
442
|
|
|
252
443
|
let password/*: string = undefined!*/;
|
|
253
444
|
|
|
@@ -349,18 +540,12 @@ async function promptPassword(prompt/*: string*/) {
|
|
|
349
540
|
// Command: mkcert - Generate client or server certificate
|
|
350
541
|
async function mkcertCommand() {
|
|
351
542
|
const { values, positionals } = parseArgs({
|
|
352
|
-
args: process.argv.slice(3),
|
|
353
|
-
options:
|
|
354
|
-
client: { type: 'boolean' },
|
|
355
|
-
user: { type: 'string', short: 'u' },
|
|
356
|
-
ca: { type: 'string' },
|
|
357
|
-
'ca-key': { type: 'string' },
|
|
358
|
-
key: { type: 'string' },
|
|
359
|
-
cert: { type: 'string' },
|
|
360
|
-
},
|
|
543
|
+
args: process.argv.slice(3),
|
|
544
|
+
options: argsOptions('mkcert'),
|
|
361
545
|
strict: true,
|
|
362
546
|
allowPositionals: true,
|
|
363
547
|
});
|
|
548
|
+
if (values.help) showCommandHelp('mkcert');
|
|
364
549
|
|
|
365
550
|
const isClientCert = values.client || false;
|
|
366
551
|
const user = values.user || 'dev-user';
|
|
@@ -471,27 +656,13 @@ async function mkcertCommand() {
|
|
|
471
656
|
// Command: run - Start the server
|
|
472
657
|
async function runServer() {
|
|
473
658
|
const { values } = parseArgs({
|
|
474
|
-
args: process.argv.slice(3),
|
|
475
|
-
options:
|
|
476
|
-
port: { type: 'string', short: 'p' },
|
|
477
|
-
host: { type: 'string', short: 'H' },
|
|
478
|
-
user: { type: 'string', short: 'u' },
|
|
479
|
-
debug: { type: 'boolean' },
|
|
480
|
-
ssl: { type: 'boolean', short: 'S' },
|
|
481
|
-
tls: { type: 'boolean' },
|
|
482
|
-
cert: { type: 'string' },
|
|
483
|
-
key: { type: 'string' },
|
|
484
|
-
ca: { type: 'string' },
|
|
485
|
-
'ca-key': { type: 'string' },
|
|
486
|
-
config: { type: 'string', short: 'c' },
|
|
487
|
-
gateway: { type: 'boolean', short: 'g' },
|
|
488
|
-
static: { type: 'string', short: 's', multiple: true },
|
|
489
|
-
auth: { type: 'boolean' }
|
|
490
|
-
},
|
|
659
|
+
args: process.argv.slice(3),
|
|
660
|
+
options: argsOptions('run'),
|
|
491
661
|
strict: true,
|
|
492
662
|
allowNegative: true,
|
|
493
663
|
allowPositionals: false,
|
|
494
664
|
});
|
|
665
|
+
if (values.help) showCommandHelp('run');
|
|
495
666
|
|
|
496
667
|
const options = {
|
|
497
668
|
port: values.port,
|
package/changelog.md
CHANGED
|
@@ -2,6 +2,13 @@
|
|
|
2
2
|
|
|
3
3
|
# Change Log
|
|
4
4
|
|
|
5
|
+
## 0.24.0 (2026-03-22)
|
|
6
|
+
### Added
|
|
7
|
+
- feat: move build sea as part of the cli (npx @interopio/gateway-server build)###
|
|
8
|
+
### Changed
|
|
9
|
+
- chore: bump @interopio/gateway to 0.25.1
|
|
10
|
+
- chore: bump undici to 7.24.4
|
|
11
|
+
|
|
5
12
|
## 0.23.1 (2026-03-13)
|
|
6
13
|
### Fixed
|
|
7
14
|
- fix: legacy config token-ttl
|
package/dist/tools.cjs
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
"use strict";var
|
|
1
|
+
"use strict";var fe=Object.create;var $=Object.defineProperty;var de=Object.getOwnPropertyDescriptor;var he=Object.getOwnPropertyNames;var ye=Object.getPrototypeOf,be=Object.prototype.hasOwnProperty;var A=(e,t)=>{for(var r in t)$(e,r,{get:t[r],enumerable:!0})},q=(e,t,r,n)=>{if(t&&typeof t=="object"||typeof t=="function")for(let s of he(t))!be.call(e,s)&&s!==r&&$(e,s,{get:()=>t[s],enumerable:!(n=de(t,s))||n.enumerable});return e};var N=(e,t,r)=>(r=e!=null?fe(ye(e)):{},q(t||!e||!e.__esModule?$(r,"default",{value:e,enumerable:!0}):r,e)),we=e=>q($({},"__esModule",{value:!0}),e);var Oe={};A(Oe,{argon2:()=>_,build:()=>B,keygen:()=>L,manage:()=>T,mkcert:()=>H});module.exports=we(Oe);var _={};A(_,{ARGON2_VERSION:()=>X,ARGON2_VERSION_10:()=>z,ARGON2_VERSION_13:()=>Q,DEFAULT_ALGORITHM:()=>Se,DEFAULT_HASH_LENGTH:()=>Z,DEFAULT_MEMORY:()=>R,DEFAULT_PARALLELISM:()=>j,DEFAULT_PASSES:()=>U,DEFAULT_SALT_LENGTH:()=>I,createHash:()=>K,decode:()=>ee,encode:()=>te,hash:()=>xe,verify:()=>Ee});var L={};A(L,{createSalt:()=>P});var Y=require("node:crypto");function P(e){return(0,Y.getRandomValues)(Buffer.alloc(e))}var k;async function Ae(){if(k===void 0)try{let e=await import("node:crypto");if(!e.argon2)throw new Error("argon2 not available");k=e.argon2}catch{throw new Error("argon2 is not available in this Node.js version. Node.js 24.7.0 or later is required for Argon2 password encoding. Please upgrade Node.js or use a different authentication method.")}return k}var z=16,Q=19,X=Q,Se="argon2id",I=16,Z=32,j=4,R=65536,U=3;function ee(e){let t=e.split("$");if(t.length<4)throw new Error("Invalid encoded Argon2 hash");let r=1,n=t[r++];if(n!=="argon2d"&&n!=="argon2i"&&n!=="argon2id")throw new Error("Invalid Argon2 type");let s=z;t[r].startsWith("v=")&&(s=parseInt(t[r].substring(2),10),r++);let a={},g=t[r++].split(",");for(let l of g){let[m,o]=l.split("=");switch(m){case"m":a.memory=parseInt(o,10);break;case"t":a.passes=parseInt(o,10);break;case"p":a.parallelism=parseInt(o,10);break}}a.nonce=Buffer.from(t[r++],"base64url");let i=Buffer.from(t[r++],"base64url");return{algorithm:n,version:s,parameters:a,hash:i}}function te(e){let{algorithm:t,version:r,parameters:n,hash:s}=e;return`$${t}$v=${r}$m=${n.memory},t=${n.passes},p=${n.parallelism}$${n.nonce.toString("base64url")}$${s.toString("base64url")}`}async function K(e,t,r,n){let s=n?.nonce??P(I),a=n?.memory??R,g=n?.passes??U,i=n?.parallelism??j,l={message:t,tagLength:r,nonce:s,memory:a,passes:g,parallelism:i},m=await Ae();return new Promise((o,d)=>{m(e,l,(y,w)=>{y?d(y):w?o(Buffer.from(w)):d(new Error("argon2 returned no result"))})})}async function xe(e,t){let r=t?.algorithm??"argon2id",n=t?.saltLength??I,s=t?.hashLength??Z,a=t?.parallelism??j,g=t?.memory??R,i=t?.passes??U,l=P(n),m={memory:g,passes:i,parallelism:a,nonce:l},o=await K(r,e,s,m);return te({algorithm:r,version:X,parameters:m,hash:o})}async function Ee(e,t){try{let r=ee(e),n=await K(r.algorithm,t,r.hash.length,r.parameters);return r.hash.equals(n)}catch{return!1}}var T={};A(T,{sendCommand:()=>$e});var re=N(require("net"),1);function $e(e,t,r={}){let{timeout:n=5e3}=r,s=e?.path?{path:e.path}:{port:e?.port??0},a=e?.path??`port ${e?.port}`;return new Promise((g,i)=>{let l=re.default.connect(s,()=>{l.write(JSON.stringify(t))}),m=setTimeout(()=>{l.destroy(),i(new Error(`Connection timed out after ${n}`))},n);l.on("data",o=>{clearTimeout(m);try{let d=JSON.parse(o.toString());d.error?i(new Error(d.error)):g(d.result)}catch{g(o.toString())}l.end()}),l.on("error",o=>{clearTimeout(m),o.code==="ENOENT"||o.code==="ECONNREFUSED"?i(new Error(`Cannot connect to gateway at ${a}. Make sure the gateway server is running and the path is correct.`,{cause:o})):i(o)})})}var H={};A(H,{DEFAULT_CA_NAME:()=>oe,generateCert:()=>Pe,generateRootCA:()=>Ne});var u=require("jsrsasign"),C=require("node:os"),ne=require("node:crypto"),v=`${(0,C.userInfo)().username}@${(0,C.hostname)()}`;function se(){return(0,ne.randomBytes)(16).toString("hex")}var O="io.Gateway Dev CA",oe=`${O} ${v}`;function Ne(e){let t=e?.name||oe,r=e?.passphrase,n=u.KEYUTIL.generateKeypair("EC","secp384r1"),s=n.prvKeyObj,a=n.pubKeyObj,g=r?u.KEYUTIL.getPEM(s,"PKCS8PRV",r,"AES-256-CBC"):u.KEYUTIL.getPEM(s,"PKCS8PRV"),l=new u.KJUR.asn1.x509.Certificate({version:3,serial:{hex:se()},issuer:{str:`/CN=${t}/O=${O}/OU=${v}`},subject:{str:`/CN=${t}/O=${O}/OU=${v}`},notbefore:(0,u.datetozulu)(new Date(Date.now()-60*1e3),!1,!1),notafter:(0,u.datetozulu)(new Date(Date.now()+10*365*24*60*60*1e3),!1,!1),sbjpubkey:a,ext:[{extname:"basicConstraints",critical:!0,cA:!0},{extname:"keyUsage",critical:!0,names:["keyCertSign"]}],sigalg:"SHA384withECDSA",cakey:s}).getPEM();return{key:g,cert:l}}function Pe(e,t,r,n=!1,s=7){let a=u.KEYUTIL.generateKeypair("EC","secp256r1"),g=a.prvKeyObj,i=a.pubKeyObj,l=u.KEYUTIL.getPEM(g,"PKCS8PRV"),m=[],o=n?"dev-user":"localhost";for(let f of r)if(f.toLowerCase().startsWith("ip:"))m.push({ip:f.substring(3)});else if(f.toLowerCase().startsWith("email:"))m.push({rfc822:f.substring(6)});else{let x=f.toLowerCase().startsWith("dns:");if(n)o=x?f.substring(4):f;else{let E=x?f.substring(4):f;m.push({dns:E}),m.length===1&&(o=E)}}let d=[{extname:"basicConstraints",cA:!1},{extname:"keyUsage",critical:!0,names:["digitalSignature","keyEncipherment"]},{extname:"extKeyUsage",array:[n?"clientAuth":"serverAuth"]}];m.length>0&&d.push({extname:"subjectAltName",array:m});let w=new u.KJUR.asn1.x509.Certificate({version:3,serial:{hex:se()},issuer:{str:t},subject:{str:`/CN=${o}/O=${O}/OU=${v}`},notbefore:(0,u.datetozulu)(new Date(Date.now()-60*1e3),!1,!1),notafter:(0,u.datetozulu)(new Date(Date.now()+s*24*60*60*1e3),!1,!1),sbjpubkey:i,ext:d,sigalg:"SHA256withECDSA",cakey:e}).getPEM();return{key:l,cert:w}}var B={};A(B,{buildSea:()=>ve});var p=require("node:fs/promises"),ie=require("node:child_process"),ce=require("node:util"),le=require("node:crypto"),b=require("node:path"),S=(0,ce.promisify)(ie.execFile);function M(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}async function ve(e,t){let r=t?.outDir??"./build",n=t?.config?.executable??process.execPath,s=M(e),a=M(t?.version??""),g=M(r.replace(/\\/g,"/")),{stdout:i}=await S(n,["-e",`
|
|
2
|
+
const { mkdirSync } = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const appVersion = '${a}'.trim();
|
|
5
|
+
const dirName = '${s}' + (appVersion ? '-v' + appVersion : '') + '.' + process.platform + '-' + process.arch;
|
|
6
|
+
const dir = path.resolve('${g}', dirName);
|
|
7
|
+
mkdirSync(dir, { recursive: true });
|
|
8
|
+
process.stdout.write(JSON.stringify({ dirName, nodeVersion: process.version, platform: process.platform, arch: process.arch }));
|
|
9
|
+
`.trim()]),{dirName:l,nodeVersion:m,platform:o,arch:d}=JSON.parse(i),y;if(t?.esbuild){let c;try{c=await import("esbuild")}catch{throw new Error(`esbuild is required to bundle the entry point. Install it with:
|
|
10
|
+
|
|
11
|
+
npm install --save-dev esbuild
|
|
12
|
+
`)}y=`${r}/${e}.js`,await c.build({format:"cjs",target:"node20",platform:"node",bundle:!0,external:["esbuild","postject"],loader:{".md":"file",".d.ts":"file"},assetNames:`${l}/[name]`,entryNames:"[name]",outdir:r,minify:!0,logLevel:"info",...t.esbuild})}else if(t?.config?.main)y=(0,b.resolve)(t.config.main);else throw new Error("Either esbuild options (with entryPoints) or config.main must be provided.");let w=(0,b.resolve)(`${r}/${e}.sea.node-${m}-${o}-${d}.blob`),f=(0,b.resolve)(`${r}/${e}.sea-config.${l}.json`),x={disableExperimentalSEAWarning:!0,useSnapshot:!1,useCodeCache:!1,...t?.config,main:(0,b.resolve)(y),output:w};await(0,p.writeFile)(f,JSON.stringify(x,null,2));let E=(0,b.resolve)(r,l),D=o==="win32",F=o==="darwin",me=D?`${e}.exe`:e,h=`${E}/${me}`,ge=await(0,p.readFile)(y),V=`${r}/${(0,b.basename)(y)}.sha`,J=(0,le.createHash)("sha256").update(ge).digest("hex"),W=!1;try{let[c]=await Promise.all([(0,p.readFile)(V,"utf8"),(0,p.access)(h)]);W=c===J}catch{}if(W)return console.log("SEA build skipped - esbuild output unchanged and target exists"),h;if(await S(n,["--experimental-sea-config",f]),await(0,p.copyFile)(n,h),D)try{let c=await ae();c&&(console.log(`Found signtool at: ${c}`),await S(c,["remove","/s",h]),console.log(`Signature removed from ${h} executable`))}catch(c){console.warn("Failed to remove signature:",c.message)}else if(F)try{await S("codesign",["--remove-signature",h]),console.log(`Signature removed from ${h} executable`)}catch(c){console.warn("Failed to remove signature:",c.message)}let G;try{({inject:G}=await import("postject"))}catch{throw new Error(`postject is required to build a SEA. Install it with:
|
|
13
|
+
|
|
14
|
+
npm install --save-dev postject
|
|
15
|
+
`)}let ue=await(0,p.readFile)(w),pe=["NODE","SEA","FUSE","fce680ab2cc467b6e072b8b5df1996b2"].join("_");if(await G(h,"NODE_SEA_BLOB",ue,{overwrite:!0,sentinelFuse:pe,...F?{machoSegmentName:"NODE_SEA"}:{}}),D)try{let c=await ae();c&&(console.log(`Signing executable with signtool at: ${c}`),await S(c,["sign","/fd","SHA256",h]),console.log("Executable signed successfully"))}catch(c){console.warn("Failed to sign executable:",c.message)}else if(F)try{await S("codesign",["--sign","-",h]),console.log("Executable signed successfully")}catch(c){console.warn("Failed to sign executable:",c.message)}return await(0,p.writeFile)(V,J),h}async function ae(){let e="C:\\Program Files (x86)\\Windows Kits\\10\\bin";try{let r=(await(0,p.readdir)(e,{withFileTypes:!0})).filter(n=>n.isDirectory()&&/^10\.0\.\d+\.\d+$/.test(n.name)).map(n=>n.name).sort((n,s)=>{let a=n.split(".").map(Number),g=s.split(".").map(Number);for(let i=0;i<a.length;i++)if(a[i]!==g[i])return g[i]-a[i];return 0});for(let n of r){let s=`${e}\\${n}\\${process.arch}\\signtool.exe`;try{return await(0,p.access)(s),s}catch{}}return console.warn("signtool.exe not found in any Windows SDK version"),null}catch(t){return console.warn(`Windows SDK not found at ${e}: ${t.message}`),null}}0&&(module.exports={argon2,build,keygen,manage,mkcert});
|
|
2
16
|
//# sourceMappingURL=tools.cjs.map
|
package/dist/tools.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/tools/index.ts", "../src/tools/crypto/argon2.ts", "../src/tools/crypto/keygen.ts", "../src/manage/client.ts", "../src/tools/mkcert.ts"],
|
|
4
|
-
"sourcesContent": ["export * as argon2 from './crypto/argon2.ts';\nexport * as keygen from './crypto/keygen.ts';\nexport * as manage from '../manage/client.ts';\nexport * as mkcert from './mkcert.ts';\n", "import type {\n Argon2Algorithm,\n Argon2Parameters\n} from 'node:crypto';\n\nimport { createSalt } from './keygen.ts';\nimport type { Argon2Hash, Argon2HashParameters } from '../../../types/crypto/argon2';\n\n// Lazy import for argon2 (added in Node.js 24.7.0)\n// This allows the module to load on older Node.js versions\nlet argon2: typeof import('node:crypto').argon2 | undefined;\n\nasync function getArgon2() {\n if (argon2 === undefined) {\n try {\n const crypto = await import('node:crypto');\n if (!crypto.argon2) {\n throw new Error('argon2 not available');\n }\n argon2 = crypto.argon2;\n } catch (err) {\n throw new Error(\n 'argon2 is not available in this Node.js version. ' +\n 'Node.js 24.7.0 or later is required for Argon2 password encoding. ' +\n 'Please upgrade Node.js or use a different authentication method.'\n );\n }\n }\n return argon2;\n}\n\n// Argon2 version constants\nexport const ARGON2_VERSION_10 = 0x10; // 16\nexport const ARGON2_VERSION_13 = 0x13; // 19\nexport const ARGON2_VERSION = ARGON2_VERSION_13;\n\n// Default parameters for Argon2 hashing\nexport const DEFAULT_ALGORITHM: Argon2Algorithm = 'argon2id';\nexport const DEFAULT_SALT_LENGTH = 16;\nexport const DEFAULT_HASH_LENGTH = 32;\nexport const DEFAULT_PARALLELISM = 4;\nexport const DEFAULT_MEMORY = 65536; // 64 MB in KiB\nexport const DEFAULT_PASSES = 3;\n\n/**\n * Decode an encoded Argon2 hash string into its components.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param encodedHash - The encoded Argon2 hash string\n * @returns Decoded hash components\n * @see https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244\n */\nexport function decode(encodedHash: string): Argon2Hash {\n const parts = encodedHash.split('$'); // ['', 'argon2id', 'v=19', 'm=65536,t=3,p=4', 'base64salt', 'base64hash']\n if (parts.length < 4) {\n throw new Error('Invalid encoded Argon2 hash');\n }\n let current = 1;\n const algorithm = parts[current++];\n if (algorithm !== 'argon2d' && algorithm !== 'argon2i' && algorithm !== 'argon2id') {\n throw new Error('Invalid Argon2 type');\n }\n let version = ARGON2_VERSION_10;\n if (parts[current].startsWith('v=')) {\n version = parseInt(parts[current].substring(2), 10);\n current++;\n }\n const parameters: Partial<Argon2HashParameters> = {};\n const paramsParts = parts[current++].split(',');\n\n for (const param of paramsParts) {\n const [key, value] = param.split('=');\n switch (key) {\n case 'm':\n parameters.memory = parseInt(value, 10);\n break;\n case 't':\n parameters.passes = parseInt(value, 10);\n break;\n case 'p':\n parameters.parallelism = parseInt(value, 10);\n break;\n }\n }\n parameters.nonce = Buffer.from(parts[current++], 'base64url');\n const hash = Buffer.from(parts[current++], 'base64url');\n\n return { algorithm, version, parameters: parameters as Argon2Hash['parameters'], hash };\n}\n\n/**\n * Encode Argon2 hash components into a standard string format.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param hashData - The hash components to encode\n * @returns Encoded hash string\n */\nexport function encode(hashData: Argon2Hash): string {\n const { algorithm, version, parameters, hash } = hashData;\n return `$${algorithm}$v=${version}$m=${parameters.memory},t=${parameters.passes},p=${parameters.parallelism}$${parameters.nonce.toString('base64url')}$${hash.toString('base64url')}`;\n}\n\n\n/**\n * Create an Argon2 hash from parameters.\n * Low-level wrapper around node:crypto's argon2.\n *\n * @param algorithm - Argon2 algorithm variant ('argon2d' | 'argon2i' | 'argon2id')\n * @param password - The password to hash\n * @param hashLength - Length of the output hash in bytes\n * @param parameters - Argon2 parameters (nonce, memory, passes, parallelism). If not provided, defaults will be used.\n * @returns The hash buffer\n */\nexport async function createHash(\n algorithm: Argon2Algorithm,\n password: string,\n hashLength: number,\n parameters?: Argon2Hash['parameters']\n): Promise<Buffer> {\n const nonce = parameters?.nonce ?? createSalt(DEFAULT_SALT_LENGTH);\n const memory = parameters?.memory ?? DEFAULT_MEMORY;\n const passes = parameters?.passes ?? DEFAULT_PASSES;\n const parallelism = parameters?.parallelism ?? DEFAULT_PARALLELISM;\n\n const argon2Params: Argon2Parameters = {\n message: password,\n tagLength: hashLength,\n nonce,\n memory,\n passes,\n parallelism\n };\n const argon2Fn = await getArgon2();\n\n // Wrap callback-based argon2 in a Promise\n return new Promise((resolve, reject) => {\n argon2Fn(algorithm, argon2Params, (err: Error | null, result?: Uint8Array) => {\n if (err) {\n reject(err);\n }\n else if (result) {\n resolve(Buffer.from(result));\n }\n else {\n reject(new Error('argon2 returned no result'));\n }\n });\n });\n}\n\n\n/**\n * Hash a password using Argon2.\n *\n * @param password - The plain text password to hash\n * @param options - Optional parameters object. If not provided, defaults will be used.\n * @returns The encoded Argon2 hash string\n */\nexport async function hash(\n password: string,\n options?: {\n algorithm?: Argon2Algorithm;\n saltLength?: number;\n hashLength?: number;\n parallelism?: number;\n memory?: number;\n passes?: number;\n }\n): Promise<string> {\n const algorithm = options?.algorithm ?? 'argon2id';\n const saltLength = options?.saltLength ?? DEFAULT_SALT_LENGTH;\n const hashLength = options?.hashLength ?? DEFAULT_HASH_LENGTH;\n const parallelism = options?.parallelism ?? DEFAULT_PARALLELISM;\n const memory = options?.memory ?? DEFAULT_MEMORY;\n const passes = options?.passes ?? DEFAULT_PASSES;\n\n const nonce = createSalt(saltLength);\n const parameters = { memory, passes, parallelism, nonce };\n const hashBuffer = await createHash(algorithm, password, hashLength, parameters);\n return encode({\n algorithm,\n version: ARGON2_VERSION,\n parameters,\n hash: hashBuffer\n });\n}\n\n/**\n * Verify a password against an Argon2 hash.\n *\n * @param encodedHash - The encoded Argon2 hash to verify against\n * @param password - The plain text password to verify\n * @returns true if password matches the hash, false otherwise\n */\nexport async function verify(encodedHash: string, password: string): Promise<boolean> {\n try {\n const decoded = decode(encodedHash);\n const hashBuffer = await createHash(\n decoded.algorithm,\n password,\n decoded.hash.length,\n decoded.parameters\n );\n return decoded.hash.equals(hashBuffer);\n } catch {\n return false;\n }\n}\n\n", "import { getRandomValues } from 'node:crypto';\n\n/**\n * Create a random salt (nonce) for cryptographic operations.\n *\n * @param length - Length of the salt in bytes\n * @returns Random salt buffer\n */\nexport function createSalt(length: number): Buffer {\n return getRandomValues(Buffer.alloc(length));\n}\n\n", "import net from 'net';\nimport type { ManagementCommand, ManagementEndpoint, SendCommandOptions } from '../../types/manage.d.ts';\n\nexport function sendCommand(\n server: ManagementEndpoint,\n command: ManagementCommand,\n options: SendCommandOptions = {}\n): Promise<unknown> {\n const { timeout = 5000 } = options;\n\n // Determine connection target: named pipe/socket path or port\n const connectOptions: net.NetConnectOpts = server?.path\n ? { path: server.path }\n : { port: server?.port ?? 0 };\n\n const target = server?.path ?? `port ${server?.port}`;\n\n return new Promise((resolve, reject) => {\n const client = net.connect(connectOptions, () => {\n client.write(JSON.stringify(command));\n });\n\n const timeoutId = setTimeout(() => {\n client.destroy();\n reject(new Error(`Connection timed out after ${timeout}`));\n }, timeout);\n\n client.on('data', (data) => {\n clearTimeout(timeoutId);\n try {\n const response = JSON.parse(data.toString());\n if (response.error) {\n reject(new Error(response.error));\n }\n else {\n resolve(response.result);\n }\n }\n catch {\n // Not JSON, return as raw string\n resolve(data.toString());\n }\n client.end();\n });\n\n client.on('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeoutId);\n if (err.code === 'ENOENT' || err.code === 'ECONNREFUSED') {\n reject(new Error(`Cannot connect to gateway at ${target}. Make sure the gateway server is running and the path is correct.`, { cause: err }));\n }\n else {\n reject(err);\n }\n });\n });\n}\n\n", "import { KEYUTIL, KJUR, RSAKey, datetozulu } from \"jsrsasign\";\nimport { userInfo, hostname } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\nconst userAndHost = `${userInfo().username}@${hostname()}`;\n\nfunction randomSerialNumber(): string {\n const bytes = randomBytes(16);\n return bytes.toString('hex');\n}\n\nconst DEFAULT_ORGANISATION = `io.Gateway Dev CA`;\nexport const DEFAULT_CA_NAME = `${DEFAULT_ORGANISATION} ${userAndHost}`;\n\nexport function generateRootCA(options?: { name?: string, passphrase?: string } ): { key: string, cert: string } {\n\n const commonName = options?.name || DEFAULT_CA_NAME;\n const passphrase = options?.passphrase;\n\n // STEP 1. generate a key pair for Root CA (secp384r1 for higher security)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp384r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = passphrase\n ? KEYUTIL.getPEM(prv, \"PKCS8PRV\", passphrase, \"AES-256-CBC\")\n : KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // STEP 2: create self-signed CA certificate\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000), false, false), // 10 years\n\n sbjpubkey: pub,\n\n ext: [\n {extname: \"basicConstraints\", critical: true, cA: true},\n {extname: \"keyUsage\", critical: true, names: [\"keyCertSign\"]}\n ],\n\n sigalg: \"SHA384withECDSA\",\n cakey: prv\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n\n\n/**\n * Generate a certificate with custom SAN entries\n * @param cakey - CA private key\n * @param issuer - Issuer DN string\n * @param sanEntries - Array of SAN entry strings (e.g., \"localhost\", \"IP:192.168.1.1\", \"EMAIL:user@example.com\")\n * @param isClient - Generate client cert (clientAuth) vs server cert (serverAuth)\n * @param validityDays - Certificate validity period\n */\nexport function generateCert(\n cakey: string | RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA,\n issuer: string,\n sanEntries: string[],\n isClient: boolean = false,\n validityDays: number = 7\n): {\n key: string,\n cert: string\n} {\n // STEP 1. generate key pair (secp256r1 for faster generation)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp256r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // Parse SAN entries\n const sanArray: Array<{dns?: string, ip?: string, rfc822?: string}> = [];\n let commonName = isClient ? 'dev-user' : 'localhost';\n\n for (const entry of sanEntries) {\n if (entry.toLowerCase().startsWith('ip:')) {\n sanArray.push({ip: entry.substring(3)});\n }\n else if (entry.toLowerCase().startsWith('email:')) {\n sanArray.push({rfc822: entry.substring(6)});\n }\n else {\n const dnsPrefixed = entry.toLowerCase().startsWith('dns:');\n if (isClient) {\n commonName = dnsPrefixed ? entry.substring(4) : entry;\n }\n else {\n const dns = dnsPrefixed ? entry.substring(4) : entry;\n sanArray.push({dns});\n if (sanArray.length === 1) {\n commonName = dns; // Use first DNS as CN\n }\n }\n }\n }\n\n // STEP 2: create certificate signed by CA\n const extensions: Array<{\n extname: string;\n cA?: boolean;\n critical?: boolean;\n names?: string[];\n array?: (string[] | Array<{dns?: string, ip?: string, rfc822?: string}>);\n }> = [\n {extname: \"basicConstraints\", cA: false},\n {\n extname: \"keyUsage\",\n critical: true,\n names: [\"digitalSignature\", \"keyEncipherment\"]\n },\n {\n extname: \"extKeyUsage\",\n array: [isClient ? \"clientAuth\" : \"serverAuth\"]\n }\n ];\n\n // Add SAN only if we have entries\n if (sanArray.length > 0) {\n extensions.push({\n extname: \"subjectAltName\",\n array: sanArray\n });\n }\n\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: issuer },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}`},\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + validityDays * 24 * 60 * 60 * 1000), false, false),\n\n sbjpubkey: pub,\n ext: extensions,\n\n sigalg: \"SHA256withECDSA\",\n cakey: cakey\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["index_exports", "__export", "argon2_exports", "keygen_exports", "client_exports", "mkcert_exports", "__toCommonJS", "argon2_exports", "__export", "ARGON2_VERSION", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "DEFAULT_ALGORITHM", "DEFAULT_HASH_LENGTH", "DEFAULT_MEMORY", "DEFAULT_PARALLELISM", "DEFAULT_PASSES", "DEFAULT_SALT_LENGTH", "createHash", "decode", "encode", "hash", "verify", "keygen_exports", "__export", "createSalt", "import_node_crypto", "length", "argon2", "getArgon2", "crypto", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "ARGON2_VERSION", "DEFAULT_ALGORITHM", "DEFAULT_SALT_LENGTH", "DEFAULT_HASH_LENGTH", "DEFAULT_PARALLELISM", "DEFAULT_MEMORY", "DEFAULT_PASSES", "decode", "encodedHash", "parts", "current", "algorithm", "version", "parameters", "paramsParts", "param", "key", "value", "hash", "encode", "hashData", "createHash", "password", "hashLength", "nonce", "createSalt", "memory", "passes", "parallelism", "argon2Params", "argon2Fn", "resolve", "reject", "err", "result", "options", "saltLength", "hashBuffer", "verify", "decoded", "client_exports", "__export", "sendCommand", "import_net", "server", "command", "options", "timeout", "connectOptions", "target", "resolve", "reject", "client", "net", "timeoutId", "data", "response", "err", "mkcert_exports", "__export", "DEFAULT_CA_NAME", "generateCert", "generateRootCA", "import_jsrsasign", "import_node_os", "import_node_crypto", "userAndHost", "randomSerialNumber", "DEFAULT_ORGANISATION", "options", "commonName", "passphrase", "kp", "prv", "pub", "prvPem", "certPem", "cakey", "issuer", "sanEntries", "isClient", "validityDays", "sanArray", "entry", "dnsPrefixed", "dns", "extensions"]
|
|
3
|
+
"sources": ["../src/tools/index.ts", "../src/tools/crypto/argon2.ts", "../src/tools/crypto/keygen.ts", "../src/manage/client.ts", "../src/tools/mkcert.ts", "../src/tools/build.ts"],
|
|
4
|
+
"sourcesContent": ["export * as argon2 from './crypto/argon2.ts';\nexport * as keygen from './crypto/keygen.ts';\nexport * as manage from '../manage/client.ts';\nexport * as mkcert from './mkcert.ts';\nexport * as build from './build.ts';\n", "import type {\n Argon2Algorithm,\n Argon2Parameters\n} from 'node:crypto';\n\nimport { createSalt } from './keygen.ts';\nimport type { Argon2Hash, Argon2HashParameters } from '../../../types/crypto/argon2';\n\n// Lazy import for argon2 (added in Node.js 24.7.0)\n// This allows the module to load on older Node.js versions\nlet argon2: typeof import('node:crypto').argon2 | undefined;\n\nasync function getArgon2() {\n if (argon2 === undefined) {\n try {\n const crypto = await import('node:crypto');\n if (!crypto.argon2) {\n throw new Error('argon2 not available');\n }\n argon2 = crypto.argon2;\n } catch (err) {\n throw new Error(\n 'argon2 is not available in this Node.js version. ' +\n 'Node.js 24.7.0 or later is required for Argon2 password encoding. ' +\n 'Please upgrade Node.js or use a different authentication method.'\n );\n }\n }\n return argon2;\n}\n\n// Argon2 version constants\nexport const ARGON2_VERSION_10 = 0x10; // 16\nexport const ARGON2_VERSION_13 = 0x13; // 19\nexport const ARGON2_VERSION = ARGON2_VERSION_13;\n\n// Default parameters for Argon2 hashing\nexport const DEFAULT_ALGORITHM: Argon2Algorithm = 'argon2id';\nexport const DEFAULT_SALT_LENGTH = 16;\nexport const DEFAULT_HASH_LENGTH = 32;\nexport const DEFAULT_PARALLELISM = 4;\nexport const DEFAULT_MEMORY = 65536; // 64 MB in KiB\nexport const DEFAULT_PASSES = 3;\n\n/**\n * Decode an encoded Argon2 hash string into its components.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param encodedHash - The encoded Argon2 hash string\n * @returns Decoded hash components\n * @see https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244\n */\nexport function decode(encodedHash: string): Argon2Hash {\n const parts = encodedHash.split('$'); // ['', 'argon2id', 'v=19', 'm=65536,t=3,p=4', 'base64salt', 'base64hash']\n if (parts.length < 4) {\n throw new Error('Invalid encoded Argon2 hash');\n }\n let current = 1;\n const algorithm = parts[current++];\n if (algorithm !== 'argon2d' && algorithm !== 'argon2i' && algorithm !== 'argon2id') {\n throw new Error('Invalid Argon2 type');\n }\n let version = ARGON2_VERSION_10;\n if (parts[current].startsWith('v=')) {\n version = parseInt(parts[current].substring(2), 10);\n current++;\n }\n const parameters: Partial<Argon2HashParameters> = {};\n const paramsParts = parts[current++].split(',');\n\n for (const param of paramsParts) {\n const [key, value] = param.split('=');\n switch (key) {\n case 'm':\n parameters.memory = parseInt(value, 10);\n break;\n case 't':\n parameters.passes = parseInt(value, 10);\n break;\n case 'p':\n parameters.parallelism = parseInt(value, 10);\n break;\n }\n }\n parameters.nonce = Buffer.from(parts[current++], 'base64url');\n const hash = Buffer.from(parts[current++], 'base64url');\n\n return { algorithm, version, parameters: parameters as Argon2Hash['parameters'], hash };\n}\n\n/**\n * Encode Argon2 hash components into a standard string format.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param hashData - The hash components to encode\n * @returns Encoded hash string\n */\nexport function encode(hashData: Argon2Hash): string {\n const { algorithm, version, parameters, hash } = hashData;\n return `$${algorithm}$v=${version}$m=${parameters.memory},t=${parameters.passes},p=${parameters.parallelism}$${parameters.nonce.toString('base64url')}$${hash.toString('base64url')}`;\n}\n\n\n/**\n * Create an Argon2 hash from parameters.\n * Low-level wrapper around node:crypto's argon2.\n *\n * @param algorithm - Argon2 algorithm variant ('argon2d' | 'argon2i' | 'argon2id')\n * @param password - The password to hash\n * @param hashLength - Length of the output hash in bytes\n * @param parameters - Argon2 parameters (nonce, memory, passes, parallelism). If not provided, defaults will be used.\n * @returns The hash buffer\n */\nexport async function createHash(\n algorithm: Argon2Algorithm,\n password: string,\n hashLength: number,\n parameters?: Argon2Hash['parameters']\n): Promise<Buffer> {\n const nonce = parameters?.nonce ?? createSalt(DEFAULT_SALT_LENGTH);\n const memory = parameters?.memory ?? DEFAULT_MEMORY;\n const passes = parameters?.passes ?? DEFAULT_PASSES;\n const parallelism = parameters?.parallelism ?? DEFAULT_PARALLELISM;\n\n const argon2Params: Argon2Parameters = {\n message: password,\n tagLength: hashLength,\n nonce,\n memory,\n passes,\n parallelism\n };\n const argon2Fn = await getArgon2();\n\n // Wrap callback-based argon2 in a Promise\n return new Promise((resolve, reject) => {\n argon2Fn(algorithm, argon2Params, (err: Error | null, result?: Uint8Array) => {\n if (err) {\n reject(err);\n }\n else if (result) {\n resolve(Buffer.from(result));\n }\n else {\n reject(new Error('argon2 returned no result'));\n }\n });\n });\n}\n\n\n/**\n * Hash a password using Argon2.\n *\n * @param password - The plain text password to hash\n * @param options - Optional parameters object. If not provided, defaults will be used.\n * @returns The encoded Argon2 hash string\n */\nexport async function hash(\n password: string,\n options?: {\n algorithm?: Argon2Algorithm;\n saltLength?: number;\n hashLength?: number;\n parallelism?: number;\n memory?: number;\n passes?: number;\n }\n): Promise<string> {\n const algorithm = options?.algorithm ?? 'argon2id';\n const saltLength = options?.saltLength ?? DEFAULT_SALT_LENGTH;\n const hashLength = options?.hashLength ?? DEFAULT_HASH_LENGTH;\n const parallelism = options?.parallelism ?? DEFAULT_PARALLELISM;\n const memory = options?.memory ?? DEFAULT_MEMORY;\n const passes = options?.passes ?? DEFAULT_PASSES;\n\n const nonce = createSalt(saltLength);\n const parameters = { memory, passes, parallelism, nonce };\n const hashBuffer = await createHash(algorithm, password, hashLength, parameters);\n return encode({\n algorithm,\n version: ARGON2_VERSION,\n parameters,\n hash: hashBuffer\n });\n}\n\n/**\n * Verify a password against an Argon2 hash.\n *\n * @param encodedHash - The encoded Argon2 hash to verify against\n * @param password - The plain text password to verify\n * @returns true if password matches the hash, false otherwise\n */\nexport async function verify(encodedHash: string, password: string): Promise<boolean> {\n try {\n const decoded = decode(encodedHash);\n const hashBuffer = await createHash(\n decoded.algorithm,\n password,\n decoded.hash.length,\n decoded.parameters\n );\n return decoded.hash.equals(hashBuffer);\n } catch {\n return false;\n }\n}\n\n", "import { getRandomValues } from 'node:crypto';\n\n/**\n * Create a random salt (nonce) for cryptographic operations.\n *\n * @param length - Length of the salt in bytes\n * @returns Random salt buffer\n */\nexport function createSalt(length: number): Buffer {\n return getRandomValues(Buffer.alloc(length));\n}\n\n", "import net from 'net';\nimport type { ManagementCommand, ManagementEndpoint, SendCommandOptions } from '../../types/manage.d.ts';\n\nexport function sendCommand(\n server: ManagementEndpoint,\n command: ManagementCommand,\n options: SendCommandOptions = {}\n): Promise<unknown> {\n const { timeout = 5000 } = options;\n\n // Determine connection target: named pipe/socket path or port\n const connectOptions: net.NetConnectOpts = server?.path\n ? { path: server.path }\n : { port: server?.port ?? 0 };\n\n const target = server?.path ?? `port ${server?.port}`;\n\n return new Promise((resolve, reject) => {\n const client = net.connect(connectOptions, () => {\n client.write(JSON.stringify(command));\n });\n\n const timeoutId = setTimeout(() => {\n client.destroy();\n reject(new Error(`Connection timed out after ${timeout}`));\n }, timeout);\n\n client.on('data', (data) => {\n clearTimeout(timeoutId);\n try {\n const response = JSON.parse(data.toString());\n if (response.error) {\n reject(new Error(response.error));\n }\n else {\n resolve(response.result);\n }\n }\n catch {\n // Not JSON, return as raw string\n resolve(data.toString());\n }\n client.end();\n });\n\n client.on('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeoutId);\n if (err.code === 'ENOENT' || err.code === 'ECONNREFUSED') {\n reject(new Error(`Cannot connect to gateway at ${target}. Make sure the gateway server is running and the path is correct.`, { cause: err }));\n }\n else {\n reject(err);\n }\n });\n });\n}\n\n", "import { KEYUTIL, KJUR, RSAKey, datetozulu } from \"jsrsasign\";\nimport { userInfo, hostname } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\nconst userAndHost = `${userInfo().username}@${hostname()}`;\n\nfunction randomSerialNumber(): string {\n const bytes = randomBytes(16);\n return bytes.toString('hex');\n}\n\nconst DEFAULT_ORGANISATION = `io.Gateway Dev CA`;\nexport const DEFAULT_CA_NAME = `${DEFAULT_ORGANISATION} ${userAndHost}`;\n\nexport function generateRootCA(options?: { name?: string, passphrase?: string } ): { key: string, cert: string } {\n\n const commonName = options?.name || DEFAULT_CA_NAME;\n const passphrase = options?.passphrase;\n\n // STEP 1. generate a key pair for Root CA (secp384r1 for higher security)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp384r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = passphrase\n ? KEYUTIL.getPEM(prv, \"PKCS8PRV\", passphrase, \"AES-256-CBC\")\n : KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // STEP 2: create self-signed CA certificate\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000), false, false), // 10 years\n\n sbjpubkey: pub,\n\n ext: [\n {extname: \"basicConstraints\", critical: true, cA: true},\n {extname: \"keyUsage\", critical: true, names: [\"keyCertSign\"]}\n ],\n\n sigalg: \"SHA384withECDSA\",\n cakey: prv\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n\n\n/**\n * Generate a certificate with custom SAN entries\n * @param cakey - CA private key\n * @param issuer - Issuer DN string\n * @param sanEntries - Array of SAN entry strings (e.g., \"localhost\", \"IP:192.168.1.1\", \"EMAIL:user@example.com\")\n * @param isClient - Generate client cert (clientAuth) vs server cert (serverAuth)\n * @param validityDays - Certificate validity period\n */\nexport function generateCert(\n cakey: string | RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA,\n issuer: string,\n sanEntries: string[],\n isClient: boolean = false,\n validityDays: number = 7\n): {\n key: string,\n cert: string\n} {\n // STEP 1. generate key pair (secp256r1 for faster generation)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp256r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // Parse SAN entries\n const sanArray: Array<{dns?: string, ip?: string, rfc822?: string}> = [];\n let commonName = isClient ? 'dev-user' : 'localhost';\n\n for (const entry of sanEntries) {\n if (entry.toLowerCase().startsWith('ip:')) {\n sanArray.push({ip: entry.substring(3)});\n }\n else if (entry.toLowerCase().startsWith('email:')) {\n sanArray.push({rfc822: entry.substring(6)});\n }\n else {\n const dnsPrefixed = entry.toLowerCase().startsWith('dns:');\n if (isClient) {\n commonName = dnsPrefixed ? entry.substring(4) : entry;\n }\n else {\n const dns = dnsPrefixed ? entry.substring(4) : entry;\n sanArray.push({dns});\n if (sanArray.length === 1) {\n commonName = dns; // Use first DNS as CN\n }\n }\n }\n }\n\n // STEP 2: create certificate signed by CA\n const extensions: Array<{\n extname: string;\n cA?: boolean;\n critical?: boolean;\n names?: string[];\n array?: (string[] | Array<{dns?: string, ip?: string, rfc822?: string}>);\n }> = [\n {extname: \"basicConstraints\", cA: false},\n {\n extname: \"keyUsage\",\n critical: true,\n names: [\"digitalSignature\", \"keyEncipherment\"]\n },\n {\n extname: \"extKeyUsage\",\n array: [isClient ? \"clientAuth\" : \"serverAuth\"]\n }\n ];\n\n // Add SAN only if we have entries\n if (sanArray.length > 0) {\n extensions.push({\n extname: \"subjectAltName\",\n array: sanArray\n });\n }\n\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: issuer },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}`},\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + validityDays * 24 * 60 * 60 * 1000), false, false),\n\n sbjpubkey: pub,\n ext: extensions,\n\n sigalg: \"SHA256withECDSA\",\n cakey: cakey\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n", "import { access, copyFile, readdir, readFile, writeFile } from 'node:fs/promises';\nimport { execFile as execFileCb } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createHash } from 'node:crypto';\nimport { basename, resolve } from 'node:path';\n\nimport type { BuildSeaOptions } from '../../types/build.d.ts';\n\nconst execFile = promisify(execFileCb);\n\n/**\n * Escapes a string for safe interpolation inside a single-quoted JS string literal.\n */\nfunction escapeForSingleQuotedString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nexport async function buildSea(name: string, options?: BuildSeaOptions): Promise<string> {\n const outDir = options?.outDir ?? './build';\n const nodeExecutable = options?.config?.executable ?? process.execPath;\n\n const safeName = escapeForSingleQuotedString(name);\n const safeVersion = escapeForSingleQuotedString(options?.version ?? '');\n const safeOutDir = escapeForSingleQuotedString(outDir.replace(/\\\\/g, '/'));\n\n // Use the target node executable to create the output directory and resolve\n // platform-specific paths. This also validates the executable is functional.\n const { stdout } = await execFile(nodeExecutable, ['-e', `\n const { mkdirSync } = require('node:fs');\n const path = require('node:path');\n const appVersion = '${safeVersion}'.trim();\n const dirName = '${safeName}' + (appVersion ? '-v' + appVersion : '') + '.' + process.platform + '-' + process.arch;\n const dir = path.resolve('${safeOutDir}', dirName);\n mkdirSync(dir, { recursive: true });\n process.stdout.write(JSON.stringify({ dirName, nodeVersion: process.version, platform: process.platform, arch: process.arch }));\n `.trim()]);\n\n const { dirName, nodeVersion, platform, arch } = JSON.parse(stdout);\n\n // Step 1: Produce the SEA JavaScript file\n let seaMain: string;\n if (options?.esbuild) {\n let esbuild: typeof import('esbuild');\n try {\n esbuild = await import('esbuild');\n }\n catch {\n throw new Error('esbuild is required to bundle the entry point. Install it with:\\n\\n npm install --save-dev esbuild\\n');\n }\n seaMain = `${outDir}/${name}.js`;\n await esbuild.build({\n format: 'cjs',\n target: 'node20',\n platform: 'node',\n bundle: true,\n external: ['esbuild', 'postject'], // exclude esbuild from the bundle since it's only needed at build time\n loader: {\n \".md\": \"file\",\n \".d.ts\": \"file\",\n },\n assetNames: `${dirName}/[name]`,\n entryNames: '[name]',\n outdir: outDir,\n minify: true,\n logLevel: 'info',\n ...options.esbuild,\n });\n }\n else if (options?.config?.main) {\n seaMain = resolve(options.config.main);\n }\n else {\n throw new Error('Either esbuild options (with entryPoints) or config.main must be provided.');\n }\n\n // Write SEA config file in the build folder\n const blobPath = resolve(`${outDir}/${name}.sea.node-${nodeVersion}-${platform}-${arch}.blob`);\n const configPath = resolve(`${outDir}/${name}.sea-config.${dirName}.json`);\n const seaConfig = {\n disableExperimentalSEAWarning: true,\n useSnapshot: false,\n useCodeCache: false,\n ...options?.config,\n main: resolve(seaMain),\n output: blobPath,\n };\n await writeFile(configPath, JSON.stringify(seaConfig, null, 2));\n\n const nativePath = resolve(outDir, dirName);\n\n const isWindows = platform === 'win32';\n const isMacos = platform === 'darwin';\n const targetFile = isWindows ? `${name}.exe` : name;\n const targetPath = `${nativePath}/${targetFile}`;\n\n\n // Check if we can skip the SEA build\n const seaJsContent = await readFile(seaMain);\n const shaPath = `${outDir}/${basename(seaMain)}.sha`;\n\n const currentSha = createHash('sha256').update(seaJsContent).digest('hex');\n let canSkip = false;\n\n try {\n const [previousSha] = await Promise.all([\n readFile(shaPath, 'utf8'),\n access(targetPath)\n ]);\n canSkip = previousSha === currentSha;\n }\n catch {\n // SHA file or target doesn't exist, need to build\n }\n if (canSkip) {\n console.log('SEA build skipped - esbuild output unchanged and target exists');\n return targetPath;\n }\n\n // Step 3: Generate the blob to be injected\n await execFile(nodeExecutable, ['--experimental-sea-config', configPath]);\n\n // Step 4: Copy the Node.js executable to the target path\n await copyFile(nodeExecutable, targetPath);\n\n // Step 5: Remove the signature of the binary\n if (isWindows) {\n try {\n const signtool = await findSigntool();\n if (signtool) {\n console.log(`Found signtool at: ${signtool}`);\n await execFile(signtool, ['remove', '/s', targetPath]);\n console.log(`Signature removed from ${targetPath} executable`);\n }\n }\n catch (e: any) {\n console.warn('Failed to remove signature:', e.message);\n }\n }\n else if (isMacos) {\n try {\n await execFile('codesign', ['--remove-signature', targetPath]);\n console.log(`Signature removed from ${targetPath} executable`);\n }\n catch (e: any) {\n console.warn('Failed to remove signature:', e.message);\n }\n }\n\n // Step 6: Inject the SEA blob into the binary\n type InjectOptions = {\n /**\n * @default '__POSTJECT'\n */\n machoSegmentName?: string;\n /**\n * @default false\n */\n overwrite?: boolean;\n /**\n * @default 'POSTJECT_SENTINEL_fce680ab2cc467b6e072b8b5df1996b2'\n */\n sentinelFuse?: string\n };\n type Inject = (filename: string, resourceName: string, resourceData: Buffer, options?: InjectOptions) => Promise<void>;\n\n let inject: Inject;\n try {\n ({ inject } = await import('postject') as { inject: Inject });\n }\n catch {\n throw new Error('postject is required to build a SEA. Install it with:\\n\\n npm install --save-dev postject\\n');\n }\n\n const resourceData = await readFile(blobPath);\n\n // Construct the sentinel fuse at runtime to avoid the literal appearing in the\n // bundled SEA output \u2014 postject would otherwise find multiple occurrences.\n const sentinelFuse = ['NODE', 'SEA', 'FUSE', 'fce680ab2cc467b6e072b8b5df1996b2'].join('_');\n\n await inject(\n targetPath,\n 'NODE_SEA_BLOB',\n resourceData,\n {\n overwrite: true,\n sentinelFuse,\n ...(isMacos ? { machoSegmentName: 'NODE_SEA' } : {})\n });\n\n // Step 7: Sign the binary\n if (isWindows) {\n try {\n const signtool = await findSigntool();\n if (signtool) {\n console.log(`Signing executable with signtool at: ${signtool}`);\n await execFile(signtool, ['sign', '/fd', 'SHA256', targetPath]);\n console.log(`Executable signed successfully`);\n }\n }\n catch (e: any) {\n console.warn('Failed to sign executable:', e.message);\n }\n }\n else if (isMacos) {\n try {\n await execFile('codesign', ['--sign', '-', targetPath]);\n console.log(`Executable signed successfully`);\n }\n catch (e: any) {\n console.warn('Failed to sign executable:', e.message);\n }\n }\n\n // Save SHA for next build comparison\n await writeFile(shaPath, currentSha);\n return targetPath;\n}\n\nasync function findSigntool(): Promise<string | null> {\n const windowsKitsPath = 'C:\\\\Program Files (x86)\\\\Windows Kits\\\\10\\\\bin';\n\n try {\n const entries = await readdir(windowsKitsPath, { withFileTypes: true });\n\n // Filter directories that match version pattern (e.g., 10.0.22621.0)\n const versionDirs = entries\n .filter(entry => entry.isDirectory() && /^10\\.0\\.\\d+\\.\\d+$/.test(entry.name))\n .map(entry => entry.name)\n .sort((a, b) => {\n // Sort by version number descending to get the latest\n const partsA = a.split('.').map(Number);\n const partsB = b.split('.').map(Number);\n for (let i = 0; i < partsA.length; i++) {\n if (partsA[i] !== partsB[i]) {\n return partsB[i] - partsA[i];\n }\n }\n return 0;\n });\n\n // Try each version directory, starting with the latest\n for (const version of versionDirs) {\n const signtoolPath = `${windowsKitsPath}\\\\${version}\\\\${process.arch}\\\\signtool.exe`;\n try {\n await access(signtoolPath);\n return signtoolPath;\n }\n catch {\n // signtool not found in this version, try next\n }\n }\n\n console.warn('signtool.exe not found in any Windows SDK version');\n return null;\n }\n catch (e: any) {\n console.warn(`Windows SDK not found at ${windowsKitsPath}: ${e.message}`);\n return null;\n }\n}\n\n"],
|
|
5
|
+
"mappings": "qkBAAA,IAAAA,GAAA,GAAAC,EAAAD,GAAA,YAAAE,EAAA,UAAAC,EAAA,WAAAC,EAAA,WAAAC,EAAA,WAAAC,IAAA,eAAAC,GAAAP,ICAA,IAAAQ,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,sBAAAC,GAAA,wBAAAC,EAAA,mBAAAC,EAAA,wBAAAC,EAAA,mBAAAC,EAAA,wBAAAC,EAAA,eAAAC,EAAA,WAAAC,GAAA,WAAAC,GAAA,SAAAC,GAAA,WAAAC,KCAA,IAAAC,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,IAAA,IAAAC,EAAgC,uBAQzB,SAASD,EAAWE,EAAwB,CAC/C,SAAO,mBAAgB,OAAO,MAAMA,CAAM,CAAC,CAC/C,CDAA,IAAIC,EAEJ,eAAeC,IAAY,CACvB,GAAID,IAAW,OACX,GAAI,CACA,IAAME,EAAS,KAAM,QAAO,aAAa,EACzC,GAAI,CAACA,EAAO,OACR,MAAM,IAAI,MAAM,sBAAsB,EAE1CF,EAASE,EAAO,MACpB,MAAc,CACV,MAAM,IAAI,MACN,qLAGJ,CACJ,CAEJ,OAAOF,CACX,CAGO,IAAMG,EAAoB,GACpBC,EAAoB,GACpBC,EAAiBD,EAGjBE,GAAqC,WACrCC,EAAsB,GACtBC,EAAsB,GACtBC,EAAsB,EACtBC,EAAiB,MACjBC,EAAiB,EAUvB,SAASC,GAAOC,EAAiC,CACpD,IAAMC,EAAQD,EAAY,MAAM,GAAG,EACnC,GAAIC,EAAM,OAAS,EACf,MAAM,IAAI,MAAM,6BAA6B,EAEjD,IAAIC,EAAU,EACRC,EAAYF,EAAMC,GAAS,EACjC,GAAIC,IAAc,WAAaA,IAAc,WAAaA,IAAc,WACpE,MAAM,IAAI,MAAM,qBAAqB,EAEzC,IAAIC,EAAUd,EACVW,EAAMC,CAAO,EAAE,WAAW,IAAI,IAC9BE,EAAU,SAASH,EAAMC,CAAO,EAAE,UAAU,CAAC,EAAG,EAAE,EAClDA,KAEJ,IAAMG,EAA4C,CAAC,EAC7CC,EAAcL,EAAMC,GAAS,EAAE,MAAM,GAAG,EAE9C,QAAWK,KAASD,EAAa,CAC7B,GAAM,CAACE,EAAKC,CAAK,EAAIF,EAAM,MAAM,GAAG,EACpC,OAAQC,EAAK,CACT,IAAK,IACDH,EAAW,OAAS,SAASI,EAAO,EAAE,EACtC,MACJ,IAAK,IACDJ,EAAW,OAAS,SAASI,EAAO,EAAE,EACtC,MACJ,IAAK,IACDJ,EAAW,YAAc,SAASI,EAAO,EAAE,EAC3C,KACR,CACJ,CACAJ,EAAW,MAAQ,OAAO,KAAKJ,EAAMC,GAAS,EAAG,WAAW,EAC5D,IAAMQ,EAAO,OAAO,KAAKT,EAAMC,GAAS,EAAG,WAAW,EAEtD,MAAO,CAAE,UAAAC,EAAW,QAAAC,EAAS,WAAYC,EAAwC,KAAAK,CAAK,CAC1F,CASO,SAASC,GAAOC,EAA8B,CACjD,GAAM,CAAE,UAAAT,EAAW,QAAAC,EAAS,WAAAC,EAAY,KAAAK,CAAK,EAAIE,EACjD,MAAO,IAAIT,CAAS,MAAMC,CAAO,MAAMC,EAAW,MAAM,MAAMA,EAAW,MAAM,MAAMA,EAAW,WAAW,IAAIA,EAAW,MAAM,SAAS,WAAW,CAAC,IAAIK,EAAK,SAAS,WAAW,CAAC,EACvL,CAaA,eAAsBG,EAClBV,EACAW,EACAC,EACAV,EACe,CACf,IAAMW,EAAQX,GAAY,OAASY,EAAWvB,CAAmB,EAC3DwB,EAASb,GAAY,QAAUR,EAC/BsB,EAASd,GAAY,QAAUP,EAC/BsB,EAAcf,GAAY,aAAeT,EAEzCyB,EAAiC,CACnC,QAASP,EACT,UAAWC,EACX,MAAAC,EACA,OAAAE,EACA,OAAAC,EACA,YAAAC,CACJ,EACME,EAAW,MAAMlC,GAAU,EAGjC,OAAO,IAAI,QAAQ,CAACmC,EAASC,IAAW,CACpCF,EAASnB,EAAWkB,EAAc,CAACI,EAAmBC,IAAwB,CACtED,EACAD,EAAOC,CAAG,EAELC,EACLH,EAAQ,OAAO,KAAKG,CAAM,CAAC,EAG3BF,EAAO,IAAI,MAAM,2BAA2B,CAAC,CAErD,CAAC,CACL,CAAC,CACL,CAUA,eAAsBd,GAClBI,EACAa,EAQe,CACf,IAAMxB,EAAYwB,GAAS,WAAa,WAClCC,EAAaD,GAAS,YAAcjC,EACpCqB,EAAaY,GAAS,YAAchC,EACpCyB,EAAcO,GAAS,aAAe/B,EACtCsB,EAASS,GAAS,QAAU9B,EAC5BsB,EAASQ,GAAS,QAAU7B,EAE5BkB,EAAQC,EAAWW,CAAU,EAC7BvB,EAAa,CAAE,OAAAa,EAAQ,OAAAC,EAAQ,YAAAC,EAAa,MAAAJ,CAAM,EAClDa,EAAa,MAAMhB,EAAWV,EAAWW,EAAUC,EAAYV,CAAU,EAC/E,OAAOM,GAAO,CACV,UAAAR,EACA,QAASX,EACT,WAAAa,EACA,KAAMwB,CACV,CAAC,CACL,CASA,eAAsBC,GAAO9B,EAAqBc,EAAoC,CAClF,GAAI,CACA,IAAMiB,EAAUhC,GAAOC,CAAW,EAC5B6B,EAAa,MAAMhB,EACrBkB,EAAQ,UACRjB,EACAiB,EAAQ,KAAK,OACbA,EAAQ,UACZ,EACA,OAAOA,EAAQ,KAAK,OAAOF,CAAU,CACzC,MAAQ,CACJ,MAAO,EACX,CACJ,CE/MA,IAAAG,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,KAAA,IAAAC,GAAgB,oBAGT,SAASD,GACZE,EACAC,EACAC,EAA8B,CAAC,EACf,CAChB,GAAM,CAAE,QAAAC,EAAU,GAAK,EAAID,EAGrBE,EAAqCJ,GAAQ,KAC7C,CAAE,KAAMA,EAAO,IAAK,EACpB,CAAE,KAAMA,GAAQ,MAAQ,CAAE,EAE1BK,EAASL,GAAQ,MAAQ,QAAQA,GAAQ,IAAI,GAEnD,OAAO,IAAI,QAAQ,CAACM,EAASC,IAAW,CACpC,IAAMC,EAAS,GAAAC,QAAI,QAAQL,EAAgB,IAAM,CAC7CI,EAAO,MAAM,KAAK,UAAUP,CAAO,CAAC,CACxC,CAAC,EAEKS,EAAY,WAAW,IAAM,CAC/BF,EAAO,QAAQ,EACfD,EAAO,IAAI,MAAM,8BAA8BJ,CAAO,EAAE,CAAC,CAC7D,EAAGA,CAAO,EAEVK,EAAO,GAAG,OAASG,GAAS,CACxB,aAAaD,CAAS,EACtB,GAAI,CACA,IAAME,EAAW,KAAK,MAAMD,EAAK,SAAS,CAAC,EACvCC,EAAS,MACTL,EAAO,IAAI,MAAMK,EAAS,KAAK,CAAC,EAGhCN,EAAQM,EAAS,MAAM,CAE/B,MACM,CAEFN,EAAQK,EAAK,SAAS,CAAC,CAC3B,CACAH,EAAO,IAAI,CACf,CAAC,EAEDA,EAAO,GAAG,QAAUK,GAA+B,CAC/C,aAAaH,CAAS,EAClBG,EAAI,OAAS,UAAYA,EAAI,OAAS,eACtCN,EAAO,IAAI,MAAM,gCAAgCF,CAAM,qEAAsE,CAAE,MAAOQ,CAAI,CAAC,CAAC,EAG5IN,EAAOM,CAAG,CAElB,CAAC,CACL,CAAC,CACL,CCvDA,IAAAC,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,GAAA,iBAAAC,GAAA,mBAAAC,KAAA,IAAAC,EAAkD,qBAClDC,EAAmC,mBACnCC,GAA4B,uBAEtBC,EAAc,MAAG,YAAS,EAAE,QAAQ,OAAI,YAAS,CAAC,GAExD,SAASC,IAA6B,CAElC,SADc,gBAAY,EAAE,EACf,SAAS,KAAK,CAC/B,CAEA,IAAMC,EAAuB,oBAChBR,GAAkB,GAAGQ,CAAoB,IAAIF,CAAW,GAE9D,SAASJ,GAAeO,EAAkF,CAE7G,IAAMC,EAAaD,GAAS,MAAQT,GAC9BW,EAAaF,GAAS,WAGtBG,EAAK,UAAQ,gBAAgB,KAAM,WAAW,EAC9CC,EAAMD,EAAG,UACTE,EAAMF,EAAG,UAETG,EAASJ,EACT,UAAQ,OAAOE,EAAK,WAAYF,EAAY,aAAa,EACzD,UAAQ,OAAOE,EAAK,UAAU,EAuB9BG,EApBO,IAAI,OAAK,KAAK,KAAK,YAAY,CACxC,QAAS,EACT,OAAQ,CAAE,IAAKT,GAAmB,CAAE,EACpC,OAAQ,CAAE,IAAK,OAAOG,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAG,EAC/E,QAAS,CAAE,IAAK,OAAOI,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAG,EAEhF,aAAW,cAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,GAAI,EAAG,GAAO,EAAK,EACpE,YAAU,cAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,IAAM,GAAK,GAAK,GAAK,GAAI,EAAG,GAAO,EAAK,EAExF,UAAWQ,EAEX,IAAK,CACD,CAAC,QAAS,mBAAoB,SAAU,GAAM,GAAI,EAAI,EACtD,CAAC,QAAS,WAAY,SAAU,GAAM,MAAO,CAAC,aAAa,CAAC,CAChE,EAEA,OAAQ,kBACR,MAAOD,CACX,CAAC,EAEoB,OAAO,EAE5B,MAAO,CACH,IAAKE,EACL,KAAMC,CACV,CACJ,CAWO,SAASf,GACZgB,EACAC,EACAC,EACAC,EAAoB,GACpBC,EAAuB,EAIzB,CAEE,IAAMT,EAAK,UAAQ,gBAAgB,KAAM,WAAW,EAC9CC,EAAMD,EAAG,UACTE,EAAMF,EAAG,UAETG,EAAS,UAAQ,OAAOF,EAAK,UAAU,EAGvCS,EAAgE,CAAC,EACnEZ,EAAaU,EAAW,WAAa,YAEzC,QAAWG,KAASJ,EAChB,GAAII,EAAM,YAAY,EAAE,WAAW,KAAK,EACpCD,EAAS,KAAK,CAAC,GAAIC,EAAM,UAAU,CAAC,CAAC,CAAC,UAEjCA,EAAM,YAAY,EAAE,WAAW,QAAQ,EAC5CD,EAAS,KAAK,CAAC,OAAQC,EAAM,UAAU,CAAC,CAAC,CAAC,MAEzC,CACD,IAAMC,EAAcD,EAAM,YAAY,EAAE,WAAW,MAAM,EACzD,GAAIH,EACAV,EAAac,EAAcD,EAAM,UAAU,CAAC,EAAIA,MAE/C,CACD,IAAME,EAAMD,EAAcD,EAAM,UAAU,CAAC,EAAIA,EAC/CD,EAAS,KAAK,CAAC,IAAAG,CAAG,CAAC,EACfH,EAAS,SAAW,IACpBZ,EAAae,EAErB,CACJ,CAIJ,IAAMC,EAMD,CACD,CAAC,QAAS,mBAAoB,GAAI,EAAK,EACvC,CACI,QAAS,WACT,SAAU,GACV,MAAO,CAAC,mBAAoB,iBAAiB,CACjD,EACA,CACI,QAAS,cACT,MAAO,CAACN,EAAW,aAAe,YAAY,CAClD,CACJ,EAGIE,EAAS,OAAS,GAClBI,EAAW,KAAK,CACZ,QAAS,iBACT,MAAOJ,CACX,CAAC,EAmBL,IAAMN,EAhBO,IAAI,OAAK,KAAK,KAAK,YAAY,CACxC,QAAS,EACT,OAAQ,CAAE,IAAKT,GAAmB,CAAE,EACpC,OAAQ,CAAE,IAAKW,CAAO,EACtB,QAAS,CAAE,IAAK,OAAOR,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAE,EAE/E,aAAW,cAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,GAAI,EAAG,GAAO,EAAK,EACpE,YAAU,cAAW,IAAI,KAAK,KAAK,IAAI,EAAIe,EAAe,GAAK,GAAK,GAAK,GAAI,EAAG,GAAO,EAAK,EAE5F,UAAWP,EACX,IAAKY,EAEL,OAAQ,kBACR,MAAOT,CACX,CAAC,EAEoB,OAAO,EAE5B,MAAO,CACH,IAAKF,EACL,KAAMC,CACV,CACJ,CC/JA,IAAAW,EAAA,GAAAC,EAAAD,EAAA,cAAAE,KAAA,IAAAC,EAA+D,4BAC/DC,GAAuC,8BACvCC,GAA0B,qBAC1BC,GAA2B,uBAC3BC,EAAkC,qBAI5BC,KAAW,cAAU,GAAAC,QAAU,EAKrC,SAASC,EAA4BC,EAAuB,CACxD,OAAOA,EAAM,QAAQ,MAAO,MAAM,EAAE,QAAQ,KAAM,KAAK,CAC3D,CAEA,eAAsBT,GAASU,EAAcC,EAA4C,CACrF,IAAMC,EAASD,GAAS,QAAU,UAC5BE,EAAiBF,GAAS,QAAQ,YAAc,QAAQ,SAExDG,EAAWN,EAA4BE,CAAI,EAC3CK,EAAcP,EAA4BG,GAAS,SAAW,EAAE,EAChEK,EAAaR,EAA4BI,EAAO,QAAQ,MAAO,GAAG,CAAC,EAInE,CAAE,OAAAK,CAAO,EAAI,MAAMX,EAASO,EAAgB,CAAC,KAAM;AAAA;AAAA;AAAA,8BAG/BE,CAAW;AAAA,2BACdD,CAAQ;AAAA,oCACCE,CAAU;AAAA;AAAA;AAAA,MAGxC,KAAK,CAAC,CAAC,EAEH,CAAE,QAAAE,EAAS,YAAAC,EAAa,SAAAC,EAAU,KAAAC,CAAK,EAAI,KAAK,MAAMJ,CAAM,EAG9DK,EACJ,GAAIX,GAAS,QAAS,CAClB,IAAIY,EACJ,GAAI,CACAA,EAAU,KAAM,QAAO,SAAS,CACpC,MACM,CACF,MAAM,IAAI,MAAM;AAAA;AAAA;AAAA,CAAuG,CAC3H,CACAD,EAAU,GAAGV,CAAM,IAAIF,CAAI,MAC3B,MAAMa,EAAQ,MAAM,CAChB,OAAQ,MACR,OAAQ,SACR,SAAU,OACV,OAAQ,GACR,SAAU,CAAC,UAAW,UAAU,EAChC,OAAQ,CACJ,MAAO,OACP,QAAS,MACb,EACA,WAAY,GAAGL,CAAO,UACtB,WAAY,SACZ,OAAQN,EACR,OAAQ,GACR,SAAU,OACV,GAAGD,EAAQ,OACf,CAAC,CACL,SACSA,GAAS,QAAQ,KACtBW,KAAU,WAAQX,EAAQ,OAAO,IAAI,MAGrC,OAAM,IAAI,MAAM,4EAA4E,EAIhG,IAAMa,KAAW,WAAQ,GAAGZ,CAAM,IAAIF,CAAI,aAAaS,CAAW,IAAIC,CAAQ,IAAIC,CAAI,OAAO,EACvFI,KAAa,WAAQ,GAAGb,CAAM,IAAIF,CAAI,eAAeQ,CAAO,OAAO,EACnEQ,EAAY,CACd,8BAA+B,GAC/B,YAAa,GACb,aAAc,GACd,GAAGf,GAAS,OACZ,QAAM,WAAQW,CAAO,EACrB,OAAQE,CACZ,EACA,QAAM,aAAUC,EAAY,KAAK,UAAUC,EAAW,KAAM,CAAC,CAAC,EAE9D,IAAMC,KAAa,WAAQf,EAAQM,CAAO,EAEpCU,EAAYR,IAAa,QACzBS,EAAUT,IAAa,SACvBU,GAAaF,EAAY,GAAGlB,CAAI,OAASA,EACzCqB,EAAa,GAAGJ,CAAU,IAAIG,EAAU,GAIxCE,GAAe,QAAM,YAASV,CAAO,EACrCW,EAAU,GAAGrB,CAAM,OAAI,YAASU,CAAO,CAAC,OAExCY,KAAa,eAAW,QAAQ,EAAE,OAAOF,EAAY,EAAE,OAAO,KAAK,EACrEG,EAAU,GAEd,GAAI,CACA,GAAM,CAACC,CAAW,EAAI,MAAM,QAAQ,IAAI,IACpC,YAASH,EAAS,MAAM,KACxB,UAAOF,CAAU,CACrB,CAAC,EACDI,EAAUC,IAAgBF,CAC9B,MACM,CAEN,CACA,GAAIC,EACA,eAAQ,IAAI,gEAAgE,EACrEJ,EAUX,GANA,MAAMzB,EAASO,EAAgB,CAAC,4BAA6BY,CAAU,CAAC,EAGxE,QAAM,YAASZ,EAAgBkB,CAAU,EAGrCH,EACA,GAAI,CACA,IAAMS,EAAW,MAAMC,GAAa,EAChCD,IACA,QAAQ,IAAI,sBAAsBA,CAAQ,EAAE,EAC5C,MAAM/B,EAAS+B,EAAU,CAAC,SAAU,KAAMN,CAAU,CAAC,EACrD,QAAQ,IAAI,0BAA0BA,CAAU,aAAa,EAErE,OACOQ,EAAQ,CACX,QAAQ,KAAK,8BAA+BA,EAAE,OAAO,CACzD,SAEKV,EACL,GAAI,CACA,MAAMvB,EAAS,WAAY,CAAC,qBAAsByB,CAAU,CAAC,EAC7D,QAAQ,IAAI,0BAA0BA,CAAU,aAAa,CACjE,OACOQ,EAAQ,CACX,QAAQ,KAAK,8BAA+BA,EAAE,OAAO,CACzD,CAoBJ,IAAIC,EACJ,GAAI,EACC,CAAE,OAAAA,CAAO,EAAI,KAAM,QAAO,UAAU,EACzC,MACM,CACF,MAAM,IAAI,MAAM;AAAA;AAAA;AAAA,CAA8F,CAClH,CAEA,IAAMC,GAAe,QAAM,YAASjB,CAAQ,EAItCkB,GAAe,CAAC,OAAQ,MAAO,OAAQ,kCAAkC,EAAE,KAAK,GAAG,EAazF,GAXA,MAAMF,EACFT,EACA,gBACAU,GACA,CACI,UAAW,GACX,aAAAC,GACA,GAAIb,EAAU,CAAE,iBAAkB,UAAW,EAAI,CAAC,CACtD,CAAC,EAGDD,EACA,GAAI,CACA,IAAMS,EAAW,MAAMC,GAAa,EAChCD,IACA,QAAQ,IAAI,wCAAwCA,CAAQ,EAAE,EAC9D,MAAM/B,EAAS+B,EAAU,CAAC,OAAQ,MAAO,SAAUN,CAAU,CAAC,EAC9D,QAAQ,IAAI,gCAAgC,EAEpD,OACOQ,EAAQ,CACX,QAAQ,KAAK,6BAA8BA,EAAE,OAAO,CACxD,SAEKV,EACL,GAAI,CACA,MAAMvB,EAAS,WAAY,CAAC,SAAU,IAAKyB,CAAU,CAAC,EACtD,QAAQ,IAAI,gCAAgC,CAChD,OACOQ,EAAQ,CACX,QAAQ,KAAK,6BAA8BA,EAAE,OAAO,CACxD,CAIJ,eAAM,aAAUN,EAASC,CAAU,EAC5BH,CACX,CAEA,eAAeO,IAAuC,CAClD,IAAMK,EAAkB,iDAExB,GAAI,CAIA,IAAMC,GAHU,QAAM,WAAQD,EAAiB,CAAE,cAAe,EAAK,CAAC,GAIjE,OAAOE,GAASA,EAAM,YAAY,GAAK,oBAAoB,KAAKA,EAAM,IAAI,CAAC,EAC3E,IAAIA,GAASA,EAAM,IAAI,EACvB,KAAK,CAACC,EAAGC,IAAM,CAEZ,IAAMC,EAASF,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EAChCG,EAASF,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EACtC,QAAS,EAAI,EAAG,EAAIC,EAAO,OAAQ,IAC/B,GAAIA,EAAO,CAAC,IAAMC,EAAO,CAAC,EACtB,OAAOA,EAAO,CAAC,EAAID,EAAO,CAAC,EAGnC,MAAO,EACX,CAAC,EAGL,QAAWE,KAAWN,EAAa,CAC/B,IAAMO,EAAe,GAAGR,CAAe,KAAKO,CAAO,KAAK,QAAQ,IAAI,iBACpE,GAAI,CACA,eAAM,UAAOC,CAAY,EAClBA,CACX,MACM,CAEN,CACJ,CAEA,eAAQ,KAAK,mDAAmD,EACzD,IACX,OACOZ,EAAQ,CACX,eAAQ,KAAK,4BAA4BI,CAAe,KAAKJ,EAAE,OAAO,EAAE,EACjE,IACX,CACJ",
|
|
6
|
+
"names": ["index_exports", "__export", "argon2_exports", "build_exports", "keygen_exports", "client_exports", "mkcert_exports", "__toCommonJS", "argon2_exports", "__export", "ARGON2_VERSION", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "DEFAULT_ALGORITHM", "DEFAULT_HASH_LENGTH", "DEFAULT_MEMORY", "DEFAULT_PARALLELISM", "DEFAULT_PASSES", "DEFAULT_SALT_LENGTH", "createHash", "decode", "encode", "hash", "verify", "keygen_exports", "__export", "createSalt", "import_node_crypto", "length", "argon2", "getArgon2", "crypto", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "ARGON2_VERSION", "DEFAULT_ALGORITHM", "DEFAULT_SALT_LENGTH", "DEFAULT_HASH_LENGTH", "DEFAULT_PARALLELISM", "DEFAULT_MEMORY", "DEFAULT_PASSES", "decode", "encodedHash", "parts", "current", "algorithm", "version", "parameters", "paramsParts", "param", "key", "value", "hash", "encode", "hashData", "createHash", "password", "hashLength", "nonce", "createSalt", "memory", "passes", "parallelism", "argon2Params", "argon2Fn", "resolve", "reject", "err", "result", "options", "saltLength", "hashBuffer", "verify", "decoded", "client_exports", "__export", "sendCommand", "import_net", "server", "command", "options", "timeout", "connectOptions", "target", "resolve", "reject", "client", "net", "timeoutId", "data", "response", "err", "mkcert_exports", "__export", "DEFAULT_CA_NAME", "generateCert", "generateRootCA", "import_jsrsasign", "import_node_os", "import_node_crypto", "userAndHost", "randomSerialNumber", "DEFAULT_ORGANISATION", "options", "commonName", "passphrase", "kp", "prv", "pub", "prvPem", "certPem", "cakey", "issuer", "sanEntries", "isClient", "validityDays", "sanArray", "entry", "dnsPrefixed", "dns", "extensions", "build_exports", "__export", "buildSea", "import_promises", "import_node_child_process", "import_node_util", "import_node_crypto", "import_node_path", "execFile", "execFileCb", "escapeForSingleQuotedString", "value", "name", "options", "outDir", "nodeExecutable", "safeName", "safeVersion", "safeOutDir", "stdout", "dirName", "nodeVersion", "platform", "arch", "seaMain", "esbuild", "blobPath", "configPath", "seaConfig", "nativePath", "isWindows", "isMacos", "targetFile", "targetPath", "seaJsContent", "shaPath", "currentSha", "canSkip", "previousSha", "signtool", "findSigntool", "e", "inject", "resourceData", "sentinelFuse", "windowsKitsPath", "versionDirs", "entry", "a", "b", "partsA", "partsB", "version", "signtoolPath"]
|
|
7
7
|
}
|
package/dist/tools.js
CHANGED
|
@@ -1,2 +1,16 @@
|
|
|
1
|
-
var
|
|
1
|
+
var ce=Object.defineProperty;var b=(e,t)=>{for(var n in t)ce(e,n,{get:t[n],enumerable:!0})};var q={};b(q,{ARGON2_VERSION:()=>V,ARGON2_VERSION_10:()=>M,ARGON2_VERSION_13:()=>B,DEFAULT_ALGORITHM:()=>ge,DEFAULT_HASH_LENGTH:()=>J,DEFAULT_MEMORY:()=>L,DEFAULT_PARALLELISM:()=>F,DEFAULT_PASSES:()=>k,DEFAULT_SALT_LENGTH:()=>D,createHash:()=>I,decode:()=>W,encode:()=>G,hash:()=>ue,verify:()=>pe});var H={};b(H,{createSalt:()=>E});import{getRandomValues as le}from"node:crypto";function E(e){return le(Buffer.alloc(e))}var C;async function me(){if(C===void 0)try{let e=await import("node:crypto");if(!e.argon2)throw new Error("argon2 not available");C=e.argon2}catch{throw new Error("argon2 is not available in this Node.js version. Node.js 24.7.0 or later is required for Argon2 password encoding. Please upgrade Node.js or use a different authentication method.")}return C}var M=16,B=19,V=B,ge="argon2id",D=16,J=32,F=4,L=65536,k=3;function W(e){let t=e.split("$");if(t.length<4)throw new Error("Invalid encoded Argon2 hash");let n=1,r=t[n++];if(r!=="argon2d"&&r!=="argon2i"&&r!=="argon2id")throw new Error("Invalid Argon2 type");let s=M;t[n].startsWith("v=")&&(s=parseInt(t[n].substring(2),10),n++);let a={},g=t[n++].split(",");for(let l of g){let[m,o]=l.split("=");switch(m){case"m":a.memory=parseInt(o,10);break;case"t":a.passes=parseInt(o,10);break;case"p":a.parallelism=parseInt(o,10);break}}a.nonce=Buffer.from(t[n++],"base64url");let i=Buffer.from(t[n++],"base64url");return{algorithm:r,version:s,parameters:a,hash:i}}function G(e){let{algorithm:t,version:n,parameters:r,hash:s}=e;return`$${t}$v=${n}$m=${r.memory},t=${r.passes},p=${r.parallelism}$${r.nonce.toString("base64url")}$${s.toString("base64url")}`}async function I(e,t,n,r){let s=r?.nonce??E(D),a=r?.memory??L,g=r?.passes??k,i=r?.parallelism??F,l={message:t,tagLength:n,nonce:s,memory:a,passes:g,parallelism:i},m=await me();return new Promise((o,p)=>{m(e,l,(d,h)=>{d?p(d):h?o(Buffer.from(h)):p(new Error("argon2 returned no result"))})})}async function ue(e,t){let n=t?.algorithm??"argon2id",r=t?.saltLength??D,s=t?.hashLength??J,a=t?.parallelism??F,g=t?.memory??L,i=t?.passes??k,l=E(r),m={memory:g,passes:i,parallelism:a,nonce:l},o=await I(n,e,s,m);return G({algorithm:n,version:V,parameters:m,hash:o})}async function pe(e,t){try{let n=W(e),r=await I(n.algorithm,t,n.hash.length,n.parameters);return n.hash.equals(r)}catch{return!1}}var Y={};b(Y,{sendCommand:()=>de});import fe from"net";function de(e,t,n={}){let{timeout:r=5e3}=n,s=e?.path?{path:e.path}:{port:e?.port??0},a=e?.path??`port ${e?.port}`;return new Promise((g,i)=>{let l=fe.connect(s,()=>{l.write(JSON.stringify(t))}),m=setTimeout(()=>{l.destroy(),i(new Error(`Connection timed out after ${r}`))},r);l.on("data",o=>{clearTimeout(m);try{let p=JSON.parse(o.toString());p.error?i(new Error(p.error)):g(p.result)}catch{g(o.toString())}l.end()}),l.on("error",o=>{clearTimeout(m),o.code==="ENOENT"||o.code==="ECONNREFUSED"?i(new Error(`Cannot connect to gateway at ${a}. Make sure the gateway server is running and the path is correct.`,{cause:o})):i(o)})})}var Z={};b(Z,{DEFAULT_CA_NAME:()=>X,generateCert:()=>Ae,generateRootCA:()=>we});import{KEYUTIL as w,KJUR as z,datetozulu as $}from"jsrsasign";import{userInfo as he,hostname as ye}from"node:os";import{randomBytes as be}from"node:crypto";var N=`${he().username}@${ye()}`;function Q(){return be(16).toString("hex")}var P="io.Gateway Dev CA",X=`${P} ${N}`;function we(e){let t=e?.name||X,n=e?.passphrase,r=w.generateKeypair("EC","secp384r1"),s=r.prvKeyObj,a=r.pubKeyObj,g=n?w.getPEM(s,"PKCS8PRV",n,"AES-256-CBC"):w.getPEM(s,"PKCS8PRV"),l=new z.asn1.x509.Certificate({version:3,serial:{hex:Q()},issuer:{str:`/CN=${t}/O=${P}/OU=${N}`},subject:{str:`/CN=${t}/O=${P}/OU=${N}`},notbefore:$(new Date(Date.now()-60*1e3),!1,!1),notafter:$(new Date(Date.now()+10*365*24*60*60*1e3),!1,!1),sbjpubkey:a,ext:[{extname:"basicConstraints",critical:!0,cA:!0},{extname:"keyUsage",critical:!0,names:["keyCertSign"]}],sigalg:"SHA384withECDSA",cakey:s}).getPEM();return{key:g,cert:l}}function Ae(e,t,n,r=!1,s=7){let a=w.generateKeypair("EC","secp256r1"),g=a.prvKeyObj,i=a.pubKeyObj,l=w.getPEM(g,"PKCS8PRV"),m=[],o=r?"dev-user":"localhost";for(let u of n)if(u.toLowerCase().startsWith("ip:"))m.push({ip:u.substring(3)});else if(u.toLowerCase().startsWith("email:"))m.push({rfc822:u.substring(6)});else{let S=u.toLowerCase().startsWith("dns:");if(r)o=S?u.substring(4):u;else{let x=S?u.substring(4):u;m.push({dns:x}),m.length===1&&(o=x)}}let p=[{extname:"basicConstraints",cA:!1},{extname:"keyUsage",critical:!0,names:["digitalSignature","keyEncipherment"]},{extname:"extKeyUsage",array:[r?"clientAuth":"serverAuth"]}];m.length>0&&p.push({extname:"subjectAltName",array:m});let h=new z.asn1.x509.Certificate({version:3,serial:{hex:Q()},issuer:{str:t},subject:{str:`/CN=${o}/O=${P}/OU=${N}`},notbefore:$(new Date(Date.now()-60*1e3),!1,!1),notafter:$(new Date(Date.now()+s*24*60*60*1e3),!1,!1),sbjpubkey:i,ext:p,sigalg:"SHA256withECDSA",cakey:e}).getPEM();return{key:l,cert:h}}var ne={};b(ne,{buildSea:()=>ve});import{access as re,copyFile as Se,readdir as xe,readFile as j,writeFile as ee}from"node:fs/promises";import{execFile as Ee}from"node:child_process";import{promisify as $e}from"node:util";import{createHash as Ne}from"node:crypto";import{basename as Pe,resolve as A}from"node:path";var y=$e(Ee);function R(e){return e.replace(/\\/g,"\\\\").replace(/'/g,"\\'")}async function ve(e,t){let n=t?.outDir??"./build",r=t?.config?.executable??process.execPath,s=R(e),a=R(t?.version??""),g=R(n.replace(/\\/g,"/")),{stdout:i}=await y(r,["-e",`
|
|
2
|
+
const { mkdirSync } = require('node:fs');
|
|
3
|
+
const path = require('node:path');
|
|
4
|
+
const appVersion = '${a}'.trim();
|
|
5
|
+
const dirName = '${s}' + (appVersion ? '-v' + appVersion : '') + '.' + process.platform + '-' + process.arch;
|
|
6
|
+
const dir = path.resolve('${g}', dirName);
|
|
7
|
+
mkdirSync(dir, { recursive: true });
|
|
8
|
+
process.stdout.write(JSON.stringify({ dirName, nodeVersion: process.version, platform: process.platform, arch: process.arch }));
|
|
9
|
+
`.trim()]),{dirName:l,nodeVersion:m,platform:o,arch:p}=JSON.parse(i),d;if(t?.esbuild){let c;try{c=await import("esbuild")}catch{throw new Error(`esbuild is required to bundle the entry point. Install it with:
|
|
10
|
+
|
|
11
|
+
npm install --save-dev esbuild
|
|
12
|
+
`)}d=`${n}/${e}.js`,await c.build({format:"cjs",target:"node20",platform:"node",bundle:!0,external:["esbuild","postject"],loader:{".md":"file",".d.ts":"file"},assetNames:`${l}/[name]`,entryNames:"[name]",outdir:n,minify:!0,logLevel:"info",...t.esbuild})}else if(t?.config?.main)d=A(t.config.main);else throw new Error("Either esbuild options (with entryPoints) or config.main must be provided.");let h=A(`${n}/${e}.sea.node-${m}-${o}-${p}.blob`),u=A(`${n}/${e}.sea-config.${l}.json`),S={disableExperimentalSEAWarning:!0,useSnapshot:!1,useCodeCache:!1,...t?.config,main:A(d),output:h};await ee(u,JSON.stringify(S,null,2));let x=A(n,l),v=o==="win32",O=o==="darwin",se=v?`${e}.exe`:e,f=`${x}/${se}`,oe=await j(d),U=`${n}/${Pe(d)}.sha`,K=Ne("sha256").update(oe).digest("hex"),_=!1;try{let[c]=await Promise.all([j(U,"utf8"),re(f)]);_=c===K}catch{}if(_)return console.log("SEA build skipped - esbuild output unchanged and target exists"),f;if(await y(r,["--experimental-sea-config",u]),await Se(r,f),v)try{let c=await te();c&&(console.log(`Found signtool at: ${c}`),await y(c,["remove","/s",f]),console.log(`Signature removed from ${f} executable`))}catch(c){console.warn("Failed to remove signature:",c.message)}else if(O)try{await y("codesign",["--remove-signature",f]),console.log(`Signature removed from ${f} executable`)}catch(c){console.warn("Failed to remove signature:",c.message)}let T;try{({inject:T}=await import("postject"))}catch{throw new Error(`postject is required to build a SEA. Install it with:
|
|
13
|
+
|
|
14
|
+
npm install --save-dev postject
|
|
15
|
+
`)}let ae=await j(h),ie=["NODE","SEA","FUSE","fce680ab2cc467b6e072b8b5df1996b2"].join("_");if(await T(f,"NODE_SEA_BLOB",ae,{overwrite:!0,sentinelFuse:ie,...O?{machoSegmentName:"NODE_SEA"}:{}}),v)try{let c=await te();c&&(console.log(`Signing executable with signtool at: ${c}`),await y(c,["sign","/fd","SHA256",f]),console.log("Executable signed successfully"))}catch(c){console.warn("Failed to sign executable:",c.message)}else if(O)try{await y("codesign",["--sign","-",f]),console.log("Executable signed successfully")}catch(c){console.warn("Failed to sign executable:",c.message)}return await ee(U,K),f}async function te(){let e="C:\\Program Files (x86)\\Windows Kits\\10\\bin";try{let n=(await xe(e,{withFileTypes:!0})).filter(r=>r.isDirectory()&&/^10\.0\.\d+\.\d+$/.test(r.name)).map(r=>r.name).sort((r,s)=>{let a=r.split(".").map(Number),g=s.split(".").map(Number);for(let i=0;i<a.length;i++)if(a[i]!==g[i])return g[i]-a[i];return 0});for(let r of n){let s=`${e}\\${r}\\${process.arch}\\signtool.exe`;try{return await re(s),s}catch{}}return console.warn("signtool.exe not found in any Windows SDK version"),null}catch(t){return console.warn(`Windows SDK not found at ${e}: ${t.message}`),null}}export{q as argon2,ne as build,H as keygen,Y as manage,Z as mkcert};
|
|
2
16
|
//# sourceMappingURL=tools.js.map
|
package/dist/tools.js.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
|
-
"sources": ["../src/tools/crypto/argon2.ts", "../src/tools/crypto/keygen.ts", "../src/manage/client.ts", "../src/tools/mkcert.ts"],
|
|
4
|
-
"sourcesContent": ["import type {\n Argon2Algorithm,\n Argon2Parameters\n} from 'node:crypto';\n\nimport { createSalt } from './keygen.ts';\nimport type { Argon2Hash, Argon2HashParameters } from '../../../types/crypto/argon2';\n\n// Lazy import for argon2 (added in Node.js 24.7.0)\n// This allows the module to load on older Node.js versions\nlet argon2: typeof import('node:crypto').argon2 | undefined;\n\nasync function getArgon2() {\n if (argon2 === undefined) {\n try {\n const crypto = await import('node:crypto');\n if (!crypto.argon2) {\n throw new Error('argon2 not available');\n }\n argon2 = crypto.argon2;\n } catch (err) {\n throw new Error(\n 'argon2 is not available in this Node.js version. ' +\n 'Node.js 24.7.0 or later is required for Argon2 password encoding. ' +\n 'Please upgrade Node.js or use a different authentication method.'\n );\n }\n }\n return argon2;\n}\n\n// Argon2 version constants\nexport const ARGON2_VERSION_10 = 0x10; // 16\nexport const ARGON2_VERSION_13 = 0x13; // 19\nexport const ARGON2_VERSION = ARGON2_VERSION_13;\n\n// Default parameters for Argon2 hashing\nexport const DEFAULT_ALGORITHM: Argon2Algorithm = 'argon2id';\nexport const DEFAULT_SALT_LENGTH = 16;\nexport const DEFAULT_HASH_LENGTH = 32;\nexport const DEFAULT_PARALLELISM = 4;\nexport const DEFAULT_MEMORY = 65536; // 64 MB in KiB\nexport const DEFAULT_PASSES = 3;\n\n/**\n * Decode an encoded Argon2 hash string into its components.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param encodedHash - The encoded Argon2 hash string\n * @returns Decoded hash components\n * @see https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244\n */\nexport function decode(encodedHash: string): Argon2Hash {\n const parts = encodedHash.split('$'); // ['', 'argon2id', 'v=19', 'm=65536,t=3,p=4', 'base64salt', 'base64hash']\n if (parts.length < 4) {\n throw new Error('Invalid encoded Argon2 hash');\n }\n let current = 1;\n const algorithm = parts[current++];\n if (algorithm !== 'argon2d' && algorithm !== 'argon2i' && algorithm !== 'argon2id') {\n throw new Error('Invalid Argon2 type');\n }\n let version = ARGON2_VERSION_10;\n if (parts[current].startsWith('v=')) {\n version = parseInt(parts[current].substring(2), 10);\n current++;\n }\n const parameters: Partial<Argon2HashParameters> = {};\n const paramsParts = parts[current++].split(',');\n\n for (const param of paramsParts) {\n const [key, value] = param.split('=');\n switch (key) {\n case 'm':\n parameters.memory = parseInt(value, 10);\n break;\n case 't':\n parameters.passes = parseInt(value, 10);\n break;\n case 'p':\n parameters.parallelism = parseInt(value, 10);\n break;\n }\n }\n parameters.nonce = Buffer.from(parts[current++], 'base64url');\n const hash = Buffer.from(parts[current++], 'base64url');\n\n return { algorithm, version, parameters: parameters as Argon2Hash['parameters'], hash };\n}\n\n/**\n * Encode Argon2 hash components into a standard string format.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param hashData - The hash components to encode\n * @returns Encoded hash string\n */\nexport function encode(hashData: Argon2Hash): string {\n const { algorithm, version, parameters, hash } = hashData;\n return `$${algorithm}$v=${version}$m=${parameters.memory},t=${parameters.passes},p=${parameters.parallelism}$${parameters.nonce.toString('base64url')}$${hash.toString('base64url')}`;\n}\n\n\n/**\n * Create an Argon2 hash from parameters.\n * Low-level wrapper around node:crypto's argon2.\n *\n * @param algorithm - Argon2 algorithm variant ('argon2d' | 'argon2i' | 'argon2id')\n * @param password - The password to hash\n * @param hashLength - Length of the output hash in bytes\n * @param parameters - Argon2 parameters (nonce, memory, passes, parallelism). If not provided, defaults will be used.\n * @returns The hash buffer\n */\nexport async function createHash(\n algorithm: Argon2Algorithm,\n password: string,\n hashLength: number,\n parameters?: Argon2Hash['parameters']\n): Promise<Buffer> {\n const nonce = parameters?.nonce ?? createSalt(DEFAULT_SALT_LENGTH);\n const memory = parameters?.memory ?? DEFAULT_MEMORY;\n const passes = parameters?.passes ?? DEFAULT_PASSES;\n const parallelism = parameters?.parallelism ?? DEFAULT_PARALLELISM;\n\n const argon2Params: Argon2Parameters = {\n message: password,\n tagLength: hashLength,\n nonce,\n memory,\n passes,\n parallelism\n };\n const argon2Fn = await getArgon2();\n\n // Wrap callback-based argon2 in a Promise\n return new Promise((resolve, reject) => {\n argon2Fn(algorithm, argon2Params, (err: Error | null, result?: Uint8Array) => {\n if (err) {\n reject(err);\n }\n else if (result) {\n resolve(Buffer.from(result));\n }\n else {\n reject(new Error('argon2 returned no result'));\n }\n });\n });\n}\n\n\n/**\n * Hash a password using Argon2.\n *\n * @param password - The plain text password to hash\n * @param options - Optional parameters object. If not provided, defaults will be used.\n * @returns The encoded Argon2 hash string\n */\nexport async function hash(\n password: string,\n options?: {\n algorithm?: Argon2Algorithm;\n saltLength?: number;\n hashLength?: number;\n parallelism?: number;\n memory?: number;\n passes?: number;\n }\n): Promise<string> {\n const algorithm = options?.algorithm ?? 'argon2id';\n const saltLength = options?.saltLength ?? DEFAULT_SALT_LENGTH;\n const hashLength = options?.hashLength ?? DEFAULT_HASH_LENGTH;\n const parallelism = options?.parallelism ?? DEFAULT_PARALLELISM;\n const memory = options?.memory ?? DEFAULT_MEMORY;\n const passes = options?.passes ?? DEFAULT_PASSES;\n\n const nonce = createSalt(saltLength);\n const parameters = { memory, passes, parallelism, nonce };\n const hashBuffer = await createHash(algorithm, password, hashLength, parameters);\n return encode({\n algorithm,\n version: ARGON2_VERSION,\n parameters,\n hash: hashBuffer\n });\n}\n\n/**\n * Verify a password against an Argon2 hash.\n *\n * @param encodedHash - The encoded Argon2 hash to verify against\n * @param password - The plain text password to verify\n * @returns true if password matches the hash, false otherwise\n */\nexport async function verify(encodedHash: string, password: string): Promise<boolean> {\n try {\n const decoded = decode(encodedHash);\n const hashBuffer = await createHash(\n decoded.algorithm,\n password,\n decoded.hash.length,\n decoded.parameters\n );\n return decoded.hash.equals(hashBuffer);\n } catch {\n return false;\n }\n}\n\n", "import { getRandomValues } from 'node:crypto';\n\n/**\n * Create a random salt (nonce) for cryptographic operations.\n *\n * @param length - Length of the salt in bytes\n * @returns Random salt buffer\n */\nexport function createSalt(length: number): Buffer {\n return getRandomValues(Buffer.alloc(length));\n}\n\n", "import net from 'net';\nimport type { ManagementCommand, ManagementEndpoint, SendCommandOptions } from '../../types/manage.d.ts';\n\nexport function sendCommand(\n server: ManagementEndpoint,\n command: ManagementCommand,\n options: SendCommandOptions = {}\n): Promise<unknown> {\n const { timeout = 5000 } = options;\n\n // Determine connection target: named pipe/socket path or port\n const connectOptions: net.NetConnectOpts = server?.path\n ? { path: server.path }\n : { port: server?.port ?? 0 };\n\n const target = server?.path ?? `port ${server?.port}`;\n\n return new Promise((resolve, reject) => {\n const client = net.connect(connectOptions, () => {\n client.write(JSON.stringify(command));\n });\n\n const timeoutId = setTimeout(() => {\n client.destroy();\n reject(new Error(`Connection timed out after ${timeout}`));\n }, timeout);\n\n client.on('data', (data) => {\n clearTimeout(timeoutId);\n try {\n const response = JSON.parse(data.toString());\n if (response.error) {\n reject(new Error(response.error));\n }\n else {\n resolve(response.result);\n }\n }\n catch {\n // Not JSON, return as raw string\n resolve(data.toString());\n }\n client.end();\n });\n\n client.on('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeoutId);\n if (err.code === 'ENOENT' || err.code === 'ECONNREFUSED') {\n reject(new Error(`Cannot connect to gateway at ${target}. Make sure the gateway server is running and the path is correct.`, { cause: err }));\n }\n else {\n reject(err);\n }\n });\n });\n}\n\n", "import { KEYUTIL, KJUR, RSAKey, datetozulu } from \"jsrsasign\";\nimport { userInfo, hostname } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\nconst userAndHost = `${userInfo().username}@${hostname()}`;\n\nfunction randomSerialNumber(): string {\n const bytes = randomBytes(16);\n return bytes.toString('hex');\n}\n\nconst DEFAULT_ORGANISATION = `io.Gateway Dev CA`;\nexport const DEFAULT_CA_NAME = `${DEFAULT_ORGANISATION} ${userAndHost}`;\n\nexport function generateRootCA(options?: { name?: string, passphrase?: string } ): { key: string, cert: string } {\n\n const commonName = options?.name || DEFAULT_CA_NAME;\n const passphrase = options?.passphrase;\n\n // STEP 1. generate a key pair for Root CA (secp384r1 for higher security)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp384r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = passphrase\n ? KEYUTIL.getPEM(prv, \"PKCS8PRV\", passphrase, \"AES-256-CBC\")\n : KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // STEP 2: create self-signed CA certificate\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000), false, false), // 10 years\n\n sbjpubkey: pub,\n\n ext: [\n {extname: \"basicConstraints\", critical: true, cA: true},\n {extname: \"keyUsage\", critical: true, names: [\"keyCertSign\"]}\n ],\n\n sigalg: \"SHA384withECDSA\",\n cakey: prv\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n\n\n/**\n * Generate a certificate with custom SAN entries\n * @param cakey - CA private key\n * @param issuer - Issuer DN string\n * @param sanEntries - Array of SAN entry strings (e.g., \"localhost\", \"IP:192.168.1.1\", \"EMAIL:user@example.com\")\n * @param isClient - Generate client cert (clientAuth) vs server cert (serverAuth)\n * @param validityDays - Certificate validity period\n */\nexport function generateCert(\n cakey: string | RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA,\n issuer: string,\n sanEntries: string[],\n isClient: boolean = false,\n validityDays: number = 7\n): {\n key: string,\n cert: string\n} {\n // STEP 1. generate key pair (secp256r1 for faster generation)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp256r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // Parse SAN entries\n const sanArray: Array<{dns?: string, ip?: string, rfc822?: string}> = [];\n let commonName = isClient ? 'dev-user' : 'localhost';\n\n for (const entry of sanEntries) {\n if (entry.toLowerCase().startsWith('ip:')) {\n sanArray.push({ip: entry.substring(3)});\n }\n else if (entry.toLowerCase().startsWith('email:')) {\n sanArray.push({rfc822: entry.substring(6)});\n }\n else {\n const dnsPrefixed = entry.toLowerCase().startsWith('dns:');\n if (isClient) {\n commonName = dnsPrefixed ? entry.substring(4) : entry;\n }\n else {\n const dns = dnsPrefixed ? entry.substring(4) : entry;\n sanArray.push({dns});\n if (sanArray.length === 1) {\n commonName = dns; // Use first DNS as CN\n }\n }\n }\n }\n\n // STEP 2: create certificate signed by CA\n const extensions: Array<{\n extname: string;\n cA?: boolean;\n critical?: boolean;\n names?: string[];\n array?: (string[] | Array<{dns?: string, ip?: string, rfc822?: string}>);\n }> = [\n {extname: \"basicConstraints\", cA: false},\n {\n extname: \"keyUsage\",\n critical: true,\n names: [\"digitalSignature\", \"keyEncipherment\"]\n },\n {\n extname: \"extKeyUsage\",\n array: [isClient ? \"clientAuth\" : \"serverAuth\"]\n }\n ];\n\n // Add SAN only if we have entries\n if (sanArray.length > 0) {\n extensions.push({\n extname: \"subjectAltName\",\n array: sanArray\n });\n }\n\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: issuer },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}`},\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + validityDays * 24 * 60 * 60 * 1000), false, false),\n\n sbjpubkey: pub,\n ext: extensions,\n\n sigalg: \"SHA256withECDSA\",\n cakey: cakey\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n"],
|
|
5
|
-
"mappings": "
|
|
6
|
-
"names": ["argon2_exports", "__export", "ARGON2_VERSION", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "DEFAULT_ALGORITHM", "DEFAULT_HASH_LENGTH", "DEFAULT_MEMORY", "DEFAULT_PARALLELISM", "DEFAULT_PASSES", "DEFAULT_SALT_LENGTH", "createHash", "decode", "encode", "hash", "verify", "keygen_exports", "__export", "createSalt", "getRandomValues", "length", "argon2", "getArgon2", "crypto", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "ARGON2_VERSION", "DEFAULT_ALGORITHM", "DEFAULT_SALT_LENGTH", "DEFAULT_HASH_LENGTH", "DEFAULT_PARALLELISM", "DEFAULT_MEMORY", "DEFAULT_PASSES", "decode", "encodedHash", "parts", "current", "algorithm", "version", "parameters", "paramsParts", "param", "key", "value", "hash", "encode", "hashData", "createHash", "password", "hashLength", "nonce", "createSalt", "memory", "passes", "parallelism", "argon2Params", "argon2Fn", "resolve", "reject", "err", "result", "options", "saltLength", "hashBuffer", "verify", "decoded", "client_exports", "__export", "sendCommand", "net", "server", "command", "options", "timeout", "connectOptions", "target", "resolve", "reject", "client", "timeoutId", "data", "response", "err", "mkcert_exports", "__export", "DEFAULT_CA_NAME", "generateCert", "generateRootCA", "KEYUTIL", "KJUR", "datetozulu", "userInfo", "hostname", "randomBytes", "userAndHost", "randomSerialNumber", "DEFAULT_ORGANISATION", "options", "commonName", "passphrase", "kp", "prv", "pub", "prvPem", "certPem", "cakey", "issuer", "sanEntries", "isClient", "validityDays", "sanArray", "entry", "dnsPrefixed", "dns", "extensions"]
|
|
3
|
+
"sources": ["../src/tools/crypto/argon2.ts", "../src/tools/crypto/keygen.ts", "../src/manage/client.ts", "../src/tools/mkcert.ts", "../src/tools/build.ts"],
|
|
4
|
+
"sourcesContent": ["import type {\n Argon2Algorithm,\n Argon2Parameters\n} from 'node:crypto';\n\nimport { createSalt } from './keygen.ts';\nimport type { Argon2Hash, Argon2HashParameters } from '../../../types/crypto/argon2';\n\n// Lazy import for argon2 (added in Node.js 24.7.0)\n// This allows the module to load on older Node.js versions\nlet argon2: typeof import('node:crypto').argon2 | undefined;\n\nasync function getArgon2() {\n if (argon2 === undefined) {\n try {\n const crypto = await import('node:crypto');\n if (!crypto.argon2) {\n throw new Error('argon2 not available');\n }\n argon2 = crypto.argon2;\n } catch (err) {\n throw new Error(\n 'argon2 is not available in this Node.js version. ' +\n 'Node.js 24.7.0 or later is required for Argon2 password encoding. ' +\n 'Please upgrade Node.js or use a different authentication method.'\n );\n }\n }\n return argon2;\n}\n\n// Argon2 version constants\nexport const ARGON2_VERSION_10 = 0x10; // 16\nexport const ARGON2_VERSION_13 = 0x13; // 19\nexport const ARGON2_VERSION = ARGON2_VERSION_13;\n\n// Default parameters for Argon2 hashing\nexport const DEFAULT_ALGORITHM: Argon2Algorithm = 'argon2id';\nexport const DEFAULT_SALT_LENGTH = 16;\nexport const DEFAULT_HASH_LENGTH = 32;\nexport const DEFAULT_PARALLELISM = 4;\nexport const DEFAULT_MEMORY = 65536; // 64 MB in KiB\nexport const DEFAULT_PASSES = 3;\n\n/**\n * Decode an encoded Argon2 hash string into its components.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param encodedHash - The encoded Argon2 hash string\n * @returns Decoded hash components\n * @see https://github.com/P-H-C/phc-winner-argon2/blob/master/src/encoding.c#L244\n */\nexport function decode(encodedHash: string): Argon2Hash {\n const parts = encodedHash.split('$'); // ['', 'argon2id', 'v=19', 'm=65536,t=3,p=4', 'base64salt', 'base64hash']\n if (parts.length < 4) {\n throw new Error('Invalid encoded Argon2 hash');\n }\n let current = 1;\n const algorithm = parts[current++];\n if (algorithm !== 'argon2d' && algorithm !== 'argon2i' && algorithm !== 'argon2id') {\n throw new Error('Invalid Argon2 type');\n }\n let version = ARGON2_VERSION_10;\n if (parts[current].startsWith('v=')) {\n version = parseInt(parts[current].substring(2), 10);\n current++;\n }\n const parameters: Partial<Argon2HashParameters> = {};\n const paramsParts = parts[current++].split(',');\n\n for (const param of paramsParts) {\n const [key, value] = param.split('=');\n switch (key) {\n case 'm':\n parameters.memory = parseInt(value, 10);\n break;\n case 't':\n parameters.passes = parseInt(value, 10);\n break;\n case 'p':\n parameters.parallelism = parseInt(value, 10);\n break;\n }\n }\n parameters.nonce = Buffer.from(parts[current++], 'base64url');\n const hash = Buffer.from(parts[current++], 'base64url');\n\n return { algorithm, version, parameters: parameters as Argon2Hash['parameters'], hash };\n}\n\n/**\n * Encode Argon2 hash components into a standard string format.\n * Format: $argon2id$v=19$m=65536,t=3,p=4$base64salt$base64hash\n *\n * @param hashData - The hash components to encode\n * @returns Encoded hash string\n */\nexport function encode(hashData: Argon2Hash): string {\n const { algorithm, version, parameters, hash } = hashData;\n return `$${algorithm}$v=${version}$m=${parameters.memory},t=${parameters.passes},p=${parameters.parallelism}$${parameters.nonce.toString('base64url')}$${hash.toString('base64url')}`;\n}\n\n\n/**\n * Create an Argon2 hash from parameters.\n * Low-level wrapper around node:crypto's argon2.\n *\n * @param algorithm - Argon2 algorithm variant ('argon2d' | 'argon2i' | 'argon2id')\n * @param password - The password to hash\n * @param hashLength - Length of the output hash in bytes\n * @param parameters - Argon2 parameters (nonce, memory, passes, parallelism). If not provided, defaults will be used.\n * @returns The hash buffer\n */\nexport async function createHash(\n algorithm: Argon2Algorithm,\n password: string,\n hashLength: number,\n parameters?: Argon2Hash['parameters']\n): Promise<Buffer> {\n const nonce = parameters?.nonce ?? createSalt(DEFAULT_SALT_LENGTH);\n const memory = parameters?.memory ?? DEFAULT_MEMORY;\n const passes = parameters?.passes ?? DEFAULT_PASSES;\n const parallelism = parameters?.parallelism ?? DEFAULT_PARALLELISM;\n\n const argon2Params: Argon2Parameters = {\n message: password,\n tagLength: hashLength,\n nonce,\n memory,\n passes,\n parallelism\n };\n const argon2Fn = await getArgon2();\n\n // Wrap callback-based argon2 in a Promise\n return new Promise((resolve, reject) => {\n argon2Fn(algorithm, argon2Params, (err: Error | null, result?: Uint8Array) => {\n if (err) {\n reject(err);\n }\n else if (result) {\n resolve(Buffer.from(result));\n }\n else {\n reject(new Error('argon2 returned no result'));\n }\n });\n });\n}\n\n\n/**\n * Hash a password using Argon2.\n *\n * @param password - The plain text password to hash\n * @param options - Optional parameters object. If not provided, defaults will be used.\n * @returns The encoded Argon2 hash string\n */\nexport async function hash(\n password: string,\n options?: {\n algorithm?: Argon2Algorithm;\n saltLength?: number;\n hashLength?: number;\n parallelism?: number;\n memory?: number;\n passes?: number;\n }\n): Promise<string> {\n const algorithm = options?.algorithm ?? 'argon2id';\n const saltLength = options?.saltLength ?? DEFAULT_SALT_LENGTH;\n const hashLength = options?.hashLength ?? DEFAULT_HASH_LENGTH;\n const parallelism = options?.parallelism ?? DEFAULT_PARALLELISM;\n const memory = options?.memory ?? DEFAULT_MEMORY;\n const passes = options?.passes ?? DEFAULT_PASSES;\n\n const nonce = createSalt(saltLength);\n const parameters = { memory, passes, parallelism, nonce };\n const hashBuffer = await createHash(algorithm, password, hashLength, parameters);\n return encode({\n algorithm,\n version: ARGON2_VERSION,\n parameters,\n hash: hashBuffer\n });\n}\n\n/**\n * Verify a password against an Argon2 hash.\n *\n * @param encodedHash - The encoded Argon2 hash to verify against\n * @param password - The plain text password to verify\n * @returns true if password matches the hash, false otherwise\n */\nexport async function verify(encodedHash: string, password: string): Promise<boolean> {\n try {\n const decoded = decode(encodedHash);\n const hashBuffer = await createHash(\n decoded.algorithm,\n password,\n decoded.hash.length,\n decoded.parameters\n );\n return decoded.hash.equals(hashBuffer);\n } catch {\n return false;\n }\n}\n\n", "import { getRandomValues } from 'node:crypto';\n\n/**\n * Create a random salt (nonce) for cryptographic operations.\n *\n * @param length - Length of the salt in bytes\n * @returns Random salt buffer\n */\nexport function createSalt(length: number): Buffer {\n return getRandomValues(Buffer.alloc(length));\n}\n\n", "import net from 'net';\nimport type { ManagementCommand, ManagementEndpoint, SendCommandOptions } from '../../types/manage.d.ts';\n\nexport function sendCommand(\n server: ManagementEndpoint,\n command: ManagementCommand,\n options: SendCommandOptions = {}\n): Promise<unknown> {\n const { timeout = 5000 } = options;\n\n // Determine connection target: named pipe/socket path or port\n const connectOptions: net.NetConnectOpts = server?.path\n ? { path: server.path }\n : { port: server?.port ?? 0 };\n\n const target = server?.path ?? `port ${server?.port}`;\n\n return new Promise((resolve, reject) => {\n const client = net.connect(connectOptions, () => {\n client.write(JSON.stringify(command));\n });\n\n const timeoutId = setTimeout(() => {\n client.destroy();\n reject(new Error(`Connection timed out after ${timeout}`));\n }, timeout);\n\n client.on('data', (data) => {\n clearTimeout(timeoutId);\n try {\n const response = JSON.parse(data.toString());\n if (response.error) {\n reject(new Error(response.error));\n }\n else {\n resolve(response.result);\n }\n }\n catch {\n // Not JSON, return as raw string\n resolve(data.toString());\n }\n client.end();\n });\n\n client.on('error', (err: NodeJS.ErrnoException) => {\n clearTimeout(timeoutId);\n if (err.code === 'ENOENT' || err.code === 'ECONNREFUSED') {\n reject(new Error(`Cannot connect to gateway at ${target}. Make sure the gateway server is running and the path is correct.`, { cause: err }));\n }\n else {\n reject(err);\n }\n });\n });\n}\n\n", "import { KEYUTIL, KJUR, RSAKey, datetozulu } from \"jsrsasign\";\nimport { userInfo, hostname } from 'node:os';\nimport { randomBytes } from 'node:crypto';\n\nconst userAndHost = `${userInfo().username}@${hostname()}`;\n\nfunction randomSerialNumber(): string {\n const bytes = randomBytes(16);\n return bytes.toString('hex');\n}\n\nconst DEFAULT_ORGANISATION = `io.Gateway Dev CA`;\nexport const DEFAULT_CA_NAME = `${DEFAULT_ORGANISATION} ${userAndHost}`;\n\nexport function generateRootCA(options?: { name?: string, passphrase?: string } ): { key: string, cert: string } {\n\n const commonName = options?.name || DEFAULT_CA_NAME;\n const passphrase = options?.passphrase;\n\n // STEP 1. generate a key pair for Root CA (secp384r1 for higher security)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp384r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = passphrase\n ? KEYUTIL.getPEM(prv, \"PKCS8PRV\", passphrase, \"AES-256-CBC\")\n : KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // STEP 2: create self-signed CA certificate\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}` },\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + 10 * 365 * 24 * 60 * 60 * 1000), false, false), // 10 years\n\n sbjpubkey: pub,\n\n ext: [\n {extname: \"basicConstraints\", critical: true, cA: true},\n {extname: \"keyUsage\", critical: true, names: [\"keyCertSign\"]}\n ],\n\n sigalg: \"SHA384withECDSA\",\n cakey: prv\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n\n\n/**\n * Generate a certificate with custom SAN entries\n * @param cakey - CA private key\n * @param issuer - Issuer DN string\n * @param sanEntries - Array of SAN entry strings (e.g., \"localhost\", \"IP:192.168.1.1\", \"EMAIL:user@example.com\")\n * @param isClient - Generate client cert (clientAuth) vs server cert (serverAuth)\n * @param validityDays - Certificate validity period\n */\nexport function generateCert(\n cakey: string | RSAKey | KJUR.crypto.DSA | KJUR.crypto.ECDSA,\n issuer: string,\n sanEntries: string[],\n isClient: boolean = false,\n validityDays: number = 7\n): {\n key: string,\n cert: string\n} {\n // STEP 1. generate key pair (secp256r1 for faster generation)\n const kp = KEYUTIL.generateKeypair(\"EC\", \"secp256r1\");\n const prv = kp.prvKeyObj;\n const pub = kp.pubKeyObj;\n\n const prvPem = KEYUTIL.getPEM(prv, \"PKCS8PRV\");\n\n // Parse SAN entries\n const sanArray: Array<{dns?: string, ip?: string, rfc822?: string}> = [];\n let commonName = isClient ? 'dev-user' : 'localhost';\n\n for (const entry of sanEntries) {\n if (entry.toLowerCase().startsWith('ip:')) {\n sanArray.push({ip: entry.substring(3)});\n }\n else if (entry.toLowerCase().startsWith('email:')) {\n sanArray.push({rfc822: entry.substring(6)});\n }\n else {\n const dnsPrefixed = entry.toLowerCase().startsWith('dns:');\n if (isClient) {\n commonName = dnsPrefixed ? entry.substring(4) : entry;\n }\n else {\n const dns = dnsPrefixed ? entry.substring(4) : entry;\n sanArray.push({dns});\n if (sanArray.length === 1) {\n commonName = dns; // Use first DNS as CN\n }\n }\n }\n }\n\n // STEP 2: create certificate signed by CA\n const extensions: Array<{\n extname: string;\n cA?: boolean;\n critical?: boolean;\n names?: string[];\n array?: (string[] | Array<{dns?: string, ip?: string, rfc822?: string}>);\n }> = [\n {extname: \"basicConstraints\", cA: false},\n {\n extname: \"keyUsage\",\n critical: true,\n names: [\"digitalSignature\", \"keyEncipherment\"]\n },\n {\n extname: \"extKeyUsage\",\n array: [isClient ? \"clientAuth\" : \"serverAuth\"]\n }\n ];\n\n // Add SAN only if we have entries\n if (sanArray.length > 0) {\n extensions.push({\n extname: \"subjectAltName\",\n array: sanArray\n });\n }\n\n const cert = new KJUR.asn1.x509.Certificate({\n version: 3,\n serial: { hex: randomSerialNumber() },\n issuer: { str: issuer },\n subject: { str: `/CN=${commonName}/O=${DEFAULT_ORGANISATION}/OU=${userAndHost}`},\n\n notbefore: datetozulu(new Date(Date.now() - 60 * 1000), false, false),\n notafter: datetozulu(new Date(Date.now() + validityDays * 24 * 60 * 60 * 1000), false, false),\n\n sbjpubkey: pub,\n ext: extensions,\n\n sigalg: \"SHA256withECDSA\",\n cakey: cakey\n });\n\n const certPem = cert.getPEM();\n\n return {\n key: prvPem,\n cert: certPem\n };\n}\n", "import { access, copyFile, readdir, readFile, writeFile } from 'node:fs/promises';\nimport { execFile as execFileCb } from 'node:child_process';\nimport { promisify } from 'node:util';\nimport { createHash } from 'node:crypto';\nimport { basename, resolve } from 'node:path';\n\nimport type { BuildSeaOptions } from '../../types/build.d.ts';\n\nconst execFile = promisify(execFileCb);\n\n/**\n * Escapes a string for safe interpolation inside a single-quoted JS string literal.\n */\nfunction escapeForSingleQuotedString(value: string): string {\n return value.replace(/\\\\/g, '\\\\\\\\').replace(/'/g, \"\\\\'\");\n}\n\nexport async function buildSea(name: string, options?: BuildSeaOptions): Promise<string> {\n const outDir = options?.outDir ?? './build';\n const nodeExecutable = options?.config?.executable ?? process.execPath;\n\n const safeName = escapeForSingleQuotedString(name);\n const safeVersion = escapeForSingleQuotedString(options?.version ?? '');\n const safeOutDir = escapeForSingleQuotedString(outDir.replace(/\\\\/g, '/'));\n\n // Use the target node executable to create the output directory and resolve\n // platform-specific paths. This also validates the executable is functional.\n const { stdout } = await execFile(nodeExecutable, ['-e', `\n const { mkdirSync } = require('node:fs');\n const path = require('node:path');\n const appVersion = '${safeVersion}'.trim();\n const dirName = '${safeName}' + (appVersion ? '-v' + appVersion : '') + '.' + process.platform + '-' + process.arch;\n const dir = path.resolve('${safeOutDir}', dirName);\n mkdirSync(dir, { recursive: true });\n process.stdout.write(JSON.stringify({ dirName, nodeVersion: process.version, platform: process.platform, arch: process.arch }));\n `.trim()]);\n\n const { dirName, nodeVersion, platform, arch } = JSON.parse(stdout);\n\n // Step 1: Produce the SEA JavaScript file\n let seaMain: string;\n if (options?.esbuild) {\n let esbuild: typeof import('esbuild');\n try {\n esbuild = await import('esbuild');\n }\n catch {\n throw new Error('esbuild is required to bundle the entry point. Install it with:\\n\\n npm install --save-dev esbuild\\n');\n }\n seaMain = `${outDir}/${name}.js`;\n await esbuild.build({\n format: 'cjs',\n target: 'node20',\n platform: 'node',\n bundle: true,\n external: ['esbuild', 'postject'], // exclude esbuild from the bundle since it's only needed at build time\n loader: {\n \".md\": \"file\",\n \".d.ts\": \"file\",\n },\n assetNames: `${dirName}/[name]`,\n entryNames: '[name]',\n outdir: outDir,\n minify: true,\n logLevel: 'info',\n ...options.esbuild,\n });\n }\n else if (options?.config?.main) {\n seaMain = resolve(options.config.main);\n }\n else {\n throw new Error('Either esbuild options (with entryPoints) or config.main must be provided.');\n }\n\n // Write SEA config file in the build folder\n const blobPath = resolve(`${outDir}/${name}.sea.node-${nodeVersion}-${platform}-${arch}.blob`);\n const configPath = resolve(`${outDir}/${name}.sea-config.${dirName}.json`);\n const seaConfig = {\n disableExperimentalSEAWarning: true,\n useSnapshot: false,\n useCodeCache: false,\n ...options?.config,\n main: resolve(seaMain),\n output: blobPath,\n };\n await writeFile(configPath, JSON.stringify(seaConfig, null, 2));\n\n const nativePath = resolve(outDir, dirName);\n\n const isWindows = platform === 'win32';\n const isMacos = platform === 'darwin';\n const targetFile = isWindows ? `${name}.exe` : name;\n const targetPath = `${nativePath}/${targetFile}`;\n\n\n // Check if we can skip the SEA build\n const seaJsContent = await readFile(seaMain);\n const shaPath = `${outDir}/${basename(seaMain)}.sha`;\n\n const currentSha = createHash('sha256').update(seaJsContent).digest('hex');\n let canSkip = false;\n\n try {\n const [previousSha] = await Promise.all([\n readFile(shaPath, 'utf8'),\n access(targetPath)\n ]);\n canSkip = previousSha === currentSha;\n }\n catch {\n // SHA file or target doesn't exist, need to build\n }\n if (canSkip) {\n console.log('SEA build skipped - esbuild output unchanged and target exists');\n return targetPath;\n }\n\n // Step 3: Generate the blob to be injected\n await execFile(nodeExecutable, ['--experimental-sea-config', configPath]);\n\n // Step 4: Copy the Node.js executable to the target path\n await copyFile(nodeExecutable, targetPath);\n\n // Step 5: Remove the signature of the binary\n if (isWindows) {\n try {\n const signtool = await findSigntool();\n if (signtool) {\n console.log(`Found signtool at: ${signtool}`);\n await execFile(signtool, ['remove', '/s', targetPath]);\n console.log(`Signature removed from ${targetPath} executable`);\n }\n }\n catch (e: any) {\n console.warn('Failed to remove signature:', e.message);\n }\n }\n else if (isMacos) {\n try {\n await execFile('codesign', ['--remove-signature', targetPath]);\n console.log(`Signature removed from ${targetPath} executable`);\n }\n catch (e: any) {\n console.warn('Failed to remove signature:', e.message);\n }\n }\n\n // Step 6: Inject the SEA blob into the binary\n type InjectOptions = {\n /**\n * @default '__POSTJECT'\n */\n machoSegmentName?: string;\n /**\n * @default false\n */\n overwrite?: boolean;\n /**\n * @default 'POSTJECT_SENTINEL_fce680ab2cc467b6e072b8b5df1996b2'\n */\n sentinelFuse?: string\n };\n type Inject = (filename: string, resourceName: string, resourceData: Buffer, options?: InjectOptions) => Promise<void>;\n\n let inject: Inject;\n try {\n ({ inject } = await import('postject') as { inject: Inject });\n }\n catch {\n throw new Error('postject is required to build a SEA. Install it with:\\n\\n npm install --save-dev postject\\n');\n }\n\n const resourceData = await readFile(blobPath);\n\n // Construct the sentinel fuse at runtime to avoid the literal appearing in the\n // bundled SEA output \u2014 postject would otherwise find multiple occurrences.\n const sentinelFuse = ['NODE', 'SEA', 'FUSE', 'fce680ab2cc467b6e072b8b5df1996b2'].join('_');\n\n await inject(\n targetPath,\n 'NODE_SEA_BLOB',\n resourceData,\n {\n overwrite: true,\n sentinelFuse,\n ...(isMacos ? { machoSegmentName: 'NODE_SEA' } : {})\n });\n\n // Step 7: Sign the binary\n if (isWindows) {\n try {\n const signtool = await findSigntool();\n if (signtool) {\n console.log(`Signing executable with signtool at: ${signtool}`);\n await execFile(signtool, ['sign', '/fd', 'SHA256', targetPath]);\n console.log(`Executable signed successfully`);\n }\n }\n catch (e: any) {\n console.warn('Failed to sign executable:', e.message);\n }\n }\n else if (isMacos) {\n try {\n await execFile('codesign', ['--sign', '-', targetPath]);\n console.log(`Executable signed successfully`);\n }\n catch (e: any) {\n console.warn('Failed to sign executable:', e.message);\n }\n }\n\n // Save SHA for next build comparison\n await writeFile(shaPath, currentSha);\n return targetPath;\n}\n\nasync function findSigntool(): Promise<string | null> {\n const windowsKitsPath = 'C:\\\\Program Files (x86)\\\\Windows Kits\\\\10\\\\bin';\n\n try {\n const entries = await readdir(windowsKitsPath, { withFileTypes: true });\n\n // Filter directories that match version pattern (e.g., 10.0.22621.0)\n const versionDirs = entries\n .filter(entry => entry.isDirectory() && /^10\\.0\\.\\d+\\.\\d+$/.test(entry.name))\n .map(entry => entry.name)\n .sort((a, b) => {\n // Sort by version number descending to get the latest\n const partsA = a.split('.').map(Number);\n const partsB = b.split('.').map(Number);\n for (let i = 0; i < partsA.length; i++) {\n if (partsA[i] !== partsB[i]) {\n return partsB[i] - partsA[i];\n }\n }\n return 0;\n });\n\n // Try each version directory, starting with the latest\n for (const version of versionDirs) {\n const signtoolPath = `${windowsKitsPath}\\\\${version}\\\\${process.arch}\\\\signtool.exe`;\n try {\n await access(signtoolPath);\n return signtoolPath;\n }\n catch {\n // signtool not found in this version, try next\n }\n }\n\n console.warn('signtool.exe not found in any Windows SDK version');\n return null;\n }\n catch (e: any) {\n console.warn(`Windows SDK not found at ${windowsKitsPath}: ${e.message}`);\n return null;\n }\n}\n\n"],
|
|
5
|
+
"mappings": "4FAAA,IAAAA,EAAA,GAAAC,EAAAD,EAAA,oBAAAE,EAAA,sBAAAC,EAAA,sBAAAC,EAAA,sBAAAC,GAAA,wBAAAC,EAAA,mBAAAC,EAAA,wBAAAC,EAAA,mBAAAC,EAAA,wBAAAC,EAAA,eAAAC,EAAA,WAAAC,EAAA,WAAAC,EAAA,SAAAC,GAAA,WAAAC,KCAA,IAAAC,EAAA,GAAAC,EAAAD,EAAA,gBAAAE,IAAA,OAAS,mBAAAC,OAAuB,cAQzB,SAASD,EAAWE,EAAwB,CAC/C,OAAOD,GAAgB,OAAO,MAAMC,CAAM,CAAC,CAC/C,CDAA,IAAIC,EAEJ,eAAeC,IAAY,CACvB,GAAID,IAAW,OACX,GAAI,CACA,IAAME,EAAS,KAAM,QAAO,aAAa,EACzC,GAAI,CAACA,EAAO,OACR,MAAM,IAAI,MAAM,sBAAsB,EAE1CF,EAASE,EAAO,MACpB,MAAc,CACV,MAAM,IAAI,MACN,qLAGJ,CACJ,CAEJ,OAAOF,CACX,CAGO,IAAMG,EAAoB,GACpBC,EAAoB,GACpBC,EAAiBD,EAGjBE,GAAqC,WACrCC,EAAsB,GACtBC,EAAsB,GACtBC,EAAsB,EACtBC,EAAiB,MACjBC,EAAiB,EAUvB,SAASC,EAAOC,EAAiC,CACpD,IAAMC,EAAQD,EAAY,MAAM,GAAG,EACnC,GAAIC,EAAM,OAAS,EACf,MAAM,IAAI,MAAM,6BAA6B,EAEjD,IAAIC,EAAU,EACRC,EAAYF,EAAMC,GAAS,EACjC,GAAIC,IAAc,WAAaA,IAAc,WAAaA,IAAc,WACpE,MAAM,IAAI,MAAM,qBAAqB,EAEzC,IAAIC,EAAUd,EACVW,EAAMC,CAAO,EAAE,WAAW,IAAI,IAC9BE,EAAU,SAASH,EAAMC,CAAO,EAAE,UAAU,CAAC,EAAG,EAAE,EAClDA,KAEJ,IAAMG,EAA4C,CAAC,EAC7CC,EAAcL,EAAMC,GAAS,EAAE,MAAM,GAAG,EAE9C,QAAWK,KAASD,EAAa,CAC7B,GAAM,CAACE,EAAKC,CAAK,EAAIF,EAAM,MAAM,GAAG,EACpC,OAAQC,EAAK,CACT,IAAK,IACDH,EAAW,OAAS,SAASI,EAAO,EAAE,EACtC,MACJ,IAAK,IACDJ,EAAW,OAAS,SAASI,EAAO,EAAE,EACtC,MACJ,IAAK,IACDJ,EAAW,YAAc,SAASI,EAAO,EAAE,EAC3C,KACR,CACJ,CACAJ,EAAW,MAAQ,OAAO,KAAKJ,EAAMC,GAAS,EAAG,WAAW,EAC5D,IAAMQ,EAAO,OAAO,KAAKT,EAAMC,GAAS,EAAG,WAAW,EAEtD,MAAO,CAAE,UAAAC,EAAW,QAAAC,EAAS,WAAYC,EAAwC,KAAAK,CAAK,CAC1F,CASO,SAASC,EAAOC,EAA8B,CACjD,GAAM,CAAE,UAAAT,EAAW,QAAAC,EAAS,WAAAC,EAAY,KAAAK,CAAK,EAAIE,EACjD,MAAO,IAAIT,CAAS,MAAMC,CAAO,MAAMC,EAAW,MAAM,MAAMA,EAAW,MAAM,MAAMA,EAAW,WAAW,IAAIA,EAAW,MAAM,SAAS,WAAW,CAAC,IAAIK,EAAK,SAAS,WAAW,CAAC,EACvL,CAaA,eAAsBG,EAClBV,EACAW,EACAC,EACAV,EACe,CACf,IAAMW,EAAQX,GAAY,OAASY,EAAWvB,CAAmB,EAC3DwB,EAASb,GAAY,QAAUR,EAC/BsB,EAASd,GAAY,QAAUP,EAC/BsB,EAAcf,GAAY,aAAeT,EAEzCyB,EAAiC,CACnC,QAASP,EACT,UAAWC,EACX,MAAAC,EACA,OAAAE,EACA,OAAAC,EACA,YAAAC,CACJ,EACME,EAAW,MAAMlC,GAAU,EAGjC,OAAO,IAAI,QAAQ,CAACmC,EAASC,IAAW,CACpCF,EAASnB,EAAWkB,EAAc,CAACI,EAAmBC,IAAwB,CACtED,EACAD,EAAOC,CAAG,EAELC,EACLH,EAAQ,OAAO,KAAKG,CAAM,CAAC,EAG3BF,EAAO,IAAI,MAAM,2BAA2B,CAAC,CAErD,CAAC,CACL,CAAC,CACL,CAUA,eAAsBd,GAClBI,EACAa,EAQe,CACf,IAAMxB,EAAYwB,GAAS,WAAa,WAClCC,EAAaD,GAAS,YAAcjC,EACpCqB,EAAaY,GAAS,YAAchC,EACpCyB,EAAcO,GAAS,aAAe/B,EACtCsB,EAASS,GAAS,QAAU9B,EAC5BsB,EAASQ,GAAS,QAAU7B,EAE5BkB,EAAQC,EAAWW,CAAU,EAC7BvB,EAAa,CAAE,OAAAa,EAAQ,OAAAC,EAAQ,YAAAC,EAAa,MAAAJ,CAAM,EAClDa,EAAa,MAAMhB,EAAWV,EAAWW,EAAUC,EAAYV,CAAU,EAC/E,OAAOM,EAAO,CACV,UAAAR,EACA,QAASX,EACT,WAAAa,EACA,KAAMwB,CACV,CAAC,CACL,CASA,eAAsBC,GAAO9B,EAAqBc,EAAoC,CAClF,GAAI,CACA,IAAMiB,EAAUhC,EAAOC,CAAW,EAC5B6B,EAAa,MAAMhB,EACrBkB,EAAQ,UACRjB,EACAiB,EAAQ,KAAK,OACbA,EAAQ,UACZ,EACA,OAAOA,EAAQ,KAAK,OAAOF,CAAU,CACzC,MAAQ,CACJ,MAAO,EACX,CACJ,CE/MA,IAAAG,EAAA,GAAAC,EAAAD,EAAA,iBAAAE,KAAA,OAAOC,OAAS,MAGT,SAASD,GACZE,EACAC,EACAC,EAA8B,CAAC,EACf,CAChB,GAAM,CAAE,QAAAC,EAAU,GAAK,EAAID,EAGrBE,EAAqCJ,GAAQ,KAC7C,CAAE,KAAMA,EAAO,IAAK,EACpB,CAAE,KAAMA,GAAQ,MAAQ,CAAE,EAE1BK,EAASL,GAAQ,MAAQ,QAAQA,GAAQ,IAAI,GAEnD,OAAO,IAAI,QAAQ,CAACM,EAASC,IAAW,CACpC,IAAMC,EAAST,GAAI,QAAQK,EAAgB,IAAM,CAC7CI,EAAO,MAAM,KAAK,UAAUP,CAAO,CAAC,CACxC,CAAC,EAEKQ,EAAY,WAAW,IAAM,CAC/BD,EAAO,QAAQ,EACfD,EAAO,IAAI,MAAM,8BAA8BJ,CAAO,EAAE,CAAC,CAC7D,EAAGA,CAAO,EAEVK,EAAO,GAAG,OAASE,GAAS,CACxB,aAAaD,CAAS,EACtB,GAAI,CACA,IAAME,EAAW,KAAK,MAAMD,EAAK,SAAS,CAAC,EACvCC,EAAS,MACTJ,EAAO,IAAI,MAAMI,EAAS,KAAK,CAAC,EAGhCL,EAAQK,EAAS,MAAM,CAE/B,MACM,CAEFL,EAAQI,EAAK,SAAS,CAAC,CAC3B,CACAF,EAAO,IAAI,CACf,CAAC,EAEDA,EAAO,GAAG,QAAUI,GAA+B,CAC/C,aAAaH,CAAS,EAClBG,EAAI,OAAS,UAAYA,EAAI,OAAS,eACtCL,EAAO,IAAI,MAAM,gCAAgCF,CAAM,qEAAsE,CAAE,MAAOO,CAAI,CAAC,CAAC,EAG5IL,EAAOK,CAAG,CAElB,CAAC,CACL,CAAC,CACL,CCvDA,IAAAC,EAAA,GAAAC,EAAAD,EAAA,qBAAAE,EAAA,iBAAAC,GAAA,mBAAAC,KAAA,OAAS,WAAAC,EAAS,QAAAC,EAAc,cAAAC,MAAkB,YAClD,OAAS,YAAAC,GAAU,YAAAC,OAAgB,UACnC,OAAS,eAAAC,OAAmB,cAE5B,IAAMC,EAAc,GAAGH,GAAS,EAAE,QAAQ,IAAIC,GAAS,CAAC,GAExD,SAASG,GAA6B,CAElC,OADcF,GAAY,EAAE,EACf,SAAS,KAAK,CAC/B,CAEA,IAAMG,EAAuB,oBAChBX,EAAkB,GAAGW,CAAoB,IAAIF,CAAW,GAE9D,SAASP,GAAeU,EAAkF,CAE7G,IAAMC,EAAaD,GAAS,MAAQZ,EAC9Bc,EAAaF,GAAS,WAGtBG,EAAKZ,EAAQ,gBAAgB,KAAM,WAAW,EAC9Ca,EAAMD,EAAG,UACTE,EAAMF,EAAG,UAETG,EAASJ,EACTX,EAAQ,OAAOa,EAAK,WAAYF,EAAY,aAAa,EACzDX,EAAQ,OAAOa,EAAK,UAAU,EAuB9BG,EApBO,IAAIf,EAAK,KAAK,KAAK,YAAY,CACxC,QAAS,EACT,OAAQ,CAAE,IAAKM,EAAmB,CAAE,EACpC,OAAQ,CAAE,IAAK,OAAOG,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAG,EAC/E,QAAS,CAAE,IAAK,OAAOI,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAG,EAEhF,UAAWJ,EAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,GAAI,EAAG,GAAO,EAAK,EACpE,SAAUA,EAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,IAAM,GAAK,GAAK,GAAK,GAAI,EAAG,GAAO,EAAK,EAExF,UAAWY,EAEX,IAAK,CACD,CAAC,QAAS,mBAAoB,SAAU,GAAM,GAAI,EAAI,EACtD,CAAC,QAAS,WAAY,SAAU,GAAM,MAAO,CAAC,aAAa,CAAC,CAChE,EAEA,OAAQ,kBACR,MAAOD,CACX,CAAC,EAEoB,OAAO,EAE5B,MAAO,CACH,IAAKE,EACL,KAAMC,CACV,CACJ,CAWO,SAASlB,GACZmB,EACAC,EACAC,EACAC,EAAoB,GACpBC,EAAuB,EAIzB,CAEE,IAAMT,EAAKZ,EAAQ,gBAAgB,KAAM,WAAW,EAC9Ca,EAAMD,EAAG,UACTE,EAAMF,EAAG,UAETG,EAASf,EAAQ,OAAOa,EAAK,UAAU,EAGvCS,EAAgE,CAAC,EACnEZ,EAAaU,EAAW,WAAa,YAEzC,QAAWG,KAASJ,EAChB,GAAII,EAAM,YAAY,EAAE,WAAW,KAAK,EACpCD,EAAS,KAAK,CAAC,GAAIC,EAAM,UAAU,CAAC,CAAC,CAAC,UAEjCA,EAAM,YAAY,EAAE,WAAW,QAAQ,EAC5CD,EAAS,KAAK,CAAC,OAAQC,EAAM,UAAU,CAAC,CAAC,CAAC,MAEzC,CACD,IAAMC,EAAcD,EAAM,YAAY,EAAE,WAAW,MAAM,EACzD,GAAIH,EACAV,EAAac,EAAcD,EAAM,UAAU,CAAC,EAAIA,MAE/C,CACD,IAAME,EAAMD,EAAcD,EAAM,UAAU,CAAC,EAAIA,EAC/CD,EAAS,KAAK,CAAC,IAAAG,CAAG,CAAC,EACfH,EAAS,SAAW,IACpBZ,EAAae,EAErB,CACJ,CAIJ,IAAMC,EAMD,CACD,CAAC,QAAS,mBAAoB,GAAI,EAAK,EACvC,CACI,QAAS,WACT,SAAU,GACV,MAAO,CAAC,mBAAoB,iBAAiB,CACjD,EACA,CACI,QAAS,cACT,MAAO,CAACN,EAAW,aAAe,YAAY,CAClD,CACJ,EAGIE,EAAS,OAAS,GAClBI,EAAW,KAAK,CACZ,QAAS,iBACT,MAAOJ,CACX,CAAC,EAmBL,IAAMN,EAhBO,IAAIf,EAAK,KAAK,KAAK,YAAY,CACxC,QAAS,EACT,OAAQ,CAAE,IAAKM,EAAmB,CAAE,EACpC,OAAQ,CAAE,IAAKW,CAAO,EACtB,QAAS,CAAE,IAAK,OAAOR,CAAU,MAAMF,CAAoB,OAAOF,CAAW,EAAE,EAE/E,UAAWJ,EAAW,IAAI,KAAK,KAAK,IAAI,EAAI,GAAK,GAAI,EAAG,GAAO,EAAK,EACpE,SAAUA,EAAW,IAAI,KAAK,KAAK,IAAI,EAAImB,EAAe,GAAK,GAAK,GAAK,GAAI,EAAG,GAAO,EAAK,EAE5F,UAAWP,EACX,IAAKY,EAEL,OAAQ,kBACR,MAAOT,CACX,CAAC,EAEoB,OAAO,EAE5B,MAAO,CACH,IAAKF,EACL,KAAMC,CACV,CACJ,CC/JA,IAAAW,GAAA,GAAAC,EAAAD,GAAA,cAAAE,KAAA,OAAS,UAAAC,GAAQ,YAAAC,GAAU,WAAAC,GAAS,YAAAC,EAAU,aAAAC,OAAiB,mBAC/D,OAAS,YAAYC,OAAkB,qBACvC,OAAS,aAAAC,OAAiB,YAC1B,OAAS,cAAAC,OAAkB,cAC3B,OAAS,YAAAC,GAAU,WAAAC,MAAe,YAIlC,IAAMC,EAAWJ,GAAUD,EAAU,EAKrC,SAASM,EAA4BC,EAAuB,CACxD,OAAOA,EAAM,QAAQ,MAAO,MAAM,EAAE,QAAQ,KAAM,KAAK,CAC3D,CAEA,eAAsBb,GAASc,EAAcC,EAA4C,CACrF,IAAMC,EAASD,GAAS,QAAU,UAC5BE,EAAiBF,GAAS,QAAQ,YAAc,QAAQ,SAExDG,EAAWN,EAA4BE,CAAI,EAC3CK,EAAcP,EAA4BG,GAAS,SAAW,EAAE,EAChEK,EAAaR,EAA4BI,EAAO,QAAQ,MAAO,GAAG,CAAC,EAInE,CAAE,OAAAK,CAAO,EAAI,MAAMV,EAASM,EAAgB,CAAC,KAAM;AAAA;AAAA;AAAA,8BAG/BE,CAAW;AAAA,2BACdD,CAAQ;AAAA,oCACCE,CAAU;AAAA;AAAA;AAAA,MAGxC,KAAK,CAAC,CAAC,EAEH,CAAE,QAAAE,EAAS,YAAAC,EAAa,SAAAC,EAAU,KAAAC,CAAK,EAAI,KAAK,MAAMJ,CAAM,EAG9DK,EACJ,GAAIX,GAAS,QAAS,CAClB,IAAIY,EACJ,GAAI,CACAA,EAAU,KAAM,QAAO,SAAS,CACpC,MACM,CACF,MAAM,IAAI,MAAM;AAAA;AAAA;AAAA,CAAuG,CAC3H,CACAD,EAAU,GAAGV,CAAM,IAAIF,CAAI,MAC3B,MAAMa,EAAQ,MAAM,CAChB,OAAQ,MACR,OAAQ,SACR,SAAU,OACV,OAAQ,GACR,SAAU,CAAC,UAAW,UAAU,EAChC,OAAQ,CACJ,MAAO,OACP,QAAS,MACb,EACA,WAAY,GAAGL,CAAO,UACtB,WAAY,SACZ,OAAQN,EACR,OAAQ,GACR,SAAU,OACV,GAAGD,EAAQ,OACf,CAAC,CACL,SACSA,GAAS,QAAQ,KACtBW,EAAUhB,EAAQK,EAAQ,OAAO,IAAI,MAGrC,OAAM,IAAI,MAAM,4EAA4E,EAIhG,IAAMa,EAAWlB,EAAQ,GAAGM,CAAM,IAAIF,CAAI,aAAaS,CAAW,IAAIC,CAAQ,IAAIC,CAAI,OAAO,EACvFI,EAAanB,EAAQ,GAAGM,CAAM,IAAIF,CAAI,eAAeQ,CAAO,OAAO,EACnEQ,EAAY,CACd,8BAA+B,GAC/B,YAAa,GACb,aAAc,GACd,GAAGf,GAAS,OACZ,KAAML,EAAQgB,CAAO,EACrB,OAAQE,CACZ,EACA,MAAMvB,GAAUwB,EAAY,KAAK,UAAUC,EAAW,KAAM,CAAC,CAAC,EAE9D,IAAMC,EAAarB,EAAQM,EAAQM,CAAO,EAEpCU,EAAYR,IAAa,QACzBS,EAAUT,IAAa,SACvBU,GAAaF,EAAY,GAAGlB,CAAI,OAASA,EACzCqB,EAAa,GAAGJ,CAAU,IAAIG,EAAU,GAIxCE,GAAe,MAAMhC,EAASsB,CAAO,EACrCW,EAAU,GAAGrB,CAAM,IAAIP,GAASiB,CAAO,CAAC,OAExCY,EAAa9B,GAAW,QAAQ,EAAE,OAAO4B,EAAY,EAAE,OAAO,KAAK,EACrEG,EAAU,GAEd,GAAI,CACA,GAAM,CAACC,CAAW,EAAI,MAAM,QAAQ,IAAI,CACpCpC,EAASiC,EAAS,MAAM,EACxBpC,GAAOkC,CAAU,CACrB,CAAC,EACDI,EAAUC,IAAgBF,CAC9B,MACM,CAEN,CACA,GAAIC,EACA,eAAQ,IAAI,gEAAgE,EACrEJ,EAUX,GANA,MAAMxB,EAASM,EAAgB,CAAC,4BAA6BY,CAAU,CAAC,EAGxE,MAAM3B,GAASe,EAAgBkB,CAAU,EAGrCH,EACA,GAAI,CACA,IAAMS,EAAW,MAAMC,GAAa,EAChCD,IACA,QAAQ,IAAI,sBAAsBA,CAAQ,EAAE,EAC5C,MAAM9B,EAAS8B,EAAU,CAAC,SAAU,KAAMN,CAAU,CAAC,EACrD,QAAQ,IAAI,0BAA0BA,CAAU,aAAa,EAErE,OACOQ,EAAQ,CACX,QAAQ,KAAK,8BAA+BA,EAAE,OAAO,CACzD,SAEKV,EACL,GAAI,CACA,MAAMtB,EAAS,WAAY,CAAC,qBAAsBwB,CAAU,CAAC,EAC7D,QAAQ,IAAI,0BAA0BA,CAAU,aAAa,CACjE,OACOQ,EAAQ,CACX,QAAQ,KAAK,8BAA+BA,EAAE,OAAO,CACzD,CAoBJ,IAAIC,EACJ,GAAI,EACC,CAAE,OAAAA,CAAO,EAAI,KAAM,QAAO,UAAU,EACzC,MACM,CACF,MAAM,IAAI,MAAM;AAAA;AAAA;AAAA,CAA8F,CAClH,CAEA,IAAMC,GAAe,MAAMzC,EAASwB,CAAQ,EAItCkB,GAAe,CAAC,OAAQ,MAAO,OAAQ,kCAAkC,EAAE,KAAK,GAAG,EAazF,GAXA,MAAMF,EACFT,EACA,gBACAU,GACA,CACI,UAAW,GACX,aAAAC,GACA,GAAIb,EAAU,CAAE,iBAAkB,UAAW,EAAI,CAAC,CACtD,CAAC,EAGDD,EACA,GAAI,CACA,IAAMS,EAAW,MAAMC,GAAa,EAChCD,IACA,QAAQ,IAAI,wCAAwCA,CAAQ,EAAE,EAC9D,MAAM9B,EAAS8B,EAAU,CAAC,OAAQ,MAAO,SAAUN,CAAU,CAAC,EAC9D,QAAQ,IAAI,gCAAgC,EAEpD,OACOQ,EAAQ,CACX,QAAQ,KAAK,6BAA8BA,EAAE,OAAO,CACxD,SAEKV,EACL,GAAI,CACA,MAAMtB,EAAS,WAAY,CAAC,SAAU,IAAKwB,CAAU,CAAC,EACtD,QAAQ,IAAI,gCAAgC,CAChD,OACOQ,EAAQ,CACX,QAAQ,KAAK,6BAA8BA,EAAE,OAAO,CACxD,CAIJ,aAAMtC,GAAUgC,EAASC,CAAU,EAC5BH,CACX,CAEA,eAAeO,IAAuC,CAClD,IAAMK,EAAkB,iDAExB,GAAI,CAIA,IAAMC,GAHU,MAAM7C,GAAQ4C,EAAiB,CAAE,cAAe,EAAK,CAAC,GAIjE,OAAOE,GAASA,EAAM,YAAY,GAAK,oBAAoB,KAAKA,EAAM,IAAI,CAAC,EAC3E,IAAIA,GAASA,EAAM,IAAI,EACvB,KAAK,CAACC,EAAGC,IAAM,CAEZ,IAAMC,EAASF,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EAChCG,EAASF,EAAE,MAAM,GAAG,EAAE,IAAI,MAAM,EACtC,QAAS,EAAI,EAAG,EAAIC,EAAO,OAAQ,IAC/B,GAAIA,EAAO,CAAC,IAAMC,EAAO,CAAC,EACtB,OAAOA,EAAO,CAAC,EAAID,EAAO,CAAC,EAGnC,MAAO,EACX,CAAC,EAGL,QAAWE,KAAWN,EAAa,CAC/B,IAAMO,EAAe,GAAGR,CAAe,KAAKO,CAAO,KAAK,QAAQ,IAAI,iBACpE,GAAI,CACA,aAAMrD,GAAOsD,CAAY,EAClBA,CACX,MACM,CAEN,CACJ,CAEA,eAAQ,KAAK,mDAAmD,EACzD,IACX,OACOZ,EAAQ,CACX,eAAQ,KAAK,4BAA4BI,CAAe,KAAKJ,EAAE,OAAO,EAAE,EACjE,IACX,CACJ",
|
|
6
|
+
"names": ["argon2_exports", "__export", "ARGON2_VERSION", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "DEFAULT_ALGORITHM", "DEFAULT_HASH_LENGTH", "DEFAULT_MEMORY", "DEFAULT_PARALLELISM", "DEFAULT_PASSES", "DEFAULT_SALT_LENGTH", "createHash", "decode", "encode", "hash", "verify", "keygen_exports", "__export", "createSalt", "getRandomValues", "length", "argon2", "getArgon2", "crypto", "ARGON2_VERSION_10", "ARGON2_VERSION_13", "ARGON2_VERSION", "DEFAULT_ALGORITHM", "DEFAULT_SALT_LENGTH", "DEFAULT_HASH_LENGTH", "DEFAULT_PARALLELISM", "DEFAULT_MEMORY", "DEFAULT_PASSES", "decode", "encodedHash", "parts", "current", "algorithm", "version", "parameters", "paramsParts", "param", "key", "value", "hash", "encode", "hashData", "createHash", "password", "hashLength", "nonce", "createSalt", "memory", "passes", "parallelism", "argon2Params", "argon2Fn", "resolve", "reject", "err", "result", "options", "saltLength", "hashBuffer", "verify", "decoded", "client_exports", "__export", "sendCommand", "net", "server", "command", "options", "timeout", "connectOptions", "target", "resolve", "reject", "client", "timeoutId", "data", "response", "err", "mkcert_exports", "__export", "DEFAULT_CA_NAME", "generateCert", "generateRootCA", "KEYUTIL", "KJUR", "datetozulu", "userInfo", "hostname", "randomBytes", "userAndHost", "randomSerialNumber", "DEFAULT_ORGANISATION", "options", "commonName", "passphrase", "kp", "prv", "pub", "prvPem", "certPem", "cakey", "issuer", "sanEntries", "isClient", "validityDays", "sanArray", "entry", "dnsPrefixed", "dns", "extensions", "build_exports", "__export", "buildSea", "access", "copyFile", "readdir", "readFile", "writeFile", "execFileCb", "promisify", "createHash", "basename", "resolve", "execFile", "escapeForSingleQuotedString", "value", "name", "options", "outDir", "nodeExecutable", "safeName", "safeVersion", "safeOutDir", "stdout", "dirName", "nodeVersion", "platform", "arch", "seaMain", "esbuild", "blobPath", "configPath", "seaConfig", "nativePath", "isWindows", "isMacos", "targetFile", "targetPath", "seaJsContent", "shaPath", "currentSha", "canSkip", "previousSha", "signtool", "findSigntool", "e", "inject", "resourceData", "sentinelFuse", "windowsKitsPath", "versionDirs", "entry", "a", "b", "partsA", "partsB", "version", "signtoolPath"]
|
|
7
7
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@interopio/gateway-server",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"keywords": [
|
|
5
5
|
"gateway",
|
|
6
6
|
"server",
|
|
@@ -91,13 +91,13 @@
|
|
|
91
91
|
"node": ">=20.18 || >=22.12 || >=24"
|
|
92
92
|
},
|
|
93
93
|
"dependencies": {
|
|
94
|
-
"@interopio/gateway": "^0.25.
|
|
94
|
+
"@interopio/gateway": "^0.25.1",
|
|
95
95
|
"tough-cookie": "^6.0.1",
|
|
96
96
|
"http-cookie-agent": "^7.0.3",
|
|
97
97
|
"ws": "^8.19.0"
|
|
98
98
|
},
|
|
99
99
|
"peerDependencies": {
|
|
100
|
-
"undici": "^7.24.
|
|
100
|
+
"undici": "^7.24.4"
|
|
101
101
|
},
|
|
102
102
|
"peerDependenciesMeta": {
|
|
103
103
|
"undici": {
|
package/types/build.d.ts
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import type { BuildOptions } from 'esbuild';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Options for building a Single Executable Application (SEA) with `buildSea`.
|
|
5
|
+
*/
|
|
6
|
+
export interface BuildSeaOptions {
|
|
7
|
+
|
|
8
|
+
/** Application version included in the output directory name (e.g. `1.2.3` → `<name>-v1.2.3.<platform>-<arch>`). */
|
|
9
|
+
version?: string;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* esbuild options used to bundle the entry point into `<name>.sea.js`.
|
|
13
|
+
* Must include at least `entryPoints`. When provided, `esbuild` is loaded
|
|
14
|
+
* dynamically — install it with `npm install --save-dev esbuild`.
|
|
15
|
+
*
|
|
16
|
+
* Mutually exclusive with `config.main` — provide one or the other.
|
|
17
|
+
*/
|
|
18
|
+
esbuild?: BuildOptions;
|
|
19
|
+
|
|
20
|
+
/** Output directory for build artifacts (default: `./build`). */
|
|
21
|
+
outDir?: string;
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* SEA configuration written to the `<name>.sea-config.json` file.
|
|
25
|
+
* When `esbuild` is not provided, `main` must point to a pre-built script.
|
|
26
|
+
*
|
|
27
|
+
* @see https://nodejs.org/api/single-executable-applications.html#generating-single-executable-preparation-blobs
|
|
28
|
+
*/
|
|
29
|
+
config?: {
|
|
30
|
+
/** Path to the pre-built script to embed. Required when `esbuild` is not provided. */
|
|
31
|
+
main: string;
|
|
32
|
+
mainFormat?: 'commonjs' | 'module';
|
|
33
|
+
executable?: string;
|
|
34
|
+
output: string;
|
|
35
|
+
disableExperimentalSEAWarning?: boolean;
|
|
36
|
+
useSnapshot?: false;
|
|
37
|
+
useCodeCache?: false;
|
|
38
|
+
execArgv?: string[];
|
|
39
|
+
execArgvExtension: 'none' | 'env' | 'cli';
|
|
40
|
+
assets?: {
|
|
41
|
+
[assetKey: string]: string;
|
|
42
|
+
};
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Builds a Node.js Single Executable Application (SEA).
|
|
48
|
+
*
|
|
49
|
+
* Provide **either** `esbuild` (to bundle an entry point on the fly) **or**
|
|
50
|
+
* `config.main` (to use a pre-built script). At least one must be specified.
|
|
51
|
+
*
|
|
52
|
+
* When `esbuild` is provided, the entry point is bundled into `<outDir>/<name>.sea.js`
|
|
53
|
+
* and that file is used as the SEA main script. Both `esbuild` and `postject` are
|
|
54
|
+
* loaded lazily — they are only required as dev dependencies.
|
|
55
|
+
*
|
|
56
|
+
* The build is skipped when the SHA-256 of the bundled script is unchanged and the
|
|
57
|
+
* target executable already exists.
|
|
58
|
+
*
|
|
59
|
+
* @param name - Base name for the executable and intermediate files (e.g. `gateway-server`, `io-bridge`)
|
|
60
|
+
* @param options - Build options
|
|
61
|
+
* @returns The path to the built executable
|
|
62
|
+
*/
|
|
63
|
+
export function buildSea(name: string, options?: BuildSeaOptions): Promise<string>;
|
package/types/tools.d.ts
CHANGED