1mod entities;
8mod utils;
9
10pub use hdk_extensions::hdi;
11pub use hdk_extensions::hdi_extensions;
12pub use hdk_extensions::hdk;
13pub use hdk_extensions;
14
15use std::convert::TryFrom;
16use hdk::prelude::*;
17use hdi_extensions::{
18 summon_create_action,
19 trace_origin_root,
20};
21use hdk_extensions::{
22 must_get,
23 follow_evolutions,
24};
25
26pub use entities::{
27 Entity, EmptyEntity,
28 EntryModel,
29};
30pub use utils::{
31 now,
32 to_entry_type,
33 create_link_input,
34};
35
36
37pub type EntityId = ActionHash;
38
39
40#[derive(Debug, Serialize, Deserialize)]
41pub struct GetEntityInput {
42 pub id: ActionHash,
43}
44
45impl Into<GetEntityInput> for ActionHash {
46 fn into(self) -> GetEntityInput {
47 GetEntityInput {
48 id: self,
49 }
50 }
51}
52
53#[derive(Debug, Serialize, Deserialize)]
54pub struct UpdateEntityInput<T> {
55 pub base: ActionHash,
56 pub properties: T,
57}
58
59impl<T> UpdateEntityInput<T> {
60 pub fn new(base: ActionHash, properties: T) -> Self {
61 UpdateEntityInput { base, properties }
62 }
63}
64
65
66
67pub fn create_entity<T,I,E>(entry: &T) -> ExternResult<Entity<T>>
69where
70 ScopedEntryDefIndex: for<'a> TryFrom<&'a I, Error = WasmError>,
71 EntryVisibility: for<'a> From<&'a I>,
72 Entry: TryFrom<I, Error = E>,
73 Entry: TryFrom<T, Error = E>,
74 WasmError: From<E>,
75 T: Clone + EntryModel<I>,
76{
77 let entry_hash = hash_entry( entry.to_owned() )?;
78 let action_hash = create_entry( entry.to_input() )?;
79
80 Ok(Entity {
81 id: action_hash.to_owned(),
82 address: entry_hash,
83 action: action_hash,
84 ctype: entry.get_type(),
85 content: entry.to_owned(),
86 })
87}
88
89pub fn get_entity<I,ET>(id: &ActionHash) -> ExternResult<Entity<I>>
91where
92 I: TryFrom<Record, Error = WasmError> + Clone + EntryModel<ET>,
93 Entry: TryFrom<I, Error = WasmError>,
94 ScopedEntryDefIndex: for<'a> TryFrom<&'a ET, Error = WasmError>,
95{
96 must_get( id )?;
98 summon_create_action( id )?;
100
101 let latest_addr = follow_evolutions( &id )?.last().unwrap().to_owned();
102 let record = must_get( &latest_addr )?;
103 let content : I = to_entry_type( record.clone() )?;
104 let address = record
105 .action()
106 .entry_hash().unwrap(); Ok(Entity {
109 id: id.to_owned(),
110 action: record.action_address().to_owned(),
111 address: address.to_owned(),
112 ctype: content.get_type(),
113 content: content,
114 })
115}
116
117pub fn update_entity<T,I,F,E>(addr: &ActionHash, callback: F) -> ExternResult<Entity<T>>
119where
120 ScopedEntryDefIndex: for<'a> TryFrom<&'a I, Error = WasmError>,
121 Entry: TryFrom<I, Error = E>,
122 Entry: TryFrom<T, Error = E>,
123 WasmError: From<E>,
124 T: TryFrom<Record, Error = WasmError>,
125 T: Clone + EntryModel<I>,
126 F: FnOnce(T, Record) -> ExternResult<T>,
127{
128 let (id,_) = trace_origin_root( &addr )?;
131 let record = must_get( addr )?;
132
133 let current : T = to_entry_type( record.clone() )?;
134 let updated_entry = callback( current, record.clone() )?;
135
136 let entry_hash = hash_entry( updated_entry.to_owned() )?;
137 let action_hash = update_entry( addr.clone(), updated_entry.to_input() )?;
138
139 Ok(Entity {
140 id: id,
141 action: action_hash,
142 address: entry_hash,
143 ctype: updated_entry.get_type(),
144 content: updated_entry,
145 })
146}
147
148pub fn delete_entity<T,ET>(id: &ActionHash) -> ExternResult<ActionHash>
150where
151 T: TryFrom<Record, Error = WasmError> + Clone + EntryModel<ET>,
152 Entry: TryFrom<T, Error = WasmError>,
153 ScopedEntryDefIndex: for<'a> TryFrom<&'a ET, Error = WasmError>,
154{
155 summon_create_action( &id )?;
157
158 let record = must_get( id )?;
159 let _ : T = to_entry_type( record.clone() )?;
160 debug!("Deleting record of Entity ID: {}", id );
161 let delete_hash = delete_entry( id.to_owned() )?;
162
163 Ok( delete_hash )
164}
165
166
167pub fn get_entities<T,LT,ET,B>(id: &B, link_type: LT, tag: Option<Vec<u8>>) -> ExternResult<Vec<Entity<T>>>
169where
170 T: TryFrom<Record, Error = WasmError> + Clone + EntryModel<ET>,
171 B: Into<AnyLinkableHash> + Clone,
172 LT: LinkTypeFilterExt + Clone,
173 Entry: TryFrom<T, Error = WasmError>,
174 ScopedEntryDefIndex: for<'a> TryFrom<&'a ET, Error = WasmError>,
175{
176 let links = get_links(
177 create_link_input(
178 id,
179 &link_type,
180 &tag,
181 )?
182 )?;
183
184 debug!("get_entities for {} links: {:#?}", links.len(), links );
185 let list = links.into_iter()
186 .filter_map(|link| {
187 debug!("Get entity for ID: {:?}", link.target );
188 link.target.into_action_hash()
189 .and_then( |target| get_entity( &target ).ok() )
190 })
191 .collect();
192
193 Ok(list)
194}