@hydranium/protocol 1.0.0-next.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/LICENSE +21 -0
- package/README.md +81 -0
- package/lib/abstract-logger.d.ts +66 -0
- package/lib/abstract-logger.d.ts.map +1 -0
- package/lib/abstract-logger.js +110 -0
- package/lib/abstract-logger.js.map +1 -0
- package/lib/browser-runtime.d.ts +124 -0
- package/lib/browser-runtime.d.ts.map +1 -0
- package/lib/browser-runtime.js +11 -0
- package/lib/browser-runtime.js.map +1 -0
- package/lib/client/data-events.d.ts +49 -0
- package/lib/client/data-events.d.ts.map +1 -0
- package/lib/client/data-events.js +60 -0
- package/lib/client/data-events.js.map +1 -0
- package/lib/client/data-port.d.ts +95 -0
- package/lib/client/data-port.d.ts.map +1 -0
- package/lib/client/data-port.js +11 -0
- package/lib/client/data-port.js.map +1 -0
- package/lib/client/data-session.d.ts +129 -0
- package/lib/client/data-session.d.ts.map +1 -0
- package/lib/client/data-session.js +179 -0
- package/lib/client/data-session.js.map +1 -0
- package/lib/client/index.d.ts +39 -0
- package/lib/client/index.d.ts.map +1 -0
- package/lib/client/index.js +55 -0
- package/lib/client/index.js.map +1 -0
- package/lib/client/message-relay.d.ts +111 -0
- package/lib/client/message-relay.d.ts.map +1 -0
- package/lib/client/message-relay.js +139 -0
- package/lib/client/message-relay.js.map +1 -0
- package/lib/client/post-message-transport.d.ts +77 -0
- package/lib/client/post-message-transport.d.ts.map +1 -0
- package/lib/client/post-message-transport.js +95 -0
- package/lib/client/post-message-transport.js.map +1 -0
- package/lib/clock.d.ts +111 -0
- package/lib/clock.d.ts.map +1 -0
- package/lib/clock.js +74 -0
- package/lib/clock.js.map +1 -0
- package/lib/data/data-protocol-methods.d.ts +39 -0
- package/lib/data/data-protocol-methods.d.ts.map +1 -0
- package/lib/data/data-protocol-methods.js +61 -0
- package/lib/data/data-protocol-methods.js.map +1 -0
- package/lib/data/data-server-protocol.d.ts +264 -0
- package/lib/data/data-server-protocol.d.ts.map +1 -0
- package/lib/data/data-server-protocol.js +11 -0
- package/lib/data/data-server-protocol.js.map +1 -0
- package/lib/data/diagnostics.d.ts +97 -0
- package/lib/data/diagnostics.d.ts.map +1 -0
- package/lib/data/diagnostics.js +25 -0
- package/lib/data/diagnostics.js.map +1 -0
- package/lib/data/events.d.ts +107 -0
- package/lib/data/events.d.ts.map +1 -0
- package/lib/data/events.js +11 -0
- package/lib/data/events.js.map +1 -0
- package/lib/data/index.d.ts +15 -0
- package/lib/data/index.d.ts.map +1 -0
- package/lib/data/index.js +38 -0
- package/lib/data/index.js.map +1 -0
- package/lib/data/methods.d.ts +57 -0
- package/lib/data/methods.d.ts.map +1 -0
- package/lib/data/methods.js +60 -0
- package/lib/data/methods.js.map +1 -0
- package/lib/data/requests.d.ts +65 -0
- package/lib/data/requests.d.ts.map +1 -0
- package/lib/data/requests.js +11 -0
- package/lib/data/requests.js.map +1 -0
- package/lib/debouncer.d.ts +75 -0
- package/lib/debouncer.d.ts.map +1 -0
- package/lib/debouncer.js +91 -0
- package/lib/debouncer.js.map +1 -0
- package/lib/errors.d.ts +84 -0
- package/lib/errors.d.ts.map +1 -0
- package/lib/errors.js +113 -0
- package/lib/errors.js.map +1 -0
- package/lib/host-diagnostics.d.ts +58 -0
- package/lib/host-diagnostics.d.ts.map +1 -0
- package/lib/host-diagnostics.js +18 -0
- package/lib/host-diagnostics.js.map +1 -0
- package/lib/index.d.ts +34 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js +56 -0
- package/lib/index.js.map +1 -0
- package/lib/latency-collector.d.ts +126 -0
- package/lib/latency-collector.d.ts.map +1 -0
- package/lib/latency-collector.js +137 -0
- package/lib/latency-collector.js.map +1 -0
- package/lib/logger.d.ts +119 -0
- package/lib/logger.d.ts.map +1 -0
- package/lib/logger.js +126 -0
- package/lib/logger.js.map +1 -0
- package/lib/model-server.d.ts +352 -0
- package/lib/model-server.d.ts.map +1 -0
- package/lib/model-server.js +160 -0
- package/lib/model-server.js.map +1 -0
- package/lib/model-service/args.d.ts +64 -0
- package/lib/model-service/args.d.ts.map +1 -0
- package/lib/model-service/args.js +11 -0
- package/lib/model-service/args.js.map +1 -0
- package/lib/model-service/index.d.ts +11 -0
- package/lib/model-service/index.d.ts.map +1 -0
- package/lib/model-service/index.js +31 -0
- package/lib/model-service/index.js.map +1 -0
- package/lib/model-service/reference-candidate.d.ts +56 -0
- package/lib/model-service/reference-candidate.d.ts.map +1 -0
- package/lib/model-service/reference-candidate.js +11 -0
- package/lib/model-service/reference-candidate.js.map +1 -0
- package/lib/noop-logger.d.ts +25 -0
- package/lib/noop-logger.d.ts.map +1 -0
- package/lib/noop-logger.js +36 -0
- package/lib/noop-logger.js.map +1 -0
- package/lib/observable-value.d.ts +72 -0
- package/lib/observable-value.d.ts.map +1 -0
- package/lib/observable-value.js +52 -0
- package/lib/observable-value.js.map +1 -0
- package/lib/patch-merge.d.ts +123 -0
- package/lib/patch-merge.d.ts.map +1 -0
- package/lib/patch-merge.js +104 -0
- package/lib/patch-merge.js.map +1 -0
- package/lib/profile-session.d.ts +87 -0
- package/lib/profile-session.d.ts.map +1 -0
- package/lib/profile-session.js +98 -0
- package/lib/profile-session.js.map +1 -0
- package/lib/profiling.d.ts +83 -0
- package/lib/profiling.d.ts.map +1 -0
- package/lib/profiling.js +20 -0
- package/lib/profiling.js.map +1 -0
- package/lib/project.d.ts +121 -0
- package/lib/project.d.ts.map +1 -0
- package/lib/project.js +34 -0
- package/lib/project.js.map +1 -0
- package/lib/rpc/bind-rpc-methods.d.ts +100 -0
- package/lib/rpc/bind-rpc-methods.d.ts.map +1 -0
- package/lib/rpc/bind-rpc-methods.js +110 -0
- package/lib/rpc/bind-rpc-methods.js.map +1 -0
- package/lib/rpc/create-rpc-proxy.d.ts +188 -0
- package/lib/rpc/create-rpc-proxy.d.ts.map +1 -0
- package/lib/rpc/create-rpc-proxy.js +158 -0
- package/lib/rpc/create-rpc-proxy.js.map +1 -0
- package/lib/rpc/index.d.ts +12 -0
- package/lib/rpc/index.d.ts.map +1 -0
- package/lib/rpc/index.js +31 -0
- package/lib/rpc/index.js.map +1 -0
- package/lib/rpc/wire-prefix.d.ts +37 -0
- package/lib/rpc/wire-prefix.d.ts.map +1 -0
- package/lib/rpc/wire-prefix.js +49 -0
- package/lib/rpc/wire-prefix.js.map +1 -0
- package/lib/testing/data-doubles.d.ts +121 -0
- package/lib/testing/data-doubles.d.ts.map +1 -0
- package/lib/testing/data-doubles.js +102 -0
- package/lib/testing/data-doubles.js.map +1 -0
- package/lib/testing/fake-clock.d.ts +35 -0
- package/lib/testing/fake-clock.d.ts.map +1 -0
- package/lib/testing/fake-clock.js +86 -0
- package/lib/testing/fake-clock.js.map +1 -0
- package/lib/testing/harness.d.ts +24 -0
- package/lib/testing/harness.d.ts.map +1 -0
- package/lib/testing/harness.js +11 -0
- package/lib/testing/harness.js.map +1 -0
- package/lib/testing/index.d.ts +13 -0
- package/lib/testing/index.d.ts.map +1 -0
- package/lib/testing/index.js +41 -0
- package/lib/testing/index.js.map +1 -0
- package/lib/testing/node/duplex-connection.d.ts +25 -0
- package/lib/testing/node/duplex-connection.d.ts.map +1 -0
- package/lib/testing/node/duplex-connection.js +34 -0
- package/lib/testing/node/duplex-connection.js.map +1 -0
- package/lib/testing/node/duplex-stream.d.ts +32 -0
- package/lib/testing/node/duplex-stream.d.ts.map +1 -0
- package/lib/testing/node/duplex-stream.js +35 -0
- package/lib/testing/node/duplex-stream.js.map +1 -0
- package/lib/testing/node/index.d.ts +11 -0
- package/lib/testing/node/index.d.ts.map +1 -0
- package/lib/testing/node/index.js +37 -0
- package/lib/testing/node/index.js.map +1 -0
- package/lib/testing/wait-for.d.ts +69 -0
- package/lib/testing/wait-for.d.ts.map +1 -0
- package/lib/testing/wait-for.js +67 -0
- package/lib/testing/wait-for.js.map +1 -0
- package/lib/tracer.d.ts +115 -0
- package/lib/tracer.d.ts.map +1 -0
- package/lib/tracer.js +205 -0
- package/lib/tracer.js.map +1 -0
- package/lib/transfer-diagnostic.d.ts +73 -0
- package/lib/transfer-diagnostic.d.ts.map +1 -0
- package/lib/transfer-diagnostic.js +45 -0
- package/lib/transfer-diagnostic.js.map +1 -0
- package/lib/transfer-document.d.ts +73 -0
- package/lib/transfer-document.d.ts.map +1 -0
- package/lib/transfer-document.js +46 -0
- package/lib/transfer-document.js.map +1 -0
- package/lib/transfer-element.d.ts +39 -0
- package/lib/transfer-element.d.ts.map +1 -0
- package/lib/transfer-element.js +11 -0
- package/lib/transfer-element.js.map +1 -0
- package/lib/uri.d.ts +62 -0
- package/lib/uri.d.ts.map +1 -0
- package/lib/uri.js +28 -0
- package/lib/uri.js.map +1 -0
- package/lib/util.d.ts +147 -0
- package/lib/util.d.ts.map +1 -0
- package/lib/util.js +211 -0
- package/lib/util.js.map +1 -0
- package/package.json +100 -0
- package/src/abstract-logger.ts +120 -0
- package/src/browser-runtime.ts +135 -0
- package/src/client/data-events.ts +71 -0
- package/src/client/data-port.ts +99 -0
- package/src/client/data-session.ts +209 -0
- package/src/client/index.ts +40 -0
- package/src/client/message-relay.ts +216 -0
- package/src/client/post-message-transport.ts +167 -0
- package/src/clock.ts +173 -0
- package/src/data/data-protocol-methods.ts +79 -0
- package/src/data/data-server-protocol.ts +296 -0
- package/src/data/diagnostics.ts +116 -0
- package/src/data/events.ts +127 -0
- package/src/data/index.ts +23 -0
- package/src/data/methods.ts +59 -0
- package/src/data/requests.ts +70 -0
- package/src/debouncer.ts +118 -0
- package/src/errors.ts +127 -0
- package/src/host-diagnostics.ts +63 -0
- package/src/index.ts +41 -0
- package/src/latency-collector.ts +231 -0
- package/src/logger.ts +172 -0
- package/src/model-server.ts +479 -0
- package/src/model-service/args.ts +67 -0
- package/src/model-service/index.ts +16 -0
- package/src/model-service/reference-candidate.ts +58 -0
- package/src/noop-logger.ts +36 -0
- package/src/observable-value.ts +92 -0
- package/src/patch-merge.ts +165 -0
- package/src/profile-session.ts +164 -0
- package/src/profiling.ts +113 -0
- package/src/project.ts +125 -0
- package/src/rpc/README.md +163 -0
- package/src/rpc/bind-rpc-methods.ts +180 -0
- package/src/rpc/create-rpc-proxy.ts +292 -0
- package/src/rpc/index.ts +16 -0
- package/src/rpc/wire-prefix.ts +48 -0
- package/src/testing/data-doubles.ts +178 -0
- package/src/testing/fake-clock.ts +106 -0
- package/src/testing/harness.ts +24 -0
- package/src/testing/index.ts +26 -0
- package/src/testing/node/duplex-connection.ts +50 -0
- package/src/testing/node/duplex-stream.ts +51 -0
- package/src/testing/node/index.ts +22 -0
- package/src/testing/wait-for.ts +94 -0
- package/src/tracer.ts +277 -0
- package/src/transfer-diagnostic.ts +92 -0
- package/src/transfer-document.ts +99 -0
- package/src/transfer-element.ts +43 -0
- package/src/uri.ts +61 -0
- package/src/util.ts +250 -0
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.DefaultProfileSession = void 0;
|
|
12
|
+
const logger_1 = require("./logger");
|
|
13
|
+
/**
|
|
14
|
+
* Default {@link ProfileSession}. Times against an injected {@link Clock} (so
|
|
15
|
+
* it is fake-clock deterministic in tests, unlike a raw `performance.now`) and
|
|
16
|
+
* dumps through an injected {@link Logger}.
|
|
17
|
+
*/
|
|
18
|
+
class DefaultProfileSession {
|
|
19
|
+
logger;
|
|
20
|
+
identifier;
|
|
21
|
+
/** Single monotonic timeline for the whole session; per-scope readings are deltas off it. */
|
|
22
|
+
sessionStopwatch;
|
|
23
|
+
stack = [];
|
|
24
|
+
entries = new Map();
|
|
25
|
+
constructor(logger, clock, identifier) {
|
|
26
|
+
this.logger = logger;
|
|
27
|
+
this.identifier = identifier;
|
|
28
|
+
this.sessionStopwatch = clock.stopwatch();
|
|
29
|
+
}
|
|
30
|
+
scope(id, fn) {
|
|
31
|
+
const frame = { id, start: this.sessionStopwatch.elapsedMs, childMs: 0 };
|
|
32
|
+
this.stack.push(frame);
|
|
33
|
+
let result;
|
|
34
|
+
try {
|
|
35
|
+
result = fn();
|
|
36
|
+
}
|
|
37
|
+
catch (error) {
|
|
38
|
+
this.closeFrame(frame);
|
|
39
|
+
throw error;
|
|
40
|
+
}
|
|
41
|
+
if (result instanceof Promise) {
|
|
42
|
+
return result.then(value => {
|
|
43
|
+
this.closeFrame(frame);
|
|
44
|
+
return value;
|
|
45
|
+
}, error => {
|
|
46
|
+
this.closeFrame(frame);
|
|
47
|
+
throw error;
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
this.closeFrame(frame);
|
|
51
|
+
return result;
|
|
52
|
+
}
|
|
53
|
+
/** Pop `frame`, charge its full duration to the parent, and record its self-time. */
|
|
54
|
+
closeFrame(frame) {
|
|
55
|
+
this.stack.pop();
|
|
56
|
+
const duration = this.sessionStopwatch.elapsedMs - frame.start;
|
|
57
|
+
const parent = this.stack[this.stack.length - 1];
|
|
58
|
+
if (parent) {
|
|
59
|
+
parent.childMs += duration;
|
|
60
|
+
}
|
|
61
|
+
const selfMs = duration - frame.childMs;
|
|
62
|
+
const samples = this.entries.get(frame.id);
|
|
63
|
+
if (samples) {
|
|
64
|
+
samples.push(selfMs);
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
this.entries.set(frame.id, [selfMs]);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
records() {
|
|
71
|
+
const totalMs = this.sessionStopwatch.elapsedMs;
|
|
72
|
+
const records = [];
|
|
73
|
+
for (const [id, samples] of this.entries) {
|
|
74
|
+
const selfMs = samples.reduce((sum, value) => sum + value, 0);
|
|
75
|
+
records.push({ id, count: samples.length, selfMs, selfPct: totalMs > 0 ? (100 * selfMs) / totalMs : 0 });
|
|
76
|
+
}
|
|
77
|
+
return records.sort((left, right) => right.selfMs - left.selfMs);
|
|
78
|
+
}
|
|
79
|
+
report(logLevel = 'debug') {
|
|
80
|
+
if (logLevel === 'off' || !logger_1.Logger.isLevelEnabled(logLevel)) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
const totalMs = this.sessionStopwatch.elapsedMs;
|
|
84
|
+
const records = this.records();
|
|
85
|
+
const emit = this.logger[logLevel].bind(this.logger);
|
|
86
|
+
for (const record of records) {
|
|
87
|
+
emit(`[profile ${this.identifier}] ${record.id} ×${record.count} ${Math.round(record.selfPct)}% ${logger_1.Format.elapsed(record.selfMs)}`);
|
|
88
|
+
}
|
|
89
|
+
const accountedMs = records.reduce((sum, record) => sum + record.selfMs, 0);
|
|
90
|
+
const unaccountedMs = totalMs - accountedMs;
|
|
91
|
+
if (unaccountedMs >= 0.5) {
|
|
92
|
+
const pct = totalMs > 0 ? Math.round((100 * unaccountedMs) / totalMs) : 0;
|
|
93
|
+
emit(`[profile ${this.identifier}] (unaccounted) ${pct}% ${logger_1.Format.elapsed(unaccountedMs)}`);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
exports.DefaultProfileSession = DefaultProfileSession;
|
|
98
|
+
//# sourceMappingURL=profile-session.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profile-session.js","sourceRoot":"","sources":["../src/profile-session.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/** Which dimensions to capture, and the two sampling knobs. All off by default. */
|
|
10
|
+
export interface ProfileCaptureOptions {
|
|
11
|
+
cpu?: boolean;
|
|
12
|
+
allocation?: boolean;
|
|
13
|
+
gc?: boolean;
|
|
14
|
+
eventLoopDelay?: boolean;
|
|
15
|
+
/** Also drop a retained `.heapsnapshot` at stop (for the memory analyzer). */
|
|
16
|
+
heapSnapshot?: boolean;
|
|
17
|
+
/** CPU sampling interval in µs (implementation default 1000). */
|
|
18
|
+
cpuIntervalMicros?: number;
|
|
19
|
+
/** Allocation sampling interval in bytes (implementation default 32768). */
|
|
20
|
+
allocationIntervalBytes?: number;
|
|
21
|
+
}
|
|
22
|
+
export declare const PROFILING_SCHEMA_VERSION = 1;
|
|
23
|
+
/**
|
|
24
|
+
* The locked, origin-first artefact kinds (the kind equals the artefact's filename stem).
|
|
25
|
+
* A closed union so a producer cannot emit a stale or typo'd kind and still
|
|
26
|
+
* compile — the drift the naming scheme forbids.
|
|
27
|
+
*/
|
|
28
|
+
export type ProfilingArtifactKind = 'server-cpu' | 'server-alloc' | 'server-heap' | 'server-summary' | 'server-latency' | 'server-ast' | 'server-memory-report' | 'server-log' | 'browser-runtime' | 'browser-timeline' | 'browser-heap' | 'browser-console';
|
|
29
|
+
/** One entry in the manifest — a captured file plus enough context for a skill to know what it is. */
|
|
30
|
+
export interface ProfilingArtifact {
|
|
31
|
+
/** The artefact's origin-first kind; equals its filename stem. */
|
|
32
|
+
kind: ProfilingArtifactKind;
|
|
33
|
+
/** Path relative to the manifest (the artefact lives beside it in the session directory). */
|
|
34
|
+
path: string;
|
|
35
|
+
/** The window the artefact was captured in, when it is window-scoped. */
|
|
36
|
+
window?: string;
|
|
37
|
+
/** Pointer to a compact digest file for a heavy artefact (added by the digest emitters). */
|
|
38
|
+
digest?: string;
|
|
39
|
+
}
|
|
40
|
+
/** What a skill reads to know what to expect from a run (browser entries only in `app` mode, etc.). */
|
|
41
|
+
export interface ProfilingEnvironment {
|
|
42
|
+
mode: 'harness' | 'app';
|
|
43
|
+
/** Whether a cgroup memory controller is present (running in a pod) vs local. */
|
|
44
|
+
container: boolean;
|
|
45
|
+
commit?: string;
|
|
46
|
+
workspace?: string;
|
|
47
|
+
node: string;
|
|
48
|
+
windows: {
|
|
49
|
+
label: string;
|
|
50
|
+
ms: number;
|
|
51
|
+
}[];
|
|
52
|
+
}
|
|
53
|
+
/** The `manifest.json` contents — the index over one run's artefacts. */
|
|
54
|
+
export interface ProfilingManifest {
|
|
55
|
+
/**
|
|
56
|
+
* Always {@link PROFILING_SCHEMA_VERSION} as written; declared as `number`
|
|
57
|
+
* because a READER may be newer than the run it is opening. Check it before
|
|
58
|
+
* trusting any field — an older manifest can be missing fields this
|
|
59
|
+
* declaration says are required.
|
|
60
|
+
*/
|
|
61
|
+
schemaVersion: number;
|
|
62
|
+
/**
|
|
63
|
+
* Names the session directory the manifest sits in, so it identifies a run
|
|
64
|
+
* without carrying an absolute path. Unique per run by construction (a
|
|
65
|
+
* timestamp when the caller supplies none), but nothing enforces that a
|
|
66
|
+
* caller-supplied id is not reused.
|
|
67
|
+
*/
|
|
68
|
+
sessionId: string;
|
|
69
|
+
/**
|
|
70
|
+
* What the run was captured against — needed to know which artefacts to
|
|
71
|
+
* expect at all, since the browser kinds only occur in `app` mode, and to
|
|
72
|
+
* know whether two runs are comparable.
|
|
73
|
+
*/
|
|
74
|
+
environment: ProfilingEnvironment;
|
|
75
|
+
/**
|
|
76
|
+
* Every file written beside the manifest. Presence is the only signal that a
|
|
77
|
+
* dimension was captured: an artefact for a dimension that was not requested
|
|
78
|
+
* is absent rather than empty, and a kind may occur more than once when the
|
|
79
|
+
* run has several windows.
|
|
80
|
+
*/
|
|
81
|
+
artifacts: ProfilingArtifact[];
|
|
82
|
+
}
|
|
83
|
+
//# sourceMappingURL=profiling.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiling.d.ts","sourceRoot":"","sources":["../src/profiling.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAUlF,mFAAmF;AACnF,MAAM,WAAW,qBAAqB;IACnC,GAAG,CAAC,EAAE,OAAO,CAAC;IACd,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,EAAE,CAAC,EAAE,OAAO,CAAC;IACb,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,8EAA8E;IAC9E,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iEAAiE;IACjE,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,4EAA4E;IAC5E,uBAAuB,CAAC,EAAE,MAAM,CAAC;CACnC;AAUD,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C;;;;GAIG;AACH,MAAM,MAAM,qBAAqB,GAC5B,YAAY,GACZ,cAAc,GACd,aAAa,GACb,gBAAgB,GAChB,gBAAgB,GAChB,YAAY,GACZ,sBAAsB,GACtB,YAAY,GACZ,iBAAiB,GACjB,kBAAkB,GAClB,cAAc,GACd,iBAAiB,CAAC;AAEvB,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAC/B,kEAAkE;IAClE,IAAI,EAAE,qBAAqB,CAAC;IAC5B,6FAA6F;IAC7F,IAAI,EAAE,MAAM,CAAC;IACb,yEAAyE;IACzE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,4FAA4F;IAC5F,MAAM,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,uGAAuG;AACvG,MAAM,WAAW,oBAAoB;IAClC,IAAI,EAAE,SAAS,GAAG,KAAK,CAAC;IACxB,iFAAiF;IACjF,SAAS,EAAE,OAAO,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,EAAE,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C;AAED,yEAAyE;AACzE,MAAM,WAAW,iBAAiB;IAC/B;;;;;OAKG;IACH,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;OAKG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB;;;;OAIG;IACH,WAAW,EAAE,oBAAoB,CAAC;IAClC;;;;;OAKG;IACH,SAAS,EAAE,iBAAiB,EAAE,CAAC;CACjC"}
|
package/lib/profiling.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.PROFILING_SCHEMA_VERSION = void 0;
|
|
12
|
+
/*
|
|
13
|
+
* The manifest schema — the self-describing index over one profiling run's
|
|
14
|
+
* artefacts. It lives in `protocol` (not the Node-only `ProfilingRun` that writes
|
|
15
|
+
* it) so both the server-side assembler AND a Playwright-side assembler can share
|
|
16
|
+
* the shape without a `node`-only dependency chain. `ProfilingRun` re-exports
|
|
17
|
+
* these from `@hydranium/core/node`.
|
|
18
|
+
*/
|
|
19
|
+
exports.PROFILING_SCHEMA_VERSION = 1;
|
|
20
|
+
//# sourceMappingURL=profiling.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"profiling.js","sourceRoot":"","sources":["../src/profiling.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAwBlF;;;;;;GAMG;AAEU,QAAA,wBAAwB,GAAG,CAAC,CAAC"}
|
package/lib/project.d.ts
ADDED
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
/**
|
|
10
|
+
* Cross-cutting domain type for the project tier — a descriptor-discovered,
|
|
11
|
+
* optionally versioned and dependency-aware sub-grouping of model files
|
|
12
|
+
* inside an LSP workspace folder.
|
|
13
|
+
*
|
|
14
|
+
* Owned by `@hydranium/protocol` (rather than `@hydranium/core`) so
|
|
15
|
+
* protocol consumers — including browser-bundle frontend code that
|
|
16
|
+
* imports the typed data-server proxy — pull this type without
|
|
17
|
+
* transitively depending on Langium. The `Project` shape is the structural
|
|
18
|
+
* baseline both the framework's runtime project tier (`ProjectManager` in
|
|
19
|
+
* `@hydranium/core`) and its wire-level surface (`DataServerProtocol`
|
|
20
|
+
* methods returning projects) agree on; collapsing them into one
|
|
21
|
+
* type eliminates a duplicate definition that would otherwise drift.
|
|
22
|
+
*
|
|
23
|
+
* **Project tier rationale.** Sits at a tier Langium itself deliberately
|
|
24
|
+
* does not provide. Langium's `WorkspaceManager` indexes all files in all
|
|
25
|
+
* workspace folders into one flat global scope; the maintainers have
|
|
26
|
+
* on-record stated they intend to keep it that way — see
|
|
27
|
+
* [Discussion #1375 — *Multiple Languages from different Projects*](https://github.com/eclipse-langium/langium/discussions/1375).
|
|
28
|
+
* This framework fills that gap so consumers don't have to reinvent it.
|
|
29
|
+
* Consumers that don't need projects bind `SingleProjectManager` and pay
|
|
30
|
+
* no cost — one synthetic project at runtime, no descriptor tracking,
|
|
31
|
+
* no events.
|
|
32
|
+
*
|
|
33
|
+
* **Extension model.** Adopters with richer per-project metadata declare a
|
|
34
|
+
* subtype `interface MyProject extends Project { ... }` and parameterise
|
|
35
|
+
* `ProjectManager<MyProject>` / `DataServer<TRoot, TDiagnostic, MyProject>`.
|
|
36
|
+
* The framework's structural read from a project is `id` (registry key,
|
|
37
|
+
* dependency-graph identity) plus optionally `dependencies` (visibility-
|
|
38
|
+
* closure walk); every other field is either wire metadata (`version`) or
|
|
39
|
+
* adopter-specific extension carried transparently through the typed
|
|
40
|
+
* surface. The framework imposes no format on extension fields — they
|
|
41
|
+
* ride on the JSON-RPC envelope as additional properties when crossing
|
|
42
|
+
* the wire.
|
|
43
|
+
*/
|
|
44
|
+
export interface Project {
|
|
45
|
+
/**
|
|
46
|
+
* Stable, unique identifier. Used as the lookup key in
|
|
47
|
+
* `ProjectManager.getProjectById` and as the value in
|
|
48
|
+
* {@link dependencies} entries that point at this project.
|
|
49
|
+
* Conventionally a name-plus-version string (e.g.
|
|
50
|
+
* `"example-dwh@1.0.0"`), but the framework imposes no format — any
|
|
51
|
+
* non-empty string works.
|
|
52
|
+
*
|
|
53
|
+
* The framework's internal identifier — map keys, visibility-set
|
|
54
|
+
* membership, dependency-declaration matching. Distinct from the
|
|
55
|
+
* user-facing {@link referenceName}; see there for why they are separate.
|
|
56
|
+
*/
|
|
57
|
+
readonly id: string;
|
|
58
|
+
/**
|
|
59
|
+
* User-facing prefix used in qualified-name references that cross
|
|
60
|
+
* project boundaries. Composed by `NameProvider.getProjectQualifiedName`
|
|
61
|
+
* to produce the workspace-unique form that the linker resolves
|
|
62
|
+
* cross-project references against; emitted as the name of the
|
|
63
|
+
* `TieredAstNodeDescription` produced by
|
|
64
|
+
* `HydraniumScopeComputation.addExportedSymbol` when the project-
|
|
65
|
+
* qualified form differs from the document-qualified form.
|
|
66
|
+
*
|
|
67
|
+
* Set to {@link UNQUALIFIED_PROJECT_REFERENCE} (`''`) to contribute no
|
|
68
|
+
* prefix at all — see that constant for the semantics.
|
|
69
|
+
*
|
|
70
|
+
* **Why this is a separate field from {@link id}.** Two reasons:
|
|
71
|
+
* 1. Versioned ids (e.g. `"example-dwh@1.0.0"`) need un-versioned
|
|
72
|
+
* names in reference syntax (`example-dwh.User.email`) — the
|
|
73
|
+
* version pinning only matters for dependency declarations.
|
|
74
|
+
* 2. Names with grammar-illegal characters (dots, spaces) need
|
|
75
|
+
* sanitisation. The framework cannot safely sanitise {@link id}
|
|
76
|
+
* (it would break dependency matching); a separate field lets
|
|
77
|
+
* adopters sanitise once at parse time.
|
|
78
|
+
*/
|
|
79
|
+
readonly referenceName: string;
|
|
80
|
+
/**
|
|
81
|
+
* Optional semantic version of the project. Distinct from {@link id}
|
|
82
|
+
* because two versions of the same logical project are different
|
|
83
|
+
* projects (different {@link id}s) — `version` is metadata for tooling /
|
|
84
|
+
* display / version-matched dependency declarations, not part of
|
|
85
|
+
* identity. The framework does not read this field internally; it
|
|
86
|
+
* passes through to clients as-is.
|
|
87
|
+
*/
|
|
88
|
+
readonly version?: string;
|
|
89
|
+
/**
|
|
90
|
+
* Ids of other projects this project explicitly depends on. Concrete
|
|
91
|
+
* `ProjectManager` implementations decide what "depends on" means
|
|
92
|
+
* and combine these into the visibility closure via
|
|
93
|
+
* `ProjectManager.getVisibleProjects` — the framework default in
|
|
94
|
+
* `AbstractProjectManager` walks them transitively; adopters can
|
|
95
|
+
* override.
|
|
96
|
+
*/
|
|
97
|
+
readonly dependencies?: readonly string[];
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Sentinel value for {@link Project.referenceName} indicating the
|
|
101
|
+
* project does not prefix its names with a reference segment. Names
|
|
102
|
+
* from such projects contribute to the workspace-wide namespace as-is —
|
|
103
|
+
* `NameProvider.getProjectQualifiedName` collapses to
|
|
104
|
+
* `getDocumentQualifiedName`, and `HydraniumScopeComputation` emits a
|
|
105
|
+
* single description per node (no separate `tier: 'public'` entry,
|
|
106
|
+
* since it would carry the same name).
|
|
107
|
+
*
|
|
108
|
+
* Typical use:
|
|
109
|
+
* - `SingleProjectManager` workspaces (no inter-project disambiguation
|
|
110
|
+
* needed — there is only one project, the synthetic workspace project).
|
|
111
|
+
* - Adopters whose grammar has no qualified-name reference syntax (e.g.
|
|
112
|
+
* class references written as bare `[Class:ID]` tokens at the framework
|
|
113
|
+
* boundary; per-package projects all bind this sentinel).
|
|
114
|
+
*
|
|
115
|
+
* The empty string is chosen so that `referenceName + nameSeparator + name`
|
|
116
|
+
* compositions detect the unqualified case without an explicit null
|
|
117
|
+
* check on the consumer side — but for predicate readability prefer
|
|
118
|
+
* `ProjectManager.isUnqualifiedProjectReference(uri)`.
|
|
119
|
+
*/
|
|
120
|
+
export declare const UNQUALIFIED_PROJECT_REFERENCE = "";
|
|
121
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAkCG;AACH,MAAM,WAAW,OAAO;IACrB;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAEpB;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAE/B;;;;;;;OAOG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,MAAM,CAAC;IAE1B;;;;;;;OAOG;IACH,QAAQ,CAAC,YAAY,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;CAC5C;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,6BAA6B,KAAK,CAAC"}
|
package/lib/project.js
ADDED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.UNQUALIFIED_PROJECT_REFERENCE = void 0;
|
|
12
|
+
/**
|
|
13
|
+
* Sentinel value for {@link Project.referenceName} indicating the
|
|
14
|
+
* project does not prefix its names with a reference segment. Names
|
|
15
|
+
* from such projects contribute to the workspace-wide namespace as-is —
|
|
16
|
+
* `NameProvider.getProjectQualifiedName` collapses to
|
|
17
|
+
* `getDocumentQualifiedName`, and `HydraniumScopeComputation` emits a
|
|
18
|
+
* single description per node (no separate `tier: 'public'` entry,
|
|
19
|
+
* since it would carry the same name).
|
|
20
|
+
*
|
|
21
|
+
* Typical use:
|
|
22
|
+
* - `SingleProjectManager` workspaces (no inter-project disambiguation
|
|
23
|
+
* needed — there is only one project, the synthetic workspace project).
|
|
24
|
+
* - Adopters whose grammar has no qualified-name reference syntax (e.g.
|
|
25
|
+
* class references written as bare `[Class:ID]` tokens at the framework
|
|
26
|
+
* boundary; per-package projects all bind this sentinel).
|
|
27
|
+
*
|
|
28
|
+
* The empty string is chosen so that `referenceName + nameSeparator + name`
|
|
29
|
+
* compositions detect the unqualified case without an explicit null
|
|
30
|
+
* check on the consumer side — but for predicate readability prefer
|
|
31
|
+
* `ProjectManager.isUnqualifiedProjectReference(uri)`.
|
|
32
|
+
*/
|
|
33
|
+
exports.UNQUALIFIED_PROJECT_REFERENCE = '';
|
|
34
|
+
//# sourceMappingURL=project.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.js","sourceRoot":"","sources":["../src/project.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;;AAgGlF;;;;;;;;;;;;;;;;;;;;GAoBG;AACU,QAAA,6BAA6B,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
/********************************************************************************
|
|
2
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
3
|
+
*
|
|
4
|
+
* This program and the accompanying materials are made available under the
|
|
5
|
+
* terms of the MIT License which is available in the project root.
|
|
6
|
+
*
|
|
7
|
+
* SPDX-License-Identifier: MIT
|
|
8
|
+
********************************************************************************/
|
|
9
|
+
import type { MessageConnection } from 'vscode-jsonrpc';
|
|
10
|
+
import type { LatencyCollector } from '../latency-collector';
|
|
11
|
+
import { type Disposable } from '../util';
|
|
12
|
+
/**
|
|
13
|
+
* Options controlling how method names are translated into wire-method
|
|
14
|
+
* registrations on the supplied connection. The defaults match
|
|
15
|
+
* `createRpcProxy` so the two helpers compose cleanly: an adopter
|
|
16
|
+
* defining a contract `T` registers handlers with `bindRpcMethods(conn, target, names, opts)`
|
|
17
|
+
* on one side and a typed proxy with `createRpcProxy<T>(conn, opts)` on
|
|
18
|
+
* the other — same wire prefix, same notification heuristic, no drift.
|
|
19
|
+
*/
|
|
20
|
+
export interface BindRpcMethodsOptions {
|
|
21
|
+
/**
|
|
22
|
+
* Prefix prepended to each method name to form the JSON-RPC wire string.
|
|
23
|
+
* Defaults to the empty string.
|
|
24
|
+
*/
|
|
25
|
+
readonly methodNamespace?: string;
|
|
26
|
+
/**
|
|
27
|
+
* Predicate to discriminate notification methods from request methods.
|
|
28
|
+
* Notification methods register with `connection.onNotification`;
|
|
29
|
+
* request methods register with `connection.onRequest`. Default: `on`
|
|
30
|
+
* followed by an uppercase letter marks a notification, matching
|
|
31
|
+
* `createRpcProxy`.
|
|
32
|
+
*/
|
|
33
|
+
readonly isNotification?: (methodName: string) => boolean;
|
|
34
|
+
/**
|
|
35
|
+
* When `true` (the default), every name in `methodNames` MUST exist
|
|
36
|
+
* as a function on `target` — missing names throw at attach time. This
|
|
37
|
+
* catches typos in adopter-supplied `additionalMethods` arrays where
|
|
38
|
+
* the names are string literals.
|
|
39
|
+
*
|
|
40
|
+
* Set to `false` to fall back to the silent-skip behaviour (useful
|
|
41
|
+
* for transitional method-name lists where some methods are not yet
|
|
42
|
+
* implemented on every target).
|
|
43
|
+
*/
|
|
44
|
+
readonly requireAll?: boolean;
|
|
45
|
+
/**
|
|
46
|
+
* Invoked when a notification handler throws. Notifications have no reply
|
|
47
|
+
* channel, so the error cannot propagate back to the caller; this hook
|
|
48
|
+
* lets a caller that holds a logger route the failure somewhere
|
|
49
|
+
* structured. Receives the wire-method name and the thrown value.
|
|
50
|
+
*
|
|
51
|
+
* Defaults to `console.error` — the protocol layer carries no logger of
|
|
52
|
+
* its own, and a caller in a process whose stdout is not the JSON-RPC
|
|
53
|
+
* transport (the framework's IPC / socket heads) can leave the default in
|
|
54
|
+
* place. Callers binding handlers over a `--stdio` LSP connection should
|
|
55
|
+
* pass a hook that routes through `connection.console` instead.
|
|
56
|
+
*/
|
|
57
|
+
readonly onNotificationError?: (wireName: string, error: unknown) => void;
|
|
58
|
+
/**
|
|
59
|
+
* When supplied, every dispatched handler is timed into this collector under
|
|
60
|
+
* its wire name (`<prefix><methodName>`) — the single RPC chokepoint the
|
|
61
|
+
* latency/throughput surface hooks, so no per-handler change is needed.
|
|
62
|
+
* Requests and notifications are both timed. Absent by default (no overhead).
|
|
63
|
+
*/
|
|
64
|
+
readonly latency?: LatencyCollector;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Register each named method on `target` as a handler on `connection`
|
|
68
|
+
* under the wire-name `<prefix><methodName>`. Notification methods (by
|
|
69
|
+
* default `on` + an uppercase letter) register as fire-and-forget listeners; request
|
|
70
|
+
* methods register as request handlers and propagate the method's return
|
|
71
|
+
* value back to the caller.
|
|
72
|
+
*
|
|
73
|
+
* The returned disposable tears down every registered handler in one call —
|
|
74
|
+
* sufficient for the framework's lifecycle: bind handlers at construction,
|
|
75
|
+
* dispose at shutdown.
|
|
76
|
+
*
|
|
77
|
+
* Method dispatch always passes the JSON-RPC `params` to the target
|
|
78
|
+
* method as a single argument. This matches the single-arg-per-method
|
|
79
|
+
* convention used throughout the framework's typed contracts — adopters
|
|
80
|
+
* defining methods with multiple positional parameters would need a
|
|
81
|
+
* different binder.
|
|
82
|
+
*
|
|
83
|
+
* Errors thrown synchronously from a request handler — or surfaced as a
|
|
84
|
+
* rejected promise — propagate back to the caller through vscode-jsonrpc's
|
|
85
|
+
* standard error envelope. Errors from a notification handler cannot, and are
|
|
86
|
+
* routed to {@link BindRpcMethodsOptions.onNotificationError} instead.
|
|
87
|
+
*
|
|
88
|
+
* Accepts either a ready connection or a `Promise<MessageConnection>` —
|
|
89
|
+
* registrations queue until the connection resolves, then attach. The
|
|
90
|
+
* returned disposable can be invoked at any time: if it fires before the
|
|
91
|
+
* connection resolves the queued work is cancelled and never attaches;
|
|
92
|
+
* if it fires afterwards the registrations dispose normally. Mirrors
|
|
93
|
+
* `createRpcProxy`'s deferred-connection pattern so adopters can wire
|
|
94
|
+
* inbound handlers in `@postConstruct` before the underlying transport
|
|
95
|
+
* exists. Wire-side safety: no notifications can arrive before
|
|
96
|
+
* `connection.listen()` runs, so a not-yet-attached handler cannot drop
|
|
97
|
+
* a real message.
|
|
98
|
+
*/
|
|
99
|
+
export declare function bindRpcMethods<T extends object>(connection: MessageConnection | Promise<MessageConnection>, target: T, methodNames: readonly (keyof T & string)[], options?: BindRpcMethodsOptions): Disposable;
|
|
100
|
+
//# sourceMappingURL=bind-rpc-methods.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind-rpc-methods.d.ts","sourceRoot":"","sources":["../../src/rpc/bind-rpc-methods.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AACxD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,KAAK,UAAU,EAAwB,MAAM,SAAS,CAAC;AAIhE;;;;;;;GAOG;AACH,MAAM,WAAW,qBAAqB;IACnC;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,CAAC;IAElC;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC,UAAU,EAAE,MAAM,KAAK,OAAO,CAAC;IAE1D;;;;;;;;;OASG;IACH,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC;IAE9B;;;;;;;;;;;OAWG;IACH,QAAQ,CAAC,mBAAmB,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAE1E;;;;;OAKG;IACH,QAAQ,CAAC,OAAO,CAAC,EAAE,gBAAgB,CAAC;CACtC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,MAAM,EAC5C,UAAU,EAAE,iBAAiB,GAAG,OAAO,CAAC,iBAAiB,CAAC,EAC1D,MAAM,EAAE,CAAC,EACT,WAAW,EAAE,SAAS,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,EAAE,EAC1C,OAAO,GAAE,qBAA0B,GACnC,UAAU,CAmEZ"}
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/********************************************************************************
|
|
3
|
+
* Copyright (c) 2026 CrossBreeze, EclipseSource and others.
|
|
4
|
+
*
|
|
5
|
+
* This program and the accompanying materials are made available under the
|
|
6
|
+
* terms of the MIT License which is available in the project root.
|
|
7
|
+
*
|
|
8
|
+
* SPDX-License-Identifier: MIT
|
|
9
|
+
********************************************************************************/
|
|
10
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
11
|
+
exports.bindRpcMethods = bindRpcMethods;
|
|
12
|
+
const util_1 = require("../util");
|
|
13
|
+
const create_rpc_proxy_1 = require("./create-rpc-proxy");
|
|
14
|
+
const wire_prefix_1 = require("./wire-prefix");
|
|
15
|
+
/**
|
|
16
|
+
* Register each named method on `target` as a handler on `connection`
|
|
17
|
+
* under the wire-name `<prefix><methodName>`. Notification methods (by
|
|
18
|
+
* default `on` + an uppercase letter) register as fire-and-forget listeners; request
|
|
19
|
+
* methods register as request handlers and propagate the method's return
|
|
20
|
+
* value back to the caller.
|
|
21
|
+
*
|
|
22
|
+
* The returned disposable tears down every registered handler in one call —
|
|
23
|
+
* sufficient for the framework's lifecycle: bind handlers at construction,
|
|
24
|
+
* dispose at shutdown.
|
|
25
|
+
*
|
|
26
|
+
* Method dispatch always passes the JSON-RPC `params` to the target
|
|
27
|
+
* method as a single argument. This matches the single-arg-per-method
|
|
28
|
+
* convention used throughout the framework's typed contracts — adopters
|
|
29
|
+
* defining methods with multiple positional parameters would need a
|
|
30
|
+
* different binder.
|
|
31
|
+
*
|
|
32
|
+
* Errors thrown synchronously from a request handler — or surfaced as a
|
|
33
|
+
* rejected promise — propagate back to the caller through vscode-jsonrpc's
|
|
34
|
+
* standard error envelope. Errors from a notification handler cannot, and are
|
|
35
|
+
* routed to {@link BindRpcMethodsOptions.onNotificationError} instead.
|
|
36
|
+
*
|
|
37
|
+
* Accepts either a ready connection or a `Promise<MessageConnection>` —
|
|
38
|
+
* registrations queue until the connection resolves, then attach. The
|
|
39
|
+
* returned disposable can be invoked at any time: if it fires before the
|
|
40
|
+
* connection resolves the queued work is cancelled and never attaches;
|
|
41
|
+
* if it fires afterwards the registrations dispose normally. Mirrors
|
|
42
|
+
* `createRpcProxy`'s deferred-connection pattern so adopters can wire
|
|
43
|
+
* inbound handlers in `@postConstruct` before the underlying transport
|
|
44
|
+
* exists. Wire-side safety: no notifications can arrive before
|
|
45
|
+
* `connection.listen()` runs, so a not-yet-attached handler cannot drop
|
|
46
|
+
* a real message.
|
|
47
|
+
*/
|
|
48
|
+
function bindRpcMethods(connection, target, methodNames, options = {}) {
|
|
49
|
+
const methodNamespace = options.methodNamespace ?? '';
|
|
50
|
+
(0, wire_prefix_1.assertValidMethodNamespace)(methodNamespace, 'bindRpcMethods');
|
|
51
|
+
const isNotification = options.isNotification ?? create_rpc_proxy_1.defaultIsNotification;
|
|
52
|
+
const requireAll = options.requireAll ?? true;
|
|
53
|
+
const onNotificationError = options.onNotificationError ??
|
|
54
|
+
((wireName, error) => console.error(`[bindRpcMethods] notification handler '${wireName}' threw:`, error));
|
|
55
|
+
const disposables = new util_1.DisposableCollection();
|
|
56
|
+
let cancelled = false;
|
|
57
|
+
const attach = (resolved) => {
|
|
58
|
+
if (cancelled) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
for (const methodName of methodNames) {
|
|
62
|
+
const wireName = methodNamespace + methodName;
|
|
63
|
+
const method = target[methodName];
|
|
64
|
+
if (typeof method !== 'function') {
|
|
65
|
+
if (requireAll) {
|
|
66
|
+
throw new Error(`bindRpcMethods: method '${methodName}' is not a function on the target. ` +
|
|
67
|
+
`Either fix the typo, implement the method, or pass { requireAll: false } to opt into silent-skip ` +
|
|
68
|
+
'for transitional method-name lists.');
|
|
69
|
+
}
|
|
70
|
+
continue;
|
|
71
|
+
}
|
|
72
|
+
const bound = method.bind(target);
|
|
73
|
+
// Time the dispatch at this one chokepoint when a collector is present.
|
|
74
|
+
const latency = options.latency;
|
|
75
|
+
const dispatch = latency ? (params) => latency.time(wireName, () => bound(params)) : bound;
|
|
76
|
+
if (isNotification(methodName)) {
|
|
77
|
+
disposables.push(resolved.onNotification(wireName, (params) => {
|
|
78
|
+
try {
|
|
79
|
+
dispatch(params);
|
|
80
|
+
}
|
|
81
|
+
catch (err) {
|
|
82
|
+
onNotificationError(wireName, err);
|
|
83
|
+
}
|
|
84
|
+
}));
|
|
85
|
+
}
|
|
86
|
+
else {
|
|
87
|
+
disposables.push(resolved.onRequest(wireName, async (params) => dispatch(params)));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
};
|
|
91
|
+
if (connection instanceof Promise) {
|
|
92
|
+
void connection
|
|
93
|
+
.then(resolved => attach(resolved))
|
|
94
|
+
.catch(() => {
|
|
95
|
+
// Connection promise rejected — treat as never-resolved; nothing
|
|
96
|
+
// to register. Adopters observe transport failures through their
|
|
97
|
+
// own connection-construction error handling.
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
else {
|
|
101
|
+
attach(connection);
|
|
102
|
+
}
|
|
103
|
+
return {
|
|
104
|
+
dispose() {
|
|
105
|
+
cancelled = true;
|
|
106
|
+
disposables.dispose();
|
|
107
|
+
}
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
//# sourceMappingURL=bind-rpc-methods.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"bind-rpc-methods.js","sourceRoot":"","sources":["../../src/rpc/bind-rpc-methods.ts"],"names":[],"mappings":";AAAA;;;;;;;kFAOkF;;AAoGlF,wCAwEC;AAxKD,kCAAgE;AAChE,yDAA2D;AAC3D,+CAA2D;AA6D3D;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgCG;AACH,SAAgB,cAAc,CAC3B,UAA0D,EAC1D,MAAS,EACT,WAA0C,EAC1C,UAAiC,EAAE;IAEnC,MAAM,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,EAAE,CAAC;IACtD,IAAA,wCAA0B,EAAC,eAAe,EAAE,gBAAgB,CAAC,CAAC;IAC9D,MAAM,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,wCAAqB,CAAC;IACvE,MAAM,UAAU,GAAG,OAAO,CAAC,UAAU,IAAI,IAAI,CAAC;IAC9C,MAAM,mBAAmB,GACtB,OAAO,CAAC,mBAAmB;QAC3B,CAAC,CAAC,QAAgB,EAAE,KAAc,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,CAAC,0CAA0C,QAAQ,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IAC9H,MAAM,WAAW,GAAG,IAAI,2BAAoB,EAAE,CAAC;IAC/C,IAAI,SAAS,GAAG,KAAK,CAAC;IAEtB,MAAM,MAAM,GAAG,CAAC,QAA2B,EAAQ,EAAE;QAClD,IAAI,SAAS,EAAE,CAAC;YACb,OAAO;QACV,CAAC;QACD,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;YACpC,MAAM,QAAQ,GAAG,eAAe,GAAG,UAAU,CAAC;YAC9C,MAAM,MAAM,GAAG,MAAM,CAAC,UAAU,CAAC,CAAC;YAClC,IAAI,OAAO,MAAM,KAAK,UAAU,EAAE,CAAC;gBAChC,IAAI,UAAU,EAAE,CAAC;oBACd,MAAM,IAAI,KAAK,CACZ,2BAA2B,UAAU,qCAAqC;wBACvE,mGAAmG;wBACnG,qCAAqC,CAC1C,CAAC;gBACL,CAAC;gBACD,SAAS;YACZ,CAAC;YACD,MAAM,KAAK,GAAI,MAAuC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACpE,wEAAwE;YACxE,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;YAChC,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAe,EAAW,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;YAE7G,IAAI,cAAc,CAAC,UAAU,CAAC,EAAE,CAAC;gBAC9B,WAAW,CAAC,IAAI,CACb,QAAQ,CAAC,cAAc,CAAC,QAAQ,EAAE,CAAC,MAAe,EAAE,EAAE;oBACnD,IAAI,CAAC;wBACF,QAAQ,CAAC,MAAM,CAAC,CAAC;oBACpB,CAAC;oBAAC,OAAO,GAAY,EAAE,CAAC;wBACrB,mBAAmB,CAAC,QAAQ,EAAE,GAAG,CAAC,CAAC;oBACtC,CAAC;gBACJ,CAAC,CAAC,CACJ,CAAC;YACL,CAAC;iBAAM,CAAC;gBACL,WAAW,CAAC,IAAI,CAAC,QAAQ,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,EAAE,MAAe,EAAE,EAAE,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC;YAC/F,CAAC;QACJ,CAAC;IACJ,CAAC,CAAC;IAEF,IAAI,UAAU,YAAY,OAAO,EAAE,CAAC;QACjC,KAAK,UAAU;aACX,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;aAClC,KAAK,CAAC,GAAG,EAAE;YACT,iEAAiE;YACjE,iEAAiE;YACjE,8CAA8C;QACjD,CAAC,CAAC,CAAC;IACT,CAAC;SAAM,CAAC;QACL,MAAM,CAAC,UAAU,CAAC,CAAC;IACtB,CAAC;IAED,OAAO;QACJ,OAAO;YACJ,SAAS,GAAG,IAAI,CAAC;YACjB,WAAW,CAAC,OAAO,EAAE,CAAC;QACzB,CAAC;KACH,CAAC;AACL,CAAC"}
|