@lagz0ne/nats-embedded 0.2.0 → 0.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +74 -9
- package/dist/index.cjs +238 -0
- package/dist/index.d.cts +112 -0
- package/dist/index.d.cts.map +1 -0
- package/dist/index.d.mts +112 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +236 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +22 -14
- package/dist/index.d.ts +0 -92
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js +0 -143
- package/dist/index.js.map +0 -1
- package/dist/parse.d.ts +0 -2
- package/dist/parse.d.ts.map +0 -1
- package/dist/parse.js +0 -5
- package/dist/parse.js.map +0 -1
- package/dist/resolve.d.ts +0 -2
- package/dist/resolve.d.ts.map +0 -1
- package/dist/resolve.js +0 -36
- package/dist/resolve.js.map +0 -1
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
3
|
Embedded [NATS](https://nats.io) server for Node.js and Bun. Bundles the official `nats-server` binary as a managed child process with automatic random port allocation — zero conflicts, zero configuration.
|
|
4
4
|
|
|
5
|
+
Works with both ESM and CommonJS.
|
|
6
|
+
|
|
5
7
|
## Install
|
|
6
8
|
|
|
7
9
|
```bash
|
|
@@ -23,17 +25,72 @@ console.log(server.url); // nats://127.0.0.1:52431
|
|
|
23
25
|
await server.stop();
|
|
24
26
|
```
|
|
25
27
|
|
|
28
|
+
CommonJS:
|
|
29
|
+
|
|
30
|
+
```javascript
|
|
31
|
+
const { NatsServer } = require('@lagz0ne/nats-embedded');
|
|
32
|
+
```
|
|
33
|
+
|
|
26
34
|
## Options
|
|
27
35
|
|
|
36
|
+
All nats-server CLI flags are exposed as typed options. No guards — NATS validates.
|
|
37
|
+
|
|
38
|
+
```typescript
|
|
39
|
+
const server = await NatsServer.start({
|
|
40
|
+
// Server
|
|
41
|
+
port: -1, // -1 = random (default), 0 = nats default (4222)
|
|
42
|
+
host: '127.0.0.1', // default: localhost only
|
|
43
|
+
serverName: 'my-server', // default: auto-generated
|
|
44
|
+
|
|
45
|
+
// JetStream
|
|
46
|
+
jetstream: true,
|
|
47
|
+
storeDir: '/tmp/js',
|
|
48
|
+
|
|
49
|
+
// WebSocket
|
|
50
|
+
websocket: true, // random port, no TLS (embedded defaults)
|
|
51
|
+
// or: websocket: { port: 8080, noTls: false }
|
|
52
|
+
|
|
53
|
+
// Auth
|
|
54
|
+
user: 'admin',
|
|
55
|
+
pass: 'secret',
|
|
56
|
+
token: 'auth-token',
|
|
57
|
+
|
|
58
|
+
// TLS
|
|
59
|
+
tls: true,
|
|
60
|
+
tlsCert: '/path/to/cert.pem',
|
|
61
|
+
tlsKey: '/path/to/key.pem',
|
|
62
|
+
|
|
63
|
+
// Logging
|
|
64
|
+
debug: true, // NATS -D flag
|
|
65
|
+
trace: true, // NATS -V flag
|
|
66
|
+
verbose: true, // forward nats-server stderr to process.stderr
|
|
67
|
+
|
|
68
|
+
// Monitoring
|
|
69
|
+
httpPort: 8222,
|
|
70
|
+
|
|
71
|
+
// Escape hatches
|
|
72
|
+
config: './nats.conf', // custom config file
|
|
73
|
+
args: [], // extra CLI arguments
|
|
74
|
+
});
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
## WebSocket
|
|
78
|
+
|
|
28
79
|
```typescript
|
|
80
|
+
const server = await NatsServer.start({ websocket: true });
|
|
81
|
+
|
|
82
|
+
console.log(server.wsUrl); // ws://127.0.0.1:54322
|
|
83
|
+
console.log(server.wsPort); // 54322
|
|
84
|
+
|
|
85
|
+
// Full control over websocket config block
|
|
86
|
+
const server = await NatsServer.start({
|
|
87
|
+
websocket: { port: 8080, noTls: false },
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
// Combined with custom config file (your file takes precedence)
|
|
29
91
|
const server = await NatsServer.start({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
jetstream: true, // enable JetStream (default: false)
|
|
33
|
-
storeDir: '/tmp/js', // JetStream storage directory
|
|
34
|
-
debug: false, // forward nats-server logs to stderr
|
|
35
|
-
config: './nats.conf', // custom config file
|
|
36
|
-
args: [], // extra CLI arguments
|
|
92
|
+
websocket: true,
|
|
93
|
+
config: './my-nats.conf',
|
|
37
94
|
});
|
|
38
95
|
```
|
|
39
96
|
|
|
@@ -41,7 +98,7 @@ const server = await NatsServer.start({
|
|
|
41
98
|
|
|
42
99
|
### `NatsServer.start(opts?): Promise<NatsServer>`
|
|
43
100
|
|
|
44
|
-
Starts a new nats-server process. Resolves when
|
|
101
|
+
Starts a new nats-server process. Resolves when all listeners are ready.
|
|
45
102
|
|
|
46
103
|
### `server.url: string`
|
|
47
104
|
|
|
@@ -49,7 +106,15 @@ NATS connection URL (e.g. `nats://127.0.0.1:52431`).
|
|
|
49
106
|
|
|
50
107
|
### `server.port: number`
|
|
51
108
|
|
|
52
|
-
Assigned port number.
|
|
109
|
+
Assigned TCP port number.
|
|
110
|
+
|
|
111
|
+
### `server.wsUrl?: string`
|
|
112
|
+
|
|
113
|
+
WebSocket URL (e.g. `ws://127.0.0.1:54322`). Undefined if websocket not enabled.
|
|
114
|
+
|
|
115
|
+
### `server.wsPort?: number`
|
|
116
|
+
|
|
117
|
+
WebSocket port. Undefined if websocket not enabled.
|
|
53
118
|
|
|
54
119
|
### `server.stop(): Promise<void>`
|
|
55
120
|
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,238 @@
|
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
let node_child_process = require("node:child_process");
|
|
3
|
+
let node_fs = require("node:fs");
|
|
4
|
+
let node_path = require("node:path");
|
|
5
|
+
let node_os = require("node:os");
|
|
6
|
+
let node_module = require("node:module");
|
|
7
|
+
let node_url = require("node:url");
|
|
8
|
+
//#region src/resolve.ts
|
|
9
|
+
const PLATFORM_MAP = {
|
|
10
|
+
"linux-x64": "@lagz0ne/nats-embedded-linux-x64",
|
|
11
|
+
"linux-arm64": "@lagz0ne/nats-embedded-linux-arm64",
|
|
12
|
+
"darwin-x64": "@lagz0ne/nats-embedded-darwin-x64",
|
|
13
|
+
"darwin-arm64": "@lagz0ne/nats-embedded-darwin-arm64",
|
|
14
|
+
"win32-x64": "@lagz0ne/nats-embedded-win32-x64",
|
|
15
|
+
"win32-arm64": "@lagz0ne/nats-embedded-win32-arm64"
|
|
16
|
+
};
|
|
17
|
+
const BINARY_NAME = (0, node_os.platform)() === "win32" ? "nats-server.exe" : "nats-server";
|
|
18
|
+
function resolve() {
|
|
19
|
+
if (process.env.NATS_EMBEDDED_BINARY) return process.env.NATS_EMBEDDED_BINARY;
|
|
20
|
+
const key = `${(0, node_os.platform)()}-${(0, node_os.arch)()}`;
|
|
21
|
+
const pkg = PLATFORM_MAP[key];
|
|
22
|
+
if (!pkg) throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`);
|
|
23
|
+
try {
|
|
24
|
+
return (0, node_module.createRequire)(require("url").pathToFileURL(__filename).href).resolve(`${pkg}/${BINARY_NAME}`);
|
|
25
|
+
} catch {
|
|
26
|
+
const sibling = (0, node_path.join)((0, node_path.dirname)((0, node_url.fileURLToPath)(require("url").pathToFileURL(__filename).href)), "..", "..", key, BINARY_NAME);
|
|
27
|
+
if ((0, node_fs.existsSync)(sibling)) return sibling;
|
|
28
|
+
throw new Error(`Cannot find nats-server binary. Install ${pkg} or set NATS_EMBEDDED_BINARY`);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
//#region src/parse.ts
|
|
33
|
+
function parsePort(line) {
|
|
34
|
+
const match = line.match(/Listening for client connections on .+:(\d+)/);
|
|
35
|
+
return match ? parseInt(match[1], 10) : null;
|
|
36
|
+
}
|
|
37
|
+
function parseWsPort(line) {
|
|
38
|
+
const match = line.match(/Listening for websocket clients on .+:(\d+)/);
|
|
39
|
+
return match ? parseInt(match[1], 10) : null;
|
|
40
|
+
}
|
|
41
|
+
//#endregion
|
|
42
|
+
//#region src/config.ts
|
|
43
|
+
function toSnakeCase(str) {
|
|
44
|
+
return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
45
|
+
}
|
|
46
|
+
function serializeBlock(name, obj) {
|
|
47
|
+
return `${name} {\n${Object.entries(obj).map(([k, v]) => {
|
|
48
|
+
const key = toSnakeCase(k);
|
|
49
|
+
if (typeof v === "string") return ` ${key}: "${v}"`;
|
|
50
|
+
return ` ${key}: ${v}`;
|
|
51
|
+
}).join("\n")}\n}`;
|
|
52
|
+
}
|
|
53
|
+
const WS_DEFAULTS = {
|
|
54
|
+
port: -1,
|
|
55
|
+
no_tls: true
|
|
56
|
+
};
|
|
57
|
+
function buildConfig(opts) {
|
|
58
|
+
if (!opts.websocket) return null;
|
|
59
|
+
const parts = [serializeBlock("websocket", opts.websocket === true ? { ...WS_DEFAULTS } : {
|
|
60
|
+
...WS_DEFAULTS,
|
|
61
|
+
...opts.websocket
|
|
62
|
+
})];
|
|
63
|
+
if (opts.config) parts.push(`include '${(0, node_path.resolve)(opts.config)}'`);
|
|
64
|
+
return parts.join("\n\n") + "\n";
|
|
65
|
+
}
|
|
66
|
+
//#endregion
|
|
67
|
+
//#region src/index.ts
|
|
68
|
+
/**
|
|
69
|
+
* Maps option keys to their nats-server CLI flags.
|
|
70
|
+
* - boolean options: flag is pushed only when true
|
|
71
|
+
* - string/number options: flag + value
|
|
72
|
+
* - string[] options: flag + comma-joined value
|
|
73
|
+
*
|
|
74
|
+
* Keys not in this map are handled separately (host, port, verbose, websocket, config, args).
|
|
75
|
+
*/
|
|
76
|
+
const FLAG_MAP = {
|
|
77
|
+
serverName: "--server_name",
|
|
78
|
+
pidFile: "-P",
|
|
79
|
+
httpPort: "-m",
|
|
80
|
+
httpsPort: "-ms",
|
|
81
|
+
clientAdvertise: "--client_advertise",
|
|
82
|
+
portsFileDir: "--ports_file_dir",
|
|
83
|
+
debug: "-D",
|
|
84
|
+
trace: "-V",
|
|
85
|
+
log: "-l",
|
|
86
|
+
logtime: "-T",
|
|
87
|
+
syslog: "-s",
|
|
88
|
+
remoteSyslog: "-r",
|
|
89
|
+
logSizeLimit: "--log_size_limit",
|
|
90
|
+
maxTracedMsgLen: "--max_traced_msg_len",
|
|
91
|
+
jetstream: "-js",
|
|
92
|
+
storeDir: "-sd",
|
|
93
|
+
user: "--user",
|
|
94
|
+
pass: "--pass",
|
|
95
|
+
token: "--auth",
|
|
96
|
+
tls: "--tls",
|
|
97
|
+
tlsCert: "--tlscert",
|
|
98
|
+
tlsKey: "--tlskey",
|
|
99
|
+
tlsVerify: "--tlsverify",
|
|
100
|
+
tlsCaCert: "--tlscacert",
|
|
101
|
+
routes: "--routes",
|
|
102
|
+
cluster: "--cluster",
|
|
103
|
+
clusterName: "--cluster_name",
|
|
104
|
+
noAdvertise: "--no_advertise",
|
|
105
|
+
clusterAdvertise: "--cluster_advertise",
|
|
106
|
+
connectRetries: "--connect_retries",
|
|
107
|
+
clusterListen: "--cluster_listen",
|
|
108
|
+
profile: "--profile"
|
|
109
|
+
};
|
|
110
|
+
function buildArgs(opts, configPath) {
|
|
111
|
+
const host = opts.host ?? "127.0.0.1";
|
|
112
|
+
const port = opts.port ?? -1;
|
|
113
|
+
const args = [
|
|
114
|
+
"-a",
|
|
115
|
+
host,
|
|
116
|
+
"-p",
|
|
117
|
+
String(port)
|
|
118
|
+
];
|
|
119
|
+
for (const [key, flag] of Object.entries(FLAG_MAP)) {
|
|
120
|
+
const val = opts[key];
|
|
121
|
+
if (val === void 0 || val === false) continue;
|
|
122
|
+
if (val === true) args.push(flag);
|
|
123
|
+
else if (Array.isArray(val)) args.push(flag, val.join(","));
|
|
124
|
+
else args.push(flag, String(val));
|
|
125
|
+
}
|
|
126
|
+
if (configPath) args.push("-c", configPath);
|
|
127
|
+
else if (opts.config) args.push("-c", opts.config);
|
|
128
|
+
if (opts.args) args.push(...opts.args);
|
|
129
|
+
return args;
|
|
130
|
+
}
|
|
131
|
+
var NatsServer = class NatsServer {
|
|
132
|
+
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
133
|
+
url;
|
|
134
|
+
/** Assigned port */
|
|
135
|
+
port;
|
|
136
|
+
/** WebSocket port (undefined if websocket not enabled) */
|
|
137
|
+
wsPort;
|
|
138
|
+
/** WebSocket URL (undefined if websocket not enabled) */
|
|
139
|
+
wsUrl;
|
|
140
|
+
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
141
|
+
exited;
|
|
142
|
+
proc;
|
|
143
|
+
configDir;
|
|
144
|
+
constructor(proc, host, port, wsPort, configDir) {
|
|
145
|
+
this.proc = proc;
|
|
146
|
+
this.port = port;
|
|
147
|
+
this.url = `nats://${host}:${port}`;
|
|
148
|
+
if (wsPort !== void 0) {
|
|
149
|
+
this.wsPort = wsPort;
|
|
150
|
+
this.wsUrl = `ws://${host}:${wsPort}`;
|
|
151
|
+
}
|
|
152
|
+
this.configDir = configDir;
|
|
153
|
+
this.exited = new Promise((res) => {
|
|
154
|
+
proc.on("exit", (code) => res(code));
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
static async start(opts = {}) {
|
|
158
|
+
const bin = resolve();
|
|
159
|
+
const host = opts.host ?? "127.0.0.1";
|
|
160
|
+
const needWs = !!opts.websocket;
|
|
161
|
+
let configDir = null;
|
|
162
|
+
let configPath;
|
|
163
|
+
const configContent = buildConfig(opts);
|
|
164
|
+
if (configContent) {
|
|
165
|
+
configDir = (0, node_fs.mkdtempSync)((0, node_path.join)((0, node_os.tmpdir)(), "nats-embedded-"));
|
|
166
|
+
configPath = (0, node_path.join)(configDir, "nats.conf");
|
|
167
|
+
(0, node_fs.writeFileSync)(configPath, configContent);
|
|
168
|
+
}
|
|
169
|
+
const proc = (0, node_child_process.spawn)(bin, buildArgs(opts, configPath), { stdio: [
|
|
170
|
+
"ignore",
|
|
171
|
+
"ignore",
|
|
172
|
+
"pipe"
|
|
173
|
+
] });
|
|
174
|
+
const result = await new Promise((resolve, reject) => {
|
|
175
|
+
const timeout = setTimeout(() => {
|
|
176
|
+
proc.kill("SIGKILL");
|
|
177
|
+
reject(/* @__PURE__ */ new Error("nats-server did not start within 5s"));
|
|
178
|
+
}, 5e3);
|
|
179
|
+
proc.on("error", (err) => {
|
|
180
|
+
clearTimeout(timeout);
|
|
181
|
+
reject(err);
|
|
182
|
+
});
|
|
183
|
+
proc.on("exit", (code) => {
|
|
184
|
+
clearTimeout(timeout);
|
|
185
|
+
reject(/* @__PURE__ */ new Error(`nats-server exited with code ${code} before ready`));
|
|
186
|
+
});
|
|
187
|
+
let tcpPort = null;
|
|
188
|
+
let wsPort = null;
|
|
189
|
+
let resolved = false;
|
|
190
|
+
let buffer = "";
|
|
191
|
+
proc.stderr.on("data", (chunk) => {
|
|
192
|
+
const text = chunk.toString();
|
|
193
|
+
if (opts.verbose) process.stderr.write(text);
|
|
194
|
+
if (resolved) return;
|
|
195
|
+
buffer += text;
|
|
196
|
+
const lines = buffer.split("\n");
|
|
197
|
+
buffer = lines.pop();
|
|
198
|
+
for (const line of lines) {
|
|
199
|
+
const tcp = parsePort(line);
|
|
200
|
+
if (tcp !== null) tcpPort = tcp;
|
|
201
|
+
const ws = parseWsPort(line);
|
|
202
|
+
if (ws !== null) wsPort = ws;
|
|
203
|
+
if (tcpPort !== null && (!needWs || wsPort !== null)) {
|
|
204
|
+
resolved = true;
|
|
205
|
+
clearTimeout(timeout);
|
|
206
|
+
proc.removeAllListeners("exit");
|
|
207
|
+
resolve({
|
|
208
|
+
tcpPort,
|
|
209
|
+
wsPort: wsPort ?? void 0
|
|
210
|
+
});
|
|
211
|
+
return;
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
});
|
|
215
|
+
});
|
|
216
|
+
return new NatsServer(proc, host, result.tcpPort, result.wsPort, configDir);
|
|
217
|
+
}
|
|
218
|
+
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
219
|
+
async stop() {
|
|
220
|
+
if (this.proc.exitCode !== null) return;
|
|
221
|
+
this.proc.kill("SIGTERM");
|
|
222
|
+
if (!await Promise.race([this.exited.then(() => true), new Promise((r) => setTimeout(() => r(false), 5e3))])) {
|
|
223
|
+
this.proc.kill("SIGKILL");
|
|
224
|
+
await this.exited;
|
|
225
|
+
}
|
|
226
|
+
if (this.configDir) {
|
|
227
|
+
try {
|
|
228
|
+
(0, node_fs.rmSync)(this.configDir, { recursive: true });
|
|
229
|
+
} catch {}
|
|
230
|
+
this.configDir = null;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
//#endregion
|
|
235
|
+
exports.NatsServer = NatsServer;
|
|
236
|
+
exports.buildArgs = buildArgs;
|
|
237
|
+
exports.buildConfig = buildConfig;
|
|
238
|
+
exports.resolveBinary = resolve;
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/resolve.d.ts
|
|
2
|
+
declare function resolve(): string;
|
|
3
|
+
//#endregion
|
|
4
|
+
//#region src/config.d.ts
|
|
5
|
+
type ConfigBlock = Record<string, unknown>;
|
|
6
|
+
declare function buildConfig(opts: {
|
|
7
|
+
websocket?: boolean | ConfigBlock;
|
|
8
|
+
config?: string;
|
|
9
|
+
}): string | null;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/index.d.ts
|
|
12
|
+
interface NatsServerOptions {
|
|
13
|
+
/** Port to listen on. -1 = random (default), 0 = nats default (4222). */
|
|
14
|
+
port?: number;
|
|
15
|
+
/** Host to bind to. Default: 127.0.0.1 */
|
|
16
|
+
host?: string;
|
|
17
|
+
/** Server name. Default: auto-generated by NATS */
|
|
18
|
+
serverName?: string;
|
|
19
|
+
/** File to store PID */
|
|
20
|
+
pidFile?: string;
|
|
21
|
+
/** HTTP monitoring port */
|
|
22
|
+
httpPort?: number;
|
|
23
|
+
/** HTTPS monitoring port */
|
|
24
|
+
httpsPort?: number;
|
|
25
|
+
/** Client URL to advertise to other servers */
|
|
26
|
+
clientAdvertise?: string;
|
|
27
|
+
/** Directory to write ports file */
|
|
28
|
+
portsFileDir?: string;
|
|
29
|
+
/** Enable NATS debug output (-D flag) */
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
/** Enable NATS protocol trace (-V flag) */
|
|
32
|
+
trace?: boolean;
|
|
33
|
+
/** Redirect NATS log output to file */
|
|
34
|
+
log?: string;
|
|
35
|
+
/** Timestamp log entries */
|
|
36
|
+
logtime?: boolean;
|
|
37
|
+
/** Log to syslog */
|
|
38
|
+
syslog?: boolean;
|
|
39
|
+
/** Remote syslog address (e.g. udp://localhost:514) */
|
|
40
|
+
remoteSyslog?: string;
|
|
41
|
+
/** Logfile size limit */
|
|
42
|
+
logSizeLimit?: string;
|
|
43
|
+
/** Maximum printable length for traced messages */
|
|
44
|
+
maxTracedMsgLen?: number;
|
|
45
|
+
/** Enable JetStream */
|
|
46
|
+
jetstream?: boolean;
|
|
47
|
+
/** JetStream storage directory */
|
|
48
|
+
storeDir?: string;
|
|
49
|
+
/** Username required for connections */
|
|
50
|
+
user?: string;
|
|
51
|
+
/** Password required for connections */
|
|
52
|
+
pass?: string;
|
|
53
|
+
/** Authorization token required for connections */
|
|
54
|
+
token?: string;
|
|
55
|
+
/** Enable TLS */
|
|
56
|
+
tls?: boolean;
|
|
57
|
+
/** Server certificate file */
|
|
58
|
+
tlsCert?: string;
|
|
59
|
+
/** Private key for server certificate */
|
|
60
|
+
tlsKey?: string;
|
|
61
|
+
/** Enable TLS with client certificate verification */
|
|
62
|
+
tlsVerify?: boolean;
|
|
63
|
+
/** Client certificate CA for verification */
|
|
64
|
+
tlsCaCert?: string;
|
|
65
|
+
/** Routes to solicit and connect */
|
|
66
|
+
routes?: string[];
|
|
67
|
+
/** Cluster URL for solicited routes */
|
|
68
|
+
cluster?: string;
|
|
69
|
+
/** Cluster name */
|
|
70
|
+
clusterName?: string;
|
|
71
|
+
/** Do not advertise known cluster information to clients */
|
|
72
|
+
noAdvertise?: boolean;
|
|
73
|
+
/** Cluster URL to advertise to other servers */
|
|
74
|
+
clusterAdvertise?: string;
|
|
75
|
+
/** Number of connect retries for implicit routes */
|
|
76
|
+
connectRetries?: number;
|
|
77
|
+
/** Cluster URL from which members can solicit routes */
|
|
78
|
+
clusterListen?: string;
|
|
79
|
+
/** Profiling HTTP port */
|
|
80
|
+
profile?: number;
|
|
81
|
+
/** WebSocket listener. true = embedded defaults (random port, no TLS).
|
|
82
|
+
* Object = full websocket config block passed to NATS. */
|
|
83
|
+
websocket?: boolean | Record<string, unknown>;
|
|
84
|
+
/** Forward nats-server stderr to process.stderr. Default: false */
|
|
85
|
+
verbose?: boolean;
|
|
86
|
+
/** Path to a custom nats.conf file */
|
|
87
|
+
config?: string;
|
|
88
|
+
/** Extra CLI arguments passed to nats-server */
|
|
89
|
+
args?: string[];
|
|
90
|
+
}
|
|
91
|
+
declare function buildArgs(opts: NatsServerOptions, configPath?: string): string[];
|
|
92
|
+
declare class NatsServer {
|
|
93
|
+
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
94
|
+
readonly url: string;
|
|
95
|
+
/** Assigned port */
|
|
96
|
+
readonly port: number;
|
|
97
|
+
/** WebSocket port (undefined if websocket not enabled) */
|
|
98
|
+
readonly wsPort?: number;
|
|
99
|
+
/** WebSocket URL (undefined if websocket not enabled) */
|
|
100
|
+
readonly wsUrl?: string;
|
|
101
|
+
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
102
|
+
readonly exited: Promise<number | null>;
|
|
103
|
+
private proc;
|
|
104
|
+
private configDir;
|
|
105
|
+
private constructor();
|
|
106
|
+
static start(opts?: NatsServerOptions): Promise<NatsServer>;
|
|
107
|
+
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
108
|
+
stop(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { NatsServer, NatsServerOptions, buildArgs, buildConfig, resolve as resolveBinary };
|
|
112
|
+
//# sourceMappingURL=index.d.cts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.cts","names":[],"sources":["../src/resolve.ts","../src/config.ts","../src/index.ts"],"mappings":";iBAiBgB,OAAA,CAAA;;;KCfX,WAAA,GAAc,MAAA;AAAA,iBAiBH,WAAA,CAAY,IAAA;EAC1B,SAAA,aAAsB,WAAA;EACtB,MAAA;AAAA;;;UCbe,iBAAA;EFSD;EENd,IAAA;;EAEA,IAAA;EFIqB;EEFrB,UAAA;;EAEA,OAAA;EDfG;ECiBH,QAAA;;EAEA,SAAA;EDnBuB;ECqBvB,eAAA;EDJyB;ECMzB,YAAA;EDLiC;ECSjC,KAAA;EDTsB;ECWtB,KAAA;EDZ0B;ECc1B,GAAA;EDXD;ECaC,OAAA;;EAEA,MAAA;EA7Be;EA+Bf,YAAA;;EAEA,YAAA;EA9BA;EAgCA,eAAA;EA5BA;EAgCA,SAAA;EA5BA;EA8BA,QAAA;EA1BA;EA8BA,IAAA;EAxBA;EA0BA,IAAA;EAtBA;EAwBA,KAAA;EApBA;EAwBA,GAAA;EApBA;EAsBA,OAAA;EAhBA;EAkBA,MAAA;EAZA;EAcA,SAAA;EAVA;EAYA,SAAA;EANA;EAUA,MAAA;EANA;EAQA,OAAA;EAFA;EAIA,WAAA;EAAA;EAEA,WAAA;EAEA;EAAA,gBAAA;EAIA;EAFA,cAAA;EAWA;EATA,aAAA;EAaA;EATA,OAAA;EAeA;;EAVA,SAAA,aAAsB,MAAA;EAwDR;EApDd,OAAA;;EAIA,MAAA;EAgD8B;EA9C9B,IAAA;AAAA;AAAA,iBA8Cc,SAAA,CAAU,IAAA,EAAM,iBAAA,EAAmB,UAAA;AAAA,cA2BtC,UAAA;EAAA;EAAA,SAEF,GAAA;;WAEA,IAAA;EA+BgB;EAAA,SA7BhB,MAAA;EA6ByC;EAAA,SA3BzC,KAAA;EAwGY;EAAA,SAtGZ,MAAA,EAAQ,OAAA;EAAA,QAET,IAAA;EAAA,QACA,SAAA;EAAA,QAED,WAAA,CAAA;EAAA,OAoBM,KAAA,CAAM,IAAA,GAAM,iBAAA,GAAyB,OAAA,CAAQ,UAAA;EAzBjD;EAsGH,IAAA,CAAA,GAAQ,OAAA;AAAA"}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
//#region src/resolve.d.ts
|
|
2
|
+
declare function resolve(): string;
|
|
3
|
+
//#endregion
|
|
4
|
+
//#region src/config.d.ts
|
|
5
|
+
type ConfigBlock = Record<string, unknown>;
|
|
6
|
+
declare function buildConfig(opts: {
|
|
7
|
+
websocket?: boolean | ConfigBlock;
|
|
8
|
+
config?: string;
|
|
9
|
+
}): string | null;
|
|
10
|
+
//#endregion
|
|
11
|
+
//#region src/index.d.ts
|
|
12
|
+
interface NatsServerOptions {
|
|
13
|
+
/** Port to listen on. -1 = random (default), 0 = nats default (4222). */
|
|
14
|
+
port?: number;
|
|
15
|
+
/** Host to bind to. Default: 127.0.0.1 */
|
|
16
|
+
host?: string;
|
|
17
|
+
/** Server name. Default: auto-generated by NATS */
|
|
18
|
+
serverName?: string;
|
|
19
|
+
/** File to store PID */
|
|
20
|
+
pidFile?: string;
|
|
21
|
+
/** HTTP monitoring port */
|
|
22
|
+
httpPort?: number;
|
|
23
|
+
/** HTTPS monitoring port */
|
|
24
|
+
httpsPort?: number;
|
|
25
|
+
/** Client URL to advertise to other servers */
|
|
26
|
+
clientAdvertise?: string;
|
|
27
|
+
/** Directory to write ports file */
|
|
28
|
+
portsFileDir?: string;
|
|
29
|
+
/** Enable NATS debug output (-D flag) */
|
|
30
|
+
debug?: boolean;
|
|
31
|
+
/** Enable NATS protocol trace (-V flag) */
|
|
32
|
+
trace?: boolean;
|
|
33
|
+
/** Redirect NATS log output to file */
|
|
34
|
+
log?: string;
|
|
35
|
+
/** Timestamp log entries */
|
|
36
|
+
logtime?: boolean;
|
|
37
|
+
/** Log to syslog */
|
|
38
|
+
syslog?: boolean;
|
|
39
|
+
/** Remote syslog address (e.g. udp://localhost:514) */
|
|
40
|
+
remoteSyslog?: string;
|
|
41
|
+
/** Logfile size limit */
|
|
42
|
+
logSizeLimit?: string;
|
|
43
|
+
/** Maximum printable length for traced messages */
|
|
44
|
+
maxTracedMsgLen?: number;
|
|
45
|
+
/** Enable JetStream */
|
|
46
|
+
jetstream?: boolean;
|
|
47
|
+
/** JetStream storage directory */
|
|
48
|
+
storeDir?: string;
|
|
49
|
+
/** Username required for connections */
|
|
50
|
+
user?: string;
|
|
51
|
+
/** Password required for connections */
|
|
52
|
+
pass?: string;
|
|
53
|
+
/** Authorization token required for connections */
|
|
54
|
+
token?: string;
|
|
55
|
+
/** Enable TLS */
|
|
56
|
+
tls?: boolean;
|
|
57
|
+
/** Server certificate file */
|
|
58
|
+
tlsCert?: string;
|
|
59
|
+
/** Private key for server certificate */
|
|
60
|
+
tlsKey?: string;
|
|
61
|
+
/** Enable TLS with client certificate verification */
|
|
62
|
+
tlsVerify?: boolean;
|
|
63
|
+
/** Client certificate CA for verification */
|
|
64
|
+
tlsCaCert?: string;
|
|
65
|
+
/** Routes to solicit and connect */
|
|
66
|
+
routes?: string[];
|
|
67
|
+
/** Cluster URL for solicited routes */
|
|
68
|
+
cluster?: string;
|
|
69
|
+
/** Cluster name */
|
|
70
|
+
clusterName?: string;
|
|
71
|
+
/** Do not advertise known cluster information to clients */
|
|
72
|
+
noAdvertise?: boolean;
|
|
73
|
+
/** Cluster URL to advertise to other servers */
|
|
74
|
+
clusterAdvertise?: string;
|
|
75
|
+
/** Number of connect retries for implicit routes */
|
|
76
|
+
connectRetries?: number;
|
|
77
|
+
/** Cluster URL from which members can solicit routes */
|
|
78
|
+
clusterListen?: string;
|
|
79
|
+
/** Profiling HTTP port */
|
|
80
|
+
profile?: number;
|
|
81
|
+
/** WebSocket listener. true = embedded defaults (random port, no TLS).
|
|
82
|
+
* Object = full websocket config block passed to NATS. */
|
|
83
|
+
websocket?: boolean | Record<string, unknown>;
|
|
84
|
+
/** Forward nats-server stderr to process.stderr. Default: false */
|
|
85
|
+
verbose?: boolean;
|
|
86
|
+
/** Path to a custom nats.conf file */
|
|
87
|
+
config?: string;
|
|
88
|
+
/** Extra CLI arguments passed to nats-server */
|
|
89
|
+
args?: string[];
|
|
90
|
+
}
|
|
91
|
+
declare function buildArgs(opts: NatsServerOptions, configPath?: string): string[];
|
|
92
|
+
declare class NatsServer {
|
|
93
|
+
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
94
|
+
readonly url: string;
|
|
95
|
+
/** Assigned port */
|
|
96
|
+
readonly port: number;
|
|
97
|
+
/** WebSocket port (undefined if websocket not enabled) */
|
|
98
|
+
readonly wsPort?: number;
|
|
99
|
+
/** WebSocket URL (undefined if websocket not enabled) */
|
|
100
|
+
readonly wsUrl?: string;
|
|
101
|
+
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
102
|
+
readonly exited: Promise<number | null>;
|
|
103
|
+
private proc;
|
|
104
|
+
private configDir;
|
|
105
|
+
private constructor();
|
|
106
|
+
static start(opts?: NatsServerOptions): Promise<NatsServer>;
|
|
107
|
+
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
108
|
+
stop(): Promise<void>;
|
|
109
|
+
}
|
|
110
|
+
//#endregion
|
|
111
|
+
export { NatsServer, NatsServerOptions, buildArgs, buildConfig, resolve as resolveBinary };
|
|
112
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/resolve.ts","../src/config.ts","../src/index.ts"],"mappings":";iBAiBgB,OAAA,CAAA;;;KCfX,WAAA,GAAc,MAAA;AAAA,iBAiBH,WAAA,CAAY,IAAA;EAC1B,SAAA,aAAsB,WAAA;EACtB,MAAA;AAAA;;;UCbe,iBAAA;EFSD;EENd,IAAA;;EAEA,IAAA;EFIqB;EEFrB,UAAA;;EAEA,OAAA;EDfG;ECiBH,QAAA;;EAEA,SAAA;EDnBuB;ECqBvB,eAAA;EDJyB;ECMzB,YAAA;EDLiC;ECSjC,KAAA;EDTsB;ECWtB,KAAA;EDZ0B;ECc1B,GAAA;EDXD;ECaC,OAAA;;EAEA,MAAA;EA7Be;EA+Bf,YAAA;;EAEA,YAAA;EA9BA;EAgCA,eAAA;EA5BA;EAgCA,SAAA;EA5BA;EA8BA,QAAA;EA1BA;EA8BA,IAAA;EAxBA;EA0BA,IAAA;EAtBA;EAwBA,KAAA;EApBA;EAwBA,GAAA;EApBA;EAsBA,OAAA;EAhBA;EAkBA,MAAA;EAZA;EAcA,SAAA;EAVA;EAYA,SAAA;EANA;EAUA,MAAA;EANA;EAQA,OAAA;EAFA;EAIA,WAAA;EAAA;EAEA,WAAA;EAEA;EAAA,gBAAA;EAIA;EAFA,cAAA;EAWA;EATA,aAAA;EAaA;EATA,OAAA;EAeA;;EAVA,SAAA,aAAsB,MAAA;EAwDR;EApDd,OAAA;;EAIA,MAAA;EAgD8B;EA9C9B,IAAA;AAAA;AAAA,iBA8Cc,SAAA,CAAU,IAAA,EAAM,iBAAA,EAAmB,UAAA;AAAA,cA2BtC,UAAA;EAAA;EAAA,SAEF,GAAA;;WAEA,IAAA;EA+BgB;EAAA,SA7BhB,MAAA;EA6ByC;EAAA,SA3BzC,KAAA;EAwGY;EAAA,SAtGZ,MAAA,EAAQ,OAAA;EAAA,QAET,IAAA;EAAA,QACA,SAAA;EAAA,QAED,WAAA,CAAA;EAAA,OAoBM,KAAA,CAAM,IAAA,GAAM,iBAAA,GAAyB,OAAA,CAAQ,UAAA;EAzBjD;EAsGH,IAAA,CAAA,GAAQ,OAAA;AAAA"}
|
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { createRequire } from "node:module";
|
|
2
|
+
import { spawn } from "node:child_process";
|
|
3
|
+
import { existsSync, mkdtempSync, rmSync, writeFileSync } from "node:fs";
|
|
4
|
+
import { dirname, join, resolve as resolve$1 } from "node:path";
|
|
5
|
+
import { arch, platform, tmpdir } from "node:os";
|
|
6
|
+
import { fileURLToPath } from "node:url";
|
|
7
|
+
//#region src/resolve.ts
|
|
8
|
+
const PLATFORM_MAP = {
|
|
9
|
+
"linux-x64": "@lagz0ne/nats-embedded-linux-x64",
|
|
10
|
+
"linux-arm64": "@lagz0ne/nats-embedded-linux-arm64",
|
|
11
|
+
"darwin-x64": "@lagz0ne/nats-embedded-darwin-x64",
|
|
12
|
+
"darwin-arm64": "@lagz0ne/nats-embedded-darwin-arm64",
|
|
13
|
+
"win32-x64": "@lagz0ne/nats-embedded-win32-x64",
|
|
14
|
+
"win32-arm64": "@lagz0ne/nats-embedded-win32-arm64"
|
|
15
|
+
};
|
|
16
|
+
const BINARY_NAME = platform() === "win32" ? "nats-server.exe" : "nats-server";
|
|
17
|
+
function resolve() {
|
|
18
|
+
if (process.env.NATS_EMBEDDED_BINARY) return process.env.NATS_EMBEDDED_BINARY;
|
|
19
|
+
const key = `${platform()}-${arch()}`;
|
|
20
|
+
const pkg = PLATFORM_MAP[key];
|
|
21
|
+
if (!pkg) throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`);
|
|
22
|
+
try {
|
|
23
|
+
return createRequire(import.meta.url).resolve(`${pkg}/${BINARY_NAME}`);
|
|
24
|
+
} catch {
|
|
25
|
+
const sibling = join(dirname(fileURLToPath(import.meta.url)), "..", "..", key, BINARY_NAME);
|
|
26
|
+
if (existsSync(sibling)) return sibling;
|
|
27
|
+
throw new Error(`Cannot find nats-server binary. Install ${pkg} or set NATS_EMBEDDED_BINARY`);
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
//#endregion
|
|
31
|
+
//#region src/parse.ts
|
|
32
|
+
function parsePort(line) {
|
|
33
|
+
const match = line.match(/Listening for client connections on .+:(\d+)/);
|
|
34
|
+
return match ? parseInt(match[1], 10) : null;
|
|
35
|
+
}
|
|
36
|
+
function parseWsPort(line) {
|
|
37
|
+
const match = line.match(/Listening for websocket clients on .+:(\d+)/);
|
|
38
|
+
return match ? parseInt(match[1], 10) : null;
|
|
39
|
+
}
|
|
40
|
+
//#endregion
|
|
41
|
+
//#region src/config.ts
|
|
42
|
+
function toSnakeCase(str) {
|
|
43
|
+
return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);
|
|
44
|
+
}
|
|
45
|
+
function serializeBlock(name, obj) {
|
|
46
|
+
return `${name} {\n${Object.entries(obj).map(([k, v]) => {
|
|
47
|
+
const key = toSnakeCase(k);
|
|
48
|
+
if (typeof v === "string") return ` ${key}: "${v}"`;
|
|
49
|
+
return ` ${key}: ${v}`;
|
|
50
|
+
}).join("\n")}\n}`;
|
|
51
|
+
}
|
|
52
|
+
const WS_DEFAULTS = {
|
|
53
|
+
port: -1,
|
|
54
|
+
no_tls: true
|
|
55
|
+
};
|
|
56
|
+
function buildConfig(opts) {
|
|
57
|
+
if (!opts.websocket) return null;
|
|
58
|
+
const parts = [serializeBlock("websocket", opts.websocket === true ? { ...WS_DEFAULTS } : {
|
|
59
|
+
...WS_DEFAULTS,
|
|
60
|
+
...opts.websocket
|
|
61
|
+
})];
|
|
62
|
+
if (opts.config) parts.push(`include '${resolve$1(opts.config)}'`);
|
|
63
|
+
return parts.join("\n\n") + "\n";
|
|
64
|
+
}
|
|
65
|
+
//#endregion
|
|
66
|
+
//#region src/index.ts
|
|
67
|
+
/**
|
|
68
|
+
* Maps option keys to their nats-server CLI flags.
|
|
69
|
+
* - boolean options: flag is pushed only when true
|
|
70
|
+
* - string/number options: flag + value
|
|
71
|
+
* - string[] options: flag + comma-joined value
|
|
72
|
+
*
|
|
73
|
+
* Keys not in this map are handled separately (host, port, verbose, websocket, config, args).
|
|
74
|
+
*/
|
|
75
|
+
const FLAG_MAP = {
|
|
76
|
+
serverName: "--server_name",
|
|
77
|
+
pidFile: "-P",
|
|
78
|
+
httpPort: "-m",
|
|
79
|
+
httpsPort: "-ms",
|
|
80
|
+
clientAdvertise: "--client_advertise",
|
|
81
|
+
portsFileDir: "--ports_file_dir",
|
|
82
|
+
debug: "-D",
|
|
83
|
+
trace: "-V",
|
|
84
|
+
log: "-l",
|
|
85
|
+
logtime: "-T",
|
|
86
|
+
syslog: "-s",
|
|
87
|
+
remoteSyslog: "-r",
|
|
88
|
+
logSizeLimit: "--log_size_limit",
|
|
89
|
+
maxTracedMsgLen: "--max_traced_msg_len",
|
|
90
|
+
jetstream: "-js",
|
|
91
|
+
storeDir: "-sd",
|
|
92
|
+
user: "--user",
|
|
93
|
+
pass: "--pass",
|
|
94
|
+
token: "--auth",
|
|
95
|
+
tls: "--tls",
|
|
96
|
+
tlsCert: "--tlscert",
|
|
97
|
+
tlsKey: "--tlskey",
|
|
98
|
+
tlsVerify: "--tlsverify",
|
|
99
|
+
tlsCaCert: "--tlscacert",
|
|
100
|
+
routes: "--routes",
|
|
101
|
+
cluster: "--cluster",
|
|
102
|
+
clusterName: "--cluster_name",
|
|
103
|
+
noAdvertise: "--no_advertise",
|
|
104
|
+
clusterAdvertise: "--cluster_advertise",
|
|
105
|
+
connectRetries: "--connect_retries",
|
|
106
|
+
clusterListen: "--cluster_listen",
|
|
107
|
+
profile: "--profile"
|
|
108
|
+
};
|
|
109
|
+
function buildArgs(opts, configPath) {
|
|
110
|
+
const host = opts.host ?? "127.0.0.1";
|
|
111
|
+
const port = opts.port ?? -1;
|
|
112
|
+
const args = [
|
|
113
|
+
"-a",
|
|
114
|
+
host,
|
|
115
|
+
"-p",
|
|
116
|
+
String(port)
|
|
117
|
+
];
|
|
118
|
+
for (const [key, flag] of Object.entries(FLAG_MAP)) {
|
|
119
|
+
const val = opts[key];
|
|
120
|
+
if (val === void 0 || val === false) continue;
|
|
121
|
+
if (val === true) args.push(flag);
|
|
122
|
+
else if (Array.isArray(val)) args.push(flag, val.join(","));
|
|
123
|
+
else args.push(flag, String(val));
|
|
124
|
+
}
|
|
125
|
+
if (configPath) args.push("-c", configPath);
|
|
126
|
+
else if (opts.config) args.push("-c", opts.config);
|
|
127
|
+
if (opts.args) args.push(...opts.args);
|
|
128
|
+
return args;
|
|
129
|
+
}
|
|
130
|
+
var NatsServer = class NatsServer {
|
|
131
|
+
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
132
|
+
url;
|
|
133
|
+
/** Assigned port */
|
|
134
|
+
port;
|
|
135
|
+
/** WebSocket port (undefined if websocket not enabled) */
|
|
136
|
+
wsPort;
|
|
137
|
+
/** WebSocket URL (undefined if websocket not enabled) */
|
|
138
|
+
wsUrl;
|
|
139
|
+
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
140
|
+
exited;
|
|
141
|
+
proc;
|
|
142
|
+
configDir;
|
|
143
|
+
constructor(proc, host, port, wsPort, configDir) {
|
|
144
|
+
this.proc = proc;
|
|
145
|
+
this.port = port;
|
|
146
|
+
this.url = `nats://${host}:${port}`;
|
|
147
|
+
if (wsPort !== void 0) {
|
|
148
|
+
this.wsPort = wsPort;
|
|
149
|
+
this.wsUrl = `ws://${host}:${wsPort}`;
|
|
150
|
+
}
|
|
151
|
+
this.configDir = configDir;
|
|
152
|
+
this.exited = new Promise((res) => {
|
|
153
|
+
proc.on("exit", (code) => res(code));
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
static async start(opts = {}) {
|
|
157
|
+
const bin = resolve();
|
|
158
|
+
const host = opts.host ?? "127.0.0.1";
|
|
159
|
+
const needWs = !!opts.websocket;
|
|
160
|
+
let configDir = null;
|
|
161
|
+
let configPath;
|
|
162
|
+
const configContent = buildConfig(opts);
|
|
163
|
+
if (configContent) {
|
|
164
|
+
configDir = mkdtempSync(join(tmpdir(), "nats-embedded-"));
|
|
165
|
+
configPath = join(configDir, "nats.conf");
|
|
166
|
+
writeFileSync(configPath, configContent);
|
|
167
|
+
}
|
|
168
|
+
const proc = spawn(bin, buildArgs(opts, configPath), { stdio: [
|
|
169
|
+
"ignore",
|
|
170
|
+
"ignore",
|
|
171
|
+
"pipe"
|
|
172
|
+
] });
|
|
173
|
+
const result = await new Promise((resolve, reject) => {
|
|
174
|
+
const timeout = setTimeout(() => {
|
|
175
|
+
proc.kill("SIGKILL");
|
|
176
|
+
reject(/* @__PURE__ */ new Error("nats-server did not start within 5s"));
|
|
177
|
+
}, 5e3);
|
|
178
|
+
proc.on("error", (err) => {
|
|
179
|
+
clearTimeout(timeout);
|
|
180
|
+
reject(err);
|
|
181
|
+
});
|
|
182
|
+
proc.on("exit", (code) => {
|
|
183
|
+
clearTimeout(timeout);
|
|
184
|
+
reject(/* @__PURE__ */ new Error(`nats-server exited with code ${code} before ready`));
|
|
185
|
+
});
|
|
186
|
+
let tcpPort = null;
|
|
187
|
+
let wsPort = null;
|
|
188
|
+
let resolved = false;
|
|
189
|
+
let buffer = "";
|
|
190
|
+
proc.stderr.on("data", (chunk) => {
|
|
191
|
+
const text = chunk.toString();
|
|
192
|
+
if (opts.verbose) process.stderr.write(text);
|
|
193
|
+
if (resolved) return;
|
|
194
|
+
buffer += text;
|
|
195
|
+
const lines = buffer.split("\n");
|
|
196
|
+
buffer = lines.pop();
|
|
197
|
+
for (const line of lines) {
|
|
198
|
+
const tcp = parsePort(line);
|
|
199
|
+
if (tcp !== null) tcpPort = tcp;
|
|
200
|
+
const ws = parseWsPort(line);
|
|
201
|
+
if (ws !== null) wsPort = ws;
|
|
202
|
+
if (tcpPort !== null && (!needWs || wsPort !== null)) {
|
|
203
|
+
resolved = true;
|
|
204
|
+
clearTimeout(timeout);
|
|
205
|
+
proc.removeAllListeners("exit");
|
|
206
|
+
resolve({
|
|
207
|
+
tcpPort,
|
|
208
|
+
wsPort: wsPort ?? void 0
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
});
|
|
215
|
+
return new NatsServer(proc, host, result.tcpPort, result.wsPort, configDir);
|
|
216
|
+
}
|
|
217
|
+
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
218
|
+
async stop() {
|
|
219
|
+
if (this.proc.exitCode !== null) return;
|
|
220
|
+
this.proc.kill("SIGTERM");
|
|
221
|
+
if (!await Promise.race([this.exited.then(() => true), new Promise((r) => setTimeout(() => r(false), 5e3))])) {
|
|
222
|
+
this.proc.kill("SIGKILL");
|
|
223
|
+
await this.exited;
|
|
224
|
+
}
|
|
225
|
+
if (this.configDir) {
|
|
226
|
+
try {
|
|
227
|
+
rmSync(this.configDir, { recursive: true });
|
|
228
|
+
} catch {}
|
|
229
|
+
this.configDir = null;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
//#endregion
|
|
234
|
+
export { NatsServer, buildArgs, buildConfig, resolve as resolveBinary };
|
|
235
|
+
|
|
236
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.mjs","names":["resolvePath"],"sources":["../src/resolve.ts","../src/parse.ts","../src/config.ts","../src/index.ts"],"sourcesContent":["import { platform, arch } from \"node:os\";\nimport { existsSync } from \"node:fs\";\nimport { createRequire } from \"node:module\";\nimport { join, dirname } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\n\nconst PLATFORM_MAP: Record<string, string> = {\n \"linux-x64\": \"@lagz0ne/nats-embedded-linux-x64\",\n \"linux-arm64\": \"@lagz0ne/nats-embedded-linux-arm64\",\n \"darwin-x64\": \"@lagz0ne/nats-embedded-darwin-x64\",\n \"darwin-arm64\": \"@lagz0ne/nats-embedded-darwin-arm64\",\n \"win32-x64\": \"@lagz0ne/nats-embedded-win32-x64\",\n \"win32-arm64\": \"@lagz0ne/nats-embedded-win32-arm64\",\n};\n\nconst BINARY_NAME = platform() === \"win32\" ? \"nats-server.exe\" : \"nats-server\";\n\nexport function resolve(): string {\n if (process.env.NATS_EMBEDDED_BINARY) return process.env.NATS_EMBEDDED_BINARY;\n\n const key = `${platform()}-${arch()}`;\n const pkg = PLATFORM_MAP[key];\n if (!pkg) throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(\", \")}`);\n\n // Try require.resolve first (works when platform packages are installed via npm)\n try {\n const require_ = createRequire(import.meta.url);\n return require_.resolve(`${pkg}/${BINARY_NAME}`);\n } catch {\n // Fallback: sibling package in monorepo layout\n const __dirname = dirname(fileURLToPath(import.meta.url));\n const sibling = join(__dirname, \"..\", \"..\", key, BINARY_NAME);\n if (existsSync(sibling)) return sibling;\n throw new Error(`Cannot find nats-server binary. Install ${pkg} or set NATS_EMBEDDED_BINARY`);\n }\n}\n","export function parsePort(line: string): number | null {\n const match = line.match(/Listening for client connections on .+:(\\d+)/);\n return match ? parseInt(match[1], 10) : null;\n}\n\nexport function parseWsPort(line: string): number | null {\n const match = line.match(/Listening for websocket clients on .+:(\\d+)/);\n return match ? parseInt(match[1], 10) : null;\n}\n","import { resolve as resolvePath } from \"node:path\";\n\ntype ConfigBlock = Record<string, unknown>;\n\nfunction toSnakeCase(str: string): string {\n return str.replace(/[A-Z]/g, (c) => `_${c.toLowerCase()}`);\n}\n\nfunction serializeBlock(name: string, obj: ConfigBlock): string {\n const lines = Object.entries(obj).map(([k, v]) => {\n const key = toSnakeCase(k);\n if (typeof v === \"string\") return ` ${key}: \"${v}\"`;\n return ` ${key}: ${v}`;\n });\n return `${name} {\\n${lines.join(\"\\n\")}\\n}`;\n}\n\nconst WS_DEFAULTS: ConfigBlock = { port: -1, no_tls: true };\n\nexport function buildConfig(opts: {\n websocket?: boolean | ConfigBlock;\n config?: string;\n}): string | null {\n if (!opts.websocket) return null;\n\n const ws =\n opts.websocket === true\n ? { ...WS_DEFAULTS }\n : { ...WS_DEFAULTS, ...opts.websocket };\n\n const parts: string[] = [serializeBlock(\"websocket\", ws)];\n\n if (opts.config) {\n parts.push(`include '${resolvePath(opts.config)}'`);\n }\n\n return parts.join(\"\\n\\n\") + \"\\n\";\n}\n","import { spawn, type ChildProcess } from \"node:child_process\";\nimport { mkdtempSync, writeFileSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { tmpdir } from \"node:os\";\nimport { resolve } from \"./resolve.js\";\nimport { parsePort, parseWsPort } from \"./parse.js\";\nimport { buildConfig } from \"./config.js\";\n\nexport interface NatsServerOptions {\n // ── Server ──────────────────────────────────────────────────────────\n /** Port to listen on. -1 = random (default), 0 = nats default (4222). */\n port?: number;\n /** Host to bind to. Default: 127.0.0.1 */\n host?: string;\n /** Server name. Default: auto-generated by NATS */\n serverName?: string;\n /** File to store PID */\n pidFile?: string;\n /** HTTP monitoring port */\n httpPort?: number;\n /** HTTPS monitoring port */\n httpsPort?: number;\n /** Client URL to advertise to other servers */\n clientAdvertise?: string;\n /** Directory to write ports file */\n portsFileDir?: string;\n\n // ── Logging ─────────────────────────────────────────────────────────\n /** Enable NATS debug output (-D flag) */\n debug?: boolean;\n /** Enable NATS protocol trace (-V flag) */\n trace?: boolean;\n /** Redirect NATS log output to file */\n log?: string;\n /** Timestamp log entries */\n logtime?: boolean;\n /** Log to syslog */\n syslog?: boolean;\n /** Remote syslog address (e.g. udp://localhost:514) */\n remoteSyslog?: string;\n /** Logfile size limit */\n logSizeLimit?: string;\n /** Maximum printable length for traced messages */\n maxTracedMsgLen?: number;\n\n // ── JetStream ───────────────────────────────────────────────────────\n /** Enable JetStream */\n jetstream?: boolean;\n /** JetStream storage directory */\n storeDir?: string;\n\n // ── Auth ────────────────────────────────────────────────────────────\n /** Username required for connections */\n user?: string;\n /** Password required for connections */\n pass?: string;\n /** Authorization token required for connections */\n token?: string;\n\n // ── TLS ─────────────────────────────────────────────────────────────\n /** Enable TLS */\n tls?: boolean;\n /** Server certificate file */\n tlsCert?: string;\n /** Private key for server certificate */\n tlsKey?: string;\n /** Enable TLS with client certificate verification */\n tlsVerify?: boolean;\n /** Client certificate CA for verification */\n tlsCaCert?: string;\n\n // ── Cluster ─────────────────────────────────────────────────────────\n /** Routes to solicit and connect */\n routes?: string[];\n /** Cluster URL for solicited routes */\n cluster?: string;\n /** Cluster name */\n clusterName?: string;\n /** Do not advertise known cluster information to clients */\n noAdvertise?: boolean;\n /** Cluster URL to advertise to other servers */\n clusterAdvertise?: string;\n /** Number of connect retries for implicit routes */\n connectRetries?: number;\n /** Cluster URL from which members can solicit routes */\n clusterListen?: string;\n\n // ── Profiling ───────────────────────────────────────────────────────\n /** Profiling HTTP port */\n profile?: number;\n\n // ── WebSocket ───────────────────────────────────────────────────────\n /** WebSocket listener. true = embedded defaults (random port, no TLS).\n * Object = full websocket config block passed to NATS. */\n websocket?: boolean | Record<string, unknown>;\n\n // ── Wrapper ─────────────────────────────────────────────────────────\n /** Forward nats-server stderr to process.stderr. Default: false */\n verbose?: boolean;\n\n // ── Escape hatches (forward-compat) ─────────────────────────────────\n /** Path to a custom nats.conf file */\n config?: string;\n /** Extra CLI arguments passed to nats-server */\n args?: string[];\n}\n\n/**\n * Maps option keys to their nats-server CLI flags.\n * - boolean options: flag is pushed only when true\n * - string/number options: flag + value\n * - string[] options: flag + comma-joined value\n *\n * Keys not in this map are handled separately (host, port, verbose, websocket, config, args).\n */\nconst FLAG_MAP: Record<string, string> = {\n serverName: \"--server_name\",\n pidFile: \"-P\",\n httpPort: \"-m\",\n httpsPort: \"-ms\",\n clientAdvertise: \"--client_advertise\",\n portsFileDir: \"--ports_file_dir\",\n debug: \"-D\",\n trace: \"-V\",\n log: \"-l\",\n logtime: \"-T\",\n syslog: \"-s\",\n remoteSyslog: \"-r\",\n logSizeLimit: \"--log_size_limit\",\n maxTracedMsgLen: \"--max_traced_msg_len\",\n jetstream: \"-js\",\n storeDir: \"-sd\",\n user: \"--user\",\n pass: \"--pass\",\n token: \"--auth\",\n tls: \"--tls\",\n tlsCert: \"--tlscert\",\n tlsKey: \"--tlskey\",\n tlsVerify: \"--tlsverify\",\n tlsCaCert: \"--tlscacert\",\n routes: \"--routes\",\n cluster: \"--cluster\",\n clusterName: \"--cluster_name\",\n noAdvertise: \"--no_advertise\",\n clusterAdvertise: \"--cluster_advertise\",\n connectRetries: \"--connect_retries\",\n clusterListen: \"--cluster_listen\",\n profile: \"--profile\",\n};\n\nexport function buildArgs(opts: NatsServerOptions, configPath?: string): string[] {\n const host = opts.host ?? \"127.0.0.1\";\n const port = opts.port ?? -1;\n const args = [\"-a\", host, \"-p\", String(port)];\n\n for (const [key, flag] of Object.entries(FLAG_MAP)) {\n const val = (opts as Record<string, unknown>)[key];\n if (val === undefined || val === false) continue;\n if (val === true) {\n args.push(flag);\n } else if (Array.isArray(val)) {\n args.push(flag, val.join(\",\"));\n } else {\n args.push(flag, String(val));\n }\n }\n\n if (configPath) {\n args.push(\"-c\", configPath);\n } else if (opts.config) {\n args.push(\"-c\", opts.config);\n }\n\n if (opts.args) args.push(...opts.args);\n return args;\n}\n\nexport class NatsServer {\n /** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */\n readonly url: string;\n /** Assigned port */\n readonly port: number;\n /** WebSocket port (undefined if websocket not enabled) */\n readonly wsPort?: number;\n /** WebSocket URL (undefined if websocket not enabled) */\n readonly wsUrl?: string;\n /** Resolves with the exit code when the process exits (for crash detection) */\n readonly exited: Promise<number | null>;\n\n private proc: ChildProcess;\n private configDir: string | null;\n\n private constructor(\n proc: ChildProcess,\n host: string,\n port: number,\n wsPort: number | undefined,\n configDir: string | null,\n ) {\n this.proc = proc;\n this.port = port;\n this.url = `nats://${host}:${port}`;\n if (wsPort !== undefined) {\n this.wsPort = wsPort;\n this.wsUrl = `ws://${host}:${wsPort}`;\n }\n this.configDir = configDir;\n this.exited = new Promise((res) => {\n proc.on(\"exit\", (code) => res(code));\n });\n }\n\n static async start(opts: NatsServerOptions = {}): Promise<NatsServer> {\n const bin = resolve();\n const host = opts.host ?? \"127.0.0.1\";\n const needWs = !!opts.websocket;\n\n // Generate config file if needed (websocket requires config block)\n let configDir: string | null = null;\n let configPath: string | undefined;\n const configContent = buildConfig(opts);\n if (configContent) {\n configDir = mkdtempSync(join(tmpdir(), \"nats-embedded-\"));\n configPath = join(configDir, \"nats.conf\");\n writeFileSync(configPath, configContent);\n }\n\n const args = buildArgs(opts, configPath);\n\n const proc = spawn(bin, args, {\n stdio: [\"ignore\", \"ignore\", \"pipe\"],\n });\n\n const result = await new Promise<{ tcpPort: number; wsPort?: number }>(\n (resolve, reject) => {\n const timeout = setTimeout(() => {\n proc.kill(\"SIGKILL\");\n reject(new Error(\"nats-server did not start within 5s\"));\n }, 5000);\n\n proc.on(\"error\", (err) => {\n clearTimeout(timeout);\n reject(err);\n });\n\n proc.on(\"exit\", (code) => {\n clearTimeout(timeout);\n reject(\n new Error(`nats-server exited with code ${code} before ready`),\n );\n });\n\n let tcpPort: number | null = null;\n let wsPort: number | null = null;\n let resolved = false;\n let buffer = \"\";\n\n proc.stderr!.on(\"data\", (chunk: Buffer) => {\n const text = chunk.toString();\n if (opts.verbose) process.stderr.write(text);\n if (resolved) return;\n buffer += text;\n const lines = buffer.split(\"\\n\");\n buffer = lines.pop()!;\n for (const line of lines) {\n const tcp = parsePort(line);\n if (tcp !== null) tcpPort = tcp;\n const ws = parseWsPort(line);\n if (ws !== null) wsPort = ws;\n\n if (tcpPort !== null && (!needWs || wsPort !== null)) {\n resolved = true;\n clearTimeout(timeout);\n proc.removeAllListeners(\"exit\");\n resolve({\n tcpPort,\n wsPort: wsPort ?? undefined,\n });\n return;\n }\n }\n });\n },\n );\n\n return new NatsServer(proc, host, result.tcpPort, result.wsPort, configDir);\n }\n\n /** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */\n async stop(): Promise<void> {\n if (this.proc.exitCode !== null) return;\n this.proc.kill(\"SIGTERM\");\n const exited = await Promise.race([\n this.exited.then(() => true),\n new Promise<false>((r) => setTimeout(() => r(false), 5000)),\n ]);\n if (!exited) {\n this.proc.kill(\"SIGKILL\");\n await this.exited;\n }\n if (this.configDir) {\n try {\n rmSync(this.configDir, { recursive: true });\n } catch {}\n this.configDir = null;\n }\n }\n}\n\nexport { resolve as resolveBinary } from \"./resolve.js\";\nexport { buildConfig } from \"./config.js\";\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lagz0ne/nats-embedded",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.1",
|
|
4
4
|
"description": "Embedded NATS server for Node.js and Bun — managed child process with random port allocation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "Apache-2.0",
|
|
@@ -16,30 +16,38 @@
|
|
|
16
16
|
"engines": {
|
|
17
17
|
"node": ">=18"
|
|
18
18
|
},
|
|
19
|
-
"main": "./dist/index.
|
|
20
|
-
"
|
|
19
|
+
"main": "./dist/index.cjs",
|
|
20
|
+
"module": "./dist/index.mjs",
|
|
21
|
+
"types": "./dist/index.d.mts",
|
|
21
22
|
"exports": {
|
|
22
23
|
".": {
|
|
23
|
-
"import":
|
|
24
|
-
|
|
24
|
+
"import": {
|
|
25
|
+
"types": "./dist/index.d.mts",
|
|
26
|
+
"default": "./dist/index.mjs"
|
|
27
|
+
},
|
|
28
|
+
"require": {
|
|
29
|
+
"types": "./dist/index.d.cts",
|
|
30
|
+
"default": "./dist/index.cjs"
|
|
31
|
+
}
|
|
25
32
|
}
|
|
26
33
|
},
|
|
27
34
|
"files": ["dist", "LICENSE"],
|
|
28
35
|
"scripts": {
|
|
29
|
-
"build": "
|
|
36
|
+
"build": "tsdown",
|
|
30
37
|
"test": "bun test"
|
|
31
38
|
},
|
|
32
39
|
"optionalDependencies": {
|
|
33
|
-
"@lagz0ne/nats-embedded-linux-x64": "0.
|
|
34
|
-
"@lagz0ne/nats-embedded-linux-arm64": "0.
|
|
35
|
-
"@lagz0ne/nats-embedded-darwin-x64": "0.
|
|
36
|
-
"@lagz0ne/nats-embedded-darwin-arm64": "0.
|
|
37
|
-
"@lagz0ne/nats-embedded-win32-x64": "0.
|
|
38
|
-
"@lagz0ne/nats-embedded-win32-arm64": "0.
|
|
40
|
+
"@lagz0ne/nats-embedded-linux-x64": "0.3.1",
|
|
41
|
+
"@lagz0ne/nats-embedded-linux-arm64": "0.3.1",
|
|
42
|
+
"@lagz0ne/nats-embedded-darwin-x64": "0.3.1",
|
|
43
|
+
"@lagz0ne/nats-embedded-darwin-arm64": "0.3.1",
|
|
44
|
+
"@lagz0ne/nats-embedded-win32-x64": "0.3.1",
|
|
45
|
+
"@lagz0ne/nats-embedded-win32-arm64": "0.3.1"
|
|
39
46
|
},
|
|
40
47
|
"devDependencies": {
|
|
41
|
-
"typescript": "^5.7.0",
|
|
42
48
|
"@types/node": "^22.0.0",
|
|
43
|
-
"bun-types": "^1.2.0"
|
|
49
|
+
"bun-types": "^1.2.0",
|
|
50
|
+
"tsdown": "^0.21.4",
|
|
51
|
+
"typescript": "^5.7.0"
|
|
44
52
|
}
|
|
45
53
|
}
|
package/dist/index.d.ts
DELETED
|
@@ -1,92 +0,0 @@
|
|
|
1
|
-
export interface NatsServerOptions {
|
|
2
|
-
/** Port to listen on. -1 = random (default), 0 = nats default (4222). */
|
|
3
|
-
port?: number;
|
|
4
|
-
/** Host to bind to. Default: 127.0.0.1 */
|
|
5
|
-
host?: string;
|
|
6
|
-
/** Server name. Default: auto-generated by NATS */
|
|
7
|
-
serverName?: string;
|
|
8
|
-
/** File to store PID */
|
|
9
|
-
pidFile?: string;
|
|
10
|
-
/** HTTP monitoring port */
|
|
11
|
-
httpPort?: number;
|
|
12
|
-
/** HTTPS monitoring port */
|
|
13
|
-
httpsPort?: number;
|
|
14
|
-
/** Client URL to advertise to other servers */
|
|
15
|
-
clientAdvertise?: string;
|
|
16
|
-
/** Directory to write ports file */
|
|
17
|
-
portsFileDir?: string;
|
|
18
|
-
/** Enable NATS debug output (-D flag) */
|
|
19
|
-
debug?: boolean;
|
|
20
|
-
/** Enable NATS protocol trace (-V flag) */
|
|
21
|
-
trace?: boolean;
|
|
22
|
-
/** Redirect NATS log output to file */
|
|
23
|
-
log?: string;
|
|
24
|
-
/** Timestamp log entries */
|
|
25
|
-
logtime?: boolean;
|
|
26
|
-
/** Log to syslog */
|
|
27
|
-
syslog?: boolean;
|
|
28
|
-
/** Remote syslog address (e.g. udp://localhost:514) */
|
|
29
|
-
remoteSyslog?: string;
|
|
30
|
-
/** Logfile size limit */
|
|
31
|
-
logSizeLimit?: string;
|
|
32
|
-
/** Maximum printable length for traced messages */
|
|
33
|
-
maxTracedMsgLen?: number;
|
|
34
|
-
/** Enable JetStream */
|
|
35
|
-
jetstream?: boolean;
|
|
36
|
-
/** JetStream storage directory */
|
|
37
|
-
storeDir?: string;
|
|
38
|
-
/** Username required for connections */
|
|
39
|
-
user?: string;
|
|
40
|
-
/** Password required for connections */
|
|
41
|
-
pass?: string;
|
|
42
|
-
/** Authorization token required for connections */
|
|
43
|
-
token?: string;
|
|
44
|
-
/** Enable TLS */
|
|
45
|
-
tls?: boolean;
|
|
46
|
-
/** Server certificate file */
|
|
47
|
-
tlsCert?: string;
|
|
48
|
-
/** Private key for server certificate */
|
|
49
|
-
tlsKey?: string;
|
|
50
|
-
/** Enable TLS with client certificate verification */
|
|
51
|
-
tlsVerify?: boolean;
|
|
52
|
-
/** Client certificate CA for verification */
|
|
53
|
-
tlsCaCert?: string;
|
|
54
|
-
/** Routes to solicit and connect */
|
|
55
|
-
routes?: string[];
|
|
56
|
-
/** Cluster URL for solicited routes */
|
|
57
|
-
cluster?: string;
|
|
58
|
-
/** Cluster name */
|
|
59
|
-
clusterName?: string;
|
|
60
|
-
/** Do not advertise known cluster information to clients */
|
|
61
|
-
noAdvertise?: boolean;
|
|
62
|
-
/** Cluster URL to advertise to other servers */
|
|
63
|
-
clusterAdvertise?: string;
|
|
64
|
-
/** Number of connect retries for implicit routes */
|
|
65
|
-
connectRetries?: number;
|
|
66
|
-
/** Cluster URL from which members can solicit routes */
|
|
67
|
-
clusterListen?: string;
|
|
68
|
-
/** Profiling HTTP port */
|
|
69
|
-
profile?: number;
|
|
70
|
-
/** Forward nats-server stderr to process.stderr. Default: false */
|
|
71
|
-
verbose?: boolean;
|
|
72
|
-
/** Path to a custom nats.conf file */
|
|
73
|
-
config?: string;
|
|
74
|
-
/** Extra CLI arguments passed to nats-server */
|
|
75
|
-
args?: string[];
|
|
76
|
-
}
|
|
77
|
-
export declare function buildArgs(opts: NatsServerOptions): string[];
|
|
78
|
-
export declare class NatsServer {
|
|
79
|
-
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
80
|
-
readonly url: string;
|
|
81
|
-
/** Assigned port */
|
|
82
|
-
readonly port: number;
|
|
83
|
-
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
84
|
-
readonly exited: Promise<number | null>;
|
|
85
|
-
private proc;
|
|
86
|
-
private constructor();
|
|
87
|
-
static start(opts?: NatsServerOptions): Promise<NatsServer>;
|
|
88
|
-
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
89
|
-
stop(): Promise<void>;
|
|
90
|
-
}
|
|
91
|
-
export { resolve as resolveBinary } from "./resolve.js";
|
|
92
|
-
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
DELETED
|
@@ -1,143 +0,0 @@
|
|
|
1
|
-
import { spawn } from "node:child_process";
|
|
2
|
-
import { resolve } from "./resolve.js";
|
|
3
|
-
import { parsePort } from "./parse.js";
|
|
4
|
-
/**
|
|
5
|
-
* Maps option keys to their nats-server CLI flags.
|
|
6
|
-
* - boolean options: flag is pushed only when true
|
|
7
|
-
* - string/number options: flag + value
|
|
8
|
-
* - string[] options: flag + comma-joined value
|
|
9
|
-
*
|
|
10
|
-
* Keys not in this map are handled separately (host, port, verbose, args).
|
|
11
|
-
*/
|
|
12
|
-
const FLAG_MAP = {
|
|
13
|
-
serverName: "--server_name",
|
|
14
|
-
pidFile: "-P",
|
|
15
|
-
httpPort: "-m",
|
|
16
|
-
httpsPort: "-ms",
|
|
17
|
-
clientAdvertise: "--client_advertise",
|
|
18
|
-
portsFileDir: "--ports_file_dir",
|
|
19
|
-
debug: "-D",
|
|
20
|
-
trace: "-V",
|
|
21
|
-
log: "-l",
|
|
22
|
-
logtime: "-T",
|
|
23
|
-
syslog: "-s",
|
|
24
|
-
remoteSyslog: "-r",
|
|
25
|
-
logSizeLimit: "--log_size_limit",
|
|
26
|
-
maxTracedMsgLen: "--max_traced_msg_len",
|
|
27
|
-
jetstream: "-js",
|
|
28
|
-
storeDir: "-sd",
|
|
29
|
-
user: "--user",
|
|
30
|
-
pass: "--pass",
|
|
31
|
-
token: "--auth",
|
|
32
|
-
tls: "--tls",
|
|
33
|
-
tlsCert: "--tlscert",
|
|
34
|
-
tlsKey: "--tlskey",
|
|
35
|
-
tlsVerify: "--tlsverify",
|
|
36
|
-
tlsCaCert: "--tlscacert",
|
|
37
|
-
routes: "--routes",
|
|
38
|
-
cluster: "--cluster",
|
|
39
|
-
clusterName: "--cluster_name",
|
|
40
|
-
noAdvertise: "--no_advertise",
|
|
41
|
-
clusterAdvertise: "--cluster_advertise",
|
|
42
|
-
connectRetries: "--connect_retries",
|
|
43
|
-
clusterListen: "--cluster_listen",
|
|
44
|
-
profile: "--profile",
|
|
45
|
-
config: "-c",
|
|
46
|
-
};
|
|
47
|
-
export function buildArgs(opts) {
|
|
48
|
-
const host = opts.host ?? "127.0.0.1";
|
|
49
|
-
const port = opts.port ?? -1;
|
|
50
|
-
const args = ["-a", host, "-p", String(port)];
|
|
51
|
-
for (const [key, flag] of Object.entries(FLAG_MAP)) {
|
|
52
|
-
const val = opts[key];
|
|
53
|
-
if (val === undefined || val === false)
|
|
54
|
-
continue;
|
|
55
|
-
if (val === true) {
|
|
56
|
-
args.push(flag);
|
|
57
|
-
}
|
|
58
|
-
else if (Array.isArray(val)) {
|
|
59
|
-
args.push(flag, val.join(","));
|
|
60
|
-
}
|
|
61
|
-
else {
|
|
62
|
-
args.push(flag, String(val));
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
if (opts.args)
|
|
66
|
-
args.push(...opts.args);
|
|
67
|
-
return args;
|
|
68
|
-
}
|
|
69
|
-
export class NatsServer {
|
|
70
|
-
/** Full NATS connection URL (e.g. nats://127.0.0.1:52431) */
|
|
71
|
-
url;
|
|
72
|
-
/** Assigned port */
|
|
73
|
-
port;
|
|
74
|
-
/** Resolves with the exit code when the process exits (for crash detection) */
|
|
75
|
-
exited;
|
|
76
|
-
proc;
|
|
77
|
-
constructor(proc, host, port) {
|
|
78
|
-
this.proc = proc;
|
|
79
|
-
this.port = port;
|
|
80
|
-
this.url = `nats://${host}:${port}`;
|
|
81
|
-
this.exited = new Promise((res) => {
|
|
82
|
-
proc.on("exit", (code) => res(code));
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
static async start(opts = {}) {
|
|
86
|
-
const bin = resolve();
|
|
87
|
-
const args = buildArgs(opts);
|
|
88
|
-
const host = opts.host ?? "127.0.0.1";
|
|
89
|
-
const proc = spawn(bin, args, {
|
|
90
|
-
stdio: ["ignore", "ignore", "pipe"],
|
|
91
|
-
});
|
|
92
|
-
const assignedPort = await new Promise((resolve, reject) => {
|
|
93
|
-
const timeout = setTimeout(() => {
|
|
94
|
-
proc.kill("SIGKILL");
|
|
95
|
-
reject(new Error("nats-server did not start within 5s"));
|
|
96
|
-
}, 5000);
|
|
97
|
-
proc.on("error", (err) => {
|
|
98
|
-
clearTimeout(timeout);
|
|
99
|
-
reject(err);
|
|
100
|
-
});
|
|
101
|
-
proc.on("exit", (code) => {
|
|
102
|
-
clearTimeout(timeout);
|
|
103
|
-
reject(new Error(`nats-server exited with code ${code} before ready`));
|
|
104
|
-
});
|
|
105
|
-
let buffer = "";
|
|
106
|
-
proc.stderr.on("data", (chunk) => {
|
|
107
|
-
const text = chunk.toString();
|
|
108
|
-
if (opts.verbose)
|
|
109
|
-
process.stderr.write(text);
|
|
110
|
-
buffer += text;
|
|
111
|
-
const lines = buffer.split("\n");
|
|
112
|
-
buffer = lines.pop();
|
|
113
|
-
for (const line of lines) {
|
|
114
|
-
const parsed = parsePort(line);
|
|
115
|
-
if (parsed !== null) {
|
|
116
|
-
clearTimeout(timeout);
|
|
117
|
-
// Stop listening for exit as an error once we have the port
|
|
118
|
-
proc.removeAllListeners("exit");
|
|
119
|
-
resolve(parsed);
|
|
120
|
-
return;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
});
|
|
124
|
-
});
|
|
125
|
-
return new NatsServer(proc, host, assignedPort);
|
|
126
|
-
}
|
|
127
|
-
/** Gracefully stop the server (SIGTERM → 5s timeout → SIGKILL) */
|
|
128
|
-
async stop() {
|
|
129
|
-
if (this.proc.exitCode !== null)
|
|
130
|
-
return;
|
|
131
|
-
this.proc.kill("SIGTERM");
|
|
132
|
-
const exited = await Promise.race([
|
|
133
|
-
this.exited.then(() => true),
|
|
134
|
-
new Promise((r) => setTimeout(() => r(false), 5000)),
|
|
135
|
-
]);
|
|
136
|
-
if (!exited) {
|
|
137
|
-
this.proc.kill("SIGKILL");
|
|
138
|
-
await this.exited;
|
|
139
|
-
}
|
|
140
|
-
}
|
|
141
|
-
}
|
|
142
|
-
export { resolve as resolveBinary } from "./resolve.js";
|
|
143
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/dist/parse.d.ts
DELETED
package/dist/parse.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.d.ts","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAGrD"}
|
package/dist/parse.js
DELETED
package/dist/parse.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"parse.js","sourceRoot":"","sources":["../src/parse.ts"],"names":[],"mappings":"AAAA,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,8CAA8C,CAAC,CAAC;IACzE,OAAO,KAAK,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;AAC/C,CAAC"}
|
package/dist/resolve.d.ts
DELETED
package/dist/resolve.d.ts.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.d.ts","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAiBA,wBAAgB,OAAO,IAAI,MAAM,CAkBhC"}
|
package/dist/resolve.js
DELETED
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
import { platform, arch } from "node:os";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { createRequire } from "node:module";
|
|
4
|
-
import { join, dirname } from "node:path";
|
|
5
|
-
import { fileURLToPath } from "node:url";
|
|
6
|
-
const PLATFORM_MAP = {
|
|
7
|
-
"linux-x64": "@lagz0ne/nats-embedded-linux-x64",
|
|
8
|
-
"linux-arm64": "@lagz0ne/nats-embedded-linux-arm64",
|
|
9
|
-
"darwin-x64": "@lagz0ne/nats-embedded-darwin-x64",
|
|
10
|
-
"darwin-arm64": "@lagz0ne/nats-embedded-darwin-arm64",
|
|
11
|
-
"win32-x64": "@lagz0ne/nats-embedded-win32-x64",
|
|
12
|
-
"win32-arm64": "@lagz0ne/nats-embedded-win32-arm64",
|
|
13
|
-
};
|
|
14
|
-
const BINARY_NAME = platform() === "win32" ? "nats-server.exe" : "nats-server";
|
|
15
|
-
export function resolve() {
|
|
16
|
-
if (process.env.NATS_EMBEDDED_BINARY)
|
|
17
|
-
return process.env.NATS_EMBEDDED_BINARY;
|
|
18
|
-
const key = `${platform()}-${arch()}`;
|
|
19
|
-
const pkg = PLATFORM_MAP[key];
|
|
20
|
-
if (!pkg)
|
|
21
|
-
throw new Error(`Unsupported platform: ${key}. Supported: ${Object.keys(PLATFORM_MAP).join(", ")}`);
|
|
22
|
-
// Try require.resolve first (works when platform packages are installed via npm)
|
|
23
|
-
try {
|
|
24
|
-
const require_ = createRequire(import.meta.url);
|
|
25
|
-
return require_.resolve(`${pkg}/${BINARY_NAME}`);
|
|
26
|
-
}
|
|
27
|
-
catch {
|
|
28
|
-
// Fallback: sibling package in monorepo layout
|
|
29
|
-
const __dirname = dirname(fileURLToPath(import.meta.url));
|
|
30
|
-
const sibling = join(__dirname, "..", "..", key, BINARY_NAME);
|
|
31
|
-
if (existsSync(sibling))
|
|
32
|
-
return sibling;
|
|
33
|
-
throw new Error(`Cannot find nats-server binary. Install ${pkg} or set NATS_EMBEDDED_BINARY`);
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=resolve.js.map
|
package/dist/resolve.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"resolve.js","sourceRoot":"","sources":["../src/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,MAAM,SAAS,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AACrC,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC5C,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAEzC,MAAM,YAAY,GAA2B;IAC3C,WAAW,EAAE,kCAAkC;IAC/C,aAAa,EAAE,oCAAoC;IACnD,YAAY,EAAE,mCAAmC;IACjD,cAAc,EAAE,qCAAqC;IACrD,WAAW,EAAE,kCAAkC;IAC/C,aAAa,EAAE,oCAAoC;CACpD,CAAC;AAEF,MAAM,WAAW,GAAG,QAAQ,EAAE,KAAK,OAAO,CAAC,CAAC,CAAC,iBAAiB,CAAC,CAAC,CAAC,aAAa,CAAC;AAE/E,MAAM,UAAU,OAAO;IACrB,IAAI,OAAO,CAAC,GAAG,CAAC,oBAAoB;QAAE,OAAO,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC;IAE9E,MAAM,GAAG,GAAG,GAAG,QAAQ,EAAE,IAAI,IAAI,EAAE,EAAE,CAAC;IACtC,MAAM,GAAG,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;IAC9B,IAAI,CAAC,GAAG;QAAE,MAAM,IAAI,KAAK,CAAC,yBAAyB,GAAG,gBAAgB,MAAM,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAE9G,iFAAiF;IACjF,IAAI,CAAC;QACH,MAAM,QAAQ,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,OAAO,QAAQ,CAAC,OAAO,CAAC,GAAG,GAAG,IAAI,WAAW,EAAE,CAAC,CAAC;IACnD,CAAC;IAAC,MAAM,CAAC;QACP,+CAA+C;QAC/C,MAAM,SAAS,GAAG,OAAO,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;QAC1D,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,GAAG,EAAE,WAAW,CAAC,CAAC;QAC9D,IAAI,UAAU,CAAC,OAAO,CAAC;YAAE,OAAO,OAAO,CAAC;QACxC,MAAM,IAAI,KAAK,CAAC,2CAA2C,GAAG,8BAA8B,CAAC,CAAC;IAChG,CAAC;AACH,CAAC"}
|