@hydranium/data-server 1.0.0-next.9 → 1.0.0-next.90

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 CHANGED
@@ -22,7 +22,11 @@ Installed by the server process that already composes
22
22
  - **Push notifications instead of polling:** `onDocumentUpdated` when a
23
23
  subscribed document reaches the configured build phase
24
24
  (`DataServerOptions.subscriptionPhase`, `DocumentState.Validated` by default),
25
- `onDocumentSaved` on a separate channel, and `onProjectsChanged` from the
25
+ `onDocumentSaved` on a separate channel, `onDocumentDeleted` on a third (a
26
+ deleted document has no built state to carry, and the build-phase path never
27
+ runs for one), `onDocumentsBuilt` once per build for the documents nobody
28
+ watches — chiefly those rebuilt as a cascade, which no filesystem watcher can
29
+ see because their own files did not change — and `onProjectsChanged` from the
26
30
  project registry.
27
31
  - **Projects as first-class:** `getProjects` and `getProjectForUri`, answered from
28
32
  the framework's `ProjectManager`.
@@ -6,10 +6,25 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import { DisposableCollection, ReferenceSource, type CloseModelArgs, type Disposable, type ElementSource, type FindNextNameArgs, type LatencyCollector, type LatencyReport, type OpenModelArgs, type Project, type ReferenceCandidate, type ReferenceContext, type ReferenceRequest, type ReferenceTarget, type Tracer, type TransferDiagnostic, type TransferDocument, type TransferElement } from '@hydranium/protocol';
9
+ import { DisposableCollection, ReferenceSource, type CloseModelArgs, type HydraniumResponseError, type Disposable, type ElementSource, type FindNextNameArgs, type LatencyCollector, type LatencyReport, type OpenModelArgs, type Project, type ReferenceCandidate, type ReferenceContext, type ReferenceRequest, type ReferenceTarget, type Tracer, type TransferDiagnostic, TransferDocument, type TransferElement } from '@hydranium/protocol';
10
10
  import { type DataClientProtocol, type DataServerDiagnosticsProtocol, type DataServerProtocol, type DumpServerStateArgs, type StartProfilingArgs, type StopProfilingArgs, type WriteServerHeapSnapshotArgs, type GetModelDocumentArgs, type GetProjectForUriArgs, type TransferSaveDocumentArgs, type WatchModelDocumentArgs, type TransferDocumentUpdatedEvent, type TransferUpdateDocumentArgs } from '@hydranium/protocol/data';
11
+ /**
12
+ * Raised when a profiling command arrives with no capture running.
13
+ *
14
+ * A `ResponseError` rather than a plain `Error` so the identity survives to the
15
+ * response boundary, which is where the message is rendered. An unwrapped throw
16
+ * reaches the client as a generic internal error instead: no code for a caller
17
+ * to switch on, and nothing for the boundary to render from.
18
+ */
19
+ export declare const NO_ACTIVE_PROFILE: import("@hydranium/protocol").MessageDefinition<"No profiling capture is active; call startProfiling first.">;
20
+ /**
21
+ * The JSON-RPC code, unrelated to the catalogue code above: this one is numeric,
22
+ * survives reconstruction and is what a caller switches on.
23
+ */
24
+ export declare const NO_ACTIVE_PROFILE_CODE = 1002;
25
+ export declare const noActiveProfileError: () => HydraniumResponseError;
11
26
  import type { DataServerDiagnosticsProvider, DataServerProfileCapture } from './diagnostics-provider.js';
12
- import type { ClientTextDocumentChangeEvent, HydraniumLanguageServices, LogNameOptions, ModelService, ProjectChangeEvent, ServerSharedServices, TransferEncoder } from '@hydranium/core';
27
+ import type { ClientTextDocumentChangeEvent, HydraniumLanguageServices, LogNameOptions, AstDiagnostic, ModelService, ProjectChangeEvent, ServerSharedServices, TransferEncoder } from '@hydranium/core';
13
28
  import type { TextDocument } from 'vscode-languageserver-textdocument';
14
29
  import { type AstNode, DocumentState, type LangiumDocument, type URI } from '@hydranium/langium';
15
30
  import type { CancellationToken, MessageConnection } from 'vscode-jsonrpc';
