Skip to main content

Mountain/Environment/DocumentProvider/
Notifications.rs

1//! Document lifecycle notification helpers.
2//!
3//! Sends LSP-style RPC notifications to the Cocoon extension-host sidecar
4//! so its `ExtHostDocuments` model stays in sync with Mountain's
5//! `OpenDocuments` state. All four helpers follow the same pattern:
6//! serialize a payload, call `IPCProvider::SendNotificationToSideCar`, and
7//! log any emit error without propagating it (notifications are
8//! fire-and-forget).
9//!
10//! | Helper | Cocoon RPC method | Trigger |
11//! |---|---|---|
12//! | `notify_model_added` | `$acceptModelAdded` | document opened / created |
13//! | `notify_model_changed` | `$acceptModelChanged` | incremental text edit applied |
14//! | `notify_model_saved` | `$acceptModelSaved` | document written to disk |
15//! | `notify_model_removed` | `$acceptModelRemoved` | document closed or renamed |
16
17use std::sync::Arc;
18
19use CommonLibrary::{Environment::Requires::Requires, IPC::IPCProvider::IPCProvider};
20use serde_json::json;
21use url::Url;
22
23use crate::dev_log;
24
25/// Notifies Cocoon that a new document model has been added.
26pub(super) async fn notify_model_added(
27	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
28
29	document_state_dto:&serde_json::Value,
30) {
31	let uri_string = document_state_dto
32		.get("URI")
33		.and_then(serde_json::Value::as_str)
34		.unwrap_or("unknown");
35
36	dev_log!("model", "[DocumentProvider] Notifying ModelAdded for: {}", uri_string);
37
38	let payload = json!([document_state_dto]);
39
40	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
41
42	if let Err(error) = ipc_provider
43		.SendNotificationToSideCar("cocoon-main".to_string(), "$acceptModelAdded".to_string(), payload)
44		.await
45	{
46		dev_log!(
47			"model",
48			"error: [DocumentProvider] Failed to send $acceptModelAdded for {}: {}",
49			uri_string,
50			error
51		);
52	}
53}
54
55/// Notifies Cocoon that a document's content has changed.
56pub(super) async fn notify_model_changed(
57	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
58
59	uri:&Url,
60
61	new_version:i64,
62
63	changes:serde_json::Value,
64) {
65	dev_log!("model", "[DocumentProvider] Notifying ModelChanged for: {}", uri);
66
67	let uri_components = json!({ "external": uri.to_string(), "$mid": 1 });
68
69	let event_data = json!({ "versionId": new_version, "changes": changes, "isDirty": true });
70
71	let payload = json!([uri_components, event_data]);
72
73	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
74
75	if let Err(error) = ipc_provider
76		.SendNotificationToSideCar("cocoon-main".to_string(), "$acceptModelChanged".to_string(), payload)
77		.await
78	{
79		dev_log!(
80			"model",
81			"error: [DocumentProvider] Failed to send $acceptModelChanged for {}: {}",
82			uri,
83			error
84		);
85	}
86}
87
88/// Notifies Cocoon that a document has been saved to disk.
89pub(super) async fn notify_model_saved(
90	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
91
92	uri:&Url,
93) {
94	dev_log!("model", "[DocumentProvider] Notifying ModelSaved for: {}", uri);
95
96	let uri_components = json!({ "external": uri.to_string(), "$mid": 1 });
97
98	let payload = json!([uri_components]);
99
100	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
101
102	if let Err(error) = ipc_provider
103		.SendNotificationToSideCar("cocoon-main".to_string(), "$acceptModelSaved".to_string(), payload)
104		.await
105	{
106		dev_log!(
107			"model",
108			"error: [DocumentProvider] Failed to send $acceptModelSaved for {}: {}",
109			uri,
110			error
111		);
112	}
113}
114
115/// Notifies Cocoon that a document has been closed or renamed.
116pub(super) async fn notify_model_removed(
117	environment:&crate::Environment::MountainEnvironment::MountainEnvironment,
118
119	uri:&Url,
120) {
121	dev_log!("model", "[DocumentProvider] Notifying ModelRemoved for: {}", uri);
122
123	let uri_components = json!({ "external": uri.to_string(), "$mid": 1 });
124
125	let payload = json!([uri_components]);
126
127	let ipc_provider:Arc<dyn IPCProvider> = environment.Require();
128
129	if let Err(error) = ipc_provider
130		.SendNotificationToSideCar("cocoon-main".to_string(), "$acceptModelRemoved".to_string(), payload)
131		.await
132	{
133		dev_log!(
134			"model",
135			"error: [DocumentProvider] Failed to send $acceptModelRemoved for {}: {}",
136			uri,
137			error
138		);
139	}
140}