@comake/skl-js-engine 1.3.8 → 1.3.10
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/dist/JsExecutor/PermissionBuilder.d.ts +1 -0
- package/dist/JsExecutor/PermissionBuilder.d.ts.map +1 -0
- package/dist/JsExecutor/PermissionBuilder.js.map +1 -1
- package/dist/JsExecutor/constants.d.ts +1 -0
- package/dist/JsExecutor/constants.d.ts.map +1 -0
- package/dist/JsExecutor/constants.js.map +1 -1
- package/dist/JsExecutor/denoUtils.d.ts +1 -0
- package/dist/JsExecutor/denoUtils.d.ts.map +1 -0
- package/dist/JsExecutor/denoUtils.js.map +1 -1
- package/dist/JsExecutor/errors.d.ts +1 -0
- package/dist/JsExecutor/errors.d.ts.map +1 -0
- package/dist/JsExecutor/errors.js.map +1 -1
- package/dist/JsExecutor/examples/basic/index.d.ts +1 -0
- package/dist/JsExecutor/examples/basic/index.d.ts.map +1 -0
- package/dist/JsExecutor/examples/basic/index.js.map +1 -1
- package/dist/JsExecutor/examples/basic/process.d.ts +1 -0
- package/dist/JsExecutor/examples/basic/process.d.ts.map +1 -0
- package/dist/JsExecutor/examples/basic/process.js.map +1 -1
- package/dist/JsExecutor/examples/jsExecutor/index.d.ts +1 -0
- package/dist/JsExecutor/examples/jsExecutor/index.d.ts.map +1 -0
- package/dist/JsExecutor/examples/jsExecutor/index.js.map +1 -1
- package/dist/JsExecutor/examples/jsExecutor/process.d.ts +1 -0
- package/dist/JsExecutor/examples/jsExecutor/process.d.ts.map +1 -0
- package/dist/JsExecutor/examples/jsExecutor/process.js.map +1 -1
- package/dist/JsExecutor/index.d.ts +1 -0
- package/dist/JsExecutor/index.d.ts.map +1 -0
- package/dist/JsExecutor/index.js.map +1 -1
- package/dist/JsExecutor/jsExecutor.d.ts +1 -0
- package/dist/JsExecutor/jsExecutor.d.ts.map +1 -0
- package/dist/JsExecutor/jsExecutor.js.map +1 -1
- package/dist/JsExecutor/jsonRpc/JsonRpcClient.d.ts +1 -0
- package/dist/JsExecutor/jsonRpc/JsonRpcClient.d.ts.map +1 -0
- package/dist/JsExecutor/jsonRpc/JsonRpcClient.js.map +1 -1
- package/dist/JsExecutor/jsonRpc/JsonRpcServer.d.ts +1 -0
- package/dist/JsExecutor/jsonRpc/JsonRpcServer.d.ts.map +1 -0
- package/dist/JsExecutor/jsonRpc/JsonRpcServer.js.map +1 -1
- package/dist/JsExecutor/jsonRpc/index.d.ts +1 -0
- package/dist/JsExecutor/jsonRpc/index.d.ts.map +1 -0
- package/dist/JsExecutor/jsonRpc/index.js.map +1 -1
- package/dist/JsExecutor/jsonRpc/types.d.ts +1 -0
- package/dist/JsExecutor/jsonRpc/types.d.ts.map +1 -0
- package/dist/JsExecutor/jsonRpc/types.js.map +1 -1
- package/dist/JsExecutor/transport/Transport.d.ts +1 -0
- package/dist/JsExecutor/transport/Transport.d.ts.map +1 -0
- package/dist/JsExecutor/transport/Transport.js.map +1 -1
- package/dist/JsExecutor/transport/base/BaseTransport.d.ts +1 -0
- package/dist/JsExecutor/transport/base/BaseTransport.d.ts.map +1 -0
- package/dist/JsExecutor/transport/base/BaseTransport.js.map +1 -1
- package/dist/JsExecutor/transport/index.d.ts +1 -0
- package/dist/JsExecutor/transport/index.d.ts.map +1 -0
- package/dist/JsExecutor/transport/index.js.map +1 -1
- package/dist/JsExecutor/transport/process/ProcessManager.d.ts +1 -0
- package/dist/JsExecutor/transport/process/ProcessManager.d.ts.map +1 -0
- package/dist/JsExecutor/transport/process/ProcessManager.js.map +1 -1
- package/dist/JsExecutor/transport/stdio/ChildStdioTransport.d.ts +1 -0
- package/dist/JsExecutor/transport/stdio/ChildStdioTransport.d.ts.map +1 -0
- package/dist/JsExecutor/transport/stdio/ChildStdioTransport.js.map +1 -1
- package/dist/JsExecutor/transport/stdio/ParentStdioTransport.d.ts +1 -0
- package/dist/JsExecutor/transport/stdio/ParentStdioTransport.d.ts.map +1 -0
- package/dist/JsExecutor/transport/stdio/ParentStdioTransport.js.map +1 -1
- package/dist/JsExecutor/transport/utils/MessageUtils.d.ts +1 -0
- package/dist/JsExecutor/transport/utils/MessageUtils.d.ts.map +1 -0
- package/dist/JsExecutor/transport/utils/MessageUtils.js.map +1 -1
- package/dist/JsExecutor/transport/utils/PollingUtils.d.ts +1 -0
- package/dist/JsExecutor/transport/utils/PollingUtils.d.ts.map +1 -0
- package/dist/JsExecutor/transport/utils/PollingUtils.js.map +1 -1
- package/dist/JsExecutor/types.d.ts +1 -0
- package/dist/JsExecutor/types.d.ts.map +1 -0
- package/dist/JsExecutor/types.js.map +1 -1
- package/dist/SklEngine.d.ts +1 -0
- package/dist/SklEngine.d.ts.map +1 -0
- package/dist/SklEngine.js.map +1 -1
- package/dist/SklEngineOptions.d.ts +1 -0
- package/dist/SklEngineOptions.d.ts.map +1 -0
- package/dist/SklEngineOptions.js.map +1 -1
- package/dist/constants.d.ts +1 -0
- package/dist/constants.d.ts.map +1 -0
- package/dist/constants.js.map +1 -1
- package/dist/customCapabilities.d.ts +1 -0
- package/dist/customCapabilities.d.ts.map +1 -0
- package/dist/customCapabilities.js.map +1 -1
- package/dist/examples/customCapabilitiesExample.d.ts +1 -0
- package/dist/examples/customCapabilitiesExample.d.ts.map +1 -0
- package/dist/examples/customCapabilitiesExample.js.map +1 -1
- package/dist/hooks/globalHooks.d.ts +1 -0
- package/dist/hooks/globalHooks.d.ts.map +1 -0
- package/dist/hooks/globalHooks.js.map +1 -1
- package/dist/hooks/types.d.ts +1 -0
- package/dist/hooks/types.d.ts.map +1 -0
- package/dist/hooks/types.js.map +1 -1
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js.map +1 -1
- package/dist/logger.d.ts +1 -0
- package/dist/logger.d.ts.map +1 -0
- package/dist/logger.js.map +1 -1
- package/dist/mapping/Mapper.d.ts +1 -0
- package/dist/mapping/Mapper.d.ts.map +1 -0
- package/dist/mapping/Mapper.js.map +1 -1
- package/dist/storage/FindOperator.d.ts +1 -0
- package/dist/storage/FindOperator.d.ts.map +1 -0
- package/dist/storage/FindOperator.js.map +1 -1
- package/dist/storage/FindOptionsTypes.d.ts +1 -0
- package/dist/storage/FindOptionsTypes.d.ts.map +1 -0
- package/dist/storage/FindOptionsTypes.js.map +1 -1
- package/dist/storage/GroupOptionTypes.d.ts +1 -0
- package/dist/storage/GroupOptionTypes.d.ts.map +1 -0
- package/dist/storage/GroupOptionTypes.js.map +1 -1
- package/dist/storage/operator/And.d.ts +1 -0
- package/dist/storage/operator/And.d.ts.map +1 -0
- package/dist/storage/operator/And.js.map +1 -1
- package/dist/storage/operator/Contains.d.ts +1 -0
- package/dist/storage/operator/Contains.d.ts.map +1 -0
- package/dist/storage/operator/Contains.js.map +1 -1
- package/dist/storage/operator/Equal.d.ts +1 -0
- package/dist/storage/operator/Equal.d.ts.map +1 -0
- package/dist/storage/operator/Equal.js.map +1 -1
- package/dist/storage/operator/Exists.d.ts +1 -0
- package/dist/storage/operator/Exists.d.ts.map +1 -0
- package/dist/storage/operator/Exists.js.map +1 -1
- package/dist/storage/operator/GreaterThan.d.ts +1 -0
- package/dist/storage/operator/GreaterThan.d.ts.map +1 -0
- package/dist/storage/operator/GreaterThan.js.map +1 -1
- package/dist/storage/operator/GreaterThanOrEqual.d.ts +1 -0
- package/dist/storage/operator/GreaterThanOrEqual.d.ts.map +1 -0
- package/dist/storage/operator/GreaterThanOrEqual.js.map +1 -1
- package/dist/storage/operator/In.d.ts +1 -0
- package/dist/storage/operator/In.d.ts.map +1 -0
- package/dist/storage/operator/In.js.map +1 -1
- package/dist/storage/operator/Inverse.d.ts +1 -0
- package/dist/storage/operator/Inverse.d.ts.map +1 -0
- package/dist/storage/operator/Inverse.js.map +1 -1
- package/dist/storage/operator/InversePath.d.ts +1 -0
- package/dist/storage/operator/InversePath.d.ts.map +1 -0
- package/dist/storage/operator/InversePath.js.map +1 -1
- package/dist/storage/operator/InverseRelation.d.ts +1 -0
- package/dist/storage/operator/InverseRelation.d.ts.map +1 -0
- package/dist/storage/operator/InverseRelation.js.map +1 -1
- package/dist/storage/operator/InverseRelationOrder.d.ts +1 -0
- package/dist/storage/operator/InverseRelationOrder.d.ts.map +1 -0
- package/dist/storage/operator/InverseRelationOrder.js.map +1 -1
- package/dist/storage/operator/LessThan.d.ts +1 -0
- package/dist/storage/operator/LessThan.d.ts.map +1 -0
- package/dist/storage/operator/LessThan.js.map +1 -1
- package/dist/storage/operator/LessThanOrEqual.d.ts +1 -0
- package/dist/storage/operator/LessThanOrEqual.d.ts.map +1 -0
- package/dist/storage/operator/LessThanOrEqual.js.map +1 -1
- package/dist/storage/operator/Not.d.ts +1 -0
- package/dist/storage/operator/Not.d.ts.map +1 -0
- package/dist/storage/operator/Not.js.map +1 -1
- package/dist/storage/operator/OneOrMorePath.d.ts +1 -0
- package/dist/storage/operator/OneOrMorePath.d.ts.map +1 -0
- package/dist/storage/operator/OneOrMorePath.js.map +1 -1
- package/dist/storage/operator/Sequence.d.ts +1 -0
- package/dist/storage/operator/Sequence.d.ts.map +1 -0
- package/dist/storage/operator/Sequence.js.map +1 -1
- package/dist/storage/operator/SequencePath.d.ts +1 -0
- package/dist/storage/operator/SequencePath.d.ts.map +1 -0
- package/dist/storage/operator/SequencePath.js.map +1 -1
- package/dist/storage/operator/ZeroOrMorePath.d.ts +1 -0
- package/dist/storage/operator/ZeroOrMorePath.d.ts.map +1 -0
- package/dist/storage/operator/ZeroOrMorePath.js.map +1 -1
- package/dist/storage/query-adapter/QueryAdapter.d.ts +1 -0
- package/dist/storage/query-adapter/QueryAdapter.d.ts.map +1 -0
- package/dist/storage/query-adapter/QueryAdapter.js.map +1 -1
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapter.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapter.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapter.js +28 -4
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapter.js.map +1 -1
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapterOptions.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapterOptions.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryAdapterOptions.js.map +1 -1
- package/dist/storage/query-adapter/sparql/SparqlQueryBuilder.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryBuilder.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/SparqlQueryBuilder.js +7 -21
- package/dist/storage/query-adapter/sparql/SparqlQueryBuilder.js.map +1 -1
- package/dist/storage/query-adapter/sparql/SparqlUpdateBuilder.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/SparqlUpdateBuilder.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/SparqlUpdateBuilder.js.map +1 -1
- package/dist/storage/query-adapter/sparql/VariableGenerator.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/VariableGenerator.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/VariableGenerator.js.map +1 -1
- package/dist/storage/query-adapter/sparql/query-executor/InMemorySparqlQueryExecutor.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/InMemorySparqlQueryExecutor.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/InMemorySparqlQueryExecutor.js.map +1 -1
- package/dist/storage/query-adapter/sparql/query-executor/SparqlEndpointQueryExecutor.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/SparqlEndpointQueryExecutor.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/SparqlEndpointQueryExecutor.js.map +1 -1
- package/dist/storage/query-adapter/sparql/query-executor/SparqlQueryExecutor.d.ts +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/SparqlQueryExecutor.d.ts.map +1 -0
- package/dist/storage/query-adapter/sparql/query-executor/SparqlQueryExecutor.js.map +1 -1
- package/dist/util/PerformanceLogger.d.ts +1 -0
- package/dist/util/PerformanceLogger.d.ts.map +1 -0
- package/dist/util/PerformanceLogger.js.map +1 -1
- package/dist/util/SparqlUtil.d.ts +1 -0
- package/dist/util/SparqlUtil.d.ts.map +1 -0
- package/dist/util/SparqlUtil.js.map +1 -1
- package/dist/util/TripleUtil.d.ts +1 -0
- package/dist/util/TripleUtil.d.ts.map +1 -0
- package/dist/util/TripleUtil.js +10 -0
- package/dist/util/TripleUtil.js.map +1 -1
- package/dist/util/Types.d.ts +1 -0
- package/dist/util/Types.d.ts.map +1 -0
- package/dist/util/Types.js.map +1 -1
- package/dist/util/Util.d.ts +1 -0
- package/dist/util/Util.d.ts.map +1 -0
- package/dist/util/Util.js.map +1 -1
- package/dist/util/Vocabularies/Shared.d.ts +1 -0
- package/dist/util/Vocabularies/Shared.d.ts.map +1 -0
- package/dist/util/Vocabularies/Shared.js.map +1 -1
- package/dist/util/Vocabularies/helper.d.ts +1 -0
- package/dist/util/Vocabularies/helper.d.ts.map +1 -0
- package/dist/util/Vocabularies/helper.js.map +1 -1
- package/dist/util/Vocabularies/index.d.ts +1 -0
- package/dist/util/Vocabularies/index.d.ts.map +1 -0
- package/dist/util/Vocabularies/index.js.map +1 -1
- package/dist/util/safeJsonStringify.d.ts +1 -0
- package/dist/util/safeJsonStringify.d.ts.map +1 -0
- package/dist/util/safeJsonStringify.js.map +1 -1
- package/package.json +6 -3
- package/src/JsExecutor/PermissionBuilder.ts +60 -0
- package/src/JsExecutor/constants.ts +27 -0
- package/src/JsExecutor/denoUtils.ts +20 -0
- package/src/JsExecutor/errors.ts +63 -0
- package/src/JsExecutor/examples/basic/index.ts +54 -0
- package/src/JsExecutor/examples/basic/process.ts +39 -0
- package/src/JsExecutor/examples/jsExecutor/README.md +3 -0
- package/src/JsExecutor/examples/jsExecutor/index.ts +50 -0
- package/src/JsExecutor/examples/jsExecutor/process.ts +79 -0
- package/src/JsExecutor/index.ts +19 -0
- package/src/JsExecutor/jsExecutor.ts +194 -0
- package/src/JsExecutor/jsonRpc/JsonRpcClient.ts +422 -0
- package/src/JsExecutor/jsonRpc/JsonRpcServer.ts +454 -0
- package/src/JsExecutor/jsonRpc/index.ts +4 -0
- package/src/JsExecutor/jsonRpc/types.ts +231 -0
- package/src/JsExecutor/transport/README.md +67 -0
- package/src/JsExecutor/transport/Transport.ts +106 -0
- package/src/JsExecutor/transport/base/BaseTransport.ts +83 -0
- package/src/JsExecutor/transport/index.ts +56 -0
- package/src/JsExecutor/transport/process/ProcessManager.ts +281 -0
- package/src/JsExecutor/transport/stdio/ChildStdioTransport.ts +251 -0
- package/src/JsExecutor/transport/stdio/ParentStdioTransport.ts +308 -0
- package/src/JsExecutor/transport/utils/MessageUtils.ts +139 -0
- package/src/JsExecutor/transport/utils/PollingUtils.ts +114 -0
- package/src/JsExecutor/types.ts +130 -0
- package/src/SklEngine.ts +1828 -0
- package/src/SklEngineOptions.ts +28 -0
- package/src/constants.ts +120 -0
- package/src/customCapabilities.ts +65 -0
- package/src/examples/customCapabilitiesExample.ts +77 -0
- package/src/hooks/globalHooks.ts +238 -0
- package/src/hooks/types.ts +7 -0
- package/src/index.ts +45 -0
- package/src/logger.ts +144 -0
- package/src/mapping/Mapper.ts +52 -0
- package/src/storage/FindOperator.ts +55 -0
- package/src/storage/FindOptionsTypes.ts +107 -0
- package/src/storage/GroupOptionTypes.ts +32 -0
- package/src/storage/operator/And.ts +10 -0
- package/src/storage/operator/Contains.ts +9 -0
- package/src/storage/operator/Equal.ts +13 -0
- package/src/storage/operator/Exists.ts +6 -0
- package/src/storage/operator/GreaterThan.ts +12 -0
- package/src/storage/operator/GreaterThanOrEqual.ts +12 -0
- package/src/storage/operator/In.ts +12 -0
- package/src/storage/operator/Inverse.ts +11 -0
- package/src/storage/operator/InversePath.ts +17 -0
- package/src/storage/operator/InverseRelation.ts +18 -0
- package/src/storage/operator/InverseRelationOrder.ts +17 -0
- package/src/storage/operator/LessThan.ts +12 -0
- package/src/storage/operator/LessThanOrEqual.ts +12 -0
- package/src/storage/operator/Not.ts +11 -0
- package/src/storage/operator/OneOrMorePath.ts +17 -0
- package/src/storage/operator/Sequence.ts +11 -0
- package/src/storage/operator/SequencePath.ts +17 -0
- package/src/storage/operator/ZeroOrMorePath.ts +17 -0
- package/src/storage/query-adapter/QueryAdapter.ts +110 -0
- package/src/storage/query-adapter/sparql/SparqlQueryAdapter.ts +400 -0
- package/src/storage/query-adapter/sparql/SparqlQueryAdapterOptions.ts +38 -0
- package/src/storage/query-adapter/sparql/SparqlQueryBuilder.ts +1524 -0
- package/src/storage/query-adapter/sparql/SparqlUpdateBuilder.ts +347 -0
- package/src/storage/query-adapter/sparql/VariableGenerator.ts +8 -0
- package/src/storage/query-adapter/sparql/query-executor/InMemorySparqlQueryExecutor.ts +135 -0
- package/src/storage/query-adapter/sparql/query-executor/SparqlEndpointQueryExecutor.ts +146 -0
- package/src/storage/query-adapter/sparql/query-executor/SparqlQueryExecutor.ts +51 -0
- package/src/util/PerformanceLogger.ts +286 -0
- package/src/util/SparqlUtil.ts +516 -0
- package/src/util/TripleUtil.ts +412 -0
- package/src/util/Types.ts +399 -0
- package/src/util/Util.ts +116 -0
- package/src/util/Vocabularies/Shared.ts +99 -0
- package/src/util/Vocabularies/helper.ts +14 -0
- package/src/util/Vocabularies/index.ts +108 -0
- package/src/util/safeJsonStringify.ts +19 -0
- package/dist/JsExecutor/transport/StdioTransport.d.ts +0 -0
- package/dist/JsExecutor/transport/StdioTransport.js +0 -641
- package/dist/JsExecutor/transport/StdioTransport.js.map +0 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/* eslint-disable indent */
|
|
2
|
+
import { EventEmitter } from 'node:events';
|
|
3
|
+
import type { ClientTransport } from '../../jsonRpc/JsonRpcClient';
|
|
4
|
+
import { JsonRpcClient } from '../../jsonRpc/JsonRpcClient';
|
|
5
|
+
import { JsonRpcServer } from '../../jsonRpc/JsonRpcServer';
|
|
6
|
+
import { isResponse, MessageBuffer } from '../utils/MessageUtils';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Custom logger that outputs to stderr to avoid contaminating stdout JSON-RPC channel
|
|
10
|
+
*/
|
|
11
|
+
class ChildProcessLogger {
|
|
12
|
+
private readonly name?: string;
|
|
13
|
+
private metadata: Record<string, any> = {};
|
|
14
|
+
|
|
15
|
+
public setMetadata(metadata: Record<string, any>): void {
|
|
16
|
+
this.metadata = { ...this.metadata, ...metadata };
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
public log(message: string, data?: any): void {
|
|
20
|
+
const logEntry = {
|
|
21
|
+
message,
|
|
22
|
+
metadata: this.metadata,
|
|
23
|
+
...data && { data }
|
|
24
|
+
};
|
|
25
|
+
// Use stderr to avoid contaminating stdout JSON-RPC channel
|
|
26
|
+
process.stderr.write(`${message} ${JSON.stringify(logEntry.metadata)} ${data ? JSON.stringify(data) : ''}\n`);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
public error(message: string, error?: Error): void {
|
|
30
|
+
const logEntry = {
|
|
31
|
+
level: 'error',
|
|
32
|
+
message,
|
|
33
|
+
metadata: this.metadata,
|
|
34
|
+
...error && { error: error.message, stack: error.stack }
|
|
35
|
+
};
|
|
36
|
+
process.stderr.write(`ERROR: ${JSON.stringify(logEntry)}\n`);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* Bidirectional StdioTransport for child processes
|
|
42
|
+
* This class handles both server (receiving requests) and client (sending requests) functionality
|
|
43
|
+
* over a single stdio channel with proper message routing.
|
|
44
|
+
*
|
|
45
|
+
* Usage in child process:
|
|
46
|
+
* ```typescript
|
|
47
|
+
* const transport = new ChildStdioTransport();
|
|
48
|
+
*
|
|
49
|
+
* // Register methods that parent can call
|
|
50
|
+
* transport.registerMethod('ping', async () => 'pong');
|
|
51
|
+
*
|
|
52
|
+
* // Make requests to parent
|
|
53
|
+
* const result = await transport.request('getTime');
|
|
54
|
+
* ```
|
|
55
|
+
*/
|
|
56
|
+
export class ChildStdioTransport extends EventEmitter {
|
|
57
|
+
private readonly server: JsonRpcServer;
|
|
58
|
+
private readonly client: JsonRpcClient;
|
|
59
|
+
private readonly logger = new ChildProcessLogger();
|
|
60
|
+
private readonly messageBuffer = new MessageBuffer();
|
|
61
|
+
private name?: string;
|
|
62
|
+
private initialized = false;
|
|
63
|
+
|
|
64
|
+
public constructor() {
|
|
65
|
+
super();
|
|
66
|
+
this.server = new JsonRpcServer({
|
|
67
|
+
requestTimeout: 60 * 60 * 1000
|
|
68
|
+
});
|
|
69
|
+
this.client = new JsonRpcClient({
|
|
70
|
+
defaultTimeout: 60 * 60 * 1000
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Set up the client transport that routes through our stdio
|
|
74
|
+
const clientTransport: ClientTransport = {
|
|
75
|
+
send: async(message: string): Promise<void> => {
|
|
76
|
+
this.sendMessage(message);
|
|
77
|
+
},
|
|
78
|
+
onMessage(): void {
|
|
79
|
+
// The message routing will handle client responses automatically
|
|
80
|
+
},
|
|
81
|
+
async close(): Promise<void> {
|
|
82
|
+
// Nothing to close for stdio
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
this.client.setTransport(clientTransport);
|
|
87
|
+
this.setupEventHandlers();
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Set a name for this transport (used in logging)
|
|
92
|
+
*/
|
|
93
|
+
public setName(name: string): void {
|
|
94
|
+
this.name = name;
|
|
95
|
+
this.logger.setMetadata({ name, transport: 'ChildStdioTransport' });
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Initialize the bidirectional transport
|
|
100
|
+
* This should be called once after setting up all methods
|
|
101
|
+
*/
|
|
102
|
+
public async initialize(): Promise<void> {
|
|
103
|
+
if (this.initialized) {
|
|
104
|
+
throw new Error('Transport already initialized');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
this.initialized = true;
|
|
108
|
+
this.setupStdioCommunication();
|
|
109
|
+
this.logger.log('Transport initialized');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Register a method that the parent can call
|
|
114
|
+
* @param method - Method name
|
|
115
|
+
* @param handler - Method handler function
|
|
116
|
+
*/
|
|
117
|
+
public registerMethod<TParams = any, TResult = any>(
|
|
118
|
+
method: string,
|
|
119
|
+
handler: (params: TParams) => Promise<TResult> | TResult
|
|
120
|
+
): void {
|
|
121
|
+
this.server.registerMethod(method, handler);
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Send a request to the parent process
|
|
126
|
+
* @param method - Method name
|
|
127
|
+
* @param params - Method parameters
|
|
128
|
+
* @param options - Request options
|
|
129
|
+
* @returns Promise resolving to the response
|
|
130
|
+
*/
|
|
131
|
+
public async request<TParams = any, TResult = any>(
|
|
132
|
+
method: string,
|
|
133
|
+
params?: TParams,
|
|
134
|
+
options?: { timeout?: number }
|
|
135
|
+
): Promise<TResult> {
|
|
136
|
+
if (!this.initialized) {
|
|
137
|
+
throw new Error('Transport not initialized. Call initialize() first.');
|
|
138
|
+
}
|
|
139
|
+
return this.client.request<TParams, TResult>(method, params, options);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Send a notification to the parent process (no response expected)
|
|
144
|
+
* @param method - Method name
|
|
145
|
+
* @param params - Method parameters
|
|
146
|
+
*/
|
|
147
|
+
public async notify<TParams = any>(method: string, params?: TParams): Promise<void> {
|
|
148
|
+
if (!this.initialized) {
|
|
149
|
+
throw new Error('Transport not initialized. Call initialize() first.');
|
|
150
|
+
}
|
|
151
|
+
return this.client.notify(method, params);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Get transport statistics
|
|
156
|
+
*/
|
|
157
|
+
public getStats(): {
|
|
158
|
+
serverMethods: number;
|
|
159
|
+
pendingRequests: number;
|
|
160
|
+
initialized: boolean;
|
|
161
|
+
} {
|
|
162
|
+
return {
|
|
163
|
+
serverMethods: 0,
|
|
164
|
+
pendingRequests: this.client.getStats().pendingRequests,
|
|
165
|
+
initialized: this.initialized
|
|
166
|
+
};
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* Close the transport and cleanup resources
|
|
171
|
+
*/
|
|
172
|
+
public async close(): Promise<void> {
|
|
173
|
+
await this.client.close();
|
|
174
|
+
this.initialized = false;
|
|
175
|
+
this.removeAllListeners();
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
/**
|
|
179
|
+
* Set up stdio communication handlers
|
|
180
|
+
*/
|
|
181
|
+
private setupStdioCommunication(): void {
|
|
182
|
+
// Handle incoming data from parent
|
|
183
|
+
process.stdin.on('data', async(data: Buffer): Promise<void> => {
|
|
184
|
+
const messages = this.messageBuffer.addData(data.toString());
|
|
185
|
+
|
|
186
|
+
for (const messageData of messages) {
|
|
187
|
+
await this.handleIncomingMessage(messageData);
|
|
188
|
+
}
|
|
189
|
+
});
|
|
190
|
+
|
|
191
|
+
// Handle process termination gracefully
|
|
192
|
+
process.on('SIGTERM', (): void => {
|
|
193
|
+
this.close().finally((): void => process.exit(0));
|
|
194
|
+
});
|
|
195
|
+
|
|
196
|
+
process.on('SIGINT', (): void => {
|
|
197
|
+
this.close().finally((): void => process.exit(0));
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
/**
|
|
202
|
+
* Handle incoming message and route to appropriate handler
|
|
203
|
+
*/
|
|
204
|
+
private async handleIncomingMessage(messageData: string): Promise<void> {
|
|
205
|
+
try {
|
|
206
|
+
const message = JSON.parse(messageData);
|
|
207
|
+
|
|
208
|
+
// Check if this is a response to our request (has 'result' or 'error' and 'id')
|
|
209
|
+
if (isResponse(message)) {
|
|
210
|
+
// This is a response to a request we made - route to client
|
|
211
|
+
this.logger.log(`Routing response to client: ${message.id}`);
|
|
212
|
+
await this.client.handleIncomingMessage(messageData);
|
|
213
|
+
} else {
|
|
214
|
+
// This is a request or notification for us - route to server
|
|
215
|
+
this.logger.log(`Routing request to server: ${message.method}`);
|
|
216
|
+
const response = await this.server.processMessage(messageData);
|
|
217
|
+
this.logger.log('Sending response to parent process', response);
|
|
218
|
+
// Only send response if there is one (requests get responses, notifications don't)
|
|
219
|
+
if (response) {
|
|
220
|
+
this.sendMessage(JSON.stringify(response));
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
} catch (error: unknown) {
|
|
224
|
+
process.stderr.write(`Error processing message: ${(error as Error).message}\n`);
|
|
225
|
+
this.emit('error', error);
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Send a message to the parent process
|
|
231
|
+
*/
|
|
232
|
+
private sendMessage(message: string): void {
|
|
233
|
+
this.logger.log(`Sending: ${message}`);
|
|
234
|
+
process.stdout.write(`${message}\n`);
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* Set up event handlers
|
|
239
|
+
*/
|
|
240
|
+
private setupEventHandlers(): void {
|
|
241
|
+
this.server.on('error', (error: Error): void => {
|
|
242
|
+
this.logger.error('Server error', error);
|
|
243
|
+
this.emit('error', error);
|
|
244
|
+
});
|
|
245
|
+
|
|
246
|
+
this.client.on('error', (error: Error): void => {
|
|
247
|
+
this.logger.error('Client error', error);
|
|
248
|
+
this.emit('error', error);
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
}
|
|
@@ -0,0 +1,308 @@
|
|
|
1
|
+
import { Logger } from '../../../logger';
|
|
2
|
+
import type { ClientTransport } from '../../jsonRpc/JsonRpcClient';
|
|
3
|
+
import { JsonRpcClient } from '../../jsonRpc/JsonRpcClient';
|
|
4
|
+
import type { JsonRpcServer } from '../../jsonRpc/JsonRpcServer';
|
|
5
|
+
import type { LogNotification, StatusRequest, StatusResponse } from '../../jsonRpc/types';
|
|
6
|
+
import { STANDARD_METHODS } from '../../jsonRpc/types';
|
|
7
|
+
import type { ExecutionOptions } from '../../types';
|
|
8
|
+
import { BaseTransport } from '../base/BaseTransport';
|
|
9
|
+
import { ProcessManager } from '../process/ProcessManager';
|
|
10
|
+
import type { TransportConfig } from '../Transport';
|
|
11
|
+
import { TransportStatus } from '../Transport';
|
|
12
|
+
import { isResponse, MessageBuffer } from '../utils/MessageUtils';
|
|
13
|
+
import { pollUntilSuccess } from '../utils/PollingUtils';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Client transport implementation for stdio communication
|
|
17
|
+
*/
|
|
18
|
+
export class StdioClientTransport implements ClientTransport {
|
|
19
|
+
private messageHandler?: (message: string) => void;
|
|
20
|
+
private name?: string;
|
|
21
|
+
private readonly logger = Logger.getInstance();
|
|
22
|
+
|
|
23
|
+
public constructor(private readonly processManager: ProcessManager) {}
|
|
24
|
+
|
|
25
|
+
public setName(name: string): void {
|
|
26
|
+
this.name = name;
|
|
27
|
+
this.logger.setMetadata({ name, transport: 'StdioClientTransport' });
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
public async send(message: string): Promise<void> {
|
|
31
|
+
this.logger.log('Sending message', message);
|
|
32
|
+
this.processManager.write(`${message}\n`);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
public onMessage(handler: (message: string) => void): void {
|
|
36
|
+
this.messageHandler = handler;
|
|
37
|
+
// Note: Message handling is done in the main ParentStdioTransport class
|
|
38
|
+
// This is here for interface compliance
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
public async close(): Promise<void> {
|
|
42
|
+
this.messageHandler = undefined;
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* StdioTransport implementation for parent process communication with child
|
|
48
|
+
* This is the parent-side transport that manages a child process
|
|
49
|
+
*/
|
|
50
|
+
export class ParentStdioTransport extends BaseTransport {
|
|
51
|
+
private readonly processManager = new ProcessManager();
|
|
52
|
+
private readonly server: JsonRpcServer;
|
|
53
|
+
private readonly client: JsonRpcClient;
|
|
54
|
+
private readonly clientTransport: StdioClientTransport;
|
|
55
|
+
private readonly executorScriptPath: string;
|
|
56
|
+
private readonly messageBuffer = new MessageBuffer();
|
|
57
|
+
|
|
58
|
+
public constructor(executorScriptPath: string, server: JsonRpcServer) {
|
|
59
|
+
super();
|
|
60
|
+
this.executorScriptPath = executorScriptPath;
|
|
61
|
+
this.server = server;
|
|
62
|
+
this.client = new JsonRpcClient({
|
|
63
|
+
// 1 hour
|
|
64
|
+
defaultTimeout: 60 * 60 * 1000
|
|
65
|
+
});
|
|
66
|
+
this.clientTransport = new StdioClientTransport(this.processManager);
|
|
67
|
+
|
|
68
|
+
this.setupServerMethods();
|
|
69
|
+
this.setupEventHandlers();
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* Initialize the transport connection
|
|
74
|
+
*/
|
|
75
|
+
public async initialize(config?: TransportConfig, executionOptions?: ExecutionOptions): Promise<void> {
|
|
76
|
+
if (this.internalStatus !== TransportStatus.disconnected) {
|
|
77
|
+
throw new Error(`Cannot initialize transport in ${this.internalStatus} state`);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
try {
|
|
81
|
+
this.setStatus(TransportStatus.connecting);
|
|
82
|
+
|
|
83
|
+
// Set up client transport
|
|
84
|
+
this.client.setTransport(this.clientTransport);
|
|
85
|
+
|
|
86
|
+
// Spawn the process
|
|
87
|
+
// Use spawnTimeout if provided, otherwise fall back to timeout or default
|
|
88
|
+
const spawnTimeout = config?.spawnTimeout ?? config?.timeout ?? 3000;
|
|
89
|
+
await this.processManager.spawn({
|
|
90
|
+
scriptPath: this.executorScriptPath,
|
|
91
|
+
executionOptions,
|
|
92
|
+
startupTimeout: spawnTimeout
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
// Set up process communication
|
|
96
|
+
this.setupProcessCommunication();
|
|
97
|
+
|
|
98
|
+
// Wait for process to be ready
|
|
99
|
+
// Use readyTimeout if provided, otherwise fall back to timeout or default
|
|
100
|
+
const readyTimeout = config?.readyTimeout ?? config?.timeout ?? 10000;
|
|
101
|
+
await this.waitForReady(readyTimeout);
|
|
102
|
+
|
|
103
|
+
this.setStatus(TransportStatus.connected);
|
|
104
|
+
} catch (error: unknown) {
|
|
105
|
+
this.setStatus(TransportStatus.error);
|
|
106
|
+
throw error;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Send a message through the transport
|
|
112
|
+
*/
|
|
113
|
+
public async send<TRequest, TResponse>(message: TRequest): Promise<TResponse> {
|
|
114
|
+
if (!this.isReady()) {
|
|
115
|
+
throw new Error('Transport is not ready');
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Expect message to have method and params for direct RPC calls
|
|
119
|
+
const rpcMessage = message as any;
|
|
120
|
+
if (rpcMessage.method) {
|
|
121
|
+
return this.client.request(rpcMessage.method, rpcMessage.params);
|
|
122
|
+
}
|
|
123
|
+
throw new Error('Message must have a method property for RPC calls');
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Make a direct RPC request to the child process
|
|
128
|
+
*/
|
|
129
|
+
public async request<TParams = any, TResult = any>(
|
|
130
|
+
method: string,
|
|
131
|
+
params?: TParams,
|
|
132
|
+
options?: { timeout?: number; retries?: number }
|
|
133
|
+
): Promise<TResult> {
|
|
134
|
+
if (!this.isReady()) {
|
|
135
|
+
throw new Error('Transport is not ready');
|
|
136
|
+
}
|
|
137
|
+
return this.client.request<TParams, TResult>(method, params, options);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Send a notification to the child process (no response expected)
|
|
142
|
+
*/
|
|
143
|
+
public async notify<TParams = any>(method: string, params?: TParams): Promise<void> {
|
|
144
|
+
if (!this.isReady()) {
|
|
145
|
+
throw new Error('Transport is not ready');
|
|
146
|
+
}
|
|
147
|
+
return this.client.notify(method, params);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Close the transport connection
|
|
152
|
+
*/
|
|
153
|
+
public async close(): Promise<void> {
|
|
154
|
+
if (this.internalStatus === TransportStatus.disconnected) {
|
|
155
|
+
return;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
this.setStatus(TransportStatus.disconnected);
|
|
159
|
+
|
|
160
|
+
// Close JSON-RPC client
|
|
161
|
+
await this.client.close();
|
|
162
|
+
|
|
163
|
+
// Terminate child process
|
|
164
|
+
await this.processManager.terminate();
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* Check if the transport is ready for communication
|
|
169
|
+
*/
|
|
170
|
+
public isReady(): boolean {
|
|
171
|
+
return this.internalStatus === TransportStatus.connected && this.processManager.isRunning();
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Set up server methods for handling incoming requests from Deno process
|
|
176
|
+
*/
|
|
177
|
+
private setupServerMethods(): void {
|
|
178
|
+
// Handle status requests
|
|
179
|
+
this.server.registerMethod<StatusRequest, StatusResponse>(STANDARD_METHODS.getStatus, async() => ({
|
|
180
|
+
status: 'ready',
|
|
181
|
+
uptime: process.uptime() * 1000,
|
|
182
|
+
memoryUsage: {
|
|
183
|
+
used: process.memoryUsage().heapUsed,
|
|
184
|
+
total: process.memoryUsage().heapTotal
|
|
185
|
+
}
|
|
186
|
+
}));
|
|
187
|
+
|
|
188
|
+
// Handle ping requests
|
|
189
|
+
this.server.registerMethod(STANDARD_METHODS.ping, async() => 'pong');
|
|
190
|
+
|
|
191
|
+
// Handle log notifications
|
|
192
|
+
this.server.registerMethod<LogNotification, void>(STANDARD_METHODS.log, async params => {
|
|
193
|
+
if (this.messageHandler) {
|
|
194
|
+
await this.messageHandler(params);
|
|
195
|
+
}
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* Set up event handlers
|
|
201
|
+
*/
|
|
202
|
+
private setupEventHandlers(): void {
|
|
203
|
+
this.server.on('error', error => {
|
|
204
|
+
this.emit('error', error);
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
this.client.on('error', error => {
|
|
208
|
+
this.emit('error', error);
|
|
209
|
+
});
|
|
210
|
+
|
|
211
|
+
this.processManager.on('error', error => {
|
|
212
|
+
this.emit('error', error);
|
|
213
|
+
});
|
|
214
|
+
|
|
215
|
+
this.processManager.on('exit', (code, signal) => {
|
|
216
|
+
if (this.internalStatus === TransportStatus.connected) {
|
|
217
|
+
const error = new Error(`Process exited unexpectedly (code: ${code}, signal: ${signal})`);
|
|
218
|
+
this.setStatus(TransportStatus.error);
|
|
219
|
+
this.emit('error', error);
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Set up process communication handlers
|
|
226
|
+
*/
|
|
227
|
+
private setupProcessCommunication(): void {
|
|
228
|
+
// Handle stdout data (responses from Deno process)
|
|
229
|
+
this.processManager.on('stdout', (data: Buffer) => {
|
|
230
|
+
const messages = this.messageBuffer.addData(data.toString());
|
|
231
|
+
|
|
232
|
+
for (const messageData of messages) {
|
|
233
|
+
this.logger.log('Received message', messageData);
|
|
234
|
+
this.handleIncomingMessage(messageData).catch(error => {
|
|
235
|
+
this.emit('error', error);
|
|
236
|
+
});
|
|
237
|
+
}
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Handle stderr data (log messages and errors from Deno process)
|
|
241
|
+
this.processManager.on('stderr', (data: Buffer) => {
|
|
242
|
+
const stderrOutput = data.toString().trim();
|
|
243
|
+
|
|
244
|
+
// Only treat messages starting with "ERROR:" as actual errors
|
|
245
|
+
if (stderrOutput.startsWith('ERROR:')) {
|
|
246
|
+
this.emit('error', new Error(`Deno process error: ${stderrOutput}`));
|
|
247
|
+
} else {
|
|
248
|
+
// Log normal stderr output as debug information
|
|
249
|
+
this.logger.log('Child process log', stderrOutput);
|
|
250
|
+
}
|
|
251
|
+
});
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Handle incoming message from Deno process with bidirectional routing
|
|
256
|
+
*/
|
|
257
|
+
private async handleIncomingMessage(messageData: string): Promise<void> {
|
|
258
|
+
try {
|
|
259
|
+
const message = JSON.parse(messageData);
|
|
260
|
+
|
|
261
|
+
// Check if this is a response to our request (has 'result' or 'error' and 'id')
|
|
262
|
+
if (isResponse(message)) {
|
|
263
|
+
// This is a response to a request we made - route to client
|
|
264
|
+
this.logger.log('Routing response to parent client', { id: message.id });
|
|
265
|
+
await this.client.handleIncomingMessage(messageData);
|
|
266
|
+
} else {
|
|
267
|
+
// This is a request or notification for us - route to server
|
|
268
|
+
this.logger.log('Routing request to parent server', { method: message.method, id: message.id });
|
|
269
|
+
const response = await this.server.processMessage(messageData);
|
|
270
|
+
this.logger.log('Sending response to parent process', response);
|
|
271
|
+
|
|
272
|
+
// Only send response if there is one (requests get responses, notifications don't)
|
|
273
|
+
if (response) {
|
|
274
|
+
const responseData = `${JSON.stringify(response)}\n`;
|
|
275
|
+
this.processManager.write(responseData);
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
} catch (error: unknown) {
|
|
279
|
+
// Silently ignore invalid JSON messages (likely log output from child process)
|
|
280
|
+
if (error instanceof SyntaxError && error.message.includes('JSON')) {
|
|
281
|
+
this.logger.log('Ignoring invalid JSON message', { message: messageData });
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// Re-throw other types of errors
|
|
286
|
+
this.emit('error', new Error(`Failed to handle incoming message: ${(error as Error).message}`));
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
/**
|
|
291
|
+
* Wait for the process to be ready
|
|
292
|
+
*/
|
|
293
|
+
private async waitForReady(timeout: number): Promise<void> {
|
|
294
|
+
// Use a reasonable ping timeout (1/4 of total timeout, min 500ms, max 2000ms)
|
|
295
|
+
const pingTimeout = Math.max(500, Math.min(2000, timeout / 4));
|
|
296
|
+
|
|
297
|
+
await pollUntilSuccess(
|
|
298
|
+
() => this.client.request(STANDARD_METHODS.ping, undefined, { timeout: pingTimeout }),
|
|
299
|
+
{
|
|
300
|
+
timeout,
|
|
301
|
+
interval: 100,
|
|
302
|
+
// Let process start before first ping
|
|
303
|
+
initialDelay: 100
|
|
304
|
+
},
|
|
305
|
+
'Transport initialization timed out'
|
|
306
|
+
);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import type { JsonRpcResponse } from '../../jsonRpc/types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Safely parse a JSON message, returning undefined if parsing fails
|
|
5
|
+
* @param message - String message to parse
|
|
6
|
+
* @returns Parsed object or undefined if invalid JSON
|
|
7
|
+
*/
|
|
8
|
+
export function safeParse(message: string): any {
|
|
9
|
+
try {
|
|
10
|
+
return JSON.parse(message);
|
|
11
|
+
} catch {
|
|
12
|
+
return undefined;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Check if a message is a JSON-RPC response (vs request/notification)
|
|
18
|
+
* @param message - Parsed message object
|
|
19
|
+
* @returns True if message is a response
|
|
20
|
+
*/
|
|
21
|
+
export function isResponse(message: any): boolean {
|
|
22
|
+
return message &&
|
|
23
|
+
typeof message === 'object' &&
|
|
24
|
+
('result' in message || 'error' in message) &&
|
|
25
|
+
'id' in message &&
|
|
26
|
+
!('method' in message);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Check if a message is a JSON-RPC request
|
|
31
|
+
* @param message - Parsed message object
|
|
32
|
+
* @returns True if message is a request
|
|
33
|
+
*/
|
|
34
|
+
export function isRequest(message: any): boolean {
|
|
35
|
+
return message &&
|
|
36
|
+
typeof message === 'object' &&
|
|
37
|
+
'method' in message &&
|
|
38
|
+
'id' in message;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if a message is a JSON-RPC notification
|
|
43
|
+
* @param message - Parsed message object
|
|
44
|
+
* @returns True if message is a notification
|
|
45
|
+
*/
|
|
46
|
+
export function isNotification(message: any): boolean {
|
|
47
|
+
return message &&
|
|
48
|
+
typeof message === 'object' &&
|
|
49
|
+
'method' in message &&
|
|
50
|
+
!('id' in message);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Create a JSON-RPC error response
|
|
55
|
+
* @param id - Request ID
|
|
56
|
+
* @param code - Error code
|
|
57
|
+
* @param message - Error message
|
|
58
|
+
* @param data - Optional error data
|
|
59
|
+
* @returns JSON-RPC error response object
|
|
60
|
+
*/
|
|
61
|
+
export function createErrorResponse(
|
|
62
|
+
id: string | number | null,
|
|
63
|
+
code: number,
|
|
64
|
+
message: string,
|
|
65
|
+
data?: any
|
|
66
|
+
): JsonRpcResponse {
|
|
67
|
+
return {
|
|
68
|
+
jsonrpc: '2.0',
|
|
69
|
+
id,
|
|
70
|
+
error: {
|
|
71
|
+
code,
|
|
72
|
+
message,
|
|
73
|
+
...data && { data }
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Create a JSON-RPC success response
|
|
80
|
+
* @param id - Request ID
|
|
81
|
+
* @param result - Response result
|
|
82
|
+
* @returns JSON-RPC success response object
|
|
83
|
+
*/
|
|
84
|
+
export function createSuccessResponse(id: string | number, result: any): JsonRpcResponse {
|
|
85
|
+
return {
|
|
86
|
+
jsonrpc: '2.0',
|
|
87
|
+
id,
|
|
88
|
+
result
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Validate that a message is a valid JSON-RPC message
|
|
94
|
+
* @param message - Message to validate
|
|
95
|
+
* @returns True if valid JSON-RPC message
|
|
96
|
+
*/
|
|
97
|
+
export function isValidJsonRpc(message: any): boolean {
|
|
98
|
+
return message &&
|
|
99
|
+
typeof message === 'object' &&
|
|
100
|
+
message.jsonrpc === '2.0' &&
|
|
101
|
+
(isRequest(message) || isNotification(message) || isResponse(message));
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* Buffer manager for handling streaming message data
|
|
106
|
+
*/
|
|
107
|
+
export class MessageBuffer {
|
|
108
|
+
private buffer = '';
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Add data to the buffer and extract complete messages
|
|
112
|
+
* @param data - Incoming data chunk
|
|
113
|
+
* @returns Array of complete message strings
|
|
114
|
+
*/
|
|
115
|
+
public addData(data: string): string[] {
|
|
116
|
+
this.buffer += data;
|
|
117
|
+
|
|
118
|
+
// Process complete JSON messages (newline-delimited)
|
|
119
|
+
const lines = this.buffer.split('\n');
|
|
120
|
+
// Keep incomplete line in buffer
|
|
121
|
+
this.buffer = lines.pop() ?? '';
|
|
122
|
+
|
|
123
|
+
return lines.filter((line): string => line.trim());
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Clear the buffer
|
|
128
|
+
*/
|
|
129
|
+
public clear(): void {
|
|
130
|
+
this.buffer = '';
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get current buffer content (for debugging)
|
|
135
|
+
*/
|
|
136
|
+
public getContent(): string {
|
|
137
|
+
return this.buffer;
|
|
138
|
+
}
|
|
139
|
+
}
|