@hydranium/data-server 1.0.0-next.42 → 1.0.0-next.421
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +62 -77
- package/lib/browser/index.d.ts +10 -0
- package/lib/browser/index.d.ts.map +1 -0
- package/lib/browser/index.js +15 -0
- package/lib/browser/index.js.map +1 -0
- package/lib/browser/start-data-server-in-worker.d.ts +23 -0
- package/lib/browser/start-data-server-in-worker.d.ts.map +1 -0
- package/lib/browser/start-data-server-in-worker.js +29 -0
- package/lib/browser/start-data-server-in-worker.js.map +1 -0
- package/lib/data-server.d.ts +411 -331
- package/lib/data-server.d.ts.map +1 -1
- package/lib/data-server.js +728 -530
- package/lib/data-server.js.map +1 -1
- package/lib/default-diagnostics.d.ts +1 -25
- package/lib/default-diagnostics.d.ts.map +1 -1
- package/lib/default-diagnostics.js +8 -27
- package/lib/default-diagnostics.js.map +1 -1
- package/lib/diagnostics-provider.d.ts +1 -1
- package/lib/messages/index.d.ts +1 -1
- package/lib/messages/index.d.ts.map +1 -1
- package/lib/messages/index.js +1 -1
- package/lib/messages/index.js.map +1 -1
- package/lib/node/node-diagnostics-provider.d.ts +18 -6
- package/lib/node/node-diagnostics-provider.d.ts.map +1 -1
- package/lib/node/node-diagnostics-provider.js +63 -20
- package/lib/node/node-diagnostics-provider.js.map +1 -1
- package/lib/testing/data-server-harness.d.ts +27 -14
- package/lib/testing/data-server-harness.d.ts.map +1 -1
- package/lib/testing/data-server-harness.js +5 -2
- package/lib/testing/data-server-harness.js.map +1 -1
- package/lib/testing/index.d.ts +1 -0
- package/lib/testing/index.d.ts.map +1 -1
- package/lib/testing/index.js.map +1 -1
- package/package.json +32 -44
- package/src/browser/index.ts +15 -0
- package/src/browser/start-data-server-in-worker.ts +35 -0
- package/src/data-server.ts +909 -592
- package/src/default-diagnostics.ts +8 -27
- package/src/diagnostics-provider.ts +1 -1
- package/src/messages/index.ts +8 -1
- package/src/node/node-diagnostics-provider.ts +73 -27
- package/src/testing/data-server-harness.ts +44 -25
- package/src/testing/index.ts +5 -2
- package/lib/default-diagnostics.browser.d.ts +0 -18
- package/lib/default-diagnostics.browser.d.ts.map +0 -1
- package/lib/default-diagnostics.browser.js +0 -36
- package/lib/default-diagnostics.browser.js.map +0 -1
- package/src/default-diagnostics.browser.ts +0 -41
|
@@ -8,33 +8,14 @@
|
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
10
|
import type { DataServerDiagnosticsProvider } from './diagnostics-provider.js';
|
|
11
|
-
import { nodeDataServerDiagnostics } from './node/node-diagnostics-provider.js';
|
|
12
11
|
|
|
13
|
-
/**
|
|
14
|
-
* Platform default for `DataServerOptions.diagnostics` — the Node one.
|
|
15
|
-
*
|
|
16
|
-
* # This file is swapped by the bundler, and that is the whole mechanism
|
|
17
|
-
*
|
|
18
|
-
* `package.json`'s `browser` field maps this module to
|
|
19
|
-
* `default-diagnostics.browser.js`, so a `platform: 'browser'` bundler never
|
|
20
|
-
* resolves it and never follows its `@hydranium/core/node` import. Node keeps
|
|
21
|
-
* it, because Node ignores the `browser` field.
|
|
22
|
-
*
|
|
23
|
-
* The alternative — reaching for the Node implementation directly from the head
|
|
24
|
-
* — is what made this package unbundleable for a browser: a static
|
|
25
|
-
* `@hydranium/core/node` import on the portable entry pulls `node:fs`,
|
|
26
|
-
* `node:v8` and `node:perf_hooks` into any browser build, over methods a
|
|
27
|
-
* browser cannot call.
|
|
28
|
-
*
|
|
29
|
-
* **`check:neutral` proves the swap works**, since it bundles this package's `.`
|
|
30
|
-
* entry for the browser and would fail on those imports if the mapping ever
|
|
31
|
-
* stopped applying. That is the same property the gate relies on for
|
|
32
|
-
* `@eclipse-glsp/server`, whose own `browser` field selects its node-free
|
|
33
|
-
* build.
|
|
34
|
-
*
|
|
35
|
-
* A host that wants to be explicit — or to supply its own — passes
|
|
36
|
-
* `diagnostics` and this default is not consulted.
|
|
37
|
-
*/
|
|
12
|
+
/** Reject privileged requests until the host explicitly supplies a diagnostics provider. */
|
|
38
13
|
export function defaultDataServerDiagnostics(): DataServerDiagnosticsProvider {
|
|
39
|
-
|
|
14
|
+
const unavailable = (): Promise<never> => Promise.reject(new Error('Server diagnostics are disabled by the host.'));
|
|
15
|
+
return {
|
|
16
|
+
dumpServerState: unavailable,
|
|
17
|
+
writeHeapSnapshot: unavailable,
|
|
18
|
+
dumpPodMemory: unavailable,
|
|
19
|
+
startProfiling: unavailable
|
|
20
|
+
};
|
|
40
21
|
}
|
|
@@ -27,7 +27,7 @@ import type { DumpServerStateArgs, StartProfilingArgs, StopProfilingArgs, WriteS
|
|
|
27
27
|
*
|
|
28
28
|
* Node hosts get the real implementation from `@hydranium/data-server/node`.
|
|
29
29
|
* Hosts that supply nothing keep the whole rest of the protocol and reject only
|
|
30
|
-
*
|
|
30
|
+
* process-inspection requests until the host explicitly authorizes them.
|
|
31
31
|
*/
|
|
32
32
|
export interface DataServerDiagnosticsProvider {
|
|
33
33
|
/**
|
package/src/messages/index.ts
CHANGED
|
@@ -16,4 +16,11 @@
|
|
|
16
16
|
* code is the contract, and renaming one is a breaking change.
|
|
17
17
|
*/
|
|
18
18
|
|
|
19
|
-
export {
|
|
19
|
+
export {
|
|
20
|
+
NO_ACTIVE_PROFILE,
|
|
21
|
+
NO_ACTIVE_PROFILE_CODE,
|
|
22
|
+
noActiveProfileError,
|
|
23
|
+
REFERENCE_SETTLE_TIMEOUT,
|
|
24
|
+
REFERENCE_SETTLE_TIMEOUT_CODE,
|
|
25
|
+
referenceSettleTimeoutError
|
|
26
|
+
} from '../data-server.js';
|
|
@@ -7,15 +7,13 @@
|
|
|
7
7
|
* SPDX-License-Identifier: MIT
|
|
8
8
|
********************************************************************************/
|
|
9
9
|
|
|
10
|
+
import { mkdirSync, mkdtempSync } from 'node:fs';
|
|
11
|
+
import { tmpdir } from 'node:os';
|
|
12
|
+
import { join, resolve } from 'node:path';
|
|
13
|
+
import { parseArgs } from 'node:util';
|
|
10
14
|
import type { ServerSharedServices } from '@hydranium/core';
|
|
11
|
-
import {
|
|
12
|
-
|
|
13
|
-
formatProfileReport,
|
|
14
|
-
formatServerState,
|
|
15
|
-
ProfileCapture,
|
|
16
|
-
recordServerSummaryEntry,
|
|
17
|
-
writeHeapSnapshotToDir
|
|
18
|
-
} from '@hydranium/core/node';
|
|
15
|
+
import { formatProfileReport, formatServerState, ProfileCapture, recordServerSummaryEntry } from '@hydranium/core/node';
|
|
16
|
+
import { formatPodMemory, writeHeapSnapshotToDir } from '@hydranium/protocol/node';
|
|
19
17
|
import type { DumpServerStateArgs, StartProfilingArgs, StopProfilingArgs, WriteServerHeapSnapshotArgs } from '@hydranium/protocol';
|
|
20
18
|
import type { DataServerDiagnosticsProvider, DataServerProfileCapture } from '../diagnostics-provider.js';
|
|
21
19
|
|
|
@@ -33,29 +31,45 @@ import type { DataServerDiagnosticsProvider, DataServerProfileCapture } from '..
|
|
|
33
31
|
* AST/CST — the process that OOMs.
|
|
34
32
|
*/
|
|
35
33
|
class NodeProfileCapture implements DataServerProfileCapture {
|
|
36
|
-
constructor(
|
|
34
|
+
constructor(
|
|
35
|
+
protected readonly capture: ProfileCapture,
|
|
36
|
+
protected readonly directory: string
|
|
37
|
+
) {}
|
|
37
38
|
|
|
38
39
|
async stop(args: StopProfilingArgs): Promise<string> {
|
|
39
|
-
const report = await this.capture.stop(
|
|
40
|
-
|
|
41
|
-
// window's report into `<dir>/server-summary.json` so an interactive/e2e
|
|
42
|
-
// bundle carries the same per-window summary the headless `ProfilingRun`
|
|
43
|
-
// writes.
|
|
44
|
-
if (args.directory) {
|
|
45
|
-
recordServerSummaryEntry(args.directory, args.label ?? '', report);
|
|
46
|
-
}
|
|
40
|
+
const report = await this.capture.stop(this.directory, args.label ?? '');
|
|
41
|
+
recordServerSummaryEntry(this.directory, args.label ?? '', report);
|
|
47
42
|
return formatProfileReport(report, args.label ? `Profile report (${args.label})` : undefined);
|
|
48
43
|
}
|
|
49
44
|
}
|
|
50
45
|
|
|
46
|
+
/** Server-controlled destination for diagnostic artifacts. */
|
|
47
|
+
export interface NodeDataServerDiagnosticsOptions {
|
|
48
|
+
/** A directory owned by the host. Omitted creates a private temporary directory on first use. Client directory arguments are ignored. */
|
|
49
|
+
readonly directory?: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
51
52
|
class NodeDataServerDiagnostics implements DataServerDiagnosticsProvider {
|
|
53
|
+
protected outputDirectory: string | undefined;
|
|
54
|
+
|
|
55
|
+
constructor(protected readonly options: NodeDataServerDiagnosticsOptions) {}
|
|
56
|
+
|
|
57
|
+
protected directory(): string {
|
|
58
|
+
const directory = this.outputDirectory ?? this.options.directory ?? mkdtempSync(join(tmpdir(), 'hydranium-diagnostics-'));
|
|
59
|
+
// Cleanup can remove a previous destination. Prepare it on every use so
|
|
60
|
+
// artifact writers cannot fall back to the shared temporary directory.
|
|
61
|
+
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
62
|
+
this.outputDirectory = directory;
|
|
63
|
+
return directory;
|
|
64
|
+
}
|
|
65
|
+
|
|
52
66
|
async dumpServerState(services: ServerSharedServices, args: DumpServerStateArgs): Promise<string> {
|
|
53
67
|
const openDocuments = services.workspace.TextDocuments.openDocuments();
|
|
54
|
-
return formatServerState(services.workspace
|
|
68
|
+
return formatServerState(services.workspace, args.label, { openDocuments });
|
|
55
69
|
}
|
|
56
70
|
|
|
57
71
|
async writeHeapSnapshot(args: WriteServerHeapSnapshotArgs): Promise<string> {
|
|
58
|
-
return writeHeapSnapshotToDir(
|
|
72
|
+
return writeHeapSnapshotToDir(this.directory(), args.label ?? '');
|
|
59
73
|
}
|
|
60
74
|
|
|
61
75
|
async dumpPodMemory(): Promise<string> {
|
|
@@ -66,17 +80,49 @@ class NodeDataServerDiagnostics implements DataServerDiagnosticsProvider {
|
|
|
66
80
|
// `ProfileCapture` is singleton-guarded — one inspector session per
|
|
67
81
|
// process — so a second concurrent start rejects here rather than in the
|
|
68
82
|
// caller, which is where the constraint actually lives.
|
|
69
|
-
|
|
83
|
+
const directory = this.directory();
|
|
84
|
+
return new NodeProfileCapture(await ProfileCapture.start(args), directory);
|
|
70
85
|
}
|
|
71
86
|
}
|
|
72
87
|
|
|
73
88
|
/**
|
|
74
|
-
*
|
|
75
|
-
*
|
|
76
|
-
*
|
|
77
|
-
*
|
|
78
|
-
* four diagnostics methods — so a host that never calls them can leave it out.
|
|
89
|
+
* Enable process inspection on a connection the host has authorized for it.
|
|
90
|
+
* Artifact destinations come from host options. Wire directory arguments cannot
|
|
91
|
+
* grant filesystem access. The host must keep the output directory private,
|
|
92
|
+
* since snapshots can contain secrets from every client in this process.
|
|
79
93
|
*/
|
|
80
|
-
export function nodeDataServerDiagnostics(): DataServerDiagnosticsProvider {
|
|
81
|
-
return new NodeDataServerDiagnostics();
|
|
94
|
+
export function nodeDataServerDiagnostics(options: NodeDataServerDiagnosticsOptions = {}): DataServerDiagnosticsProvider {
|
|
95
|
+
return new NodeDataServerDiagnostics(options);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* The provider `--enable-diagnostics` asks for, writing to
|
|
100
|
+
* `--diagnostics-directory <path>` when given, or `undefined` when the flag is
|
|
101
|
+
* absent. A directory alone enables nothing. Other arguments are ignored, so
|
|
102
|
+
* an entry passes its whole command line. An entry that parses `args` strictly
|
|
103
|
+
* itself must declare both options too.
|
|
104
|
+
*/
|
|
105
|
+
export function diagnosticsFromArgs(args: readonly string[] = process.argv.slice(2)): DataServerDiagnosticsProvider | undefined {
|
|
106
|
+
const { values, tokens } = parseArgs({
|
|
107
|
+
args: [...args],
|
|
108
|
+
options: { 'enable-diagnostics': { type: 'boolean' }, 'diagnostics-directory': { type: 'string' } },
|
|
109
|
+
strict: false,
|
|
110
|
+
allowPositionals: true,
|
|
111
|
+
tokens: true
|
|
112
|
+
});
|
|
113
|
+
// Non-strict parsing types every value loosely and takes a following flag
|
|
114
|
+
// as a value, so the shapes a strict parse rejects are checked here.
|
|
115
|
+
const enabled = values['enable-diagnostics'];
|
|
116
|
+
const directory = values['diagnostics-directory'];
|
|
117
|
+
if (enabled !== undefined && typeof enabled !== 'boolean') {
|
|
118
|
+
throw new Error('--enable-diagnostics takes no value');
|
|
119
|
+
}
|
|
120
|
+
const flagAsDirectory = tokens.some(
|
|
121
|
+
token => token.kind === 'option' && token.name === 'diagnostics-directory' && !token.inlineValue && token.value?.startsWith('-')
|
|
122
|
+
);
|
|
123
|
+
if (flagAsDirectory || directory === '' || (directory !== undefined && typeof directory !== 'string')) {
|
|
124
|
+
throw new Error('--diagnostics-directory requires a path');
|
|
125
|
+
}
|
|
126
|
+
// Resolved once, so a later working-directory change cannot move the output.
|
|
127
|
+
return enabled ? nodeDataServerDiagnostics({ directory: directory === undefined ? undefined : resolve(directory) }) : undefined;
|
|
82
128
|
}
|
|
@@ -15,11 +15,12 @@ import {
|
|
|
15
15
|
type DataServerProtocol,
|
|
16
16
|
type ProjectsChangedEvent,
|
|
17
17
|
type TransferDocumentDeletedEvent,
|
|
18
|
+
type TransferDocumentDirtyChangedEvent,
|
|
18
19
|
type TransferDocumentSavedEvent,
|
|
19
20
|
type TransferDocumentsBuiltEvent,
|
|
20
21
|
type TransferDocumentUpdatedEvent
|
|
21
22
|
} from '@hydranium/protocol/data';
|
|
22
|
-
import { type Harness, makeCapturingDataClient } from '@hydranium/protocol/testing';
|
|
23
|
+
import { type AdditionalClientMethod, type Harness, makeCapturingDataClient } from '@hydranium/protocol/testing';
|
|
23
24
|
import { makeDuplexConnectionPair, type DuplexConnectionPair } from '@hydranium/protocol/testing/node';
|
|
24
25
|
import type { MessageConnection } from 'vscode-jsonrpc/node';
|
|
25
26
|
|
|
@@ -31,16 +32,17 @@ import type { MessageConnection } from 'vscode-jsonrpc/node';
|
|
|
31
32
|
* (the "server side" of the duplex pair). The factory is invoked once,
|
|
32
33
|
* synchronously, after the pair is wired.
|
|
33
34
|
*
|
|
34
|
-
* `client` lets tests override individual handlers on the captured
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
35
|
+
* `client` lets tests override individual handlers on the captured client.
|
|
36
|
+
* Unspecified handlers default to pushing incoming events into the
|
|
37
|
+
* {@link DataServerHarness} bundle's `events` / `saves` / `projectsChanges`
|
|
38
|
+
* arrays — the typical assertion target.
|
|
38
39
|
*/
|
|
39
40
|
export interface MakeDataServerHarnessOptions<
|
|
40
41
|
TServer,
|
|
41
42
|
TTransfer extends TransferElement,
|
|
42
43
|
TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
|
|
43
|
-
TProject extends Project = Project
|
|
44
|
+
TProject extends Project = Project,
|
|
45
|
+
TClient extends DataClientProtocol<TTransfer, TDiagnostic, TProject> = DataClientProtocol<TTransfer, TDiagnostic, TProject>
|
|
44
46
|
> {
|
|
45
47
|
/**
|
|
46
48
|
* Construct the `DataServer` (or subclass) under test against
|
|
@@ -49,12 +51,19 @@ export interface MakeDataServerHarnessOptions<
|
|
|
49
51
|
*/
|
|
50
52
|
server: (channel: MessageConnection) => TServer;
|
|
51
53
|
/**
|
|
52
|
-
* Override per-method handlers on the captured
|
|
53
|
-
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
54
|
+
* Override per-method handlers on the captured client. An additional
|
|
55
|
+
* method's override needs the method in `additionalClientMethods`, or the
|
|
56
|
+
* harness throws. Each overridden handler REPLACES the default (which
|
|
57
|
+
* pushes into the bundle's capture arrays); test code wanting to BOTH
|
|
58
|
+
* capture AND react should push to the array manually inside the override.
|
|
56
59
|
*/
|
|
57
|
-
client?: Partial<
|
|
60
|
+
client?: Partial<TClient>;
|
|
61
|
+
/**
|
|
62
|
+
* Notification methods `TClient` adds to {@link DataClientProtocol}. Each is
|
|
63
|
+
* bound and captured into `additionalNotifications`; one left out reaches no
|
|
64
|
+
* handler.
|
|
65
|
+
*/
|
|
66
|
+
additionalClientMethods?: readonly AdditionalClientMethod<TClient>[];
|
|
58
67
|
/**
|
|
59
68
|
* Wire namespace the proxy addresses the server under. Defaults to
|
|
60
69
|
* {@link DATA_SERVER_WIRE_PREFIX}. Override when the `DataServer`
|
|
@@ -80,7 +89,8 @@ export interface DataServerHarness<
|
|
|
80
89
|
TServer,
|
|
81
90
|
TTransfer extends TransferElement,
|
|
82
91
|
TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
|
|
83
|
-
TProject extends Project = Project
|
|
92
|
+
TProject extends Project = Project,
|
|
93
|
+
TClient extends DataClientProtocol<TTransfer, TDiagnostic, TProject> = DataClientProtocol<TTransfer, TDiagnostic, TProject>
|
|
84
94
|
> extends Harness {
|
|
85
95
|
readonly server: TServer;
|
|
86
96
|
readonly proxy: DataServerProtocol<TTransfer, TDiagnostic, TProject>;
|
|
@@ -89,12 +99,18 @@ export interface DataServerHarness<
|
|
|
89
99
|
readonly events: ReadonlyArray<TransferDocumentUpdatedEvent<TTransfer, TDiagnostic>>;
|
|
90
100
|
/** Captured `onDocumentSaved` events. */
|
|
91
101
|
readonly saves: ReadonlyArray<TransferDocumentSavedEvent<TTransfer, TDiagnostic>>;
|
|
102
|
+
/** Captured `onDocumentDirtyChanged` events. */
|
|
103
|
+
readonly dirtyChanges: ReadonlyArray<TransferDocumentDirtyChangedEvent>;
|
|
92
104
|
/** Captured `onDocumentDeleted` events. */
|
|
93
105
|
readonly deletions: ReadonlyArray<TransferDocumentDeletedEvent>;
|
|
94
106
|
/** Captured `onDocumentsBuilt` events, one per build that had unwatched documents. */
|
|
95
107
|
readonly builds: ReadonlyArray<TransferDocumentsBuiltEvent>;
|
|
96
108
|
/** Captured `onProjectsChanged` events. */
|
|
97
109
|
readonly projectsChanges: ReadonlyArray<ProjectsChangedEvent<TProject>>;
|
|
110
|
+
/** Captured events of each `additionalClientMethods` entry, keyed by method. */
|
|
111
|
+
readonly additionalNotifications: {
|
|
112
|
+
readonly [K in AdditionalClientMethod<TClient>]: TClient[K] extends (event: infer TEvent) => void ? ReadonlyArray<TEvent> : never;
|
|
113
|
+
};
|
|
98
114
|
/** Dispose the underlying duplex pair. Idempotent. */
|
|
99
115
|
dispose(): void;
|
|
100
116
|
}
|
|
@@ -113,12 +129,14 @@ export function makeDataServerHarness<
|
|
|
113
129
|
TServer,
|
|
114
130
|
TTransfer extends TransferElement,
|
|
115
131
|
TDiagnostic extends TransferDiagnostic = TransferDiagnostic,
|
|
116
|
-
TProject extends Project = Project
|
|
132
|
+
TProject extends Project = Project,
|
|
133
|
+
TClient extends DataClientProtocol<TTransfer, TDiagnostic, TProject> = DataClientProtocol<TTransfer, TDiagnostic, TProject>
|
|
117
134
|
>(
|
|
118
|
-
options: MakeDataServerHarnessOptions<TServer, TTransfer, TDiagnostic, TProject>
|
|
119
|
-
): DataServerHarness<TServer, TTransfer, TDiagnostic, TProject> {
|
|
135
|
+
options: MakeDataServerHarnessOptions<TServer, TTransfer, TDiagnostic, TProject, TClient>
|
|
136
|
+
): DataServerHarness<TServer, TTransfer, TDiagnostic, TProject, TClient> {
|
|
120
137
|
const pair = makeDuplexConnectionPair();
|
|
121
138
|
const server = options.server(pair.left);
|
|
139
|
+
const additionalClientMethods = options.additionalClientMethods ?? [];
|
|
122
140
|
|
|
123
141
|
// The capture half is the shared client double, not a local copy: the same
|
|
124
142
|
// recording semantics (every channel, an override replacing rather than
|
|
@@ -129,19 +147,18 @@ export function makeDataServerHarness<
|
|
|
129
147
|
client: localClient,
|
|
130
148
|
updates: events,
|
|
131
149
|
saves,
|
|
150
|
+
dirtyChanges,
|
|
132
151
|
deletions,
|
|
133
152
|
builds,
|
|
134
|
-
projectsChanges
|
|
135
|
-
|
|
153
|
+
projectsChanges,
|
|
154
|
+
additionalNotifications
|
|
155
|
+
} = makeCapturingDataClient<TTransfer, TDiagnostic, TProject, TClient>(options.client, additionalClientMethods);
|
|
136
156
|
|
|
137
|
-
const proxy = createRpcProxy<DataServerProtocol<TTransfer, TDiagnostic, TProject>,
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
localMethods: DATA_CLIENT_PROTOCOL_METHODS
|
|
143
|
-
}
|
|
144
|
-
);
|
|
157
|
+
const proxy = createRpcProxy<DataServerProtocol<TTransfer, TDiagnostic, TProject>, TClient>(pair.right, {
|
|
158
|
+
methodNamespace: options.methodNamespace ?? DATA_SERVER_WIRE_PREFIX,
|
|
159
|
+
localTarget: localClient,
|
|
160
|
+
localMethods: [...DATA_CLIENT_PROTOCOL_METHODS, ...additionalClientMethods]
|
|
161
|
+
});
|
|
145
162
|
|
|
146
163
|
return {
|
|
147
164
|
server,
|
|
@@ -149,9 +166,11 @@ export function makeDataServerHarness<
|
|
|
149
166
|
pair,
|
|
150
167
|
events,
|
|
151
168
|
saves,
|
|
169
|
+
dirtyChanges,
|
|
152
170
|
deletions,
|
|
153
171
|
builds,
|
|
154
172
|
projectsChanges,
|
|
173
|
+
additionalNotifications,
|
|
155
174
|
dispose: () => pair.dispose()
|
|
156
175
|
};
|
|
157
176
|
}
|
package/src/testing/index.ts
CHANGED
|
@@ -12,8 +12,11 @@
|
|
|
12
12
|
// real wire. The duplex `MessageConnection` pair lives in
|
|
13
13
|
// `@hydranium/protocol/testing`, which owns the transport; only its TYPE is
|
|
14
14
|
// re-exported here, because `DataServerHarness.pair` names it in a public
|
|
15
|
-
// signature
|
|
16
|
-
//
|
|
15
|
+
// signature; `AdditionalClientMethod` is re-exported for the same reason, as
|
|
16
|
+
// the harness options name it. A test that wires its own server rather than
|
|
17
|
+
// using the harness calls `makeDuplexConnectionPair` from
|
|
18
|
+
// `@hydranium/protocol/testing` directly.
|
|
17
19
|
|
|
20
|
+
export type { AdditionalClientMethod } from '@hydranium/protocol/testing';
|
|
18
21
|
export type { DuplexConnectionPair } from '@hydranium/protocol/testing/node';
|
|
19
22
|
export * from './data-server-harness.js';
|
|
@@ -1,18 +0,0 @@
|
|
|
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 { DataServerDiagnosticsProvider } from './diagnostics-provider.js';
|
|
10
|
-
/**
|
|
11
|
-
* Platform default for a browser host, selected by `package.json`'s `browser`
|
|
12
|
-
* field in place of `default-diagnostics.js`.
|
|
13
|
-
*
|
|
14
|
-
* Free of Node imports by construction — that is its entire reason for
|
|
15
|
-
* existing, and why the head's portable entry can be bundled at all.
|
|
16
|
-
*/
|
|
17
|
-
export declare function defaultDataServerDiagnostics(): DataServerDiagnosticsProvider;
|
|
18
|
-
//# sourceMappingURL=default-diagnostics.browser.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default-diagnostics.browser.d.ts","sourceRoot":"","sources":["../src/default-diagnostics.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAElF,OAAO,KAAK,EAAE,6BAA6B,EAA4B,MAAM,2BAA2B,CAAC;AAiBzG;;;;;;GAMG;AACH,wBAAgB,4BAA4B,IAAI,6BAA6B,CAO5E"}
|
|
@@ -1,36 +0,0 @@
|
|
|
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
|
-
* Message every method of the browser default rejects with.
|
|
11
|
-
*
|
|
12
|
-
* It **throws rather than no-ops** deliberately. A no-op would hand back an
|
|
13
|
-
* empty snapshot, which reads as "the server is fine" — the same shape as a
|
|
14
|
-
* real answer, and the failure mode this whole seam exists to avoid. Saying
|
|
15
|
-
* plainly that the capability is absent is more useful than a plausible lie.
|
|
16
|
-
*/
|
|
17
|
-
function unavailable(method) {
|
|
18
|
-
return new Error(`DataServer.${method} is not available in this host: a browser has no process to inspect. ` +
|
|
19
|
-
'Heap snapshots, profiling, pod memory and server state are Node-only capabilities.');
|
|
20
|
-
}
|
|
21
|
-
/**
|
|
22
|
-
* Platform default for a browser host, selected by `package.json`'s `browser`
|
|
23
|
-
* field in place of `default-diagnostics.js`.
|
|
24
|
-
*
|
|
25
|
-
* Free of Node imports by construction — that is its entire reason for
|
|
26
|
-
* existing, and why the head's portable entry can be bundled at all.
|
|
27
|
-
*/
|
|
28
|
-
export function defaultDataServerDiagnostics() {
|
|
29
|
-
return {
|
|
30
|
-
dumpServerState: () => Promise.reject(unavailable('dumpServerState')),
|
|
31
|
-
writeHeapSnapshot: () => Promise.reject(unavailable('writeHeapSnapshot')),
|
|
32
|
-
dumpPodMemory: () => Promise.reject(unavailable('dumpPodMemory')),
|
|
33
|
-
startProfiling: () => Promise.reject(unavailable('startProfiling'))
|
|
34
|
-
};
|
|
35
|
-
}
|
|
36
|
-
//# sourceMappingURL=default-diagnostics.browser.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"default-diagnostics.browser.js","sourceRoot":"","sources":["../src/default-diagnostics.browser.ts"],"names":[],"mappings":"AAAA;;;;;;;kFAOkF;AAIlF;;;;;;;GAOG;AACH,SAAS,WAAW,CAAC,MAAc;IAChC,OAAO,IAAI,KAAK,CACb,cAAc,MAAM,uEAAuE;QACxF,oFAAoF,CACzF,CAAC;AACL,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,4BAA4B;IACzC,OAAO;QACJ,eAAe,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,iBAAiB,CAAC,CAAC;QACrE,iBAAiB,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;QACzE,aAAa,EAAE,GAAG,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,eAAe,CAAC,CAAC;QACjE,cAAc,EAAE,GAAsC,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,WAAW,CAAC,gBAAgB,CAAC,CAAC;KACxG,CAAC;AACL,CAAC"}
|
|
@@ -1,41 +0,0 @@
|
|
|
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
|
-
import type { DataServerDiagnosticsProvider, DataServerProfileCapture } from './diagnostics-provider.js';
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Message every method of the browser default rejects with.
|
|
14
|
-
*
|
|
15
|
-
* It **throws rather than no-ops** deliberately. A no-op would hand back an
|
|
16
|
-
* empty snapshot, which reads as "the server is fine" — the same shape as a
|
|
17
|
-
* real answer, and the failure mode this whole seam exists to avoid. Saying
|
|
18
|
-
* plainly that the capability is absent is more useful than a plausible lie.
|
|
19
|
-
*/
|
|
20
|
-
function unavailable(method: string): Error {
|
|
21
|
-
return new Error(
|
|
22
|
-
`DataServer.${method} is not available in this host: a browser has no process to inspect. ` +
|
|
23
|
-
'Heap snapshots, profiling, pod memory and server state are Node-only capabilities.'
|
|
24
|
-
);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
/**
|
|
28
|
-
* Platform default for a browser host, selected by `package.json`'s `browser`
|
|
29
|
-
* field in place of `default-diagnostics.js`.
|
|
30
|
-
*
|
|
31
|
-
* Free of Node imports by construction — that is its entire reason for
|
|
32
|
-
* existing, and why the head's portable entry can be bundled at all.
|
|
33
|
-
*/
|
|
34
|
-
export function defaultDataServerDiagnostics(): DataServerDiagnosticsProvider {
|
|
35
|
-
return {
|
|
36
|
-
dumpServerState: () => Promise.reject(unavailable('dumpServerState')),
|
|
37
|
-
writeHeapSnapshot: () => Promise.reject(unavailable('writeHeapSnapshot')),
|
|
38
|
-
dumpPodMemory: () => Promise.reject(unavailable('dumpPodMemory')),
|
|
39
|
-
startProfiling: (): Promise<DataServerProfileCapture> => Promise.reject(unavailable('startProfiling'))
|
|
40
|
-
};
|
|
41
|
-
}
|