stateset_embedded/
custom_objects.rs1use stateset_core::{
4 CreateCustomObject, CreateCustomObjectType, CustomObject, CustomObjectFilter, CustomObjectType,
5 CustomObjectTypeFilter, Result, UpdateCustomObject, UpdateCustomObjectType,
6};
7use stateset_db::Database;
8use std::sync::Arc;
9use uuid::Uuid;
10
11#[cfg(feature = "events")]
12use crate::events::EventSystem;
13#[cfg(feature = "events")]
14use stateset_core::CommerceEvent;
15
16pub struct CustomObjects {
18 db: Arc<dyn Database>,
19 #[cfg(feature = "events")]
20 event_system: Arc<EventSystem>,
21}
22
23impl std::fmt::Debug for CustomObjects {
24 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
25 f.debug_struct("CustomObjects").finish_non_exhaustive()
26 }
27}
28
29impl CustomObjects {
30 #[cfg(feature = "events")]
31 pub(crate) fn new(db: Arc<dyn Database>, event_system: Arc<EventSystem>) -> Self {
32 Self { db, event_system }
33 }
34
35 #[cfg(not(feature = "events"))]
36 pub(crate) fn new(db: Arc<dyn Database>) -> Self {
37 Self { db }
38 }
39
40 #[cfg(feature = "events")]
41 fn emit(&self, event: CommerceEvent) {
42 self.event_system.emit(event);
43 }
44
45 #[cfg(feature = "events")]
46 fn type_fields_changed(input: &UpdateCustomObjectType) -> Vec<String> {
47 let mut fields = Vec::new();
48 if input.display_name.is_some() {
49 fields.push("display_name".to_string());
50 }
51 if input.description.is_some() {
52 fields.push("description".to_string());
53 }
54 if input.fields.is_some() {
55 fields.push("fields".to_string());
56 }
57 fields
58 }
59
60 #[cfg(feature = "events")]
61 fn object_fields_changed(input: &UpdateCustomObject) -> Vec<String> {
62 let mut fields = Vec::new();
63 if input.handle.is_some() {
64 fields.push("handle".to_string());
65 }
66 if input.owner_type.is_some() || input.owner_id.is_some() {
67 fields.push("owner".to_string());
68 }
69 if input.values.is_some() {
70 fields.push("values".to_string());
71 }
72 fields
73 }
74
75 pub fn create_type(&self, input: CreateCustomObjectType) -> Result<CustomObjectType> {
80 let ty = self.db.custom_objects().create_type(input)?;
81 #[cfg(feature = "events")]
82 {
83 self.emit(CommerceEvent::CustomObjectTypeCreated {
84 type_id: ty.id,
85 handle: ty.handle.clone(),
86 timestamp: ty.created_at,
87 });
88 }
89 Ok(ty)
90 }
91
92 pub fn get_type(&self, id: Uuid) -> Result<Option<CustomObjectType>> {
93 self.db.custom_objects().get_type(id)
94 }
95
96 pub fn get_type_by_handle(&self, handle: &str) -> Result<Option<CustomObjectType>> {
97 self.db.custom_objects().get_type_by_handle(handle)
98 }
99
100 pub fn update_type(&self, id: Uuid, input: UpdateCustomObjectType) -> Result<CustomObjectType> {
101 #[cfg(feature = "events")]
102 let fields_changed = Self::type_fields_changed(&input);
103
104 let updated = self.db.custom_objects().update_type(id, input)?;
105
106 #[cfg(feature = "events")]
107 if !fields_changed.is_empty() {
108 self.emit(CommerceEvent::CustomObjectTypeUpdated {
109 type_id: updated.id,
110 handle: updated.handle.clone(),
111 fields_changed,
112 timestamp: updated.updated_at,
113 });
114 }
115
116 Ok(updated)
117 }
118
119 pub fn list_types(&self, filter: CustomObjectTypeFilter) -> Result<Vec<CustomObjectType>> {
120 self.db.custom_objects().list_types(filter)
121 }
122
123 pub fn delete_type(&self, id: Uuid) -> Result<()> {
124 #[cfg(feature = "events")]
125 let ty = self.db.custom_objects().get_type(id)?;
126
127 self.db.custom_objects().delete_type(id)?;
128
129 #[cfg(feature = "events")]
130 if let Some(ty) = ty {
131 self.emit(CommerceEvent::CustomObjectTypeDeleted {
132 type_id: ty.id,
133 handle: ty.handle,
134 timestamp: chrono::Utc::now(),
135 });
136 }
137
138 Ok(())
139 }
140
141 pub fn create_object(&self, input: CreateCustomObject) -> Result<CustomObject> {
146 let obj = self.db.custom_objects().create_object(input)?;
147 #[cfg(feature = "events")]
148 {
149 self.emit(CommerceEvent::CustomObjectCreated {
150 object_id: obj.id,
151 type_handle: obj.type_handle.clone(),
152 owner_type: obj.owner_type.clone(),
153 owner_id: obj.owner_id.clone(),
154 timestamp: obj.created_at,
155 });
156 }
157 Ok(obj)
158 }
159
160 pub fn get_object(&self, id: Uuid) -> Result<Option<CustomObject>> {
161 self.db.custom_objects().get_object(id)
162 }
163
164 pub fn get_object_by_handle(
165 &self,
166 type_handle: &str,
167 object_handle: &str,
168 ) -> Result<Option<CustomObject>> {
169 self.db.custom_objects().get_object_by_handle(type_handle, object_handle)
170 }
171
172 pub fn update_object(&self, id: Uuid, input: UpdateCustomObject) -> Result<CustomObject> {
173 #[cfg(feature = "events")]
174 let fields_changed = Self::object_fields_changed(&input);
175
176 let updated = self.db.custom_objects().update_object(id, input)?;
177
178 #[cfg(feature = "events")]
179 if !fields_changed.is_empty() {
180 self.emit(CommerceEvent::CustomObjectUpdated {
181 object_id: updated.id,
182 type_handle: updated.type_handle.clone(),
183 fields_changed,
184 timestamp: updated.updated_at,
185 });
186 }
187
188 Ok(updated)
189 }
190
191 pub fn list_objects(&self, filter: CustomObjectFilter) -> Result<Vec<CustomObject>> {
192 self.db.custom_objects().list_objects(filter)
193 }
194
195 pub fn delete_object(&self, id: Uuid) -> Result<()> {
196 #[cfg(feature = "events")]
197 let obj = self.db.custom_objects().get_object(id)?;
198
199 self.db.custom_objects().delete_object(id)?;
200
201 #[cfg(feature = "events")]
202 if let Some(obj) = obj {
203 self.emit(CommerceEvent::CustomObjectDeleted {
204 object_id: obj.id,
205 type_handle: obj.type_handle,
206 timestamp: chrono::Utc::now(),
207 });
208 }
209
210 Ok(())
211 }
212}