1use std::collections::{BTreeMap, HashMap, HashSet};
24
25use pax_manifest::code_serialization::{diff_html, press_code_serialization_template};
26use pax_manifest::pax_runtime_api::{Interpolatable, Property};
27use pax_manifest::{
28 ComponentDefinition, ComponentTemplate, NodeLocation, PaxManifest, PropertyDefinition,
29 SettingElement, SettingsBlockElement, TemplateNodeDefinition, TemplateNodeId,
30 TimelineDefinition, TypeId, UniqueTemplateNodeIdentifier, ValueDefinition,
31};
32use serde_derive::{Deserialize, Serialize};
33#[allow(unused_imports)]
34use serde_json;
35
36use self::manifest_modification_data::ManifestModificationData;
37use self::template::class_builder::ClassBuilder;
38use self::template::{
39 node_builder::NodeBuilder, ConvertToComponentRequest, RemoveTemplateNodeRequest,
40};
41use self::template::{GetChildrenRequest, MoveTemplateNodeRequest, PasteSubTreeRequest};
42
43use anyhow::{anyhow, Result};
44pub mod manifest_modification_data;
45pub mod template;
46#[cfg(test)]
47mod tests;
48
49pub trait Request {
50 type Response: Response;
51}
52
53pub trait Response {
54 fn set_id(&mut self, id: usize);
55 fn get_id(&self) -> usize;
56 fn get_reload_type(&self) -> Option<ReloadType> {
57 None
58 }
59}
60
61pub trait Command<R: Request> {
62 fn execute(&mut self, manifest: &mut PaxManifest) -> Result<R::Response, String>;
63 fn as_undo_redo(&mut self) -> Option<UndoRedoCommand> {
64 None
65 }
66}
67
68#[derive(Serialize, Deserialize)]
69pub struct PaxManifestORM {
70 manifest: PaxManifest,
71 #[serde(default)]
75 cartridge_abi_identity: Vec<u8>,
76 undo_stack: Vec<(usize, UndoRedoCommand)>,
77 redo_stack: Vec<(usize, UndoRedoCommand)>,
78 next_command_id: usize,
79 manifest_version: Property<usize>,
81 manifest_modification_data: ManifestModificationData,
82 next_new_component_id: usize,
83 new_components: Vec<TypeId>,
84 reload_queue: HashSet<ReloadType>,
85 pub manifest_loaded_from_server: Property<bool>,
86 pub llm_messages: HashMap<u64, Vec<String>>,
87 pub new_message: Property<Vec<MessageType>>,
88 pub last_serialized_version: HashMap<TypeId, ComponentDefinition>,
89}
90
91impl PaxManifestORM {
92 pub fn new(manifest: PaxManifest) -> Self {
93 let cartridge_abi_identity = runtime_abi_identity(&manifest)
94 .expect("the embedded cartridge manifest should always be serializable");
95 let mut last_serialized_version = HashMap::new();
96 for component in manifest.components.values() {
97 last_serialized_version.insert(component.type_id.clone(), component.clone());
98 }
99
100 PaxManifestORM {
101 manifest,
102 cartridge_abi_identity,
103 undo_stack: Vec::new(),
104 redo_stack: Vec::new(),
105 next_command_id: 0,
106 manifest_version: Property::new(0),
107 manifest_modification_data: Default::default(),
108 next_new_component_id: 1,
109 new_components: Vec::new(),
110 reload_queue: HashSet::new(),
111 manifest_loaded_from_server: Property::new(false),
112 llm_messages: HashMap::new(),
113 new_message: Property::new(vec![]),
114 last_serialized_version,
115 }
116 }
117
118 pub fn add_new_message(
119 &mut self,
120 request_id: u64,
121 message: String,
122 component: Option<ComponentDefinition>,
123 ) {
124 self.llm_messages
125 .entry(request_id)
126 .or_insert(Vec::new())
127 .push(message);
128 self.new_message.update(|msgs| {
129 msgs.push(match component {
130 Some(component) => MessageType::LLMSuccess(component),
131 None => MessageType::LLMPartial,
132 })
133 });
134 }
135
136 pub fn get_messages(&mut self, request_id: u64) -> Vec<String> {
137 self.llm_messages.remove(&request_id).unwrap_or_default()
138 }
139
140 pub fn take_manifest_modification_data(&mut self) -> ManifestModificationData {
144 std::mem::take(&mut self.manifest_modification_data)
145 }
146
147 pub fn get_new_components(&mut self) -> Vec<ComponentDefinition> {
148 let mut new_components_to_process = Vec::new();
149
150 for component_type_id in &self.new_components {
151 if let Some(component) = self.manifest.components.get(component_type_id) {
152 new_components_to_process.push(component.clone());
153 }
154 }
155 self.new_components.clear();
156 new_components_to_process
157 }
158
159 pub fn get_manifest(&self) -> &PaxManifest {
160 &self.manifest
161 }
162
163 pub fn set_manifest(&mut self, manifest: PaxManifest) {
164 self.manifest = manifest;
165 self.increment_manifest_version();
166 self.manifest_loaded_from_server.set(true);
167 self.insert_reload(ReloadType::Tree);
168 }
169
170 pub fn set_initial_server_manifest(&mut self, manifest: PaxManifest) -> Result<()> {
171 validate_runtime_manifest(&manifest)?;
172
173 let incoming_abi_identity = runtime_abi_identity(&manifest)?;
174 if self.cartridge_abi_identity.is_empty() {
175 self.cartridge_abi_identity = runtime_abi_identity(&self.manifest)?;
176 }
177 if incoming_abi_identity != self.cartridge_abi_identity {
178 return Err(anyhow!(
179 "design-server manifest requires a different cartridge generation"
180 ));
181 }
182
183 if !self.manifest_loaded_from_server.get()
184 && self.manifest_version.get() == 0
185 && self.reload_queue.is_empty()
186 {
187 let manifest_changed = !manifests_match(&self.manifest, &manifest);
188 self.manifest = manifest;
189 self.manifest_loaded_from_server.set(true);
190 if manifest_changed {
191 self.increment_manifest_version();
192 self.insert_reload(ReloadType::Tree);
193 }
194 return Ok(());
195 }
196
197 self.set_manifest(manifest);
198 Ok(())
199 }
200
201 pub fn get_manifest_version(&self) -> Property<usize> {
202 self.manifest_version.clone()
203 }
204
205 pub fn insert_reload(&mut self, reload_type: ReloadType) {
206 if let ReloadType::Tree = &reload_type {
207 self.reload_queue.clear();
208 self.reload_queue.insert(ReloadType::Tree);
209 return;
210 }
211 if !self.reload_queue.contains(&ReloadType::Tree) {
212 self.reload_queue.insert(reload_type);
213 }
214 }
215
216 pub fn set_userland_root_component_type_id(&mut self, type_id: &TypeId) {
217 self.manifest.main_component_type_id = type_id.clone();
218 }
219
220 pub fn take_reload_queue(&mut self) -> HashSet<ReloadType> {
221 std::mem::take(&mut self.reload_queue)
222 }
223
224 pub fn increment_manifest_version(&mut self) {
225 self.manifest_version.update(|v| *v += 1);
226 }
227
228 pub fn build_new_node(
229 &mut self,
230 containing_component_type_id: TypeId,
231 node_type_id: TypeId,
232 ) -> NodeBuilder<'_> {
233 NodeBuilder::new(self, containing_component_type_id, node_type_id, true)
234 }
235
236 pub fn get_node_location(&self, uni: &UniqueTemplateNodeIdentifier) -> Option<NodeLocation> {
237 let component = self
238 .manifest
239 .components
240 .get(&uni.get_containing_component_type_id())?;
241 let template = component.template.as_ref()?;
242 template.get_location(&uni.get_template_node_id())
243 }
244
245 pub fn get_siblings(
246 &self,
247 uni: &UniqueTemplateNodeIdentifier,
248 ) -> Option<Vec<UniqueTemplateNodeIdentifier>> {
249 let component = self
250 .manifest
251 .components
252 .get(&uni.get_containing_component_type_id())?;
253 let template = component.template.as_ref()?;
254 Some(
255 template
256 .get_siblings(&uni.get_template_node_id())?
257 .into_iter()
258 .map(|tid| {
259 UniqueTemplateNodeIdentifier::build(uni.get_containing_component_type_id(), tid)
260 })
261 .collect(),
262 )
263 }
264
265 pub fn get_parent(
266 &self,
267 uni: &UniqueTemplateNodeIdentifier,
268 ) -> Option<UniqueTemplateNodeIdentifier> {
269 let component = self
270 .manifest
271 .components
272 .get(&uni.get_containing_component_type_id())?;
273 let template = component.template.as_ref()?;
274 Some(UniqueTemplateNodeIdentifier::build(
275 uni.get_containing_component_type_id(),
276 template.get_parent(&uni.get_template_node_id())?,
277 ))
278 }
279
280 pub fn get_all_property_definitions(&self) -> Vec<&PropertyDefinition> {
281 self.manifest
282 .type_table
283 .values()
284 .flat_map(|v| v.property_definitions.iter())
285 .collect()
286 }
287
288 pub fn get_class(
289 &self,
290 type_id: &TypeId,
291 name: &str,
292 ) -> Result<Vec<(String, ValueDefinition, Option<TypeId>)>> {
293 if !pax_manifest::utils::valid_class_or_id(name) {
294 return Err(anyhow!("not a valid class name"));
295 }
296 let component = self
297 .manifest
298 .components
299 .get(&type_id)
300 .ok_or_else(|| anyhow!("couldn't find component with type id: {type_id:?}"))?;
301 let Some(settings) = &component.settings else {
302 return Err(anyhow!("component has no settings"));
303 };
304 let class_block = settings
305 .iter()
306 .find_map(|setting| match setting {
307 pax_manifest::SettingsBlockElement::SelectorBlock(token, block) => {
308 (token.token_value.ends_with(name)).then_some(block)
309 }
310 _ => None,
311 })
312 .ok_or_else(|| anyhow!("no class with name {name}"))?;
313 let property_definitions: Vec<_> = self.get_all_property_definitions();
316 let mut res = vec![];
317
318 for element in &class_block.elements {
319 if let SettingElement::Setting(token, value_definition) = element {
320 let name = token.token_value.clone();
321 let mut property_definitions_with_name: Vec<_> = property_definitions
322 .iter()
323 .copied()
324 .filter(|pd| pd.name == name)
325 .map(|pd| (&pd.name, &pd.type_id))
326 .collect();
327 property_definitions_with_name.sort();
328 property_definitions_with_name.dedup();
329 let property_type = if property_definitions_with_name.len() != 1 {
330 log::warn!(
331 "class property with name {:?} has an abiguous type, possible types: {:#?}",
332 name,
333 property_definitions_with_name
334 );
335 None
336 } else {
337 property_definitions_with_name.into_iter().next()
338 }
339 .map(|(_, v)| v);
340 res.push((name, value_definition.clone(), property_type.cloned()));
341 }
342 }
343 Ok(res)
344 }
345
346 pub fn get_classes(&self, type_id: &TypeId) -> Result<Vec<String>> {
347 let component = self
348 .manifest
349 .components
350 .get(&type_id)
351 .ok_or_else(|| anyhow!("couldn't find component with type id: {type_id:?}"))?;
352 let Some(settings) = &component.settings else {
353 return Ok(vec![]);
354 };
355 let classes: Vec<_> = settings
356 .iter()
357 .filter_map(|setting| match setting {
358 pax_manifest::SettingsBlockElement::SelectorBlock(token, _block) => {
359 Some(token.token_value.to_string())
360 }
361 _ => None,
362 })
363 .collect();
364 Ok(classes)
365 }
366
367 pub fn move_node(
368 &mut self,
369 uni: UniqueTemplateNodeIdentifier,
370 location: NodeLocation,
371 ) -> Result<usize, String> {
372 let res = self.execute_command(MoveTemplateNodeRequest::new(uni, location))?;
373 Ok(res.get_id())
374 }
375
376 pub fn get_node_children(
377 &mut self,
378 uni: UniqueTemplateNodeIdentifier,
379 ) -> Result<Vec<UniqueTemplateNodeIdentifier>, String> {
380 let resp = self
381 .execute_command(GetChildrenRequest { uni: uni.clone() })
382 .unwrap();
383 Ok(resp.children)
384 }
385
386 pub fn swap_main_component(&mut self, component: ComponentDefinition) -> Result<(), String> {
387 let command = template::SwapMainComponentRequest::new(component);
388 self.execute_command(command)?;
389 Ok(())
390 }
391
392 pub fn copy_subtrees(&self, type_id: &TypeId, nodes: &[TemplateNodeId]) -> Option<SubTrees> {
393 let roots: Vec<_> = nodes.iter().cloned().collect();
394 let mut children = HashMap::new();
395 let mut nodes = HashMap::new();
396
397 let component = self.manifest.components.get(type_id)?;
398 let template = component.template.as_ref()?;
399 let mut to_visit: Vec<_> = roots.iter().cloned().collect();
400 while let Some(node) = to_visit.pop() {
401 if let Some(node_def) = template.get_node(&node) {
402 nodes.insert(node.clone(), node_def.clone());
403 let node_children = template.get_children(&node).unwrap_or_default();
404 children.insert(node.clone(), node_children.clone());
405 to_visit.extend(node_children);
406 }
407 }
408
409 Some(SubTrees {
410 roots,
411 children,
412 nodes,
413 })
414 }
415
416 pub fn paste_subtrees(
417 &mut self,
418 location: NodeLocation,
419 subtrees: SubTrees,
420 ) -> Result<Vec<TemplateNodeId>, String> {
421 let res = self.execute_command(PasteSubTreeRequest::new(location, subtrees))?;
422 Ok(res.get_created().to_vec())
423 }
424
425 pub fn get_node_builder(
426 &mut self,
427 uni: UniqueTemplateNodeIdentifier,
428 overwrite_expressions: bool,
429 ) -> Option<NodeBuilder<'_>> {
430 NodeBuilder::retrieve_node(self, uni, overwrite_expressions)
431 }
432
433 pub fn get_class_builder<'a>(
434 &'a mut self,
435 component_type_id: TypeId,
436 class_name: &'a str,
437 ) -> Result<ClassBuilder<'a>> {
438 ClassBuilder::new(self, component_type_id, class_name)
439 }
440
441 pub fn get_main_component(&self) -> &TypeId {
442 &self.manifest.main_component_type_id
443 }
444
445 pub fn get_components(&self) -> Vec<TypeId> {
446 self.manifest.components.keys().cloned().collect()
447 }
448
449 pub fn get_component(&self, type_id: &TypeId) -> anyhow::Result<&ComponentDefinition> {
450 self.manifest
451 .components
452 .get(type_id)
453 .ok_or(anyhow!("couldn't find component"))
454 }
455
456 pub fn get_property(
457 &self,
458 unid: &UniqueTemplateNodeIdentifier,
459 key: &str,
460 ) -> Option<ValueDefinition> {
461 let tnd = self.manifest.get_template_node(unid)?;
462 if let Some(settings) = &tnd.settings {
463 for setting in settings {
464 if let SettingElement::Setting(token, value) = setting {
465 if token.token_value == key {
466 return Some(value.clone());
467 }
468 }
469 }
470 }
471 None
472 }
473
474 pub fn get_property_type(
475 &self,
476 unid: &UniqueTemplateNodeIdentifier,
477 key: &str,
478 ) -> Option<TypeId> {
479 let tnd = self.manifest.get_template_node(unid)?;
480 let property_types = self.manifest.type_table.get(&tnd.type_id)?;
481 property_types
482 .property_definitions
483 .iter()
484 .find(|v| v.name == key)
485 .map(|v| v.type_id.clone())
486 }
487
488 pub fn remove_node(&mut self, uni: UniqueTemplateNodeIdentifier) -> Result<usize, String> {
489 let command = RemoveTemplateNodeRequest::new(uni);
490 let resp = self.execute_command(command)?;
491 Ok(resp.get_id())
492 }
493
494 pub fn move_to_new_component(
495 &mut self,
496 nodes: &[MoveToComponentEntry],
497 x: f64,
498 y: f64,
499 width: f64,
500 height: f64,
501 ) -> Result<(), String> {
502 let new_component_number = self.next_new_component_id;
503 let command = ConvertToComponentRequest::new(
504 nodes.to_vec(),
505 new_component_number,
506 x,
507 y,
508 width,
509 height,
510 );
511 let resp = self.execute_command(command)?;
512 self.new_components.push(resp.new_component_type_id);
513 self.next_new_component_id += 1;
514 Ok(())
515 }
516
517 pub fn send_component_update(&mut self, type_id: &TypeId) {
518 let current_component = self.manifest.components.get(type_id).unwrap().clone();
519 let prev_component: Option<ComponentDefinition> =
520 self.last_serialized_version.get(type_id).cloned();
521 if let Some(prev_component) = prev_component {
522 let prev_serialized =
523 press_code_serialization_template(prev_component.clone()).unwrap_or("".to_string());
524 let post_serialized = press_code_serialization_template(current_component.clone())
525 .unwrap_or("".to_string());
526 let diff = diff_html(&prev_serialized, &post_serialized);
527 let message_type = diff.map(|d| MessageType::Serialization(d));
528 if let Some(message) = message_type {
529 self.new_message.update(|msgs| {
530 msgs.push(message);
531 });
532 }
533 }
534 self.last_serialized_version
535 .insert(type_id.clone(), current_component);
536 }
537
538 pub fn execute_command<R: Request, C>(&mut self, mut command: C) -> Result<R::Response, String>
539 where
540 C: Command<R>,
541 {
542 let mut response: <R as Request>::Response = command.execute(&mut self.manifest)?;
543 let command_id = self.next_command_id;
544 if let Some(command) = command.as_undo_redo() {
545 self.undo_stack.push((command_id, command));
546 self.redo_stack.clear();
547 }
548
549 response.set_id(command_id);
550 self.next_command_id += 1;
551 if let Some(reload_type) = response.get_reload_type() {
552 match &reload_type {
553 ReloadType::Tree | ReloadType::Subtree(_) => {
554 self.manifest_modification_data.tree_modified = true
555 }
556 ReloadType::Node(_, props) => self
557 .manifest_modification_data
558 .modified_properties
559 .extend(props.iter().cloned()),
560 }
561 self.insert_reload(reload_type);
562 self.manifest_version.update(|v| *v += 1);
563 }
564
565 Ok(response)
566 }
567
568 pub fn undo(&mut self) -> Result<(), String> {
569 if let Some((id, mut command)) = self.undo_stack.pop() {
570 command.undo(&mut self.manifest)?;
571 self.redo_stack.push((id, command));
572 self.manifest_version.update(|v| *v += 1);
573 self.insert_reload(ReloadType::Tree);
574 }
575 Ok(())
576 }
577
578 pub fn redo(&mut self) -> Result<(), String> {
579 if let Some((id, mut command)) = self.redo_stack.pop() {
580 command.redo(&mut self.manifest)?;
581 self.undo_stack.push((id, command));
582 self.manifest_version.update(|v| *v += 1);
583 self.insert_reload(ReloadType::Tree);
584 }
585 Ok(())
586 }
587
588 pub fn get_last_undo_id(&self) -> Option<usize> {
589 self.undo_stack.last().map(|l| l.0)
590 }
591
592 pub fn undo_until(&mut self, command_id: Option<usize>) -> Result<(), String> {
593 while let Some((id, _)) = self.undo_stack.last() {
594 if command_id.is_some_and(|c_id| c_id == *id) {
595 break;
596 }
597 self.undo()?;
598 }
599 Ok(())
600 }
601
602 pub fn redo_including(&mut self, command_id: usize) -> Result<(), String> {
603 while let Some(&(id, _)) = self.redo_stack.last() {
604 self.redo()?;
605 if id == command_id {
606 break;
607 }
608 }
609 Ok(())
610 }
611
612 pub fn replace_template(
613 &mut self,
614 component_type_id: TypeId,
615 template: ComponentTemplate,
616 settings_block: Vec<SettingsBlockElement>,
617 timelines: Vec<TimelineDefinition>,
618 ) -> Result<usize, String> {
619 if !self.manifest.components.contains_key(&component_type_id) {
620 return Err(format!(
621 "design-server template update targets missing component {}",
622 component_type_id
623 ));
624 }
625 validate_template_references(&self.manifest, &component_type_id, &template)
626 .map_err(|err| err.to_string())?;
627
628 let mut prospective_manifest = self.manifest.clone();
633 let component = prospective_manifest
634 .components
635 .get_mut(&component_type_id)
636 .expect("target component presence was checked above");
637 component.template = Some(template.clone());
638 component.settings = Some(settings_block.clone());
639 component.timelines.clone_from(&timelines);
640 let prospective_identity =
641 runtime_abi_identity(&prospective_manifest).map_err(|err| err.to_string())?;
642 if prospective_identity != self.cartridge_abi_identity {
643 return Err(
644 "design-server template update requires different runtime descriptors".to_string(),
645 );
646 }
647
648 let command = template::ReplaceTemplateRequest::new(
649 component_type_id,
650 template,
651 settings_block,
652 timelines,
653 );
654 let resp = self.execute_command(command)?;
655 Ok(resp.get_id())
656 }
657
658 pub fn replace_node_subtree(
659 &mut self,
660 uni: UniqueTemplateNodeIdentifier,
661 new_subtree: Option<template::SerializedTemplateNodeSubtree>,
662 reload_uni: Option<UniqueTemplateNodeIdentifier>,
663 ) -> Result<usize, String> {
664 let command = template::ReplaceNodeSubtreeRequest::new(uni, new_subtree, reload_uni);
665 let resp = self.execute_command(command)?;
666 Ok(resp.get_id())
667 }
668
669 pub fn component_has_slots(&self, type_id: &TypeId) -> bool {
670 let Some(component) = self.manifest.components.get(type_id) else {
671 return false;
672 };
673 let Some(template) = component.template.as_ref() else {
674 return false;
675 };
676 template.contains_slots()
677 }
678}
679
680fn manifests_match(left: &PaxManifest, right: &PaxManifest) -> bool {
681 if !type_tables_match(left, right) {
682 return false;
683 }
684
685 let left_identity = (
686 &left.components,
687 &left.main_component_type_id,
688 &left.assets_dirs,
689 &left.engine_import_path,
690 );
691 let right_identity = (
692 &right.components,
693 &right.main_component_type_id,
694 &right.assets_dirs,
695 &right.engine_import_path,
696 );
697 match (
698 rmp_serde::to_vec(&left_identity),
699 rmp_serde::to_vec(&right_identity),
700 ) {
701 (Ok(left), Ok(right)) => left == right,
702 _ => false,
703 }
704}
705
706fn type_tables_match(left: &PaxManifest, right: &PaxManifest) -> bool {
707 if left.type_table.len() != right.type_table.len() {
708 return false;
709 }
710
711 left.type_table.iter().all(|(type_id, left_definition)| {
712 let Some(right_definition) = right.type_table.get(type_id) else {
713 return false;
714 };
715 match (
716 rmp_serde::to_vec(left_definition),
717 rmp_serde::to_vec(right_definition),
718 ) {
719 (Ok(left), Ok(right)) => left == right,
720 _ => false,
721 }
722 })
723}
724
725pub fn runtime_abi_identity(manifest: &PaxManifest) -> Result<Vec<u8>> {
733 let component_identity = manifest
734 .components
735 .values()
736 .map(|component| {
737 (
738 &component.type_id,
739 component.is_primitive,
740 component.is_struct_only_component,
741 &component.primitive_instance_import_path,
742 )
743 })
744 .collect::<Vec<_>>();
745 let mut type_identity = manifest.type_table.iter().collect::<Vec<_>>();
746 type_identity.sort_by(|(left, _), (right, _)| left.cmp(right));
747
748 let handler_identity = generated_handler_identity(manifest)?;
749
750 rmp_serde::to_vec(&(component_identity, type_identity, handler_identity))
751 .map_err(|err| anyhow!("failed to identify cartridge ABI: {err}"))
752}
753
754fn generated_handler_identity(
759 manifest: &PaxManifest,
760) -> Result<Vec<(TypeId, Vec<(String, Vec<Option<String>>)>)>> {
761 let event_map = manifest.event_to_args_map();
762 let mut component_handlers = Vec::new();
763
764 for component in manifest.components.values() {
765 if component.is_struct_only_component {
766 continue;
767 }
768
769 let mut handlers = BTreeMap::new();
770 if let Some(settings) = &component.settings {
771 for setting in settings {
772 if let SettingsBlockElement::Handler(event, targets) = setting {
773 let args_type = event_map
774 .get(event.token_value.as_str())
775 .ok_or_else(|| {
776 anyhow!(
777 "custom handler event {} is not supported in settings blocks",
778 event.token_value
779 )
780 })?
781 .as_ref()
782 .map(|args| format!("Event<{args}>"));
783 for target in targets {
784 record_handler_identity(
785 &mut handlers,
786 clean_handler_name(&target.token_value),
787 args_type.clone(),
788 );
789 }
790 }
791 }
792 }
793
794 if let Some(template) = &component.template {
795 for node in template.get_nodes() {
796 let Some(settings) = &node.settings else {
797 continue;
798 };
799 for setting in settings {
800 if let SettingElement::Setting(
801 event,
802 ValueDefinition::EventBindingTarget(target),
803 ) = setting
804 {
805 let args_type = event_map
806 .get(event.token_value.as_str())
807 .and_then(|args| args.as_ref())
808 .map(|args| format!("Event<{args}>"));
809 record_handler_identity(
810 &mut handlers,
811 clean_handler_name(&target.name),
812 args_type,
813 );
814 }
815 }
816 }
817 }
818
819 component_handlers.push((component.type_id.clone(), handlers.into_iter().collect()));
820 }
821
822 Ok(component_handlers)
823}
824
825fn record_handler_identity(
826 handlers: &mut BTreeMap<String, Vec<Option<String>>>,
827 name: String,
828 args_type: Option<String>,
829) {
830 let signatures = handlers.entry(name).or_default();
831 let differs_from_first = signatures
832 .first()
833 .map(|first| first != &args_type)
834 .unwrap_or(true);
835
836 if differs_from_first {
840 signatures.push(args_type);
841 }
842}
843
844fn clean_handler_name(name: &str) -> String {
845 name.replace("self.", "").replace("this.", "")
846}
847
848fn validate_runtime_manifest(manifest: &PaxManifest) -> Result<()> {
849 if !manifest
850 .components
851 .contains_key(&manifest.main_component_type_id)
852 {
853 return Err(anyhow!(
854 "design-server manifest is missing its main component {}",
855 manifest.main_component_type_id
856 ));
857 }
858
859 for (containing_type_id, component) in &manifest.components {
860 let Some(template) = &component.template else {
861 continue;
862 };
863 validate_template_references(manifest, containing_type_id, template)?;
864 }
865
866 Ok(())
867}
868
869fn validate_template_references(
870 manifest: &PaxManifest,
871 containing_type_id: &TypeId,
872 template: &ComponentTemplate,
873) -> Result<()> {
874 for node in template.get_nodes() {
875 if matches!(
876 node.type_id.get_pax_type(),
877 pax_manifest::PaxType::If
878 | pax_manifest::PaxType::Router
879 | pax_manifest::PaxType::Slot
880 | pax_manifest::PaxType::Repeat
881 | pax_manifest::PaxType::Comment
882 ) {
883 continue;
884 }
885 if !manifest.components.contains_key(&node.type_id) {
886 return Err(anyhow!(
887 "design-server manifest component {} references missing component {}",
888 containing_type_id,
889 node.type_id
890 ));
891 }
892 }
893
894 Ok(())
895}
896
897pub trait Undo {
898 fn undo(&mut self, manifest: &mut PaxManifest) -> Result<(), String>;
899}
900
901#[derive(Serialize, Deserialize)]
902pub enum UndoRedoCommand {
903 AddTemplateNodeRequest(Box<template::AddTemplateNodeRequest>),
904 RemoveTemplateNodeRequest(Box<template::RemoveTemplateNodeRequest>),
905 MoveTemplateNodeRequest(Box<template::MoveTemplateNodeRequest>),
906 UpdateTemplateNodeRequest(Box<template::UpdateTemplateNodeRequest>),
907 UpdateClassRequest(Box<template::UpdateClassRequest>),
908 PasteSubTreeRequest(Box<template::PasteSubTreeRequest>),
909 ReplaceTemplateRequest(Box<template::ReplaceTemplateRequest>),
910 ReplaceNodeSubtreeRequest(Box<template::ReplaceNodeSubtreeRequest>),
911 ConvertToComponentRequest(Box<template::ConvertToComponentRequest>),
912 SwapMainComponentRequest(Box<template::SwapMainComponentRequest>),
913}
914
915impl UndoRedoCommand {
916 fn undo(&mut self, manifest: &mut PaxManifest) -> Result<(), String> {
917 match self {
918 UndoRedoCommand::MoveTemplateNodeRequest(command) => command.undo(manifest),
919 UndoRedoCommand::AddTemplateNodeRequest(command) => command.undo(manifest),
920 UndoRedoCommand::RemoveTemplateNodeRequest(command) => command.undo(manifest),
921 UndoRedoCommand::UpdateTemplateNodeRequest(command) => command.undo(manifest),
922 UndoRedoCommand::UpdateClassRequest(command) => command.undo(manifest),
923 UndoRedoCommand::PasteSubTreeRequest(command) => command.undo(manifest),
924 UndoRedoCommand::ReplaceTemplateRequest(command) => command.undo(manifest),
925 UndoRedoCommand::ReplaceNodeSubtreeRequest(command) => command.undo(manifest),
926 UndoRedoCommand::ConvertToComponentRequest(command) => command.undo(manifest),
927 UndoRedoCommand::SwapMainComponentRequest(command) => command.undo(manifest),
928 }
929 }
930
931 fn redo(&mut self, manifest: &mut PaxManifest) -> Result<(), String> {
932 match self {
933 UndoRedoCommand::AddTemplateNodeRequest(command) => {
934 let _ = command.execute(manifest);
935 }
936 UndoRedoCommand::RemoveTemplateNodeRequest(command) => {
937 let _ = command.execute(manifest);
938 }
939 UndoRedoCommand::MoveTemplateNodeRequest(command) => {
940 let _ = command.execute(manifest);
941 }
942 UndoRedoCommand::UpdateTemplateNodeRequest(command) => {
943 let _ = command.execute(manifest);
944 }
945 UndoRedoCommand::UpdateClassRequest(command) => {
946 let _ = command.execute(manifest);
947 }
948 UndoRedoCommand::PasteSubTreeRequest(command) => {
949 let _ = command.execute(manifest);
950 }
951 UndoRedoCommand::ReplaceTemplateRequest(command) => {
952 let _ = command.execute(manifest);
953 }
954 UndoRedoCommand::ReplaceNodeSubtreeRequest(command) => {
955 let _ = command.execute(manifest);
956 }
957 UndoRedoCommand::ConvertToComponentRequest(command) => {
958 let _ = command.execute(manifest);
959 }
960 UndoRedoCommand::SwapMainComponentRequest(command) => {
961 let _ = command.execute(manifest);
962 }
963 }
964 Ok(())
965 }
966}
967
968#[derive(Serialize, Deserialize, Clone, Debug)]
969pub struct MoveToComponentEntry {
970 pub x: f64,
971 pub y: f64,
972 pub width: f64,
973 pub height: f64,
974 pub id: UniqueTemplateNodeIdentifier,
975}
976
977#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, Hash, Eq)]
978pub enum ReloadType {
979 Tree,
980 Subtree(UniqueTemplateNodeIdentifier),
981 Node(UniqueTemplateNodeIdentifier, Vec<String>),
982 }
985
986impl Interpolatable for SubTrees {}
987
988#[derive(Serialize, Deserialize, Clone, Debug, Default)]
989pub struct SubTrees {
990 roots: Vec<TemplateNodeId>,
991 children: HashMap<TemplateNodeId, Vec<TemplateNodeId>>,
992 nodes: HashMap<TemplateNodeId, TemplateNodeDefinition>,
993}
994
995#[derive(Serialize, Deserialize, Clone)]
996pub enum MessageType {
997 Serialization(String),
998 LLMPartial,
999 LLMSuccess(ComponentDefinition),
1000}
1001
1002impl Interpolatable for MessageType {}