junobuild_storage/
types.rs

1pub mod state {
2    use crate::types::config::StorageConfig;
3    use crate::types::store::Asset;
4    use candid::{CandidType, Deserialize};
5    use junobuild_collections::types::rules::Rules;
6    use junobuild_shared::types::core::Key;
7    use junobuild_shared::types::domain::CustomDomains;
8    use serde::Serialize;
9    use std::collections::HashMap;
10
11    /// Represents the relative path of an asset in the storage.
12    ///
13    /// This type, `FullPath`, is an alias for `Key`, indicating the relative path of an asset within the storage system.
14    ///
15    /// `FullPath` is commonly used to identify the location of assets within a storage system.
16    pub type FullPath = Key;
17
18    /// An optional access token that can be used to make an asset private on the web.
19    /// Private as in practically unguessable (if complex enough and not shared of course).
20    pub type AssetAccessToken = Option<String>;
21
22    pub type AssetsHeap = HashMap<FullPath, Asset>;
23
24    #[derive(CandidType, Serialize, Deserialize, Clone)]
25    pub struct StorageHeapState {
26        pub assets: AssetsHeap,
27        pub rules: Rules,
28        pub config: StorageConfig,
29        pub custom_domains: CustomDomains,
30    }
31}
32
33pub mod runtime_state {
34    use crate::certification::types::certified::CertifiedAssetHashes;
35    use crate::types::store::{Batch, Chunk};
36    use junobuild_shared::rate::types::RateTokenStore;
37    use serde::{Deserialize, Serialize};
38    use std::collections::HashMap;
39
40    pub type Batches = HashMap<BatchId, Batch>;
41    pub type Chunks = HashMap<ChunkId, Chunk>;
42
43    pub type BatchId = u128;
44    pub type ChunkId = u128;
45
46    #[derive(Default, Serialize, Deserialize)]
47    pub struct State {
48        // Unstable state: State that resides only on the heap, that’s lost after an upgrade.
49        #[serde(skip, default)]
50        pub runtime: RuntimeState,
51    }
52
53    #[derive(Default, Clone)]
54    pub struct RuntimeState {
55        pub storage: StorageRuntimeState,
56    }
57
58    #[derive(Default, Clone)]
59    pub struct StorageRuntimeState {
60        pub batches: Batches,
61        pub chunks: Chunks,
62        pub asset_hashes: CertifiedAssetHashes,
63        pub rate_tokens: RateTokenStore,
64    }
65}
66
67pub mod store {
68    use crate::http::types::HeaderField;
69    use crate::types::interface::CommitBatch;
70    use crate::types::runtime_state::BatchId;
71    use crate::types::state::{AssetAccessToken, FullPath};
72    use candid::CandidType;
73    use ic_certification::Hash;
74    use junobuild_collections::types::core::CollectionKey;
75    use junobuild_shared::types::core::Blob;
76    use junobuild_shared::types::state::{Timestamp, UserId, Version};
77    use serde::{Deserialize, Serialize};
78    use std::clone::Clone;
79    use std::collections::HashMap;
80
81    #[derive(CandidType, Deserialize, Clone)]
82    pub struct Chunk {
83        pub batch_id: BatchId,
84        pub order_id: u128,
85        pub content: Blob,
86    }
87
88    // When stable memory is used, chunks are saved within a StableBTreeMap and their keys - StableEncodingChunkKey - are saved for reference as serialized values
89    pub type BlobOrKey = Blob;
90
91    #[derive(CandidType, Serialize, Deserialize, Clone)]
92    pub struct AssetEncoding {
93        pub modified: Timestamp,
94        pub content_chunks: Vec<BlobOrKey>,
95        pub total_length: u128,
96        pub sha256: Hash,
97    }
98
99    #[derive(CandidType, Serialize, Deserialize, Clone)]
100    pub struct AssetKey {
101        // myimage.jpg
102        pub name: String,
103        // /images/myimage.jpg
104        pub full_path: FullPath,
105        // ?token=1223-3345-5564-3333
106        pub token: AssetAccessToken,
107        // Assets are prefixed with full_path because these are unique. Collection is there for read (list) and write but all assets are available through http_request (that's why we use the token).
108        pub collection: CollectionKey,
109        // For security check purpose
110        pub owner: UserId,
111        // A description field which can be useful for search purpose
112        pub description: Option<String>,
113    }
114
115    pub type EncodingType = String;
116
117    #[derive(CandidType, Serialize, Deserialize, Clone)]
118    pub struct Asset {
119        pub key: AssetKey,
120        pub headers: Vec<HeaderField>,
121        pub encodings: HashMap<EncodingType, AssetEncoding>,
122        pub created_at: Timestamp,
123        pub updated_at: Timestamp,
124        pub version: Option<Version>,
125    }
126
127    pub trait BatchExpiry {
128        fn expires_at(&self) -> Timestamp;
129    }
130
131    pub type ReferenceId = u128;
132
133    #[derive(CandidType, Serialize, Deserialize, Clone)]
134    pub struct Batch {
135        pub key: AssetKey,
136        pub reference_id: Option<ReferenceId>,
137        pub expires_at: Timestamp,
138        pub encoding_type: Option<EncodingType>,
139    }
140
141    #[derive(CandidType, Serialize, Deserialize, Clone)]
142    pub struct AssetAssertUpload {
143        pub current: Option<Asset>,
144        pub batch: Batch,
145        pub commit_batch: CommitBatch,
146    }
147}
148
149pub mod interface {
150    use candid::{CandidType, Deserialize};
151    use ic_certification::Hash;
152    use junobuild_collections::types::core::CollectionKey;
153    use junobuild_shared::types::core::Blob;
154    use junobuild_shared::types::state::{Timestamp, Version};
155    use serde::Serialize;
156
157    use crate::http::types::HeaderField;
158    use crate::types::config::{
159        StorageConfigHeaders, StorageConfigIFrame, StorageConfigMaxMemorySize,
160        StorageConfigRawAccess, StorageConfigRedirects, StorageConfigRewrites,
161    };
162    use crate::types::runtime_state::{BatchId, ChunkId};
163    use crate::types::state::{AssetAccessToken, FullPath};
164    use crate::types::store::{AssetKey, EncodingType};
165
166    #[derive(CandidType, Deserialize)]
167    pub struct InitAssetKey {
168        pub name: String,
169        pub full_path: FullPath,
170        pub token: AssetAccessToken,
171        pub collection: CollectionKey,
172        pub encoding_type: Option<EncodingType>,
173        pub description: Option<String>,
174    }
175
176    #[derive(CandidType)]
177    pub struct InitUploadResult {
178        pub batch_id: BatchId,
179    }
180
181    #[derive(CandidType, Deserialize)]
182    pub struct UploadChunk {
183        pub batch_id: BatchId,
184        pub content: Blob,
185        pub order_id: Option<u128>,
186    }
187
188    #[derive(CandidType)]
189    pub struct UploadChunkResult {
190        pub chunk_id: ChunkId,
191    }
192
193    #[derive(CandidType, Serialize, Deserialize, Clone)]
194    pub struct CommitBatch {
195        pub batch_id: BatchId,
196        pub headers: Vec<HeaderField>,
197        pub chunk_ids: Vec<ChunkId>,
198    }
199
200    #[derive(CandidType, Deserialize, Clone)]
201    pub struct AssetNoContent {
202        pub key: AssetKey,
203        pub headers: Vec<HeaderField>,
204        pub encodings: Vec<(EncodingType, AssetEncodingNoContent)>,
205        pub created_at: Timestamp,
206        pub updated_at: Timestamp,
207        pub version: Option<Version>,
208    }
209
210    #[derive(CandidType, Deserialize, Clone)]
211    pub struct AssetEncodingNoContent {
212        pub modified: Timestamp,
213        pub total_length: u128,
214        pub sha256: Hash,
215    }
216
217    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
218    pub struct SetStorageConfig {
219        pub headers: StorageConfigHeaders,
220        pub rewrites: StorageConfigRewrites,
221        pub redirects: Option<StorageConfigRedirects>,
222        pub iframe: Option<StorageConfigIFrame>,
223        pub raw_access: Option<StorageConfigRawAccess>,
224        pub max_memory_size: Option<StorageConfigMaxMemorySize>,
225        pub version: Option<Version>,
226    }
227}
228
229pub mod config {
230    use crate::http::types::{HeaderField, StatusCode};
231    use candid::CandidType;
232    use junobuild_shared::types::config::ConfigMaxMemorySize;
233    use junobuild_shared::types::state::{Timestamp, Version};
234    use serde::{Deserialize, Serialize};
235    use std::collections::HashMap;
236
237    pub type StorageConfigHeaders = HashMap<String, Vec<HeaderField>>;
238    pub type StorageConfigRewrites = HashMap<String, String>;
239    pub type StorageConfigRedirects = HashMap<String, StorageConfigRedirect>;
240
241    #[derive(CandidType, Serialize, Deserialize, Clone)]
242    pub enum StorageConfigIFrame {
243        Deny,
244        SameOrigin,
245        AllowAny,
246    }
247
248    #[derive(CandidType, Serialize, Deserialize, Clone)]
249    pub enum StorageConfigRawAccess {
250        Deny,
251        Allow,
252    }
253
254    pub type StorageConfigMaxMemorySize = ConfigMaxMemorySize;
255
256    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
257    pub struct StorageConfig {
258        pub headers: StorageConfigHeaders,
259        pub rewrites: StorageConfigRewrites,
260        pub redirects: Option<StorageConfigRedirects>,
261        pub iframe: Option<StorageConfigIFrame>,
262        pub raw_access: Option<StorageConfigRawAccess>,
263        pub max_memory_size: Option<StorageConfigMaxMemorySize>,
264        pub version: Option<Version>,
265        pub created_at: Option<Timestamp>,
266        pub updated_at: Option<Timestamp>,
267    }
268
269    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
270    pub struct StorageConfigRedirect {
271        pub location: String,
272        pub status_code: StatusCode,
273    }
274}
275
276pub mod http_request {
277    use crate::http::types::StatusCode;
278    use crate::types::config::{StorageConfigIFrame, StorageConfigRedirect};
279    use crate::types::state::AssetAccessToken;
280    use crate::types::store::Asset;
281    use candid::{CandidType, Deserialize};
282    use junobuild_collections::types::rules::Memory;
283
284    #[derive(CandidType, Deserialize, Clone)]
285    pub struct MapUrl {
286        pub path: String,
287        pub token: AssetAccessToken,
288    }
289
290    #[derive(CandidType, Deserialize, Clone)]
291    pub enum Routing {
292        Default(RoutingDefault),
293        Rewrite(RoutingRewrite),
294        Redirect(RoutingRedirect),
295        RedirectRaw(RoutingRedirectRaw),
296    }
297
298    #[derive(CandidType, Deserialize, Clone)]
299    pub struct RoutingDefault {
300        pub url: String,
301        pub asset: Option<(Asset, Memory)>,
302    }
303
304    #[derive(CandidType, Deserialize, Clone)]
305    pub struct RoutingRewrite {
306        pub url: String,
307        pub asset: Option<(Asset, Memory)>,
308        pub source: String,
309        pub status_code: StatusCode,
310    }
311
312    #[derive(CandidType, Deserialize, Clone)]
313    pub struct RoutingRedirect {
314        pub url: String,
315        pub redirect: StorageConfigRedirect,
316        pub iframe: StorageConfigIFrame,
317    }
318
319    #[derive(CandidType, Deserialize, Clone)]
320    pub struct RoutingRedirectRaw {
321        pub redirect_url: String,
322        pub iframe: StorageConfigIFrame,
323    }
324}