@push.rocks/smartrust 1.1.2 → 1.2.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/changelog.md +20 -0
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.rustbinarylocator.js +12 -2
- package/dist_ts/classes.rustbridge.d.ts +20 -2
- package/dist_ts/classes.rustbridge.js +139 -26
- package/dist_ts/classes.streamingresponse.d.ts +36 -0
- package/dist_ts/classes.streamingresponse.js +102 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/interfaces/config.d.ts +5 -0
- package/dist_ts/interfaces/ipc.d.ts +23 -0
- package/dist_ts/plugins.d.ts +1 -2
- package/dist_ts/plugins.js +2 -3
- package/package.json +1 -1
- package/readme.md +167 -33
- package/test/helpers/mock-rust-binary.mjs +63 -21
- package/test/test.rustbridge.node.ts +249 -0
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.rustbinarylocator.ts +10 -1
- package/ts/classes.rustbridge.ts +166 -27
- package/ts/classes.streamingresponse.ts +110 -0
- package/ts/index.ts +1 -0
- package/ts/interfaces/config.ts +5 -0
- package/ts/interfaces/ipc.ts +22 -0
- package/ts/plugins.ts +1 -2
package/changelog.md
CHANGED
|
@@ -1,5 +1,25 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 2026-02-12 - 1.2.1 - fix(rust-binary-locator)
|
|
4
|
+
auto-fix missing execute permission for located Rust binaries
|
|
5
|
+
|
|
6
|
+
- If a located binary exists but lacks the execute bit, attempt to chmod it to 0o755 and treat it as executable.
|
|
7
|
+
- Logs an info message when the auto-fix is applied: 'Auto-fixed missing execute permission on: <filePath>'.
|
|
8
|
+
- Addresses cases where npm/pnpm installs remove the execute permission from bundled binaries.
|
|
9
|
+
|
|
10
|
+
## 2026-02-11 - 1.2.0 - feat(rustbridge)
|
|
11
|
+
add streaming responses and robust large-payload/backpressure handling to RustBridge
|
|
12
|
+
|
|
13
|
+
- Introduce StreamingResponse type and export it (for-await-of iterator + .result promise)
|
|
14
|
+
- Add sendCommandStreaming API to send streaming commands and receive chunks + final result
|
|
15
|
+
- Implement buffer-based stdout newline scanner to handle large messages and avoid readline limits
|
|
16
|
+
- Add backpressure-aware writeToStdin to wait for drain when writing large outbound payloads
|
|
17
|
+
- Add maxPayloadSize option and enforce outbound/inbound size checks to prevent OOMs
|
|
18
|
+
- Add streamTimeoutMs (inactivity timeout) and reset timeout on each received chunk
|
|
19
|
+
- Improve stderr handling (cross-chunk buffering and trimmed emits)
|
|
20
|
+
- Update mock test binary and extensive tests for streaming, large payloads, concurrency, and error cases
|
|
21
|
+
- Add TypeScript types for streaming commands (TStreamingCommandKeys, TExtractChunk, IManagementStreamChunk)
|
|
22
|
+
|
|
3
23
|
## 2026-02-10 - 1.1.2 - fix(rust-binary-locator)
|
|
4
24
|
use import.meta.resolve and url.fileURLToPath to locate bundled Rust binary in ESM environments
|
|
5
25
|
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartrust',
|
|
6
|
-
version: '1.1
|
|
6
|
+
version: '1.2.1',
|
|
7
7
|
description: 'a bridge between JS engines and rust'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLHNDQUFzQztDQUNwRCxDQUFBIn0=
|
|
@@ -110,7 +110,17 @@ export class RustBinaryLocator {
|
|
|
110
110
|
return true;
|
|
111
111
|
}
|
|
112
112
|
catch {
|
|
113
|
-
|
|
113
|
+
// File may exist but lack execute bit (common after npm/pnpm install).
|
|
114
|
+
// Try to make it executable.
|
|
115
|
+
try {
|
|
116
|
+
await plugins.fs.promises.access(filePath, plugins.fs.constants.F_OK);
|
|
117
|
+
await plugins.fs.promises.chmod(filePath, 0o755);
|
|
118
|
+
this.logger.log('info', `Auto-fixed missing execute permission on: ${filePath}`);
|
|
119
|
+
return true;
|
|
120
|
+
}
|
|
121
|
+
catch {
|
|
122
|
+
return false;
|
|
123
|
+
}
|
|
114
124
|
}
|
|
115
125
|
}
|
|
116
126
|
async findInPath(binaryName) {
|
|
@@ -124,4 +134,4 @@ export class RustBinaryLocator {
|
|
|
124
134
|
return null;
|
|
125
135
|
}
|
|
126
136
|
}
|
|
127
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
137
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YmluYXJ5bG9jYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMucnVzdGJpbmFyeWxvY2F0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLE9BQU8sTUFBTSxjQUFjLENBQUM7QUFHeEMsTUFBTSxhQUFhLEdBQXNCO0lBQ3ZDLEdBQUcsS0FBSSxDQUFDO0NBQ1QsQ0FBQztBQUVGOzs7Ozs7O0dBT0c7QUFDSCxNQUFNLE9BQU8saUJBQWlCO0lBQ3BCLE9BQU8sQ0FBd0I7SUFDL0IsTUFBTSxDQUFvQjtJQUMxQixVQUFVLEdBQWtCLElBQUksQ0FBQztJQUV6QyxZQUFZLE9BQThCLEVBQUUsTUFBMEI7UUFDcEUsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUM7UUFDdkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxNQUFNLElBQUksYUFBYSxDQUFDO0lBQ3hDLENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMsVUFBVTtRQUNyQixJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsVUFBVSxDQUFDO1FBQ3pCLENBQUM7UUFDRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN2QyxJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztRQUN2QixPQUFPLElBQUksQ0FBQztJQUNkLENBQUM7SUFFRDs7T0FFRztJQUNJLFVBQVU7UUFDZixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQztJQUN6QixDQUFDO0lBRU8sS0FBSyxDQUFDLFlBQVk7UUFDeEIsTUFBTSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FBQyxPQUFPLENBQUM7UUFFcEMsbUNBQW1DO1FBQ25DLElBQUksSUFBSSxDQUFDLE9BQU8sQ0FBQyxVQUFVLEVBQUUsQ0FBQztZQUM1QixJQUFJLE1BQU0sSUFB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
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
|
-
import
|
|
2
|
+
import { StreamingResponse } from './classes.streamingresponse.js';
|
|
3
|
+
import type { IRustBridgeOptions, TCommandMap, TStreamingCommandKeys, TExtractChunk } from './interfaces/index.js';
|
|
3
4
|
/**
|
|
4
5
|
* Generic bridge between TypeScript and a Rust binary.
|
|
5
6
|
* Communicates via JSON-over-stdin/stdout IPC protocol.
|
|
@@ -11,7 +12,8 @@ export declare class RustBridge<TCommands extends TCommandMap = TCommandMap> ext
|
|
|
11
12
|
private options;
|
|
12
13
|
private logger;
|
|
13
14
|
private childProcess;
|
|
14
|
-
private
|
|
15
|
+
private stdoutBuffer;
|
|
16
|
+
private stderrRemainder;
|
|
15
17
|
private pendingRequests;
|
|
16
18
|
private requestCounter;
|
|
17
19
|
private isRunning;
|
|
@@ -26,6 +28,12 @@ export declare class RustBridge<TCommands extends TCommandMap = TCommandMap> ext
|
|
|
26
28
|
* Send a typed command to the Rust process and wait for the response.
|
|
27
29
|
*/
|
|
28
30
|
sendCommand<K extends string & keyof TCommands>(method: K, params: TCommands[K]['params']): Promise<TCommands[K]['result']>;
|
|
31
|
+
/**
|
|
32
|
+
* Send a streaming command to the Rust process.
|
|
33
|
+
* Returns a StreamingResponse that yields chunks via `for await...of`
|
|
34
|
+
* and exposes `.result` for the final response.
|
|
35
|
+
*/
|
|
36
|
+
sendCommandStreaming<K extends string & TStreamingCommandKeys<TCommands>>(method: K, params: TCommands[K]['params']): StreamingResponse<TExtractChunk<TCommands[K]>, TCommands[K]['result']>;
|
|
29
37
|
/**
|
|
30
38
|
* Kill the Rust process and clean up all resources.
|
|
31
39
|
*/
|
|
@@ -34,6 +42,16 @@ export declare class RustBridge<TCommands extends TCommandMap = TCommandMap> ext
|
|
|
34
42
|
* Whether the bridge is currently running.
|
|
35
43
|
*/
|
|
36
44
|
get running(): boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Buffer-based newline scanner for stdout chunks.
|
|
47
|
+
* Replaces readline to handle large payloads without buffering entire lines in a separate abstraction.
|
|
48
|
+
*/
|
|
49
|
+
private handleStdoutChunk;
|
|
50
|
+
/**
|
|
51
|
+
* Write data to stdin with backpressure support.
|
|
52
|
+
* Waits for drain if the internal buffer is full.
|
|
53
|
+
*/
|
|
54
|
+
private writeToStdin;
|
|
37
55
|
private handleLine;
|
|
38
56
|
private cleanup;
|
|
39
57
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
|
+
import { StreamingResponse } from './classes.streamingresponse.js';
|
|
3
4
|
const defaultLogger = {
|
|
4
5
|
log() { },
|
|
5
6
|
};
|
|
@@ -14,7 +15,8 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
14
15
|
options;
|
|
15
16
|
logger;
|
|
16
17
|
childProcess = null;
|
|
17
|
-
|
|
18
|
+
stdoutBuffer = Buffer.alloc(0);
|
|
19
|
+
stderrRemainder = '';
|
|
18
20
|
pendingRequests = new Map();
|
|
19
21
|
requestCounter = 0;
|
|
20
22
|
isRunning = false;
|
|
@@ -27,6 +29,7 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
27
29
|
requestTimeoutMs: 30000,
|
|
28
30
|
readyTimeoutMs: 10000,
|
|
29
31
|
readyEventName: 'ready',
|
|
32
|
+
maxPayloadSize: 50 * 1024 * 1024,
|
|
30
33
|
...options,
|
|
31
34
|
};
|
|
32
35
|
this.locator = new RustBinaryLocator(options, this.logger);
|
|
@@ -49,22 +52,32 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
49
52
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
50
53
|
env,
|
|
51
54
|
});
|
|
52
|
-
// Handle stderr
|
|
55
|
+
// Handle stderr with cross-chunk buffering
|
|
53
56
|
this.childProcess.stderr?.on('data', (data) => {
|
|
54
|
-
|
|
57
|
+
this.stderrRemainder += data.toString();
|
|
58
|
+
const lines = this.stderrRemainder.split('\n');
|
|
59
|
+
// Keep the last element (incomplete line) as remainder
|
|
60
|
+
this.stderrRemainder = lines.pop();
|
|
55
61
|
for (const line of lines) {
|
|
56
|
-
|
|
57
|
-
|
|
62
|
+
const trimmed = line.trim();
|
|
63
|
+
if (trimmed) {
|
|
64
|
+
this.logger.log('debug', `[${this.options.binaryName}] ${trimmed}`);
|
|
65
|
+
this.emit('stderr', trimmed);
|
|
66
|
+
}
|
|
58
67
|
}
|
|
59
68
|
});
|
|
60
|
-
// Handle stdout via
|
|
61
|
-
this.
|
|
62
|
-
|
|
63
|
-
this.handleLine(line.trim());
|
|
69
|
+
// Handle stdout via Buffer-based newline scanner
|
|
70
|
+
this.childProcess.stdout.on('data', (chunk) => {
|
|
71
|
+
this.handleStdoutChunk(chunk);
|
|
64
72
|
});
|
|
65
73
|
// Handle process exit
|
|
66
74
|
this.childProcess.on('exit', (code, signal) => {
|
|
67
75
|
this.logger.log('info', `Process exited (code=${code}, signal=${signal})`);
|
|
76
|
+
// Flush any remaining stderr
|
|
77
|
+
if (this.stderrRemainder.trim()) {
|
|
78
|
+
this.logger.log('debug', `[${this.options.binaryName}] ${this.stderrRemainder.trim()}`);
|
|
79
|
+
this.emit('stderr', this.stderrRemainder.trim());
|
|
80
|
+
}
|
|
68
81
|
this.cleanup();
|
|
69
82
|
this.emit('exit', code, signal);
|
|
70
83
|
});
|
|
@@ -102,22 +115,62 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
102
115
|
}
|
|
103
116
|
const id = `req_${++this.requestCounter}`;
|
|
104
117
|
const request = { id, method, params };
|
|
118
|
+
const json = JSON.stringify(request);
|
|
119
|
+
// Check outbound payload size
|
|
120
|
+
const byteLength = Buffer.byteLength(json, 'utf8');
|
|
121
|
+
if (byteLength > this.options.maxPayloadSize) {
|
|
122
|
+
throw new Error(`Outbound message exceeds maxPayloadSize (${byteLength} > ${this.options.maxPayloadSize})`);
|
|
123
|
+
}
|
|
105
124
|
return new Promise((resolve, reject) => {
|
|
106
125
|
const timer = setTimeout(() => {
|
|
107
126
|
this.pendingRequests.delete(id);
|
|
108
127
|
reject(new Error(`Command '${method}' timed out after ${this.options.requestTimeoutMs}ms`));
|
|
109
128
|
}, this.options.requestTimeoutMs);
|
|
110
129
|
this.pendingRequests.set(id, { resolve, reject, timer });
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
this.pendingRequests.delete(id);
|
|
116
|
-
reject(new Error(`Failed to write to stdin: ${err.message}`));
|
|
117
|
-
}
|
|
130
|
+
this.writeToStdin(json + '\n').catch((err) => {
|
|
131
|
+
clearTimeout(timer);
|
|
132
|
+
this.pendingRequests.delete(id);
|
|
133
|
+
reject(new Error(`Failed to write to stdin: ${err.message}`));
|
|
118
134
|
});
|
|
119
135
|
});
|
|
120
136
|
}
|
|
137
|
+
/**
|
|
138
|
+
* Send a streaming command to the Rust process.
|
|
139
|
+
* Returns a StreamingResponse that yields chunks via `for await...of`
|
|
140
|
+
* and exposes `.result` for the final response.
|
|
141
|
+
*/
|
|
142
|
+
sendCommandStreaming(method, params) {
|
|
143
|
+
const streaming = new StreamingResponse();
|
|
144
|
+
if (!this.childProcess || !this.isRunning) {
|
|
145
|
+
streaming.fail(new Error(`${this.options.binaryName} bridge is not running`));
|
|
146
|
+
return streaming;
|
|
147
|
+
}
|
|
148
|
+
const id = `req_${++this.requestCounter}`;
|
|
149
|
+
const request = { id, method, params };
|
|
150
|
+
const json = JSON.stringify(request);
|
|
151
|
+
const byteLength = Buffer.byteLength(json, 'utf8');
|
|
152
|
+
if (byteLength > this.options.maxPayloadSize) {
|
|
153
|
+
streaming.fail(new Error(`Outbound message exceeds maxPayloadSize (${byteLength} > ${this.options.maxPayloadSize})`));
|
|
154
|
+
return streaming;
|
|
155
|
+
}
|
|
156
|
+
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
157
|
+
const timer = setTimeout(() => {
|
|
158
|
+
this.pendingRequests.delete(id);
|
|
159
|
+
streaming.fail(new Error(`Streaming command '${method}' timed out after ${timeoutMs}ms`));
|
|
160
|
+
}, timeoutMs);
|
|
161
|
+
this.pendingRequests.set(id, {
|
|
162
|
+
resolve: (result) => streaming.finish(result),
|
|
163
|
+
reject: (error) => streaming.fail(error),
|
|
164
|
+
timer,
|
|
165
|
+
streaming,
|
|
166
|
+
});
|
|
167
|
+
this.writeToStdin(json + '\n').catch((err) => {
|
|
168
|
+
clearTimeout(timer);
|
|
169
|
+
this.pendingRequests.delete(id);
|
|
170
|
+
streaming.fail(new Error(`Failed to write to stdin: ${err.message}`));
|
|
171
|
+
});
|
|
172
|
+
return streaming;
|
|
173
|
+
}
|
|
121
174
|
/**
|
|
122
175
|
* Kill the Rust process and clean up all resources.
|
|
123
176
|
*/
|
|
@@ -126,11 +179,9 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
126
179
|
const proc = this.childProcess;
|
|
127
180
|
this.childProcess = null;
|
|
128
181
|
this.isRunning = false;
|
|
129
|
-
//
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
this.readlineInterface = null;
|
|
133
|
-
}
|
|
182
|
+
// Clear buffers
|
|
183
|
+
this.stdoutBuffer = Buffer.alloc(0);
|
|
184
|
+
this.stderrRemainder = '';
|
|
134
185
|
// Reject pending requests
|
|
135
186
|
for (const [, pending] of this.pendingRequests) {
|
|
136
187
|
clearTimeout(pending.timer);
|
|
@@ -180,6 +231,55 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
180
231
|
get running() {
|
|
181
232
|
return this.isRunning;
|
|
182
233
|
}
|
|
234
|
+
/**
|
|
235
|
+
* Buffer-based newline scanner for stdout chunks.
|
|
236
|
+
* Replaces readline to handle large payloads without buffering entire lines in a separate abstraction.
|
|
237
|
+
*/
|
|
238
|
+
handleStdoutChunk(chunk) {
|
|
239
|
+
this.stdoutBuffer = Buffer.concat([this.stdoutBuffer, chunk]);
|
|
240
|
+
let newlineIndex;
|
|
241
|
+
while ((newlineIndex = this.stdoutBuffer.indexOf(0x0A)) !== -1) {
|
|
242
|
+
const lineBuffer = this.stdoutBuffer.subarray(0, newlineIndex);
|
|
243
|
+
this.stdoutBuffer = this.stdoutBuffer.subarray(newlineIndex + 1);
|
|
244
|
+
if (lineBuffer.length > this.options.maxPayloadSize) {
|
|
245
|
+
this.logger.log('error', `Inbound message exceeds maxPayloadSize (${lineBuffer.length} bytes), dropping`);
|
|
246
|
+
continue;
|
|
247
|
+
}
|
|
248
|
+
const line = lineBuffer.toString('utf8').trim();
|
|
249
|
+
this.handleLine(line);
|
|
250
|
+
}
|
|
251
|
+
// If accumulated buffer exceeds maxPayloadSize (sender never sends newline), clear to prevent OOM
|
|
252
|
+
if (this.stdoutBuffer.length > this.options.maxPayloadSize) {
|
|
253
|
+
this.logger.log('error', `Stdout buffer exceeded maxPayloadSize (${this.stdoutBuffer.length} bytes) without newline, clearing`);
|
|
254
|
+
this.stdoutBuffer = Buffer.alloc(0);
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Write data to stdin with backpressure support.
|
|
259
|
+
* Waits for drain if the internal buffer is full.
|
|
260
|
+
*/
|
|
261
|
+
writeToStdin(data) {
|
|
262
|
+
return new Promise((resolve, reject) => {
|
|
263
|
+
if (!this.childProcess?.stdin) {
|
|
264
|
+
reject(new Error('stdin not available'));
|
|
265
|
+
return;
|
|
266
|
+
}
|
|
267
|
+
const canContinue = this.childProcess.stdin.write(data, 'utf8', (err) => {
|
|
268
|
+
if (err) {
|
|
269
|
+
reject(err);
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
if (canContinue) {
|
|
273
|
+
resolve();
|
|
274
|
+
}
|
|
275
|
+
else {
|
|
276
|
+
// Wait for drain before resolving
|
|
277
|
+
this.childProcess.stdin.once('drain', () => {
|
|
278
|
+
resolve();
|
|
279
|
+
});
|
|
280
|
+
}
|
|
281
|
+
});
|
|
282
|
+
}
|
|
183
283
|
handleLine(line) {
|
|
184
284
|
if (!line)
|
|
185
285
|
return;
|
|
@@ -197,6 +297,21 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
197
297
|
this.emit(`management:${event.event}`, event.data);
|
|
198
298
|
return;
|
|
199
299
|
}
|
|
300
|
+
// Stream chunk (has 'id' + stream === true + 'data')
|
|
301
|
+
if ('id' in parsed && parsed.stream === true && 'data' in parsed) {
|
|
302
|
+
const pending = this.pendingRequests.get(parsed.id);
|
|
303
|
+
if (pending?.streaming) {
|
|
304
|
+
// Reset inactivity timeout
|
|
305
|
+
clearTimeout(pending.timer);
|
|
306
|
+
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
307
|
+
pending.timer = setTimeout(() => {
|
|
308
|
+
this.pendingRequests.delete(parsed.id);
|
|
309
|
+
pending.reject(new Error(`Streaming command timed out after ${timeoutMs}ms of inactivity`));
|
|
310
|
+
}, timeoutMs);
|
|
311
|
+
pending.streaming.pushChunk(parsed.data);
|
|
312
|
+
}
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
200
315
|
// Otherwise it's a response (has 'id' field)
|
|
201
316
|
if ('id' in parsed) {
|
|
202
317
|
const response = parsed;
|
|
@@ -216,10 +331,8 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
216
331
|
cleanup() {
|
|
217
332
|
this.isRunning = false;
|
|
218
333
|
this.childProcess = null;
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
this.readlineInterface = null;
|
|
222
|
-
}
|
|
334
|
+
this.stdoutBuffer = Buffer.alloc(0);
|
|
335
|
+
this.stderrRemainder = '';
|
|
223
336
|
// Reject all pending requests
|
|
224
337
|
for (const [, pending] of this.pendingRequests) {
|
|
225
338
|
clearTimeout(pending.timer);
|
|
@@ -228,4 +341,4 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
228
341
|
this.pendingRequests.clear();
|
|
229
342
|
}
|
|
230
343
|
}
|
|
231
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydXN0YnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBVW5FLE1BQU0sYUFBYSxHQUFzQjtJQUN2QyxHQUFHLEtBQUksQ0FBQztDQUNULENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxVQUF3RCxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUM5RixPQUFPLENBQW9CO0lBQzNCLE9BQU8sQ0FBZ0k7SUFDdkksTUFBTSxDQUFvQjtJQUMxQixZQUFZLEdBQTZDLElBQUksQ0FBQztJQUM5RCxpQkFBaUIsR0FBc0MsSUFBSSxDQUFDO0lBQzVELGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFJN0IsQ0FBQztJQUNHLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixVQUFVLEdBQWtCLElBQUksQ0FBQztJQUV6QyxZQUFZLE9BQTJCO1FBQ3JDLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsT0FBTyxFQUFFLENBQUMsY0FBYyxDQUFDO1lBQ3pCLGdCQUFnQixFQUFFLEtBQUs7WUFDdkIsY0FBYyxFQUFFLEtBQUs7WUFDckIsY0FBYyxFQUFFLE9BQU87WUFDdkIsR0FBRyxPQUFPO1NBQ1gsQ0FBQztRQUNGLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxpQkFBaUIsQ0FBQyxPQUFPLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDO0lBQzdELENBQUM7SUFFRDs7O09BR0c7SUFDSSxLQUFLLENBQUMs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
|
|
344
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydXN0YnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBWW5FLE1BQU0sYUFBYSxHQUFzQjtJQUN2QyxHQUFHLEtBQUksQ0FBQztDQUNULENBQUM7QUFFRjs7Ozs7R0FLRztBQUNILE1BQU0sT0FBTyxVQUF3RCxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUM5RixPQUFPLENBQW9CO0lBQzNCLE9BQU8sQ0FBbUo7SUFDMUosTUFBTSxDQUFvQjtJQUMxQixZQUFZLEdBQTZDLElBQUksQ0FBQztJQUM5RCxZQUFZLEdBQVcsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQztJQUN2QyxlQUFlLEdBQVcsRUFBRSxDQUFDO0lBQzdCLGVBQWUsR0FBRyxJQUFJLEdBQUcsRUFLN0IsQ0FBQztJQUNHLGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixVQUFVLEdBQWtCLElBQUksQ0FBQztJQUV6QyxZQUFZLE9BQTJCO1FBQ3JDLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsT0FBTyxFQUFFLENBQUMsY0FBYyxDQUFDO1lBQ3pCLGdCQUFnQixFQUFFLEtBQUs7WUFDdkIsY0FBYyxFQUFFLEtBQUs7WUFDckIsY0FBYyxFQUFFLE9BQU87WUFDdkIsY0FBYyxFQUFFLEVBQUUsR0FBRyxJQUFJLEdBQUcsSUFBSTtZQUNoQyxH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
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a streaming response from a Rust bridge command.
|
|
3
|
+
* Implements AsyncIterable to allow `for await...of` consumption of chunks,
|
|
4
|
+
* and exposes `.result` for the final response once the stream ends.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TChunk - Type of each streamed chunk
|
|
7
|
+
* @typeParam TResult - Type of the final result
|
|
8
|
+
*/
|
|
9
|
+
export declare class StreamingResponse<TChunk, TResult> implements AsyncIterable<TChunk> {
|
|
10
|
+
/** Resolves with the final result when the stream ends successfully. */
|
|
11
|
+
readonly result: Promise<TResult>;
|
|
12
|
+
private resolveResult;
|
|
13
|
+
private rejectResult;
|
|
14
|
+
/** Buffered chunks not yet consumed by the iterator. */
|
|
15
|
+
private buffer;
|
|
16
|
+
/** Waiting consumer resolve callback (when iterator is ahead of producer). */
|
|
17
|
+
private waiting;
|
|
18
|
+
/** Waiting consumer reject callback. */
|
|
19
|
+
private waitingReject;
|
|
20
|
+
private done;
|
|
21
|
+
private error;
|
|
22
|
+
constructor();
|
|
23
|
+
/**
|
|
24
|
+
* Push a chunk into the stream. Called internally by RustBridge.
|
|
25
|
+
*/
|
|
26
|
+
pushChunk(chunk: TChunk): void;
|
|
27
|
+
/**
|
|
28
|
+
* End the stream successfully with a final result. Called internally by RustBridge.
|
|
29
|
+
*/
|
|
30
|
+
finish(result: TResult): void;
|
|
31
|
+
/**
|
|
32
|
+
* End the stream with an error. Called internally by RustBridge.
|
|
33
|
+
*/
|
|
34
|
+
fail(error: Error): void;
|
|
35
|
+
[Symbol.asyncIterator](): AsyncIterator<TChunk>;
|
|
36
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Represents a streaming response from a Rust bridge command.
|
|
3
|
+
* Implements AsyncIterable to allow `for await...of` consumption of chunks,
|
|
4
|
+
* and exposes `.result` for the final response once the stream ends.
|
|
5
|
+
*
|
|
6
|
+
* @typeParam TChunk - Type of each streamed chunk
|
|
7
|
+
* @typeParam TResult - Type of the final result
|
|
8
|
+
*/
|
|
9
|
+
export class StreamingResponse {
|
|
10
|
+
/** Resolves with the final result when the stream ends successfully. */
|
|
11
|
+
result;
|
|
12
|
+
resolveResult;
|
|
13
|
+
rejectResult;
|
|
14
|
+
/** Buffered chunks not yet consumed by the iterator. */
|
|
15
|
+
buffer = [];
|
|
16
|
+
/** Waiting consumer resolve callback (when iterator is ahead of producer). */
|
|
17
|
+
waiting = null;
|
|
18
|
+
/** Waiting consumer reject callback. */
|
|
19
|
+
waitingReject = null;
|
|
20
|
+
done = false;
|
|
21
|
+
error = null;
|
|
22
|
+
constructor() {
|
|
23
|
+
this.result = new Promise((resolve, reject) => {
|
|
24
|
+
this.resolveResult = resolve;
|
|
25
|
+
this.rejectResult = reject;
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Push a chunk into the stream. Called internally by RustBridge.
|
|
30
|
+
*/
|
|
31
|
+
pushChunk(chunk) {
|
|
32
|
+
if (this.done)
|
|
33
|
+
return;
|
|
34
|
+
if (this.waiting) {
|
|
35
|
+
// A consumer is waiting — deliver immediately
|
|
36
|
+
const resolve = this.waiting;
|
|
37
|
+
this.waiting = null;
|
|
38
|
+
this.waitingReject = null;
|
|
39
|
+
resolve({ value: chunk, done: false });
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
// No consumer waiting — buffer the chunk
|
|
43
|
+
this.buffer.push(chunk);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* End the stream successfully with a final result. Called internally by RustBridge.
|
|
48
|
+
*/
|
|
49
|
+
finish(result) {
|
|
50
|
+
if (this.done)
|
|
51
|
+
return;
|
|
52
|
+
this.done = true;
|
|
53
|
+
this.resolveResult(result);
|
|
54
|
+
// If a consumer is waiting, signal end of iteration
|
|
55
|
+
if (this.waiting) {
|
|
56
|
+
const resolve = this.waiting;
|
|
57
|
+
this.waiting = null;
|
|
58
|
+
this.waitingReject = null;
|
|
59
|
+
resolve({ value: undefined, done: true });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* End the stream with an error. Called internally by RustBridge.
|
|
64
|
+
*/
|
|
65
|
+
fail(error) {
|
|
66
|
+
if (this.done)
|
|
67
|
+
return;
|
|
68
|
+
this.done = true;
|
|
69
|
+
this.error = error;
|
|
70
|
+
this.rejectResult(error);
|
|
71
|
+
// If a consumer is waiting, reject it
|
|
72
|
+
if (this.waitingReject) {
|
|
73
|
+
const reject = this.waitingReject;
|
|
74
|
+
this.waiting = null;
|
|
75
|
+
this.waitingReject = null;
|
|
76
|
+
reject(error);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
[Symbol.asyncIterator]() {
|
|
80
|
+
return {
|
|
81
|
+
next: () => {
|
|
82
|
+
// If there are buffered chunks, deliver one
|
|
83
|
+
if (this.buffer.length > 0) {
|
|
84
|
+
return Promise.resolve({ value: this.buffer.shift(), done: false });
|
|
85
|
+
}
|
|
86
|
+
// If the stream is done, signal end
|
|
87
|
+
if (this.done) {
|
|
88
|
+
if (this.error) {
|
|
89
|
+
return Promise.reject(this.error);
|
|
90
|
+
}
|
|
91
|
+
return Promise.resolve({ value: undefined, done: true });
|
|
92
|
+
}
|
|
93
|
+
// No buffered chunks and not done — wait for the next push
|
|
94
|
+
return new Promise((resolve, reject) => {
|
|
95
|
+
this.waiting = resolve;
|
|
96
|
+
this.waitingReject = reject;
|
|
97
|
+
});
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5zdHJlYW1pbmdyZXNwb25zZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3RzL2NsYXNzZXMuc3RyZWFtaW5ncmVzcG9uc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7Ozs7R0FPRztBQUNILE1BQU0sT0FBTyxpQkFBaUI7SUFDNUIsd0VBQXdFO0lBQ3hELE1BQU0sQ0FBbUI7SUFFakMsYUFBYSxDQUE0QjtJQUN6QyxZQUFZLENBQTBCO0lBRTlDLHdEQUF3RDtJQUNoRCxNQUFNLEdBQWEsRUFBRSxDQUFDO0lBQzlCLDhFQUE4RTtJQUN0RSxPQUFPLEdBQXFELElBQUksQ0FBQztJQUN6RSx3Q0FBd0M7SUFDaEMsYUFBYSxHQUFvQyxJQUFJLENBQUM7SUFFdEQsSUFBSSxHQUFHLEtBQUssQ0FBQztJQUNiLEtBQUssR0FBaUIsSUFBSSxDQUFDO0lBRW5DO1FBQ0UsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLE9BQU8sQ0FBVSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtZQUNyRCxJQUFJLENBQUMsYUFBYSxHQUFHLE9BQU8sQ0FBQztZQUM3QixJQUFJLENBQUMsWUFBWSxHQUFHLE1BQU0sQ0FBQztRQUM3QixDQUFDLENBQUMsQ0FBQztJQUNMLENBQUM7SUFFRDs7T0FFRztJQUNJLFNBQVMsQ0FBQyxLQUFhO1FBQzVCLElBQUksSUFBSSxDQUFDLElBQUk7WUFBRSxPQUFPO1FBRXRCLElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2pCLDhDQUE4QztZQUM5QyxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFDO1lBQzdCLElBQUksQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1lBQ3BCLElBQUksQ0FBQyxhQUFhLEdBQUcsSUFBSSxDQUFDO1lBQzFCLE9BQU8sQ0FBQyxFQUFFLEtBQUssRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUM7UUFDekMsQ0FB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
|
package/dist_ts/index.d.ts
CHANGED
package/dist_ts/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { RustBridge } from './classes.rustbridge.js';
|
|
2
2
|
export { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
|
+
export { StreamingResponse } from './classes.streamingresponse.js';
|
|
3
4
|
export * from './interfaces/index.js';
|
|
4
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
5
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbkUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDbkUsY0FBYyx1QkFBdUIsQ0FBQyJ9
|
|
@@ -37,4 +37,9 @@ export interface IRustBridgeOptions extends IBinaryLocatorOptions {
|
|
|
37
37
|
readyEventName?: string;
|
|
38
38
|
/** Optional logger instance */
|
|
39
39
|
logger?: IRustBridgeLogger;
|
|
40
|
+
/** Maximum message size in bytes (default: 50MB). Messages exceeding this are rejected. */
|
|
41
|
+
maxPayloadSize?: number;
|
|
42
|
+
/** Inactivity timeout for streaming commands in ms (default: same as requestTimeoutMs).
|
|
43
|
+
* Resets on each chunk received. */
|
|
44
|
+
streamTimeoutMs?: number;
|
|
40
45
|
}
|
|
@@ -34,3 +34,26 @@ export interface ICommandDefinition<TParams = any, TResult = any> {
|
|
|
34
34
|
* Used to type-safe the bridge's sendCommand method.
|
|
35
35
|
*/
|
|
36
36
|
export type TCommandMap = Record<string, ICommandDefinition>;
|
|
37
|
+
/**
|
|
38
|
+
* Stream chunk message received from the Rust binary during a streaming command.
|
|
39
|
+
*/
|
|
40
|
+
export interface IManagementStreamChunk {
|
|
41
|
+
id: string;
|
|
42
|
+
stream: true;
|
|
43
|
+
data: any;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Extract keys from a command map whose definitions include a `chunk` field,
|
|
47
|
+
* indicating they support streaming responses.
|
|
48
|
+
*/
|
|
49
|
+
export type TStreamingCommandKeys<TCommands extends TCommandMap> = {
|
|
50
|
+
[K in keyof TCommands]: TCommands[K] extends {
|
|
51
|
+
chunk: any;
|
|
52
|
+
} ? K : never;
|
|
53
|
+
}[keyof TCommands];
|
|
54
|
+
/**
|
|
55
|
+
* Extract the chunk type from a command definition that has a `chunk` field.
|
|
56
|
+
*/
|
|
57
|
+
export type TExtractChunk<TDef> = TDef extends {
|
|
58
|
+
chunk: infer C;
|
|
59
|
+
} ? C : never;
|
package/dist_ts/plugins.d.ts
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import * as childProcess from 'child_process';
|
|
4
|
-
import * as readline from 'readline';
|
|
5
4
|
import * as events from 'events';
|
|
6
5
|
import * as url from 'url';
|
|
7
|
-
export { path, fs, childProcess,
|
|
6
|
+
export { path, fs, childProcess, events, url };
|
|
8
7
|
import * as smartpath from '@push.rocks/smartpath';
|
|
9
8
|
export { smartpath };
|