@@ -136,9 +151,9 @@ export interface DataServerOptions extends LogNameOptions {
136
151
  * When supplied, every inbound data-server RPC is timed into this collector
137
152
  * (via the `createRpcProxy` binding) and exposed through
138
153
  * {@link DataServerDiagnosticsProtocol.getLatency}. A head that also runs an
139
- * LSP connection can pass the SAME collector to
140
- * `instrumentLspConnection(connection, latency)` so one report covers both
141
- * heads. Absent by default (no timing overhead).
154
+ * LSP connection can pass the SAME collector through `lspLatencyOptions` to
155
+ * that connection, so one report covers both heads. Absent by default (no
156
+ * timing overhead).
142
157
  */
143
158
  readonly latency?: LatencyCollector;
144
159
  }
@@ -177,9 +192,11 @@ interface ResolvedDataServerOptions {
177
192
  * any names supplied via {@link DataServerOptions.additionalMethods}) and
178
193
  * builds the {@link DataClientProtocol} notification proxy on the same
179
194
  * connection in one {@link createRpcProxy} call (binding `this` as its
180
- * `localTarget`) under the configured namespace, and subscribes one
181
- * `DocumentBuilder.onDocumentPhase` listener per configured phase that
182
- * dispatches subscription events via `clientProxy.onDocumentUpdated`.
195
+ * `localTarget`) under the configured namespace, and subscribes two listeners
196
+ * at the configured phase: a `DocumentBuilder.onDocumentPhase` one dispatching
197
+ * per-document `clientProxy.onDocumentUpdated` for watched URIs, and a
198
+ * `DocumentBuilder.onBuildPhase` one dispatching a single
199
+ * `clientProxy.onDocumentsBuilt` naming the batch's unwatched documents.
183
200
  *
184
201
  * The data-server requires the full {@link ServerSharedServices}
185
202
  * shape — `HydraniumTextDocuments` for client-attributed updates,
@@ -225,10 +242,12 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
225
242
  /**
226
243
  * Snapshot of the most recent `DocumentBuilder.onUpdate` event. Drives
227
244
  * `reason` discrimination on outbound `onDocumentUpdated` notifications:
228
- * a URI in the `changed` list emits `'changed'`, in `deleted` emits
229
- * `'deleted'`, otherwise `'rebuilt'` (cascade rebuild from a dependent
230
- * URI's change). The same mechanism `AstDocumentManager.onUpdate` uses on
231
- * the LSP side, so reason fidelity stays consistent between heads.
245
+ * a URI in the `changed` list emits `'changed'`, otherwise `'rebuilt'`
246
+ * (cascade rebuild from a dependent URI's change). The same mechanism
247
+ * `AstDocumentManager.onUpdate` uses on the LSP side, so reason fidelity
248
+ * stays consistent between heads. The `deleted` half is read by
249
+ * {@link dispatchDeleteEvents} rather than by the reason discrimination,
250
+ * a deletion travelling on its own channel.
232
251
  */
