@push.rocks/smartrust 1.4.0 → 1.4.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/.smartconfig.json +12 -7
- package/dist_ts/00_commitinfo_data.js +1 -1
- package/dist_ts/classes.rustbridge.d.ts +5 -2
- package/dist_ts/classes.rustbridge.js +158 -40
- package/dist_ts/classes.rustbridgerequesterror.d.ts +23 -0
- package/dist_ts/classes.rustbridgerequesterror.js +20 -0
- package/dist_ts/index.d.ts +1 -0
- package/dist_ts/index.js +2 -1
- package/dist_ts/interfaces/config.d.ts +9 -0
- package/package.json +11 -12
- package/readme.md +56 -2
- package/ts/00_commitinfo_data.ts +1 -1
- package/ts/classes.rustbridge.ts +204 -44
- package/ts/classes.rustbridgerequesterror.ts +37 -0
- package/ts/index.ts +5 -0
- package/ts/interfaces/config.ts +10 -0
package/.smartconfig.json
CHANGED
|
@@ -21,12 +21,17 @@
|
|
|
21
21
|
]
|
|
22
22
|
},
|
|
23
23
|
"release": {
|
|
24
|
-
"
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
24
|
+
"targets": {
|
|
25
|
+
"npm": {
|
|
26
|
+
"registries": [
|
|
27
|
+
"https://verdaccio.lossless.digital",
|
|
28
|
+
"https://registry.npmjs.org"
|
|
29
|
+
],
|
|
30
|
+
"accessLevel": "public"
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"schemaVersion": 2
|
|
30
35
|
},
|
|
31
36
|
"@git.zone/tsdoc": {
|
|
32
37
|
"legal": "\n## License and Legal Information\n\nThis repository contains open-source code licensed under the MIT License. A copy of the license can be found in the [license](./license) file.\n\n**Please note:** The MIT License does not grant permission to use the trade names, trademarks, service marks, or product names of the project, except as required for reasonable and customary use in describing the origin of the work and reproducing the content of the NOTICE file.\n\n### Trademarks\n\nThis project is owned and maintained by Task Venture Capital GmbH. The names and logos associated with Task Venture Capital GmbH and any related products or services are trademarks of Task Venture Capital GmbH or third parties, and are not included within the scope of the MIT license granted herein.\n\nUse of these trademarks must comply with Task Venture Capital GmbH's Trademark Guidelines or the guidelines of the respective third-party owners, and any usage must be approved in writing. Third-party trademarks used herein are the property of their respective owners and used only in a descriptive manner, e.g. for an implementation of an API or similar.\n\n### Company Information\n\nTask Venture Capital GmbH\nRegistered at District Court Bremen HRB 35230 HB, Germany\n\nFor any legal inquiries or further information, please contact us via email at hello@task.vc.\n\nBy using this repository, you acknowledge that you have read this section, agree to comply with its terms, and understand that the licensing of the code does not imply endorsement by Task Venture Capital GmbH of any derivative works.\n"
|
|
@@ -34,4 +39,4 @@
|
|
|
34
39
|
"@ship.zone/szci": {
|
|
35
40
|
"npmGlobalTools": []
|
|
36
41
|
}
|
|
37
|
-
}
|
|
42
|
+
}
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export const commitinfo = {
|
|
5
5
|
name: '@push.rocks/smartrust',
|
|
6
|
-
version: '1.4.
|
|
6
|
+
version: '1.4.1',
|
|
7
7
|
description: 'A type-safe bridge between JavaScript engines and Rust binaries.'
|
|
8
8
|
};
|
|
9
9
|
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiMDBfY29tbWl0aW5mb19kYXRhLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvMDBfY29tbWl0aW5mb19kYXRhLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sVUFBVSxHQUFHO0lBQ3hCLElBQUksRUFBRSx1QkFBdUI7SUFDN0IsT0FBTyxFQUFFLE9BQU87SUFDaEIsV0FBVyxFQUFFLGtFQUFrRTtDQUNoRixDQUFBIn0=
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { StreamingResponse } from './classes.streamingresponse.js';
|
|
3
|
-
import type { IRustBridgeOptions, ISocketConnectOptions, TCommandMap, TStreamingCommandKeys, TExtractChunk } from './interfaces/index.js';
|
|
3
|
+
import type { IRustBridgeOptions, IRustBridgeRequestOptions, ISocketConnectOptions, TCommandMap, TStreamingCommandKeys, TExtractChunk } from './interfaces/index.js';
|
|
4
4
|
/**
|
|
5
5
|
* Generic bridge between TypeScript and a Rust binary.
|
|
6
6
|
* Communicates via JSON-over-stdin/stdout IPC protocol (stdio mode)
|
|
@@ -38,7 +38,7 @@ export declare class RustBridge<TCommands extends TCommandMap = TCommandMap> ext
|
|
|
38
38
|
/**
|
|
39
39
|
* Send a typed command to the Rust process and wait for the response.
|
|
40
40
|
*/
|
|
41
|
-
sendCommand<K extends string & keyof TCommands>(method: K, params: TCommands[K]['params']): Promise<TCommands[K]['result']>;
|
|
41
|
+
sendCommand<K extends string & keyof TCommands>(method: K, params: TCommands[K]['params'], options?: IRustBridgeRequestOptions): Promise<TCommands[K]['result']>;
|
|
42
42
|
/**
|
|
43
43
|
* Send a streaming command to the Rust process.
|
|
44
44
|
* Returns a StreamingResponse that yields chunks via `for await...of`
|
|
@@ -56,5 +56,8 @@ export declare class RustBridge<TCommands extends TCommandMap = TCommandMap> ext
|
|
|
56
56
|
*/
|
|
57
57
|
get running(): boolean;
|
|
58
58
|
private handleLine;
|
|
59
|
+
private settlePendingRequest;
|
|
60
|
+
private rejectAllPendingRequests;
|
|
59
61
|
private cleanup;
|
|
62
|
+
private getErrorMessage;
|
|
60
63
|
}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
|
+
import { RustBridgeRequestError } from './classes.rustbridgerequesterror.js';
|
|
3
4
|
import { StreamingResponse } from './classes.streamingresponse.js';
|
|
4
5
|
import { StdioTransport } from './classes.stdiotransport.js';
|
|
5
6
|
import { SocketTransport } from './classes.sockettransport.js';
|
|
@@ -87,12 +88,12 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
87
88
|
});
|
|
88
89
|
transport.on('close', (...args) => {
|
|
89
90
|
this.logger.log('info', `Transport closed`);
|
|
90
|
-
this.cleanup();
|
|
91
|
+
this.cleanup(`${this.options.binaryName} process exited`);
|
|
91
92
|
this.emit('exit', ...args);
|
|
92
93
|
});
|
|
93
94
|
transport.on('error', (err) => {
|
|
94
95
|
this.logger.log('error', `Transport error: ${err.message}`);
|
|
95
|
-
this.cleanup();
|
|
96
|
+
this.cleanup(`${this.options.binaryName} process exited`, err);
|
|
96
97
|
resolve(false);
|
|
97
98
|
});
|
|
98
99
|
transport.on('reconnected', () => {
|
|
@@ -128,10 +129,23 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
128
129
|
/**
|
|
129
130
|
* Send a typed command to the Rust process and wait for the response.
|
|
130
131
|
*/
|
|
131
|
-
async sendCommand(method, params) {
|
|
132
|
+
async sendCommand(method, params, options) {
|
|
133
|
+
const timeoutMs = options?.timeoutMs ?? this.options.requestTimeoutMs;
|
|
134
|
+
if (options?.timeoutMs !== undefined
|
|
135
|
+
&& (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0)) {
|
|
136
|
+
throw new RangeError('RustBridge request timeoutMs must be a positive safe integer');
|
|
137
|
+
}
|
|
138
|
+
if (options?.signal?.aborted) {
|
|
139
|
+
throw new RustBridgeRequestError(`Command '${method}' was aborted before it was sent`, {
|
|
140
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_ABORTED',
|
|
141
|
+
method,
|
|
142
|
+
cause: options.signal.reason,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
132
145
|
if (!this.transport?.connected || !this.isRunning) {
|
|
133
146
|
throw new Error(`${this.options.binaryName} bridge is not running`);
|
|
134
147
|
}
|
|
148
|
+
const transport = this.transport;
|
|
135
149
|
const id = `req_${++this.requestCounter}`;
|
|
136
150
|
const request = { id, method, params };
|
|
137
151
|
const json = JSON.stringify(request);
|
|
@@ -141,16 +155,62 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
141
155
|
throw new Error(`Outbound message exceeds maxPayloadSize (${byteLength} > ${this.options.maxPayloadSize})`);
|
|
142
156
|
}
|
|
143
157
|
return new Promise((resolve, reject) => {
|
|
144
|
-
const
|
|
145
|
-
|
|
146
|
-
reject
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
const pending = {
|
|
159
|
+
resolve,
|
|
160
|
+
reject,
|
|
161
|
+
timer: null,
|
|
162
|
+
method,
|
|
163
|
+
abortSignal: options?.signal,
|
|
164
|
+
};
|
|
165
|
+
this.pendingRequests.set(id, pending);
|
|
166
|
+
if (options?.signal) {
|
|
167
|
+
pending.abortHandler = () => {
|
|
168
|
+
this.settlePendingRequest(id, {
|
|
169
|
+
outcome: 'reject',
|
|
170
|
+
error: new RustBridgeRequestError(`Command '${method}' was aborted`, {
|
|
171
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_ABORTED',
|
|
172
|
+
requestId: id,
|
|
173
|
+
method,
|
|
174
|
+
cause: options.signal?.reason,
|
|
175
|
+
}),
|
|
176
|
+
});
|
|
177
|
+
};
|
|
178
|
+
options.signal.addEventListener('abort', pending.abortHandler, { once: true });
|
|
179
|
+
}
|
|
180
|
+
pending.timer = setTimeout(() => {
|
|
181
|
+
this.settlePendingRequest(id, {
|
|
182
|
+
outcome: 'reject',
|
|
183
|
+
error: new RustBridgeRequestError(`Command '${method}' timed out after ${timeoutMs}ms`, {
|
|
184
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_TIMEOUT',
|
|
185
|
+
requestId: id,
|
|
186
|
+
method,
|
|
187
|
+
}),
|
|
188
|
+
});
|
|
189
|
+
}, timeoutMs);
|
|
190
|
+
try {
|
|
191
|
+
void transport.write(json + '\n').catch((err) => {
|
|
192
|
+
this.settlePendingRequest(id, {
|
|
193
|
+
outcome: 'reject',
|
|
194
|
+
error: new RustBridgeRequestError(`Failed to write to transport: ${this.getErrorMessage(err)}`, {
|
|
195
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_WRITE',
|
|
196
|
+
requestId: id,
|
|
197
|
+
method,
|
|
198
|
+
cause: err,
|
|
199
|
+
}),
|
|
200
|
+
});
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
catch (err) {
|
|
204
|
+
this.settlePendingRequest(id, {
|
|
205
|
+
outcome: 'reject',
|
|
206
|
+
error: new RustBridgeRequestError(`Failed to write to transport: ${this.getErrorMessage(err)}`, {
|
|
207
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_WRITE',
|
|
208
|
+
requestId: id,
|
|
209
|
+
method,
|
|
210
|
+
cause: err,
|
|
211
|
+
}),
|
|
212
|
+
});
|
|
213
|
+
}
|
|
154
214
|
});
|
|
155
215
|
}
|
|
156
216
|
/**
|
|
@@ -174,20 +234,32 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
174
234
|
}
|
|
175
235
|
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
176
236
|
const timer = setTimeout(() => {
|
|
177
|
-
this.
|
|
178
|
-
|
|
237
|
+
this.settlePendingRequest(id, {
|
|
238
|
+
outcome: 'reject',
|
|
239
|
+
error: new Error(`Streaming command '${method}' timed out after ${timeoutMs}ms`),
|
|
240
|
+
});
|
|
179
241
|
}, timeoutMs);
|
|
180
242
|
this.pendingRequests.set(id, {
|
|
181
243
|
resolve: (result) => streaming.finish(result),
|
|
182
244
|
reject: (error) => streaming.fail(error),
|
|
183
245
|
timer,
|
|
246
|
+
method,
|
|
184
247
|
streaming,
|
|
185
248
|
});
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
249
|
+
try {
|
|
250
|
+
void this.transport.write(json + '\n').catch((err) => {
|
|
251
|
+
this.settlePendingRequest(id, {
|
|
252
|
+
outcome: 'reject',
|
|
253
|
+
error: new Error(`Failed to write to transport: ${this.getErrorMessage(err)}`),
|
|
254
|
+
});
|
|
255
|
+
});
|
|
256
|
+
}
|
|
257
|
+
catch (err) {
|
|
258
|
+
this.settlePendingRequest(id, {
|
|
259
|
+
outcome: 'reject',
|
|
260
|
+
error: new Error(`Failed to write to transport: ${this.getErrorMessage(err)}`),
|
|
261
|
+
});
|
|
262
|
+
}
|
|
191
263
|
return streaming;
|
|
192
264
|
}
|
|
193
265
|
/**
|
|
@@ -201,11 +273,7 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
201
273
|
this.transport = null;
|
|
202
274
|
this.isRunning = false;
|
|
203
275
|
// Reject pending requests
|
|
204
|
-
|
|
205
|
-
clearTimeout(pending.timer);
|
|
206
|
-
pending.reject(new Error(`${this.options.binaryName} process killed`));
|
|
207
|
-
}
|
|
208
|
-
this.pendingRequests.clear();
|
|
276
|
+
this.rejectAllPendingRequests(`${this.options.binaryName} process killed`);
|
|
209
277
|
transport.removeAllListeners();
|
|
210
278
|
transport.disconnect();
|
|
211
279
|
}
|
|
@@ -238,11 +306,15 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
238
306
|
const pending = this.pendingRequests.get(parsed.id);
|
|
239
307
|
if (pending?.streaming) {
|
|
240
308
|
// Reset inactivity timeout
|
|
241
|
-
|
|
309
|
+
if (pending.timer) {
|
|
310
|
+
clearTimeout(pending.timer);
|
|
311
|
+
}
|
|
242
312
|
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
243
313
|
pending.timer = setTimeout(() => {
|
|
244
|
-
this.
|
|
245
|
-
|
|
314
|
+
this.settlePendingRequest(parsed.id, {
|
|
315
|
+
outcome: 'reject',
|
|
316
|
+
error: new Error(`Streaming command timed out after ${timeoutMs}ms of inactivity`),
|
|
317
|
+
});
|
|
246
318
|
}, timeoutMs);
|
|
247
319
|
pending.streaming.pushChunk(parsed.data);
|
|
248
320
|
}
|
|
@@ -253,26 +325,72 @@ export class RustBridge extends plugins.events.EventEmitter {
|
|
|
253
325
|
const response = parsed;
|
|
254
326
|
const pending = this.pendingRequests.get(response.id);
|
|
255
327
|
if (pending) {
|
|
256
|
-
clearTimeout(pending.timer);
|
|
257
|
-
this.pendingRequests.delete(response.id);
|
|
258
328
|
if (response.success) {
|
|
259
|
-
|
|
329
|
+
this.settlePendingRequest(response.id, {
|
|
330
|
+
outcome: 'resolve',
|
|
331
|
+
value: response.result,
|
|
332
|
+
});
|
|
260
333
|
}
|
|
261
334
|
else {
|
|
262
|
-
|
|
335
|
+
const message = response.error || 'Unknown error from Rust process';
|
|
336
|
+
this.settlePendingRequest(response.id, {
|
|
337
|
+
outcome: 'reject',
|
|
338
|
+
error: pending.streaming
|
|
339
|
+
? new Error(message)
|
|
340
|
+
: new RustBridgeRequestError(message, {
|
|
341
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE',
|
|
342
|
+
requestId: response.id,
|
|
343
|
+
method: pending.method,
|
|
344
|
+
}),
|
|
345
|
+
});
|
|
263
346
|
}
|
|
264
347
|
}
|
|
265
348
|
}
|
|
266
349
|
}
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
350
|
+
settlePendingRequest(id, settlement) {
|
|
351
|
+
const pending = this.pendingRequests.get(id);
|
|
352
|
+
if (!pending) {
|
|
353
|
+
return false;
|
|
354
|
+
}
|
|
355
|
+
this.pendingRequests.delete(id);
|
|
356
|
+
if (pending.timer) {
|
|
272
357
|
clearTimeout(pending.timer);
|
|
273
|
-
pending.
|
|
358
|
+
pending.timer = null;
|
|
274
359
|
}
|
|
275
|
-
|
|
360
|
+
if (pending.abortSignal && pending.abortHandler) {
|
|
361
|
+
pending.abortSignal.removeEventListener('abort', pending.abortHandler);
|
|
362
|
+
pending.abortHandler = undefined;
|
|
363
|
+
}
|
|
364
|
+
if (settlement.outcome === 'resolve') {
|
|
365
|
+
pending.resolve(settlement.value);
|
|
366
|
+
}
|
|
367
|
+
else {
|
|
368
|
+
pending.reject(settlement.error);
|
|
369
|
+
}
|
|
370
|
+
return true;
|
|
371
|
+
}
|
|
372
|
+
rejectAllPendingRequests(message, cause) {
|
|
373
|
+
for (const [id, pending] of [...this.pendingRequests]) {
|
|
374
|
+
this.settlePendingRequest(id, {
|
|
375
|
+
outcome: 'reject',
|
|
376
|
+
error: pending.streaming
|
|
377
|
+
? new Error(message)
|
|
378
|
+
: new RustBridgeRequestError(message, {
|
|
379
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_TRANSPORT',
|
|
380
|
+
requestId: id,
|
|
381
|
+
method: pending.method,
|
|
382
|
+
cause,
|
|
383
|
+
}),
|
|
384
|
+
});
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
cleanup(message, cause) {
|
|
388
|
+
this.isRunning = false;
|
|
389
|
+
this.transport = null;
|
|
390
|
+
this.rejectAllPendingRequests(message, cause);
|
|
391
|
+
}
|
|
392
|
+
getErrorMessage(error) {
|
|
393
|
+
return error instanceof Error ? error.message : String(error);
|
|
276
394
|
}
|
|
277
395
|
}
|
|
278
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydXN0YnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFjL0QsTUFBTSxhQUFhLEdBQXNCO0lBQ3ZDLEdBQUcsS0FBSSxDQUFDO0NBQ1QsQ0FBQztBQUVGOzs7Ozs7R0FNRztBQUNILE1BQU0sT0FBTyxVQUF3RCxTQUFRLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWTtJQUM5RixPQUFPLENBQW9CO0lBQzNCLE9BQU8sQ0FBbUo7SUFDMUosTUFBTSxDQUFvQjtJQUMxQixTQUFTLEdBQTBCLElBQUksQ0FBQztJQUN4QyxlQUFlLEdBQUcsSUFBSSxHQUFHLEVBSzdCLENBQUM7SUFDRyxjQUFjLEdBQUcsQ0FBQyxDQUFDO0lBQ25CLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsVUFBVSxHQUFrQixJQUFJLENBQUM7SUFFekMsWUFBWSxPQUEyQjtRQUNyQyxLQUFLLEVBQUUsQ0FBQztRQUNSLElBQUksQ0FBQyxNQUFNLEdBQUcsT0FBTyxDQUFDLE1BQU0sSUFBSSxhQUFhLENBQUM7UUFDOUMsSUFBSSxDQUFDLE9BQU8sR0FBRztZQUNiLE9BQU8sRUFBRSxDQUFDLGNBQWMsQ0FBQztZQUN6QixnQkFBZ0IsRUFBRSxLQUFLO1lBQ3ZCLGNBQWMsRUFBRSxLQUFLO1lBQ3JCLGNBQWMsRUFBRSxPQUFPO1lBQ3ZCLGNBQWMsRUFBRSxFQUFFLEdBQUcsSUFBSSxHQUFHLElB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
|
|
396
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YnJpZGdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydXN0YnJpZGdlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sS0FBSyxPQUFPLE1BQU0sY0FBYyxDQUFDO0FBQ3hDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQzdFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFlL0QsTUFBTSxhQUFhLEdBQXNCO0lBQ3ZDLEdBQUcsS0FBSSxDQUFDO0NBQ1QsQ0FBQztBQWdCRjs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sVUFBd0QsU0FBUSxPQUFPLENBQUMsTUFBTSxDQUFDLFlBQVk7SUFDOUYsT0FBTyxDQUFvQjtJQUMzQixPQUFPLENBQW1KO0lBQzFKLE1BQU0sQ0FBb0I7SUFDMUIsU0FBUyxHQUEwQixJQUFJLENBQUM7SUFDeEMsZUFBZSxHQUFHLElBQUksR0FBRyxFQUEyQixDQUFDO0lBQ3JELGNBQWMsR0FBRyxDQUFDLENBQUM7SUFDbkIsU0FBUyxHQUFHLEtBQUssQ0FBQztJQUNsQixVQUFVLEdBQWtCLElBQUksQ0FBQztJQUV6QyxZQUFZLE9BQTJCO1FBQ3JDLEtBQUssRUFBRSxDQUFDO1FBQ1IsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxJQUFJLGFBQWEsQ0FBQztRQUM5QyxJQUFJLENBQUMsT0FBTyxHQUFHO1lBQ2IsT0FBTyxFQUFFLENBQUMsY0FBYyxDQUFDO1lBQ3pCLGdCQUFnQixFQUFFLEtBQUs7WUFDdkIsY0FBYyxFQUFFLEtBQUs7WUFDckIsY0FBYyxF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
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable error codes for failures while waiting for a Rust bridge request.
|
|
3
|
+
*/
|
|
4
|
+
export type TRustBridgeRequestErrorCode = 'ERR_RUST_BRIDGE_REQUEST_TIMEOUT' | 'ERR_RUST_BRIDGE_REQUEST_ABORTED' | 'ERR_RUST_BRIDGE_REQUEST_WRITE' | 'ERR_RUST_BRIDGE_REQUEST_TRANSPORT' | 'ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE';
|
|
5
|
+
export interface IRustBridgeRequestErrorOptions {
|
|
6
|
+
code: TRustBridgeRequestErrorCode;
|
|
7
|
+
requestId?: string;
|
|
8
|
+
method?: string;
|
|
9
|
+
cause?: unknown;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Error raised while preparing or waiting for a Rust bridge request.
|
|
13
|
+
*
|
|
14
|
+
* Existing error messages are preserved while `code` provides a stable way to
|
|
15
|
+
* distinguish timeout, cancellation, transport, write, and Rust response
|
|
16
|
+
* failures.
|
|
17
|
+
*/
|
|
18
|
+
export declare class RustBridgeRequestError extends Error {
|
|
19
|
+
readonly code: TRustBridgeRequestErrorCode;
|
|
20
|
+
readonly requestId?: string;
|
|
21
|
+
readonly method?: string;
|
|
22
|
+
constructor(message: string, options: IRustBridgeRequestErrorOptions);
|
|
23
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error raised while preparing or waiting for a Rust bridge request.
|
|
3
|
+
*
|
|
4
|
+
* Existing error messages are preserved while `code` provides a stable way to
|
|
5
|
+
* distinguish timeout, cancellation, transport, write, and Rust response
|
|
6
|
+
* failures.
|
|
7
|
+
*/
|
|
8
|
+
export class RustBridgeRequestError extends Error {
|
|
9
|
+
code;
|
|
10
|
+
requestId;
|
|
11
|
+
method;
|
|
12
|
+
constructor(message, options) {
|
|
13
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
14
|
+
this.name = 'RustBridgeRequestError';
|
|
15
|
+
this.code = options.code;
|
|
16
|
+
this.requestId = options.requestId;
|
|
17
|
+
this.method = options.method;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2xhc3Nlcy5ydXN0YnJpZGdlcmVxdWVzdGVycm9yLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vdHMvY2xhc3Nlcy5ydXN0YnJpZGdlcmVxdWVzdGVycm9yLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQWlCQTs7Ozs7O0dBTUc7QUFDSCxNQUFNLE9BQU8sc0JBQXVCLFNBQVEsS0FBSztJQUMvQixJQUFJLENBQThCO0lBQ2xDLFNBQVMsQ0FBVTtJQUNuQixNQUFNLENBQVU7SUFFaEMsWUFBWSxPQUFlLEVBQUUsT0FBdUM7UUFDbEUsS0FBSyxDQUFDLE9BQU8sRUFBRSxPQUFPLENBQUMsS0FBSyxLQUFLLFNBQVMsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxFQUFFLEtBQUssRUFBRSxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUMsQ0FBQztRQUNuRixJQUFJLENBQUMsSUFBSSxHQUFHLHdCQUF3QixDQUFDO1FBQ3JDLElBQUksQ0FBQyxJQUFJLEdBQUcsT0FBTyxDQUFDLElBQUksQ0FBQztRQUN6QixJQUFJLENBQUMsU0FBUyxHQUFHLE9BQU8sQ0FBQyxTQUFTLENBQUM7UUFDbkMsSUFBSSxDQUFDLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFDO0lBQy9CLENBQUM7Q0FDRiJ9
|
package/dist_ts/index.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export { RustBridge } from './classes.rustbridge.js';
|
|
2
|
+
export { RustBridgeRequestError, type IRustBridgeRequestErrorOptions, type TRustBridgeRequestErrorCode, } from './classes.rustbridgerequesterror.js';
|
|
2
3
|
export { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
4
|
export { StreamingResponse } from './classes.streamingresponse.js';
|
|
4
5
|
export { StdioTransport } from './classes.stdiotransport.js';
|
package/dist_ts/index.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
export { RustBridge } from './classes.rustbridge.js';
|
|
2
|
+
export { RustBridgeRequestError, } from './classes.rustbridgerequesterror.js';
|
|
2
3
|
export { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
4
|
export { StreamingResponse } from './classes.streamingresponse.js';
|
|
4
5
|
export { StdioTransport } from './classes.stdiotransport.js';
|
|
5
6
|
export { SocketTransport } from './classes.sockettransport.js';
|
|
6
7
|
export { LineScanner } from './classes.linescanner.js';
|
|
7
8
|
export * from './interfaces/index.js';
|
|
8
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
9
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi90cy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDckQsT0FBTyxFQUNMLHNCQUFzQixHQUd2QixNQUFNLHFDQUFxQyxDQUFDO0FBQzdDLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBQ25FLE9BQU8sRUFBRSxjQUFjLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUM3RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDL0QsT0FBTyxFQUFFLFdBQVcsRUFBRSxNQUFNLDBCQUEwQixDQUFDO0FBQ3ZELGNBQWMsdUJBQXVCLENBQUMifQ==
|
|
@@ -4,6 +4,15 @@
|
|
|
4
4
|
export interface IRustBridgeLogger {
|
|
5
5
|
log(level: string, message: string, data?: Record<string, any>): void;
|
|
6
6
|
}
|
|
7
|
+
/**
|
|
8
|
+
* Options for one non-streaming Rust bridge request.
|
|
9
|
+
*/
|
|
10
|
+
export interface IRustBridgeRequestOptions {
|
|
11
|
+
/** Abort only the local wait for this request. */
|
|
12
|
+
signal?: AbortSignal;
|
|
13
|
+
/** Override the bridge request timeout for this call, in milliseconds. */
|
|
14
|
+
timeoutMs?: number;
|
|
15
|
+
}
|
|
7
16
|
/**
|
|
8
17
|
* Options for locating a Rust binary.
|
|
9
18
|
*/
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@push.rocks/smartrust",
|
|
3
|
-
"version": "1.4.
|
|
3
|
+
"version": "1.4.1",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "A type-safe bridge between JavaScript engines and Rust binaries.",
|
|
6
6
|
"main": "dist_ts/index.js",
|
|
@@ -8,16 +8,11 @@
|
|
|
8
8
|
"type": "module",
|
|
9
9
|
"author": "Task Venture Capital GmbH",
|
|
10
10
|
"license": "MIT",
|
|
11
|
-
"scripts": {
|
|
12
|
-
"test": "(tstest test/ --verbose --logfile --timeout 60)",
|
|
13
|
-
"build": "(tsbuild tsfolders)",
|
|
14
|
-
"buildDocs": "(tsdoc)"
|
|
15
|
-
},
|
|
16
11
|
"devDependencies": {
|
|
17
|
-
"@git.zone/tsbuild": "^4.4.
|
|
18
|
-
"@git.zone/tsrun": "^2.0.
|
|
19
|
-
"@git.zone/tstest": "^3.6.
|
|
20
|
-
"@types/node": "^
|
|
12
|
+
"@git.zone/tsbuild": "^4.4.2",
|
|
13
|
+
"@git.zone/tsrun": "^2.0.5",
|
|
14
|
+
"@git.zone/tstest": "^3.6.7",
|
|
15
|
+
"@types/node": "^26.1.1"
|
|
21
16
|
},
|
|
22
17
|
"dependencies": {
|
|
23
18
|
"@push.rocks/smartpath": "^6.0.0"
|
|
@@ -51,5 +46,9 @@
|
|
|
51
46
|
"bugs": {
|
|
52
47
|
"url": "https://code.foss.global/push.rocks/smartrust/issues"
|
|
53
48
|
},
|
|
54
|
-
"
|
|
55
|
-
|
|
49
|
+
"scripts": {
|
|
50
|
+
"test": "(tstest test/ --verbose --logfile --timeout 60)",
|
|
51
|
+
"build": "(tsbuild tsfolders)",
|
|
52
|
+
"buildDocs": "(tsdoc)"
|
|
53
|
+
}
|
|
54
|
+
}
|
package/readme.md
CHANGED
|
@@ -103,6 +103,57 @@ bridge.on('management:configChanged', (data) => {
|
|
|
103
103
|
bridge.kill();
|
|
104
104
|
```
|
|
105
105
|
|
|
106
|
+
### Per-Command Deadlines and Cancellation
|
|
107
|
+
|
|
108
|
+
Non-streaming commands accept an optional `IRustBridgeRequestOptions` argument:
|
|
109
|
+
|
|
110
|
+
```typescript
|
|
111
|
+
import { RustBridgeRequestError } from '@push.rocks/smartrust';
|
|
112
|
+
|
|
113
|
+
const controller = new AbortController();
|
|
114
|
+
|
|
115
|
+
try {
|
|
116
|
+
const metrics = await bridge.sendCommand(
|
|
117
|
+
'getMetrics',
|
|
118
|
+
{},
|
|
119
|
+
{
|
|
120
|
+
timeoutMs: 2000,
|
|
121
|
+
signal: controller.signal,
|
|
122
|
+
},
|
|
123
|
+
);
|
|
124
|
+
} catch (error) {
|
|
125
|
+
if (error instanceof RustBridgeRequestError) {
|
|
126
|
+
console.error(error.code, error.message);
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
`timeoutMs` must be a positive safe integer. When it is omitted, the bridge's
|
|
132
|
+
constructor-level `requestTimeoutMs` remains the default. An already-aborted
|
|
133
|
+
signal rejects before a request ID is allocated or anything is written.
|
|
134
|
+
|
|
135
|
+
Timeout and abort only abandon the local TypeScript wait. They do not kill or
|
|
136
|
+
disconnect the shared bridge, late responses are ignored, and later commands
|
|
137
|
+
can continue using the same bridge.
|
|
138
|
+
|
|
139
|
+
> The JSON-lines protocol has no cancellation message. After a command has
|
|
140
|
+
> been written, Rust may still execute it even if the local wait times out or
|
|
141
|
+
> is aborted. Do not blindly retry mutating commands; first establish whether
|
|
142
|
+
> the original command executed or design the command to be idempotent.
|
|
143
|
+
|
|
144
|
+
Timeout, cancellation, transport-write/exit, and Rust response failures use
|
|
145
|
+
`RustBridgeRequestError`.
|
|
146
|
+
Existing message text remains available, while `code` is stable for
|
|
147
|
+
programmatic handling:
|
|
148
|
+
|
|
149
|
+
| Code | Meaning |
|
|
150
|
+
|---|---|
|
|
151
|
+
| `ERR_RUST_BRIDGE_REQUEST_TIMEOUT` | The local request deadline elapsed |
|
|
152
|
+
| `ERR_RUST_BRIDGE_REQUEST_ABORTED` | The caller's signal aborted the local wait |
|
|
153
|
+
| `ERR_RUST_BRIDGE_REQUEST_WRITE` | The transport rejected the request write |
|
|
154
|
+
| `ERR_RUST_BRIDGE_REQUEST_TRANSPORT` | The transport exited, disconnected, or was killed |
|
|
155
|
+
| `ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE` | Rust returned `success: false` |
|
|
156
|
+
|
|
106
157
|
### Socket Mode — Connect to a Running Daemon 🔗
|
|
107
158
|
|
|
108
159
|
When the Rust binary runs as a system service (e.g., via `systemd`, `launchd`, or a Windows Service), use `connect()` to talk to it over a Unix socket or named pipe:
|
|
@@ -282,7 +333,7 @@ const bridge = new RustBridge<TMyCommands>({
|
|
|
282
333
|
|
|
283
334
|
// --- Bridge Options ---
|
|
284
335
|
cliArgs: ['--management'], // optional: args passed to binary (default: ['--management'])
|
|
285
|
-
requestTimeoutMs: 30000, // optional:
|
|
336
|
+
requestTimeoutMs: 30000, // optional: default request timeout (default: 30000)
|
|
286
337
|
streamTimeoutMs: 30000, // optional: streaming inactivity timeout (default: requestTimeoutMs)
|
|
287
338
|
readyTimeoutMs: 10000, // optional: ready event timeout (default: 10000)
|
|
288
339
|
maxPayloadSize: 50 * 1024 * 1024, // optional: max message size in bytes (default: 50MB)
|
|
@@ -486,7 +537,7 @@ fn main() {
|
|
|
486
537
|
| `constructor` | `new RustBridge<T>(options: IRustBridgeOptions)` | Create a new bridge instance |
|
|
487
538
|
| `spawn()` | `Promise<boolean>` | **Stdio mode**: Spawn the binary and wait for ready; returns `false` on failure |
|
|
488
539
|
| `connect(socketPath, options?)` | `Promise<boolean>` | **Socket mode**: Connect to a running daemon; returns `false` on failure |
|
|
489
|
-
| `sendCommand(method, params)` | `Promise<TCommands[K]['result']>` | Send a typed command
|
|
540
|
+
| `sendCommand(method, params, options?)` | `Promise<TCommands[K]['result']>` | Send a typed command with an optional per-call timeout or abort signal |
|
|
490
541
|
| `sendCommandStreaming(method, params)` | `StreamingResponse<TChunk, TResult>` | Send a streaming command; returns immediately |
|
|
491
542
|
| `kill()` | `void` | Stdio: SIGTERM the process, SIGKILL after 5s. Socket: close the connection (daemon stays alive) |
|
|
492
543
|
| `running` | `boolean` | Whether the bridge is currently connected and ready |
|
|
@@ -539,6 +590,7 @@ fn main() {
|
|
|
539
590
|
| Interface / Type | Description |
|
|
540
591
|
|---|---|
|
|
541
592
|
| `IRustBridgeOptions` | Full configuration for `RustBridge` |
|
|
593
|
+
| `IRustBridgeRequestOptions` | Per-command options: `{ signal?, timeoutMs? }` |
|
|
542
594
|
| `IBinaryLocatorOptions` | Configuration for `RustBinaryLocator` |
|
|
543
595
|
| `ISocketConnectOptions` | Socket connection options (reconnect settings) |
|
|
544
596
|
| `IRustBridgeLogger` | Logger interface: `{ log(level, message, data?) }` |
|
|
@@ -551,6 +603,8 @@ fn main() {
|
|
|
551
603
|
| `TCommandMap` | `Record<string, ICommandDefinition>` |
|
|
552
604
|
| `TStreamingCommandKeys<T>` | Extracts keys from a command map that have a `chunk` field |
|
|
553
605
|
| `TExtractChunk<T>` | Extracts the chunk type from a streaming command definition |
|
|
606
|
+
| `RustBridgeRequestError` | Request error class with stable `code`, `requestId`, and `method` fields |
|
|
607
|
+
| `TRustBridgeRequestErrorCode` | Union of stable request error code strings |
|
|
554
608
|
|
|
555
609
|
## License and Legal Information
|
|
556
610
|
|
package/ts/00_commitinfo_data.ts
CHANGED
package/ts/classes.rustbridge.ts
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import * as plugins from './plugins.js';
|
|
2
2
|
import { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
|
+
import { RustBridgeRequestError } from './classes.rustbridgerequesterror.js';
|
|
3
4
|
import { StreamingResponse } from './classes.streamingresponse.js';
|
|
4
5
|
import { StdioTransport } from './classes.stdiotransport.js';
|
|
5
6
|
import { SocketTransport } from './classes.sockettransport.js';
|
|
6
7
|
import type {
|
|
7
8
|
IRustBridgeOptions,
|
|
9
|
+
IRustBridgeRequestOptions,
|
|
8
10
|
IRustBridgeLogger,
|
|
9
11
|
ISocketConnectOptions,
|
|
10
12
|
TCommandMap,
|
|
@@ -20,6 +22,20 @@ const defaultLogger: IRustBridgeLogger = {
|
|
|
20
22
|
log() {},
|
|
21
23
|
};
|
|
22
24
|
|
|
25
|
+
interface IPendingRequest {
|
|
26
|
+
resolve: (value: any) => void;
|
|
27
|
+
reject: (error: Error) => void;
|
|
28
|
+
timer: ReturnType<typeof setTimeout> | null;
|
|
29
|
+
method: string;
|
|
30
|
+
abortSignal?: AbortSignal;
|
|
31
|
+
abortHandler?: () => void;
|
|
32
|
+
streaming?: StreamingResponse<any, any>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
type TPendingRequestSettlement =
|
|
36
|
+
| { outcome: 'resolve'; value: any }
|
|
37
|
+
| { outcome: 'reject'; error: Error };
|
|
38
|
+
|
|
23
39
|
/**
|
|
24
40
|
* Generic bridge between TypeScript and a Rust binary.
|
|
25
41
|
* Communicates via JSON-over-stdin/stdout IPC protocol (stdio mode)
|
|
@@ -32,12 +48,7 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
32
48
|
private options: Required<Pick<IRustBridgeOptions, 'cliArgs' | 'requestTimeoutMs' | 'readyTimeoutMs' | 'readyEventName' | 'maxPayloadSize'>> & IRustBridgeOptions;
|
|
33
49
|
private logger: IRustBridgeLogger;
|
|
34
50
|
private transport: IRustTransport | null = null;
|
|
35
|
-
private pendingRequests = new Map<string,
|
|
36
|
-
resolve: (value: any) => void;
|
|
37
|
-
reject: (error: Error) => void;
|
|
38
|
-
timer: ReturnType<typeof setTimeout>;
|
|
39
|
-
streaming?: StreamingResponse<any, any>;
|
|
40
|
-
}>();
|
|
51
|
+
private pendingRequests = new Map<string, IPendingRequest>();
|
|
41
52
|
private requestCounter = 0;
|
|
42
53
|
private isRunning = false;
|
|
43
54
|
private binaryPath: string | null = null;
|
|
@@ -116,13 +127,13 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
116
127
|
|
|
117
128
|
transport.on('close', (...args: any[]) => {
|
|
118
129
|
this.logger.log('info', `Transport closed`);
|
|
119
|
-
this.cleanup();
|
|
130
|
+
this.cleanup(`${this.options.binaryName} process exited`);
|
|
120
131
|
this.emit('exit', ...args);
|
|
121
132
|
});
|
|
122
133
|
|
|
123
134
|
transport.on('error', (err: Error) => {
|
|
124
135
|
this.logger.log('error', `Transport error: ${err.message}`);
|
|
125
|
-
this.cleanup();
|
|
136
|
+
this.cleanup(`${this.options.binaryName} process exited`, err);
|
|
126
137
|
resolve(false);
|
|
127
138
|
});
|
|
128
139
|
|
|
@@ -164,11 +175,32 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
164
175
|
public async sendCommand<K extends string & keyof TCommands>(
|
|
165
176
|
method: K,
|
|
166
177
|
params: TCommands[K]['params'],
|
|
178
|
+
options?: IRustBridgeRequestOptions,
|
|
167
179
|
): Promise<TCommands[K]['result']> {
|
|
180
|
+
const timeoutMs = options?.timeoutMs ?? this.options.requestTimeoutMs;
|
|
181
|
+
if (
|
|
182
|
+
options?.timeoutMs !== undefined
|
|
183
|
+
&& (!Number.isSafeInteger(options.timeoutMs) || options.timeoutMs <= 0)
|
|
184
|
+
) {
|
|
185
|
+
throw new RangeError('RustBridge request timeoutMs must be a positive safe integer');
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (options?.signal?.aborted) {
|
|
189
|
+
throw new RustBridgeRequestError(
|
|
190
|
+
`Command '${method}' was aborted before it was sent`,
|
|
191
|
+
{
|
|
192
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_ABORTED',
|
|
193
|
+
method,
|
|
194
|
+
cause: options.signal.reason,
|
|
195
|
+
},
|
|
196
|
+
);
|
|
197
|
+
}
|
|
198
|
+
|
|
168
199
|
if (!this.transport?.connected || !this.isRunning) {
|
|
169
200
|
throw new Error(`${this.options.binaryName} bridge is not running`);
|
|
170
201
|
}
|
|
171
202
|
|
|
203
|
+
const transport = this.transport;
|
|
172
204
|
const id = `req_${++this.requestCounter}`;
|
|
173
205
|
const request: IManagementRequest = { id, method, params };
|
|
174
206
|
const json = JSON.stringify(request);
|
|
@@ -182,18 +214,76 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
182
214
|
}
|
|
183
215
|
|
|
184
216
|
return new Promise<TCommands[K]['result']>((resolve, reject) => {
|
|
185
|
-
const
|
|
186
|
-
|
|
187
|
-
reject
|
|
188
|
-
|
|
217
|
+
const pending: IPendingRequest = {
|
|
218
|
+
resolve,
|
|
219
|
+
reject,
|
|
220
|
+
timer: null,
|
|
221
|
+
method,
|
|
222
|
+
abortSignal: options?.signal,
|
|
223
|
+
};
|
|
224
|
+
this.pendingRequests.set(id, pending);
|
|
225
|
+
|
|
226
|
+
if (options?.signal) {
|
|
227
|
+
pending.abortHandler = () => {
|
|
228
|
+
this.settlePendingRequest(id, {
|
|
229
|
+
outcome: 'reject',
|
|
230
|
+
error: new RustBridgeRequestError(
|
|
231
|
+
`Command '${method}' was aborted`,
|
|
232
|
+
{
|
|
233
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_ABORTED',
|
|
234
|
+
requestId: id,
|
|
235
|
+
method,
|
|
236
|
+
cause: options.signal?.reason,
|
|
237
|
+
},
|
|
238
|
+
),
|
|
239
|
+
});
|
|
240
|
+
};
|
|
241
|
+
options.signal.addEventListener('abort', pending.abortHandler, { once: true });
|
|
242
|
+
}
|
|
189
243
|
|
|
190
|
-
|
|
244
|
+
pending.timer = setTimeout(() => {
|
|
245
|
+
this.settlePendingRequest(id, {
|
|
246
|
+
outcome: 'reject',
|
|
247
|
+
error: new RustBridgeRequestError(
|
|
248
|
+
`Command '${method}' timed out after ${timeoutMs}ms`,
|
|
249
|
+
{
|
|
250
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_TIMEOUT',
|
|
251
|
+
requestId: id,
|
|
252
|
+
method,
|
|
253
|
+
},
|
|
254
|
+
),
|
|
255
|
+
});
|
|
256
|
+
}, timeoutMs);
|
|
191
257
|
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
258
|
+
try {
|
|
259
|
+
void transport.write(json + '\n').catch((err: unknown) => {
|
|
260
|
+
this.settlePendingRequest(id, {
|
|
261
|
+
outcome: 'reject',
|
|
262
|
+
error: new RustBridgeRequestError(
|
|
263
|
+
`Failed to write to transport: ${this.getErrorMessage(err)}`,
|
|
264
|
+
{
|
|
265
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_WRITE',
|
|
266
|
+
requestId: id,
|
|
267
|
+
method,
|
|
268
|
+
cause: err,
|
|
269
|
+
},
|
|
270
|
+
),
|
|
271
|
+
});
|
|
272
|
+
});
|
|
273
|
+
} catch (err: unknown) {
|
|
274
|
+
this.settlePendingRequest(id, {
|
|
275
|
+
outcome: 'reject',
|
|
276
|
+
error: new RustBridgeRequestError(
|
|
277
|
+
`Failed to write to transport: ${this.getErrorMessage(err)}`,
|
|
278
|
+
{
|
|
279
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_WRITE',
|
|
280
|
+
requestId: id,
|
|
281
|
+
method,
|
|
282
|
+
cause: err,
|
|
283
|
+
},
|
|
284
|
+
),
|
|
285
|
+
});
|
|
286
|
+
}
|
|
197
287
|
});
|
|
198
288
|
}
|
|
199
289
|
|
|
@@ -227,22 +317,33 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
227
317
|
|
|
228
318
|
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
229
319
|
const timer = setTimeout(() => {
|
|
230
|
-
this.
|
|
231
|
-
|
|
320
|
+
this.settlePendingRequest(id, {
|
|
321
|
+
outcome: 'reject',
|
|
322
|
+
error: new Error(`Streaming command '${method}' timed out after ${timeoutMs}ms`),
|
|
323
|
+
});
|
|
232
324
|
}, timeoutMs);
|
|
233
325
|
|
|
234
326
|
this.pendingRequests.set(id, {
|
|
235
327
|
resolve: (result: any) => streaming.finish(result),
|
|
236
328
|
reject: (error: Error) => streaming.fail(error),
|
|
237
329
|
timer,
|
|
330
|
+
method,
|
|
238
331
|
streaming,
|
|
239
332
|
});
|
|
240
333
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
334
|
+
try {
|
|
335
|
+
void this.transport!.write(json + '\n').catch((err: unknown) => {
|
|
336
|
+
this.settlePendingRequest(id, {
|
|
337
|
+
outcome: 'reject',
|
|
338
|
+
error: new Error(`Failed to write to transport: ${this.getErrorMessage(err)}`),
|
|
339
|
+
});
|
|
340
|
+
});
|
|
341
|
+
} catch (err: unknown) {
|
|
342
|
+
this.settlePendingRequest(id, {
|
|
343
|
+
outcome: 'reject',
|
|
344
|
+
error: new Error(`Failed to write to transport: ${this.getErrorMessage(err)}`),
|
|
345
|
+
});
|
|
346
|
+
}
|
|
246
347
|
|
|
247
348
|
return streaming;
|
|
248
349
|
}
|
|
@@ -259,11 +360,7 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
259
360
|
this.isRunning = false;
|
|
260
361
|
|
|
261
362
|
// Reject pending requests
|
|
262
|
-
|
|
263
|
-
clearTimeout(pending.timer);
|
|
264
|
-
pending.reject(new Error(`${this.options.binaryName} process killed`));
|
|
265
|
-
}
|
|
266
|
-
this.pendingRequests.clear();
|
|
363
|
+
this.rejectAllPendingRequests(`${this.options.binaryName} process killed`);
|
|
267
364
|
|
|
268
365
|
transport.removeAllListeners();
|
|
269
366
|
transport.disconnect();
|
|
@@ -300,11 +397,15 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
300
397
|
const pending = this.pendingRequests.get(parsed.id);
|
|
301
398
|
if (pending?.streaming) {
|
|
302
399
|
// Reset inactivity timeout
|
|
303
|
-
|
|
400
|
+
if (pending.timer) {
|
|
401
|
+
clearTimeout(pending.timer);
|
|
402
|
+
}
|
|
304
403
|
const timeoutMs = this.options.streamTimeoutMs ?? this.options.requestTimeoutMs;
|
|
305
404
|
pending.timer = setTimeout(() => {
|
|
306
|
-
this.
|
|
307
|
-
|
|
405
|
+
this.settlePendingRequest(parsed.id, {
|
|
406
|
+
outcome: 'reject',
|
|
407
|
+
error: new Error(`Streaming command timed out after ${timeoutMs}ms of inactivity`),
|
|
408
|
+
});
|
|
308
409
|
}, timeoutMs);
|
|
309
410
|
pending.streaming.pushChunk(parsed.data);
|
|
310
411
|
}
|
|
@@ -316,26 +417,85 @@ export class RustBridge<TCommands extends TCommandMap = TCommandMap> extends plu
|
|
|
316
417
|
const response = parsed as IManagementResponse;
|
|
317
418
|
const pending = this.pendingRequests.get(response.id);
|
|
318
419
|
if (pending) {
|
|
319
|
-
clearTimeout(pending.timer);
|
|
320
|
-
this.pendingRequests.delete(response.id);
|
|
321
420
|
if (response.success) {
|
|
322
|
-
|
|
421
|
+
this.settlePendingRequest(response.id, {
|
|
422
|
+
outcome: 'resolve',
|
|
423
|
+
value: response.result,
|
|
424
|
+
});
|
|
323
425
|
} else {
|
|
324
|
-
|
|
426
|
+
const message = response.error || 'Unknown error from Rust process';
|
|
427
|
+
this.settlePendingRequest(response.id, {
|
|
428
|
+
outcome: 'reject',
|
|
429
|
+
error: pending.streaming
|
|
430
|
+
? new Error(message)
|
|
431
|
+
: new RustBridgeRequestError(
|
|
432
|
+
message,
|
|
433
|
+
{
|
|
434
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE',
|
|
435
|
+
requestId: response.id,
|
|
436
|
+
method: pending.method,
|
|
437
|
+
},
|
|
438
|
+
),
|
|
439
|
+
});
|
|
325
440
|
}
|
|
326
441
|
}
|
|
327
442
|
}
|
|
328
443
|
}
|
|
329
444
|
|
|
330
|
-
private
|
|
331
|
-
|
|
332
|
-
|
|
445
|
+
private settlePendingRequest(
|
|
446
|
+
id: string,
|
|
447
|
+
settlement: TPendingRequestSettlement,
|
|
448
|
+
): boolean {
|
|
449
|
+
const pending = this.pendingRequests.get(id);
|
|
450
|
+
if (!pending) {
|
|
451
|
+
return false;
|
|
452
|
+
}
|
|
333
453
|
|
|
334
|
-
|
|
335
|
-
|
|
454
|
+
this.pendingRequests.delete(id);
|
|
455
|
+
if (pending.timer) {
|
|
336
456
|
clearTimeout(pending.timer);
|
|
337
|
-
pending.
|
|
457
|
+
pending.timer = null;
|
|
458
|
+
}
|
|
459
|
+
if (pending.abortSignal && pending.abortHandler) {
|
|
460
|
+
pending.abortSignal.removeEventListener('abort', pending.abortHandler);
|
|
461
|
+
pending.abortHandler = undefined;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
if (settlement.outcome === 'resolve') {
|
|
465
|
+
pending.resolve(settlement.value);
|
|
466
|
+
} else {
|
|
467
|
+
pending.reject(settlement.error);
|
|
338
468
|
}
|
|
339
|
-
|
|
469
|
+
return true;
|
|
470
|
+
}
|
|
471
|
+
|
|
472
|
+
private rejectAllPendingRequests(message: string, cause?: unknown): void {
|
|
473
|
+
for (const [id, pending] of [...this.pendingRequests]) {
|
|
474
|
+
this.settlePendingRequest(id, {
|
|
475
|
+
outcome: 'reject',
|
|
476
|
+
error: pending.streaming
|
|
477
|
+
? new Error(message)
|
|
478
|
+
: new RustBridgeRequestError(
|
|
479
|
+
message,
|
|
480
|
+
{
|
|
481
|
+
code: 'ERR_RUST_BRIDGE_REQUEST_TRANSPORT',
|
|
482
|
+
requestId: id,
|
|
483
|
+
method: pending.method,
|
|
484
|
+
cause,
|
|
485
|
+
},
|
|
486
|
+
),
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
private cleanup(message: string, cause?: unknown): void {
|
|
492
|
+
this.isRunning = false;
|
|
493
|
+
this.transport = null;
|
|
494
|
+
|
|
495
|
+
this.rejectAllPendingRequests(message, cause);
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
private getErrorMessage(error: unknown): string {
|
|
499
|
+
return error instanceof Error ? error.message : String(error);
|
|
340
500
|
}
|
|
341
501
|
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stable error codes for failures while waiting for a Rust bridge request.
|
|
3
|
+
*/
|
|
4
|
+
export type TRustBridgeRequestErrorCode =
|
|
5
|
+
| 'ERR_RUST_BRIDGE_REQUEST_TIMEOUT'
|
|
6
|
+
| 'ERR_RUST_BRIDGE_REQUEST_ABORTED'
|
|
7
|
+
| 'ERR_RUST_BRIDGE_REQUEST_WRITE'
|
|
8
|
+
| 'ERR_RUST_BRIDGE_REQUEST_TRANSPORT'
|
|
9
|
+
| 'ERR_RUST_BRIDGE_REQUEST_RUST_RESPONSE';
|
|
10
|
+
|
|
11
|
+
export interface IRustBridgeRequestErrorOptions {
|
|
12
|
+
code: TRustBridgeRequestErrorCode;
|
|
13
|
+
requestId?: string;
|
|
14
|
+
method?: string;
|
|
15
|
+
cause?: unknown;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Error raised while preparing or waiting for a Rust bridge request.
|
|
20
|
+
*
|
|
21
|
+
* Existing error messages are preserved while `code` provides a stable way to
|
|
22
|
+
* distinguish timeout, cancellation, transport, write, and Rust response
|
|
23
|
+
* failures.
|
|
24
|
+
*/
|
|
25
|
+
export class RustBridgeRequestError extends Error {
|
|
26
|
+
public readonly code: TRustBridgeRequestErrorCode;
|
|
27
|
+
public readonly requestId?: string;
|
|
28
|
+
public readonly method?: string;
|
|
29
|
+
|
|
30
|
+
constructor(message: string, options: IRustBridgeRequestErrorOptions) {
|
|
31
|
+
super(message, options.cause === undefined ? undefined : { cause: options.cause });
|
|
32
|
+
this.name = 'RustBridgeRequestError';
|
|
33
|
+
this.code = options.code;
|
|
34
|
+
this.requestId = options.requestId;
|
|
35
|
+
this.method = options.method;
|
|
36
|
+
}
|
|
37
|
+
}
|
package/ts/index.ts
CHANGED
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
export { RustBridge } from './classes.rustbridge.js';
|
|
2
|
+
export {
|
|
3
|
+
RustBridgeRequestError,
|
|
4
|
+
type IRustBridgeRequestErrorOptions,
|
|
5
|
+
type TRustBridgeRequestErrorCode,
|
|
6
|
+
} from './classes.rustbridgerequesterror.js';
|
|
2
7
|
export { RustBinaryLocator } from './classes.rustbinarylocator.js';
|
|
3
8
|
export { StreamingResponse } from './classes.streamingresponse.js';
|
|
4
9
|
export { StdioTransport } from './classes.stdiotransport.js';
|
package/ts/interfaces/config.ts
CHANGED
|
@@ -5,6 +5,16 @@ export interface IRustBridgeLogger {
|
|
|
5
5
|
log(level: string, message: string, data?: Record<string, any>): void;
|
|
6
6
|
}
|
|
7
7
|
|
|
8
|
+
/**
|
|
9
|
+
* Options for one non-streaming Rust bridge request.
|
|
10
|
+
*/
|
|
11
|
+
export interface IRustBridgeRequestOptions {
|
|
12
|
+
/** Abort only the local wait for this request. */
|
|
13
|
+
signal?: AbortSignal;
|
|
14
|
+
/** Override the bridge request timeout for this call, in milliseconds. */
|
|
15
|
+
timeoutMs?: number;
|
|
16
|
+
}
|
|
17
|
+
|
|
8
18
|
/**
|
|
9
19
|
* Options for locating a Rust binary.
|
|
10
20
|
*/
|