stac_server/backend/mod.rs
1mod memory;
2#[cfg(feature = "pgstac")]
3mod pgstac;
4
5use crate::Result;
6pub use memory::MemoryBackend;
7#[cfg(feature = "pgstac")]
8pub use pgstac::PgstacBackend;
9use stac::{Collection, Item};
10use stac_api::{ItemCollection, Items, Search};
11use std::future::Future;
12
13/// Storage backend for a STAC API.
14pub trait Backend: Clone + Sync + Send + 'static {
15 /// Returns true if this backend has item search capabilities.
16 ///
17 /// # Examples
18 ///
19 /// ```
20 /// use stac_server::{MemoryBackend, Backend};
21 ///
22 /// assert!(MemoryBackend::new().has_item_search());
23 /// ```
24 fn has_item_search(&self) -> bool;
25
26 /// Returns true if this backend has [filter](https://github.com/stac-api-extensions/filter) capabilities.
27 ///
28 /// # Examples
29 ///
30 /// ```
31 /// use stac_server::{MemoryBackend, Backend};
32 ///
33 /// assert!(!MemoryBackend::new().has_filter());
34 /// ```
35 fn has_filter(&self) -> bool;
36
37 /// Returns all collections.
38 ///
39 /// # Examples
40 ///
41 /// ```
42 /// use stac_server::{MemoryBackend, Backend};
43 /// let backend = MemoryBackend::new();
44 /// # tokio_test::block_on(async {
45 /// let collections = backend.collections().await.unwrap();
46 /// assert!(collections.is_empty());
47 /// # })
48 /// ```
49 fn collections(&self) -> impl Future<Output = Result<Vec<Collection>>> + Send;
50
51 /// Returns a single collection.
52 ///
53 /// # Examples
54 ///
55 /// ```
56 /// use stac_server::{MemoryBackend, Backend};
57 /// let backend = MemoryBackend::new();
58 /// # tokio_test::block_on(async {
59 /// let collection = backend.collection("does-not-exist").await.unwrap();
60 /// assert!(collection.is_none());
61 /// # })
62 /// ```
63 fn collection(&self, id: &str) -> impl Future<Output = Result<Option<Collection>>> + Send;
64
65 /// Adds a collection.
66 ///
67 /// # Examples
68 ///
69 /// ```
70 /// use stac::Collection;
71 /// use stac_server::{MemoryBackend, Backend};
72 ///
73 /// let mut backend = MemoryBackend::new();
74 /// # tokio_test::block_on(async {
75 /// backend.add_collection(Collection::new("an-id", "a description")).await.unwrap();
76 /// # })
77 /// ```
78 fn add_collection(&mut self, collection: Collection)
79 -> impl Future<Output = Result<()>> + Send;
80
81 /// Adds an item.
82 ///
83 /// If the item doesn't have its `collection` field set, or a collection
84 /// with that id does not exist in the backend, throws an error.
85 ///
86 /// # Examples
87 ///
88 /// ```
89 /// use stac::{Collection, Item};
90 /// use stac_server::{MemoryBackend, Backend};
91 ///
92 /// let mut backend = MemoryBackend::new();
93 /// # tokio_test::block_on(async {
94 /// assert!(backend.add_item(Item::new("item-id")).await.is_err());
95 ///
96 /// backend.add_collection(Collection::new("collection-id", "a description")).await.unwrap();
97 /// backend.add_item(Item::new("item-id").collection("collection-id")).await.unwrap();
98 /// # })
99 /// ```
100 fn add_item(&mut self, item: Item) -> impl Future<Output = Result<()>> + Send;
101
102 /// Adds multiple items.
103 fn add_items(&mut self, items: Vec<Item>) -> impl Future<Output = Result<()>> + Send {
104 tracing::debug!("adding {} items using naïve loading", items.len());
105 async move {
106 for item in items {
107 self.add_item(item).await?;
108 }
109 Ok(())
110 }
111 }
112
113 /// Retrieves items for a given collection.
114 ///
115 /// # Examples
116 ///
117 /// ```
118 /// use stac::{Collection, Item};
119 /// use stac_api::Items;
120 /// use stac_server::{MemoryBackend, Backend};
121 ///
122 /// let mut backend = MemoryBackend::new();
123 /// # tokio_test::block_on(async {
124 /// backend.add_collection(Collection::new("collection-id", "a description")).await.unwrap();
125 /// backend.add_item(Item::new("item-id").collection("collection-id")).await.unwrap();
126 /// let items = backend.items("collection-id", Items::default()).await.unwrap();
127 /// # })
128 /// ```
129 fn items(
130 &self,
131 collection_id: &str,
132 items: Items,
133 ) -> impl Future<Output = Result<Option<ItemCollection>>> + Send;
134
135 /// Retrieves an item from a collection.
136 ///
137 /// # Examples
138 ///
139 /// ```
140 /// use stac::{Collection, Item};
141 /// use stac_server::{MemoryBackend, Backend};
142 ///
143 /// let mut backend = MemoryBackend::new();
144 /// # tokio_test::block_on(async {
145 /// backend.add_collection(Collection::new("collection-id", "a description")).await.unwrap();
146 /// backend.add_item(Item::new("item-id").collection("collection-id")).await.unwrap();
147 /// let item = backend.item("collection-id", "item-id").await.unwrap().unwrap();
148 /// # })
149 /// ```
150 fn item(
151 &self,
152 collection_id: &str,
153 item_id: &str,
154 ) -> impl Future<Output = Result<Option<Item>>> + Send;
155
156 /// Searches a backend.
157 ///
158 /// # Examples
159 ///
160 /// ```
161 /// use stac_api::Search;
162 /// use stac_server::{MemoryBackend, Backend};
163 ///
164 /// let mut backend = MemoryBackend::new();
165 /// # tokio_test::block_on(async {
166 /// let item_collection = backend.search(Search::default()).await.unwrap();
167 /// # })
168 /// ```
169 fn search(&self, search: Search) -> impl Future<Output = Result<ItemCollection>> + Send;
170}