233
252
  protected lastBuildUpdate?: {
234
253
  changed: readonly URI[];
@@ -292,7 +311,7 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
292
311
  /** Per-method RPC latency collector, when the head opted in via {@link DataServerOptions.latency}. */
293
312
  protected readonly latency?: LatencyCollector;
294
313
  /** Encoder pulled from DI. Adopters rebind `services.model.TransferEncoder` to a typed-overlay subclass. */
295
- protected readonly encoder: TransferEncoder<unknown, TDiagnostic>;
314
+ protected readonly encoder: TransferEncoder<TDiagnostic>;
296
315
  /**
297
316
  * In-process workspace facade — the lifecycle delegate `get` / `update` / `save` go through.
298
317
  * The facade's AstDocument diagnostic shape is intentionally typed `unknown` here: adopters
@@ -301,7 +320,7 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
301
320
  * `astDocumentToTransferDocument` accepts both shapes (wire-shape or LSP-shape) and projects
302
321
  * to wire shape on the return — see `TransferEncoder.astDocumentToTransferDocument`.
303
322
  */
304
- protected readonly modelService: ModelService<AstNode, unknown, TTransfer>;
323
+ protected readonly modelService: ModelService<AstNode, AstDiagnostic, TTransfer>;
305
324
  constructor(connection: MessageConnection, services: ServerSharedServices<TProject>, options?: DataServerOptions);
306
325
  /**
307
326
  * Release everything the constructor wired up — the bound protocol
@@ -409,6 +428,9 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
409
428
  /**
410
429
  * Pick the language that owns a reference source, in order:
411
430
  *
431
+ * 0. A {@link isSyntheticSource} naming its own `language` routes there.
432
+ * First because every step below infers, and an inference must not
433
+ * override a caller that has said which grammar it means.
412
434
  * 1. A URI-bearing source ({@link isDocumentSource}/{@link isSyntheticSource})
413
435
  * whose URI resolves to a registered language routes by URI.
414
436
  * 2. A single-language workspace always routes to that one language — so
@@ -489,6 +511,42 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
489
511
  * regardless of subscriber count.
490
512
  */
491
513
  protected subscribeToDocumentBuilder(): void;
514
+ /**
515
+ * Report the documents that reached {@link DataServerOptions.subscriptionPhase}
516
+ * and that NOBODY on this
517
+ * connection is watching — the ones a client was not told about through
518
+ * {@link dispatchPhaseEvent}, which is gated per URI.
519
+ *
520
+ * **The gap this closes is the one no other source can observe.** A document
521
+ * the client watches, it hears about already. A file changed on disk, the
522
+ * host's own filesystem watcher reports — and on a browser host, where the
523
+ * workspace lives behind this head, an external change cannot happen at all.
524
+ * What is left, and what nothing outside the server can see, is a document
525
+ * rebuilt because something it DEPENDS ON changed: its file never changed, so
526
+ * a filesystem watcher is silent by construction, and it has no subscriber, so
527
+ * the update channel is silent by design. A consumer displaying data derived
528
+ * from that document — a tree label, a decorator — otherwise goes stale with
529
+ * no signal from any source, and repairs itself the moment someone opens the
530
+ * file to investigate, which is what makes it expensive to diagnose later.
531
+ *
532
+ * Payload-free on purpose: URIs only, so a client re-reads what it displays
533
+ * rather than being handed transfer documents it did not ask for. That is the
534
+ * property the subscription map protects, and it is preserved here by
535
+ * carrying no document rather than by gating the message.
536
+ *
537
+ * Quiet in the common case. Editing a document that an editor has open leaves
538
+ * that URI watched and therefore out of this set, so a build with no
539
+ * dependents produces nothing at all, and workspace initialisation produces
540
+ * nothing because it does not build to this phase. The ceiling is a
541
+ * whole-workspace rebuild at the subscription phase: one message, URIs only.
542
+ *
543
+ * The URI is canonicalised for the same reason the subscription map is keyed
544
+ * that way, and is untested for the same reason as its twin in
545
+ * {@link dispatchDeleteEvents}: the builder reports URIs out of its own
546
+ * store, so a non-canonical one cannot be produced without a fixture
547
+ * asserting a shape the real system never emits.
548
+ */
549
+ protected dispatchBuiltEvent(built: readonly LangiumDocument[]): void;
492
550
  /**
493
551
  * Subscribe to the universal save event on `HydraniumTextDocuments` so a
494
552
  * single `onDocumentSaved` wire notification fires for ANY save of a
@@ -511,6 +569,48 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
511
569
  * hold, so a `false` answer means this close was the last one.
512
570
  */
513
571
  protected subscribeToTextDocumentCloses(): void;
572
+ /**
573
+ * Fan out a deletion for each removed URI, to EVERY client on the connection
574
+ * rather than only to the ones watching that URI.
575
+ *
576
+ * **Deliberately ungated, where {@link dispatchPhaseEvent} and
577
+ * {@link dispatchSaveEvent} are gated.** Those two carry a built document and
578
+ * fire on every build, so the subscription map is what keeps bandwidth
579
+ * proportional to what a client asked for. A deletion is neither: it is one
580
+ * URI, it is rare, and it reports the workspace's STRUCTURE rather than a
581
+ * document's content. Gating it forces any consumer that displays the
582
+ * workspace — a model tree, a file decorator — to learn about disappearances
583
+ * from a filesystem watcher instead, which a client hosted in a browser has
584
+ * no way to run: its workspace lives behind the head. A client that does not
585
+ * care filters on the URI, which costs it a comparison.
586
+ *
587
+ * The precedent is the last-close revert broadcast (see
588
+ * {@link pendingRevertBroadcasts}), where the same judgement was already made
589
+ * in the other direction: a transition that matters enough is delivered
590
+ * without a subscription.
591
+ *
592
+ * Runs from the `DocumentBuilder.onUpdate` listener rather than from a phase
593
+ * listener, which is the only place a deletion is observable: `update`
594
+ * removes the document before deriving the rebuild set, so it is never built.
595
+ * That ordering also puts this notification ahead of the `'rebuilt'` events
596
+ * for the dependents whose references the deletion just broke.
597
+ *
598
+ * The `deleted` list arrives already expanded to concrete document URIs —
599
+ * `deleteDocuments` resolves a directory URI to the documents beneath it — so
600
+ * no caller has to handle a directory here.
601
+ *
602
+ * Per-URI derived state is dropped for the same reason it is dropped
603
+ * anywhere: it describes a document that no longer exists.
604
+ * {@link lastEmittedFingerprint} in particular can outlive its subscriptions
605
+ * through the last-close revert path — left behind, it is adopted as the
606
+ * baseline by the next {@link watchModelDocument} and suppresses the first
607
+ * emit after the file returns with its previous content.
608
+ *
609
+ * The subscription itself SURVIVES: a recreated file resumes delivering to
610
+ * the same watchers with no re-subscription, and a client that answers the
611
+ * deletion by closing releases the watch through `closeModelDocument` anyway.
612
+ */
613
+ protected dispatchDeleteEvents(deleted: readonly URI[]): void;
514
614
  /** Fan out a save event for the document's URI, gated by the subscription map. */
515
615
  protected dispatchSaveEvent(event: ClientTextDocumentChangeEvent<TextDocument>): void;
516
616
  /**
@@ -556,16 +656,16 @@ export declare class DataServer<TTransfer extends TransferElement, TDiagnostic e
556
656
  /**
557
657
  * Discriminate the reason for a phase-event-driven update notification.
558
658
  * Uses the most recent `DocumentBuilder.onUpdate` snapshot:
559
- * - URI in the `deleted` list → `'deleted'`
560
659
  * - URI in the `changed` list → `'changed'` (the URI was passed to
561
660
  * `documentBuilder.update(changed, deleted)`, which spans `didChange`
562
661
  * text-document events and programmatic `update([uri], [])` calls).
563
662
  * - Otherwise → `'rebuilt'` (cascade re-derivation: this URI was rebuilt
564
663
  * because something it depends on changed; its own text wasn't flagged).
565
664
  *
566
- * `'saved'` is NOT emitted from this code path — saves take the dedicated
567
- * `DataClientProtocol.onDocumentSaved` channel; adopters that want a
568
- * unified update stream synthesise `'saved'` in their bridge layer.
665
+ * `'saved'` is NOT emitted here — saves take the dedicated
666
+ * `DataClientProtocol.onDocumentSaved` channel, and adopters wanting a
667
+ * unified stream synthesise it in their bridge layer. A deletion is not a
668
+ * reason at all; see {@link dispatchDeleteEvents}.
569
669
  */
570
670
  protected resolveUpdateReason(uri: URI): TransferDocumentUpdatedEvent<TTransfer, TDiagnostic>['reason'];
571
671
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"data-server.d.ts","sourceRoot":"","sources":["../src/data-server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"data-server.d.ts","sourceRoot":"","sources":["../src/data-server.ts"],"names":[],"mappings":"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"}
@@ -6,10 +6,25 @@
6
6
  *
7
7
  * SPDX-License-Identifier: MIT
8
8
  ********************************************************************************/
9
- import { createRpcProxy, DisposableCollection, isDocumentSource, isElementSource, isSyntheticSource, ReferenceSource } from '@hydranium/protocol';
9
+ import { createRpcProxy, defineMessage, DisposableCollection, isDocumentSource, isElementSource, isSyntheticSource, messageError, ReferenceSource, TransferDocument, asSnapshotVersion } from '@hydranium/protocol';
10
10
  import { DATA_SERVER_DIAGNOSTICS_METHODS, DATA_SERVER_PROTOCOL_METHODS, DATA_SERVER_WIRE_PREFIX } from '@hydranium/protocol/data';
11
11
  import { REVERT_ON_CLOSE_CLIENT_ID, UNKNOWN_CLIENT_ID } from '@hydranium/core';
12
12
  import { defaultDataServerDiagnostics } from './default-diagnostics.js';
13
+ /**
14
+ * Raised when a profiling command arrives with no capture running.
15
+ *
16
+ * A `ResponseError` rather than a plain `Error` so the identity survives to the
17
+ * response boundary, which is where the message is rendered. An unwrapped throw
18
+ * reaches the client as a generic internal error instead: no code for a caller
19
+ * to switch on, and nothing for the boundary to render from.
20
+ */
21
+ export const NO_ACTIVE_PROFILE = defineMessage('hydranium/data-server/no-active-profile', 'No profiling capture is active; call startProfiling first.');
22
+ /**
23
+ * The JSON-RPC code, unrelated to the catalogue code above: this one is numeric,
24
+ * survives reconstruction and is what a caller switches on.
25
+ */
26
+ export const NO_ACTIVE_PROFILE_CODE = 1002;
27
+ export const noActiveProfileError = () => messageError(NO_ACTIVE_PROFILE_CODE, NO_ACTIVE_PROFILE);
13
28
  import { DocumentState, UriUtils } from '@hydranium/langium';
14
29
  /**
15
30
  * Domain separator between text and diagnostics inputs of
@@ -94,9 +109,11 @@ const FINGERPRINT_LOG_AFTER_MS = 5;
94
109
  * any names supplied via {@link DataServerOptions.additionalMethods}) and
95
110
  * builds the {@link DataClientProtocol} notification proxy on the same
96
111
  * connection in one {@link createRpcProxy} call (binding `this` as its
97
- * `localTarget`) under the configured namespace, and subscribes one
98
- * `DocumentBuilder.onDocumentPhase` listener per configured phase that
99
- * dispatches subscription events via `clientProxy.onDocumentUpdated`.
112
+ * `localTarget`) under the configured namespace, and subscribes two listeners
113
+ * at the configured phase: a `DocumentBuilder.onDocumentPhase` one dispatching
114
+ * per-document `clientProxy.onDocumentUpdated` for watched URIs, and a
115
+ * `DocumentBuilder.onBuildPhase` one dispatching a single
116
+ * `clientProxy.onDocumentsBuilt` naming the batch's unwatched documents.
100
117
  *
101
118
  * The data-server requires the full {@link ServerSharedServices}
102
119
  * shape — `HydraniumTextDocuments` for client-attributed updates,
@@ -144,10 +161,12 @@ export class DataServer {
144
161
  /**
145
162
  * Snapshot of the most recent `DocumentBuilder.onUpdate` event. Drives
146
163
  * `reason` discrimination on outbound `onDocumentUpdated` notifications:
147
- * a URI in the `changed` list emits `'changed'`, in `deleted` emits
148
- * `'deleted'`, otherwise `'rebuilt'` (cascade rebuild from a dependent
149
- * URI's change). The same mechanism `AstDocumentManager.onUpdate` uses on
150
- * the LSP side, so reason fidelity stays consistent between heads.
164
+ * a URI in the `changed` list emits `'changed'`, otherwise `'rebuilt'`
165
+ * (cascade rebuild from a dependent URI's change). The same mechanism
166
+ * `AstDocumentManager.onUpdate` uses on the LSP side, so reason fidelity
167
+ * stays consistent between heads. The `deleted` half is read by
168
+ * {@link dispatchDeleteEvents} rather than by the reason discrimination,
169
+ * a deletion travelling on its own channel.
151
170
  */
152
171
  lastBuildUpdate;
153
172
  /**
@@ -248,10 +267,15 @@ export class DataServer {
248
267
  methodNamespace: this.options.methodNamespace,
249
268
  localTarget: this,
250
269
  localMethods: registeredMethods,
251
- latency: this.latency
270
+ latency: this.latency,
271
+ // Bound at the chokepoint rather than per handler, so an adopter's
272
+ // `additionalMethods` are rendered on the same terms as the
273
+ // framework's own rejections.
274
+ renderErrorMessage: error => this.services.MessageRenderer.renderError(error)
252
275
  });
253
276
  this.disposables.push(this.services.workspace.DocumentBuilder.onUpdate((changed, deleted) => {
254
277
  this.lastBuildUpdate = { changed, deleted };
278
+ this.dispatchDeleteEvents(deleted);
255
279
  }));
256
280
  this.subscribeToDocumentBuilder();
257
281
  this.subscribeToTextDocumentSaves();
@@ -325,11 +349,11 @@ export class DataServer {
325
349
  // multi-client synced version whenever the open seeded the synced document
326
350
  // with a caller-supplied version id — and the synced version is what
327
351
  // `ModelService.update`'s optimistic-concurrency gate compares
328
- // `baseVersion` against, so reporting the snapshot's would make the
352
+ // `basedOn` against, so reporting the snapshot's would make the
329
353
  // caller's first tagged write self-conflict. A genuine concurrent edit
330
354
  // still trips the gate and is reconciled by the caller's replay rather
331
355
  // than predicted here.
332
- return { ...document, version: this.services.workspace.TextDocuments.version(args.uri) };
356
+ return { ...document, version: asSnapshotVersion(this.services.workspace.TextDocuments.version(args.uri)) };
333
357
  }
334
358
  async closeModelDocument(args) {
335
359
  // Closing a session also releases its watch for (uri, clientId) — a
@@ -526,7 +550,7 @@ export class DataServer {
526
550
  // synthetic source — and the create-element flow driving this method is
527
551
  // the one that produces directory URIs, on which a bare
528
552
  // `getServices(uri)` throws while `findReferenceCandidates` succeeds.
529
- const nameProvider = this.resolveReferenceServices(ReferenceSource.synthetic(args.uri, args.type)).NameProvider;
553
+ const nameProvider = this.resolveReferenceServices(ReferenceSource.synthetic(args.uri, args.type, args.language)).NameProvider;
530
554
  const tier = args.tier ?? 'project';
531
555
  if (tier === 'public') {
532
556
  return nameProvider.findNextProjectQualifiedName(args.type, args.proposal);
@@ -569,6 +593,9 @@ export class DataServer {
569
593
  /**
570
594
  * Pick the language that owns a reference source, in order:
571
595
  *
596
+ * 0. A {@link isSyntheticSource} naming its own `language` routes there.
597
+ * First because every step below infers, and an inference must not
598
+ * override a caller that has said which grammar it means.
572
599
  * 1. A URI-bearing source ({@link isDocumentSource}/{@link isSyntheticSource})
573
600
  * whose URI resolves to a registered language routes by URI.
574
601
  * 2. A single-language workspace always routes to that one language — so
@@ -587,6 +614,15 @@ export class DataServer {
587
614
  */
588
615
  resolveReferenceLanguage(source) {
589
616
  const registry = this.services.ServiceRegistry;
617
+ if (isSyntheticSource(source) && source.language !== undefined) {
618
+ const declared = registry.getServicesById(source.language);
619
+ if (declared) {
620
+ return declared;
621
+ }
622
+ // Falling through on an UNREGISTERED id rather than failing: the id
623
+ // crosses the wire, so a client built against a head with one more
624
+ // grammar would otherwise lose queries the steps below can answer.
625
+ }
590
626
  // `getServicesFor` (non-throwing, one ladder walk) gates the URI lookup:
591
627
  // an extensionless / unregistered URI falls through to the steps below
592
628
  // rather than throwing "no services for the extension ''".
@@ -698,12 +734,7 @@ export class DataServer {
698
734
  // decides policy at its own layer; `root` is optional on the envelope
699
735
  // so the compiler forces that decision. Adopters preferring to throw
700
736
  // override `envelope`.
701
- return {
702
- uri: uri.toString(),
703
- version: 0,
704
- root: undefined,
705
- diagnostics: []
706
- };
737
+ return TransferDocument.absent(uri.toString());
707
738
  }
708
739
  return this.encoder.toTransferDocument(document);
709
740
  }
@@ -715,6 +746,54 @@ export class DataServer {
715
746
  */
716
747
  subscribeToDocumentBuilder() {
717
748
  this.disposables.push(this.services.workspace.DocumentBuilder.onDocumentPhase(this.options.subscriptionPhase, (document, cancelToken) => this.dispatchPhaseEvent(document, cancelToken)));
749
+ // The BUILD-phase hook, not the per-document one: this notification is one
750
+ // message per build rather than one per document, and Langium hands the
751
+ // whole batch over here. It also does not fire for a cancelled build,
752
+ // which is what the per-document dispatch has to check by hand.
753
+ this.disposables.push(this.services.workspace.DocumentBuilder.onBuildPhase(this.options.subscriptionPhase, built => this.dispatchBuiltEvent(built)));
754
+ }
755
+ /**
756
+ * Report the documents that reached {@link DataServerOptions.subscriptionPhase}
757
+ * and that NOBODY on this
758
+ * connection is watching — the ones a client was not told about through
759
+ * {@link dispatchPhaseEvent}, which is gated per URI.
760
+ *
761
+ * **The gap this closes is the one no other source can observe.** A document
762
+ * the client watches, it hears about already. A file changed on disk, the
763
+ * host's own filesystem watcher reports — and on a browser host, where the
764
+ * workspace lives behind this head, an external change cannot happen at all.
765
+ * What is left, and what nothing outside the server can see, is a document
766
+ * rebuilt because something it DEPENDS ON changed: its file never changed, so
767
+ * a filesystem watcher is silent by construction, and it has no subscriber, so
768
+ * the update channel is silent by design. A consumer displaying data derived
769
+ * from that document — a tree label, a decorator — otherwise goes stale with
770
+ * no signal from any source, and repairs itself the moment someone opens the
771
+ * file to investigate, which is what makes it expensive to diagnose later.
772
+ *
773
+ * Payload-free on purpose: URIs only, so a client re-reads what it displays
774
+ * rather than being handed transfer documents it did not ask for. That is the
775
+ * property the subscription map protects, and it is preserved here by
776
+ * carrying no document rather than by gating the message.
777
+ *
778
+ * Quiet in the common case. Editing a document that an editor has open leaves
779
+ * that URI watched and therefore out of this set, so a build with no
780
+ * dependents produces nothing at all, and workspace initialisation produces
781
+ * nothing because it does not build to this phase. The ceiling is a
782
+ * whole-workspace rebuild at the subscription phase: one message, URIs only.
783
+ *
784
+ * The URI is canonicalised for the same reason the subscription map is keyed
785
+ * that way, and is untested for the same reason as its twin in
786
+ * {@link dispatchDeleteEvents}: the builder reports URIs out of its own
787
+ * store, so a non-canonical one cannot be produced without a fixture
788
+ * asserting a shape the real system never emits.
789
+ */
790
+ dispatchBuiltEvent(built) {
791
+ const uris = built.map(document => this.canonicalKey(document.uri.toString())).filter(uri => !this.subscriptions.has(uri));
792
+ if (uris.length === 0) {
793
+ return;
794
+ }
795
+ this.tracer.debug(`Emit onDocumentsBuilt: ${uris.length} unwatched document(s)`);
796
+ this.clientProxy.onDocumentsBuilt({ uris });
718
797
  }
719
798
  /**
720
799
  * Subscribe to the universal save event on `HydraniumTextDocuments` so a
@@ -747,6 +826,55 @@ export class DataServer {
747
826
  }
748
827
  }));
749
828
  }
829
+ /**
830
+ * Fan out a deletion for each removed URI, to EVERY client on the connection
831
+ * rather than only to the ones watching that URI.
832
+ *
833
+ * **Deliberately ungated, where {@link dispatchPhaseEvent} and
834
+ * {@link dispatchSaveEvent} are gated.** Those two carry a built document and
835
+ * fire on every build, so the subscription map is what keeps bandwidth
836
+ * proportional to what a client asked for. A deletion is neither: it is one
837
+ * URI, it is rare, and it reports the workspace's STRUCTURE rather than a
838
+ * document's content. Gating it forces any consumer that displays the
839
+ * workspace — a model tree, a file decorator — to learn about disappearances
840
+ * from a filesystem watcher instead, which a client hosted in a browser has
841
+ * no way to run: its workspace lives behind the head. A client that does not
842
+ * care filters on the URI, which costs it a comparison.
843
+ *
844
+ * The precedent is the last-close revert broadcast (see
845
+ * {@link pendingRevertBroadcasts}), where the same judgement was already made
846
+ * in the other direction: a transition that matters enough is delivered
847
+ * without a subscription.
848
+ *
849
+ * Runs from the `DocumentBuilder.onUpdate` listener rather than from a phase
850
+ * listener, which is the only place a deletion is observable: `update`
851
+ * removes the document before deriving the rebuild set, so it is never built.
852
+ * That ordering also puts this notification ahead of the `'rebuilt'` events
853
+ * for the dependents whose references the deletion just broke.
854
+ *
855
+ * The `deleted` list arrives already expanded to concrete document URIs —
856
+ * `deleteDocuments` resolves a directory URI to the documents beneath it — so
857
+ * no caller has to handle a directory here.
858
+ *
859
+ * Per-URI derived state is dropped for the same reason it is dropped
860
+ * anywhere: it describes a document that no longer exists.
861
+ * {@link lastEmittedFingerprint} in particular can outlive its subscriptions
862
+ * through the last-close revert path — left behind, it is adopted as the
863
+ * baseline by the next {@link watchModelDocument} and suppresses the first
864
+ * emit after the file returns with its previous content.
865
+ *
866
+ * The subscription itself SURVIVES: a recreated file resumes delivering to
867
+ * the same watchers with no re-subscription, and a client that answers the
868
+ * deletion by closing releases the watch through `closeModelDocument` anyway.
869
+ */
870
+ dispatchDeleteEvents(deleted) {
871
+ for (const removed of deleted) {
872
+ const uri = this.canonicalKey(removed.toString());
873
+ this.lastEmittedFingerprint.delete(uri);
874
+ this.pendingRevertBroadcasts.delete(uri);
875
+ this.clientProxy.onDocumentDeleted({ uri });
876
+ }
877
+ }
750
878
  /** Fan out a save event for the document's URI, gated by the subscription map. */
751
879
  dispatchSaveEvent(event) {
752
880
  // The save event arrives under the CLIENT URI the text store keys by (e.g. a
@@ -855,26 +983,19 @@ export class DataServer {
855
983
  /**
856
984
  * Discriminate the reason for a phase-event-driven update notification.
857
985
  * Uses the most recent `DocumentBuilder.onUpdate` snapshot:
858
- * - URI in the `deleted` list → `'deleted'`
859
986
  * - URI in the `changed` list → `'changed'` (the URI was passed to
860
987
  * `documentBuilder.update(changed, deleted)`, which spans `didChange`
861
988
  * text-document events and programmatic `update([uri], [])` calls).
862
989
  * - Otherwise → `'rebuilt'` (cascade re-derivation: this URI was rebuilt
863
990
  * because something it depends on changed; its own text wasn't flagged).
864
991
  *
865
- * `'saved'` is NOT emitted from this code path — saves take the dedicated
866
- * `DataClientProtocol.onDocumentSaved` channel; adopters that want a
867
- * unified update stream synthesise `'saved'` in their bridge layer.
992
+ * `'saved'` is NOT emitted here — saves take the dedicated
993
+ * `DataClientProtocol.onDocumentSaved` channel, and adopters wanting a
994
+ * unified stream synthesise it in their bridge layer. A deletion is not a
995
+ * reason at all; see {@link dispatchDeleteEvents}.
868
996
  */
869
997
  resolveUpdateReason(uri) {
870
- const last = this.lastBuildUpdate;
871
- if (last?.deleted.some(deleted => UriUtils.equals(deleted, uri))) {
872
- return 'deleted';
873
- }
874
- if (last?.changed.some(changed => UriUtils.equals(changed, uri))) {
875
- return 'changed';
876
- }
877
- return 'rebuilt';
998
+ return this.lastBuildUpdate?.changed.some(changed => UriUtils.equals(changed, uri)) ? 'changed' : 'rebuilt';
878
999
  }
879
1000
  /**
880
1001
  * Subscribe to the project tier's change channel and re-fan registry
@@ -967,7 +1088,7 @@ export class DataServer {
967
1088
  }
968
1089
  async stopProfiling(args) {
969
1090
  if (!this.activeProfile) {
970
- throw new Error('No profiling capture is active; call startProfiling first.');
1091
+ throw noActiveProfileError();
971
1092
  }
972
1093
  const capture = this.activeProfile;
973
1094
  this.activeProfile = undefined;