Skip to main content

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    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
229    pub struct SetStorageConfigOptions {
230        pub skip_certification: Option<bool>,
231    }
232
233    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
234    pub struct SetStorageConfigWithOptions {
235        pub config: SetStorageConfig,
236        pub options: SetStorageConfigOptions,
237    }
238
239    #[derive(CandidType, Serialize, Deserialize)]
240    pub enum CertifyAssetsCursor {
241        Heap { offset: usize },
242        Stable { key: Option<AssetKey> },
243    }
244
245    #[derive(CandidType, Serialize, Deserialize)]
246    pub enum CertifyAssetsStrategy {
247        Clear,
248        Append,
249        AppendWithRouting,
250    }
251}
252
253pub mod config {
254    use crate::http::types::{HeaderField, StatusCode};
255    use candid::CandidType;
256    use junobuild_shared::types::config::ConfigMaxMemorySize;
257    use junobuild_shared::types::state::{Timestamp, Version};
258    use serde::{Deserialize, Serialize};
259    use std::collections::HashMap;
260
261    pub type StorageConfigHeaders = HashMap<String, Vec<HeaderField>>;
262    pub type StorageConfigRewrites = HashMap<String, String>;
263    pub type StorageConfigRedirects = HashMap<String, StorageConfigRedirect>;
264
265    #[derive(CandidType, Serialize, Deserialize, Clone)]
266    pub enum StorageConfigIFrame {
267        Deny,
268        SameOrigin,
269        AllowAny,
270    }
271
272    #[derive(CandidType, Serialize, Deserialize, Clone)]
273    pub enum StorageConfigRawAccess {
274        Deny,
275        Allow,
276    }
277
278    pub type StorageConfigMaxMemorySize = ConfigMaxMemorySize;
279
280    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
281    pub struct StorageConfig {
282        pub headers: StorageConfigHeaders,
283        pub rewrites: StorageConfigRewrites,
284        pub redirects: Option<StorageConfigRedirects>,
285        pub iframe: Option<StorageConfigIFrame>,
286        pub raw_access: Option<StorageConfigRawAccess>,
287        pub max_memory_size: Option<StorageConfigMaxMemorySize>,
288        pub version: Option<Version>,
289        pub created_at: Option<Timestamp>,
290        pub updated_at: Option<Timestamp>,
291    }
292
293    #[derive(Default, CandidType, Serialize, Deserialize, Clone)]
294    pub struct StorageConfigRedirect {
295        pub location: String,
296        pub status_code: StatusCode,
297    }
298}
299
300pub mod http_request {
301    use crate::http::types::StatusCode;
302    use crate::types::config::{StorageConfigIFrame, StorageConfigRedirect};
303    use crate::types::state::AssetAccessToken;
304    use crate::types::store::Asset;
305    use candid::{CandidType, Deserialize};
306    use junobuild_collections::types::rules::Memory;
307
308    #[derive(CandidType, Deserialize, Clone)]
309    pub struct MapUrl {
310        pub path: String,
311        pub token: AssetAccessToken,
312    }
313
314    #[derive(CandidType, Deserialize, Clone)]
315    pub enum Routing {
316        Default(RoutingDefault),
317        Rewrite(RoutingRewrite),
318        Redirect(RoutingRedirect),
319        RedirectRaw(RoutingRedirectRaw),
320    }
321
322    #[derive(CandidType, Deserialize, Clone)]
323    pub struct RoutingDefault {
324        pub url: String,
325        pub asset: Option<(Asset, Memory)>,
326    }
327
328    #[derive(CandidType, Deserialize, Clone)]
329    pub struct RoutingRewrite {
330        pub url: String,
331        pub asset: Option<(Asset, Memory)>,
332        pub source: String,
333        pub status_code: StatusCode,
334    }
335
336    #[derive(CandidType, Deserialize, Clone)]
337    pub struct RoutingRedirect {
338        pub url: String,
339        pub redirect: StorageConfigRedirect,
340        pub iframe: StorageConfigIFrame,
341    }
342
343    #[derive(CandidType, Deserialize, Clone)]
344    pub struct RoutingRedirectRaw {
345        pub redirect_url: String,
346        pub iframe: StorageConfigIFrame,
347    }
348}