### Install Etebase on Node.js Source: https://docs.etebase.com/installation Install Etebase and node-fetch for Node.js environments. ```bash yarn add etebase node-fetch ``` -------------------------------- ### Fetch and Upload Collection (Kotlin) Source: https://docs.etebase.com/guides/using_collections Shows how to fetch a collection and then upload it using Kotlin. This is analogous to the Java example but uses Kotlin syntax. ```kotlin // -> On device A: val collection = colMgr.fetch(collectionUid) ``` ```kotlin // -> On device B: val collection = colMgr.fetch(collectionUid) val meta = collection.getMeta() meta.name = "New name" collection.meta = meta colMgr.upload(collection) ``` ```kotlin // -> On device A (using the previously saved collection) val meta = collection.getMeta() meta.name = "Another name" collection.meta = meta // Will fail colMgr.transaction(collection) // Will succeed colMgr.upload(collection) ``` -------------------------------- ### Install Etebase with Pip Source: https://docs.etebase.com/installation Use pip to install the Etebase Python package. ```bash pip install etebase ``` -------------------------------- ### Install Etebase on React Native Source: https://docs.etebase.com/installation Install Etebase and necessary libraries for React Native projects. ```bash yarn add etebase react-native-etebase react-native-get-random-values react-native-sodium ``` -------------------------------- ### Create and Upload Collection - Kotlin Source: https://docs.etebase.com/guides/using_collections This Kotlin example illustrates the process of creating a collection with associated metadata and then uploading it. It requires a logged-in Etebase account. ```kotlin import com.etebase.client.* val client = Client.create(httpClient, null) val etebase = Account.login(client, "username", "password") val colMgr = etebase.collectionManager // Create, encrypt and upload a new collection val collectionMetadata = ItemMetadata() collectionMetadata.name = "Holidays" collectionMetadata.description = "My holiday calendar" collectionMetadata.color = "#23aabbff" val collection = colMgr.create("cyberdyne.calendar", collectionMetadata, "") colMgr.upload(collection) ``` -------------------------------- ### Fetch and Upload Collection (Rust) Source: https://docs.etebase.com/guides/using_collections Demonstrates fetching and uploading a collection using Rust. This example highlights Rust's ownership and borrowing concepts. ```rust // -> On device A: let mut collection = collection_manager.fetch(collection_uid, None)?; ``` ```rust // -> On device B: let mut collection = collection_manager.fetch(collection_uid, None)?; let mut meta = collection.meta()?; meta.set_name("New name"); collection.set_meta(&meta)?; collection_manager.upload(&collection, None)?; ``` ```rust // -> On device A (using the previously saved collection) let mut meta = collection.meta()?; meta.set_name("Another name"); collection.set_meta(&meta)?; // Will fail collection_manager.transaction(&collection, None)?; // Will succeed collection_manager.upload(&collection, None)?; ``` -------------------------------- ### Install Etebase with Yarn Source: https://docs.etebase.com/installation Use this command to add the Etebase dependency to your project when using Yarn. ```bash yarn add etebase ``` -------------------------------- ### C: Batch and Transaction Operations with Dependencies Source: https://docs.etebase.com/guides/using_items Provides C examples for batch and transaction operations, demonstrating how concurrent modifications to an item can cause operations to fail. This is relevant when implementing Etebase clients in C. ```c // -> On device A: EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL); EtebaseItem *item2 = etebase_item_manager_fetch(item_mgr, item2_uid, NULL); // -> On device B: EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL); const char tmp[] = "Something else for item 1"; etebase_item_set_content(item1, tmp, strlen(tmp)); const EtebaseItem *items[] = { item1 }; etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); etebase_item_destroy(item1); // -> On device A (using the previously saved collection) const char tmp2[] = "New content for item 2"; etebase_item_set_content(item2, tmp2, strlen(tmp2)); // Both will fail because item1 changed const EtebaseItem *items[] = { item2 }; const EtebaseItem *deps[] = { item1 }; etebase_item_manager_batch_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL); etebase_item_manager_transaction_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL); // Can even use the item in both the list and deps in batch // Will fail because item1 changed on device B const EtebaseItem *items[] = { item1, item2 }; const EtebaseItem *deps[] = { item1 }; etebase_item_manager_batch_deps(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), deps, ETEBASE_UTILS_C_ARRAY_LEN(deps), NULL); etebase_item_destroy(item2); etebase_item_destroy(item1); ``` -------------------------------- ### Create, Encrypt, and Upload a New Item (Kotlin) Source: https://docs.etebase.com/guides/using_items A Kotlin example for creating and uploading a new file item. It involves setting item metadata, content, and then batching the item for upload. Ensure ItemManager and Collection are available. ```kotlin val meta = ItemMetadata() meta.type = "file" meta.name = "note.txt" meta.mtime = Date().getTime() val item = itemManager.create(meta, "My secret note") itemManager.batch(arrayOf(item)) ``` -------------------------------- ### Item Transaction and Batch Operations (C/C++) Source: https://docs.etebase.com/guides/using_items Provides examples of item management using transactions and batch operations in C/C++. Demonstrates fetching, modifying, and synchronizing items, including conflict handling. ```c // -> On device A: EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL); EtebaseItem *item2 = etebase_item_manager_fetch(item_mgr, item2_uid, NULL); // -> On device B: EtebaseItem *item1 = etebase_item_manager_fetch(item_mgr, item1_uid, NULL); const char tmp[] = "Something else for item 1"; etebase_item_set_content(item1, tmp, strlen(tmp)); const EtebaseItem *items[] = { item1 }; etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); etebase_item_destroy(item1); // -> On device A (using the previously saved item) const char tmp[] = "New content for item 1"; etebase_item_set_content(item1, tmp, strlen(tmp)); const char tmp2[] = "New content for item 2"; etebase_item_set_content(item2, tmp2, strlen(tmp2)); // Will fail because item1 changed on device B const EtebaseItem *items[] = { item1, item2 }; etebase_item_manager_transaction(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); // Will succeed etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); // Will succeed because item2 hasn't changed on device B const EtebaseItem *items2[] = { item2 }; etebase_item_manager_transaction(item_mgr, items2, ETEBASE_UTILS_C_ARRAY_LEN(items2), NULL); etebase_item_destroy(item2); etebase_item_destroy(item1); ``` -------------------------------- ### Get and Set Collection Content (Java) Source: https://docs.etebase.com/guides/using_collections Demonstrates retrieving collection content as bytes or a UTF-8 string, and setting it from bytes or a string. ```java // The Java API returns `byte[]` by default collection.getContent(); // Try decoding the binary data to a UTF-8 string and return that collection.getContentString(); // Sets the content to a binary blob collection.setContent("Bla".getBytes("UTF-8")); // Sets the content to a string collection.setContent("Hello"); ``` -------------------------------- ### Save and Load Collection (C/C++ - older API) Source: https://docs.etebase.com/guides/local_cache This C/C++ example demonstrates saving and loading collections using base64 encoding for the cache blob, including manual memory management. ```c // Create a collection EtebaseCollection *col = etebase_collection_manager_create(...); // The cache blob is just a Uint8Array that can be saved for later use uintptr_t cache_size; void *cache_blob = etebase_collection_manager_cache_save(col_mgr, col, &cache_size); char cache_b64[ETEBASE_UTILS_TO_BASE64_MAX_LEN(cache_size)]; etebase_utils_to_base64(cache_blob, cache_size, cache_b64, sizeof(cache_b64)); // Later on we can load the object back char decoded[ETEBASE_UTILS_FROM_BASE64_MAX_LEN(strlen(cache_b64))]; uintptr_t decoded_len = 0; etebase_utils_from_base64(cache_b64, decoded, sizeof(decoded), &decoded_len); EtebaseCollection *col = etebase_collection_manager_cache_load(col_mgr, decoded, decoded_len) // And use it like any other object: etebase_collection_get_uid(col); free(cache_blob); ``` -------------------------------- ### Control Item Content Formatting Source: https://docs.etebase.com/guides/using_items Demonstrates how to get and set item content, specifying whether it should be treated as binary data (Uint8Array) or a string. ```javascript // default, returns a Uint8Array item.getContent(); // tries to convert the binary data to a string and returns that item.getContent(Etebase.OutputFormat.String); // Sets the content to a binary blob item.setContent(Uint8Array.from([72, 101, 108, 108, 111])); // Sets the content to a string item.setContent("Hello"); ``` -------------------------------- ### Cache Item as Base64 String (C/C++) Source: https://docs.etebase.com/guides/local_cache Create an item, save its cache to a Base64 string, and later load it back. This example demonstrates manual memory management for the cache blob and uses etebase utility functions for Base64 operations. ```c // Create a item EtebaseItem *item = etebase_item_manager_create(...); // The cache blob is just a Uint8Array that can be saved for later use uintptr_t cache_size; void *cache_blob = etebase_item_manager_cache_save(item_mgr, item, &cache_size); char cache_b64[ETEBASE_UTILS_TO_BASE64_MAX_LEN(cache_size)]; etebase_utils_to_base64(cache_blob, cache_size, cache_b64, sizeof(cache_b64)); // Later on we can load the object back char decoded[ETEBASE_UTILS_FROM_BASE64_MAX_LEN(strlen(cache_b64))]; uintptr_t decoded_len = 0; etebase_utils_from_base64(cache_b64, decoded, sizeof(decoded), &decoded_len); EtebaseItem *item = etebase_item_manager_cache_load(item_mgr, decoded, decoded_len) // And use it like any other object: etebase_item_get_uid(item); free(cache_blob); ``` -------------------------------- ### JavaScript: Fetching Collection Items Source: https://docs.etebase.com/guides/using_items Shows how to get an ItemManager for a collection and fetch items, including the collection itself. Demonstrates listing items with collection data, fetching by UID, and fetching updates. ```javascript const itemManager = collectionManager.getItemManager(collection); // Will return the collection item as part of the list: const items = await itemManager.list({ withCollection: true }); // Assuming the collection is the first item returned: const colItem = items.data[0]; assert(colItem.uid === collection.uid); // You can also fetch collection items based on UID: const colItem = await itemManager.fetch(collection.uid); // Or fetch updates of the collection along with other items: const items = await itemManager.fetchUpdates([collection.item, item1]); ``` -------------------------------- ### Controlling Collection Content Format (JavaScript) Source: https://docs.etebase.com/guides/using_collections Shows how to get collection content as a Promise (default) or as a string. Also demonstrates setting content from a binary blob or a string. ```javascript // default, returns a Promise await collection.getContent(); // tries to convert the binary data to a string and returns that await collection.getContent(Etebase.OutputFormat.String); // Sets the content to a binary blob await collection.setContent(Uint8Array.from([72, 101, 108, 108, 111])); // Sets the content to a string await collection.setContent("Hello"); ``` -------------------------------- ### Java: Manipulating Collection Items Source: https://docs.etebase.com/guides/using_items Demonstrates how to get a collection as an item and use it in transactions and batch operations. Asserts that collection metadata and content match the extracted item's. ```java Collection collection = ...; Item item1 = ...; Item item2 = ...; // Get the item out of the collection Item colItem = collection.asItem(); // The collection item can then be used like any other item: itemManager.transaction(new Item[] {colItem, item1}, new Item[] {item2}); itemManager.transaction(new Item[] {item1, item2}, new Item[] {colItem}); itemManager.batch(new Item[] {colItem, item1}); // In addition, these are true: assert (collection.getMetaRaw() == colItem.getMetaRaw()); assert (collection.getContent() == colItem.getContent()); ``` -------------------------------- ### Save and Load Collection (Rust) Source: https://docs.etebase.com/guides/local_cache Demonstrates caching a collection in Rust. This example uses Result for error handling and references for cache operations. ```rust // Create an item let item = item_manager.create(...)?; // The cache blob is just a Uint8Array that can be saved for later use let cache_blob = item_manager.cache_save(&item)?; // Later on we can load the object back let mut item = item_manager.cache_load(&cache_blob)?; // And use it like any other object: item.set_content(b"New content")?; ``` -------------------------------- ### Get Collection Content as Buffer (C API) Source: https://docs.etebase.com/guides/using_collections Illustrates fetching collection content into a buffer using the C API. Content is not null-terminated by default. Handles cases where the buffer might be too small. ```c // The C API always works on binary data, // This means content is *not* NULL terminated! // It's generally fastest to just try to get the content into a buffer // if we think it's likely to be under a certain size. char tmp[500]; intptr_t len = etebase_collection_get_content(col, tmp, sizeof(tmp)); if (len < 0) { // Error } else if (len > sizeof(tmp)) { // This means we should allocate a buffer of size len to fetch into char *tmp2 = malloc(len); etebase_collection_get_content(col, tmp2, len); // Do something with tmp2 free(tmp2); } ``` -------------------------------- ### Save and Load Collection (Kotlin - older API) Source: https://docs.etebase.com/guides/local_cache An older Kotlin example for saving and loading collections, utilizing base64 encoding for the cache. ```kotlin // Create a collection val collection = colMgr.create(...) // The cache blob is just a Uint8Array that can be saved for later use val cacheB64 = Utils.toBase64(colMgr.cacheSave(collection)) // Later on we can load the object back val collection = colMgr.cacheLoad(Utils.fromBase64(cacheB64)) // And use it like any other object: collection.content = "New content" ``` -------------------------------- ### Item Transaction and Batch Operations (Rust) Source: https://docs.etebase.com/guides/using_items Shows how to manage items using transactions and batch operations in Rust. Includes examples of fetching, updating, and synchronizing items, with considerations for concurrent modifications. ```rust // -> On device A: let mut item1 = item_manager.fetch(item_uid1, None)?; let mut item2 = item_manager.fetch(item_uid2, None)?; // -> On device B: let mut item1 = item_manager.fetch(item_uid1, None)?; item1.set_content(b"Something else for item 1")?; item_manager.batch(vec![&item1].into_iter(), None)?; // -> On device A (using the previously saved item) item1.set_content(b"New content for item 1")?; item2.set_content(b"New content for item 2")?; // Will fail because item1 changed on device B item_manager.transaction(vec![&item1, &item2].into_iter(), None)?; // Will succeed item_manager.batch(vec![&item1, &item2].into_iter(), None)?; // Will succeed because item2 hasn't changed on device B item_manager.transaction(vec![&item2].into_iter(), None)?; ``` -------------------------------- ### Save and Load Collections to Cache (Kotlin) Source: https://docs.etebase.com/guides/local_cache Provides an example of saving a collection to a Uint8Array cache and loading it back in Kotlin. This is useful for local storage of collection data. ```kotlin // Create a collection val collection = colMgr.create(...) // The cache blob is just a Uint8Array that can be saved for later use val cacheBlob = colMgr.cacheSave(collection) // Later on we can load the object back val collection = colMgr.cacheLoad(cacheBlob) // And use it like any other object: collection.content = "New content" ``` -------------------------------- ### Get and Set Collection Content (Rust) Source: https://docs.etebase.com/guides/using_collections Shows how to retrieve collection content as a byte vector or decode it to a UTF-8 string, and how to set content from a byte slice or a byte vector. ```rust // The rust API returns `Vec` by default collection.content()?; // Try decoding the binary data to a UTF-8 string and return that String::from_utf8(collection.content()?); // Sets the content to a binary blob collection.set_content(&vec![0, 1, 2])?; // Sets the content to a string collection.set_content("Hello".as_bytes())?; ``` -------------------------------- ### Cache Item as Base64 String (Rust) Source: https://docs.etebase.com/guides/local_cache Create an item, save its cache to a Base64 string, and later load it back. This example uses Rust's error handling with '?' and the provided utility functions for Base64 encoding and decoding. ```rust // Create an item let item = item_manager.create(...)?; // The cache blob is just a Uint8Array that can be saved for later use let cache_b64 = utils::to_base64(&item_manager.cache_save(&item)?)?; // Later on we can load the object back let mut item = item_manager.cache_load(&utils::from_base64(&cache_b64)?)?; // And use it like any other object: item.set_content(b"New content")?; ``` -------------------------------- ### Transaction Example for Data Consistency Source: https://docs.etebase.com/guides/using_collections Demonstrates how to use transactions to ensure data consistency when multiple devices might be modifying the same collection. A transaction will fail if the collection has been modified on the server since it was last fetched. ```javascript // -> On device A: const collection = await collectionManager.fetch(collectionUid); // -> On device B: const collection = await collectionManager.fetch(collectionUid); const meta = collection.getMeta(); collection.setMeta({ ...meta, name: "New name" }); await collectionManager.upload(collection); // -> On device A (using the previously saved collection) const meta = collection.getMeta(); collection.setMeta({ ...meta, name: "Another name" }); // Will fail await collectionManager.transaction(collection); // Will succeed await collectionManager.upload(collection); ``` ```python # -> On device A: collection = col_mgr.fetch(collection_uid) # -> On device B: collection = col_mgr.fetch(collection_uid) meta = collection.meta meta["name"] = "New name" collection.meta = meta col_mgr.upload(collection) # -> On device A (using the previously saved collection) meta = collection.meta meta["name"] = "Another name" collection.meta = meta # Will fail col_mgr.transaction(collection) ``` -------------------------------- ### Java API: Get and Set Binary Content Source: https://docs.etebase.com/guides/using_items The Java API uses `byte[]` for binary content. Use `getContentString()` to get it as a decoded UTF-8 string, or `setContent()` to set it from a byte array or string. ```java item.getContent(); ``` ```java item.getContentString(); ``` ```java item.setContent("Bla".getBytes("UTF-8")); ``` ```java item.setContent("Hello"); ``` -------------------------------- ### Create and Upload Collection - C/C++ Source: https://docs.etebase.com/guides/using_collections This C/C++ snippet shows how to create a collection with metadata and upload it. It includes necessary cleanup steps for allocated memory. ```c const char *server_url = etebase_get_default_server_url(); EtebaseClient *client = etebase_client_new("client-name", server_url); EtebaseAccount *etebase = etebase_account_login(client, "username", "password"); // Create, encrypt and upload a new collection EtebaseCollectionManager *col_mgr = etebase_account_get_collection_manager(etebase); EtebaseItemMetadata *col_meta = etebase_collection_metadata_new(); etebase_collection_metadata_set_name(col_meta, "Holidays"); etebase_collection_metadata_set_description(col_meta, "My holiday calendar"); etebase_collection_metadata_set_color(col_meta, "#23aabbff"); EtebaseCollection *col = etebase_collection_manager_create("cyberdyne.calendar", col_mgr, col_meta, "", 0); etebase_collection_metadata_destroy(col_meta); etebase_collection_manager_upload(col_mgr, col, NULL); // Cleanup etebase_collection_destroy(col); etebase_collection_manager_destroy(col_mgr); ``` -------------------------------- ### Get Your Public Key Source: https://docs.etebase.com/guides/collection_sharing Retrieve your public key from the InvitationManager after logging into your account. This key can then be shared with others. ```javascript const etebase = await Etebase.Account.login("username", "password"); const invitationManager = etebase.getInvitationManager(); // You can now share your pubkey const myPubkey = invitationManager.pubkey; ``` ```python etebase = Account.login(...) invitation_manager = etebase.get_invitation_manager() # You can now share your pubkey invitation_manager.pubkey ``` ```java Account etebase = Account.login(...); CollectionInvitationManager invitationManager = etebase.getInvitationManager(); // You can now share your pubkey byte[] myPubkey = invitationManager.getPubkey(); ``` ```kotlin val etebase = Account.login(...) val invitationManager = etebase.invitationManager // You can now share your pubkey val myPubkey = invitationManager.pubkey ``` ```c EtebaseAccount *etebase = etebase_account_login(...); EtebaseCollectionInvitationManager *invitation_manager = etebase_account_get_invitation_manager(etebase); // You can now share your pubkey const char *my_pubkey = etebase_invitation_manager_get_pubkey(invitation_manager); uintptr_t pubkey_size = etebase_invitation_manager_get_pubkey_size(invitation_manager); etebase_invitation_manager_destroy(invitation_manager); ``` ```rust let etebase = Account::login(...)?; let invitation_manager = etebase.invitation_manager()?; // You can now share your pubkey let my_pubkey = invitation_manager.pubkey(); ``` -------------------------------- ### Create, Encrypt, and Upload a New Item (C/C++) Source: https://docs.etebase.com/guides/using_items This C/C++ snippet shows how to create a new file item, set its metadata including modification time, and upload it. It requires an initialized EtebaseItemManager and EtebaseCollection. Remember to handle potential errors and destroy allocated objects. ```c EtebaseItemMetadata *item_meta = etebase_item_metadata_new(); etebase_item_metadata_set_item_type(item_meta, "file"); etebase_item_metadata_set_name(item_meta, "note.txt"); time_t now = time(NULL); if (now == (time_t)(-1)) { // Error } now *= 1000; etebase_item_metadata_set_mtime(item_meta, &now); const char item_content[] = "My secret note"; EtebaseItem *item = etebase_item_manager_create(item_mgr, item_meta, item_content, strlen(item_content)); const EtebaseItem *items[] = { item }; etebase_item_manager_batch(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); etebase_item_destroy(item); etebase_item_manager_destroy(item_mgr); ``` -------------------------------- ### Fetch and Upload Collection (C/C++) Source: https://docs.etebase.com/guides/using_collections Illustrates fetching and uploading a collection using C/C++ Etebase bindings. Note the explicit memory management. ```c // -> On device A: EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL); ``` ```c // -> On device B: EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL); EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col); etebase_collection_metadata_set_name(col_meta, "New name"); etebase_collection_set_meta(col, col_meta); etebase_collection_metadata_destroy(col_meta); etebase_collection_manager_upload(col_mgr, col, NULL); etebase_collection_destroy(col); ``` ```c // -> On device A (using the previously saved collection) EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col); etebase_collection_metadata_set_name(col_meta, "Another name"); etebase_collection_set_meta(col, col_meta); etebase_collection_metadata_destroy(col_meta); // Will fail etebase_collection_manager_transaction(col_mgr, col, NULL); // Will succeed etebase_collection_manager_upload(col_mgr, col, NULL); etebase_collection_destroy(col); ``` -------------------------------- ### Fetch, Update, and Sync Collections (C/C++) Source: https://docs.etebase.com/guides/using_collections Demonstrates fetching a collection, updating its metadata, and then attempting to sync (transaction/upload) with and without a stoken. This illustrates scenarios on different devices. ```c // -> On device A: EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL); const char *stoken = etebase_collection_get_stoken(col); { // -> On device B: EtebaseCollection *col = etebase_collection_manager_fetch(col_mgr, col_uid, NULL); EtebaseItemManager *item_mgr = etebase_collection_manager_get_item_manager(col_mgr, col); etebase_item_manager_batch(...); etebase_item_manager_destroy(item_mgr); etebase_collection_destroy(col); } // -> On device A (using the previously saved collection) EtebaseItemMetadata *col_meta = etebase_collection_get_meta(col); etebase_collection_metadata_set_name(col_meta, "Another name"); etebase_collection_set_meta(col, col_meta); etebase_collection_metadata_destroy(col_meta); EtebaseFetchOptions *fetch_options = etebase_fetch_options_new(); etebase_fetch_options_set_stoken(fetch_options, stoken); // Will both fail etebase_collection_manager_transaction(col_mgr, col, fetch_options); etebase_collection_manager_upload(col_mgr, col, fetch_options); etebase_fetch_options_destroy(fetch_options); // Will both succeed etebase_collection_manager_transaction(col_mgr, col, NULL); etebase_collection_manager_upload(col_mgr, col, NULL); etebase_collection_destroy(col); ``` -------------------------------- ### Generate Random Username - Pseudo-code Source: https://docs.etebase.com/guides/basic_authentication Example of generating a random username using Etebase utilities, useful when email is used as the primary identifier. ```plaintext username = toBase64(randomBytes(24)) ``` -------------------------------- ### Create and Upload Collection - Python Source: https://docs.etebase.com/guides/using_collections This Python code demonstrates creating a new collection, including its metadata, and then uploading it. It requires an active Etebase client and logged-in account. ```python from etebase import Client, Account client = Client("client-name") etebase = Account.login(client, "username", "password") col_mgr = etebase.get_collection_manager() # Create, encrypt and upload a new collection collection = col_mgr.create("cyberdyne.calendar", { "name": "Holidays", "description": "My holiday calendar", "color": "#23aabbff", }, b"" # Empty content ) col_mgr.upload(collection) ``` -------------------------------- ### Create and Upload Collection - Java Source: https://docs.etebase.com/guides/using_collections In Java, this snippet shows how to create a collection with metadata and upload it. It assumes you have already established an Etebase client and logged into an account. ```java import com.etebase.client.*; Client client = Client.create(httpClient, null); Account etebase = Account.login(client, "username", "password"); CollectionManager colMgr = etebase.getCollectionManager(); // Create, encrypt and upload a new collection ItemMetadata collectionMetadata = new ItemMetadata() collectionMetadata.setName("Holidays"); collectionMetadata.setDescription("My holiday calendar"); collectionMetadata.setColor("#23aabbff"); Collection collection = colMgr.create("cyberdyne.calendar", collectionMetadata, ""); colMgr.upload(collection); ``` -------------------------------- ### Fetch and Upload Collection (Java) Source: https://docs.etebase.com/guides/using_collections Demonstrates fetching a collection and then uploading it. This is a basic operation for synchronizing collection data. ```java // -> On device A: Collection collection = colMgr.fetch(collectionUid); ``` ```java // -> On device B: Collection collection = colMgr.fetch(collectionUid); ItemMetadata meta = collection.getMeta(); meta.setName("New name"); collection.setMeta(meta); colMgr.upload(collection); ``` ```java // -> On device A (using the previously saved collection) ItemMetadata meta = collection.getMeta(); meta.setName("Another name"); collection.setMeta(meta); // Will fail colMgr.transaction(collection); // Will succeed colMgr.upload(collection); ``` -------------------------------- ### Iterate Outgoing Invitations in Kotlin Source: https://docs.etebase.com/guides/collection_sharing Handle paginated outgoing invitations in Kotlin. This example demonstrates the iterative fetching pattern with iterator and done status checks. ```kotlin var iterator: String? = null var done = false while (!done) { val invitations = itemManager.listOutgoing(item, FetchOptions().iterator(iterator).limit(30)) iterator = invitations.iterator done = invitations.isDone processOutgoingInvitations(invitations.data) } ``` -------------------------------- ### Python API: Get and Set Binary Content Source: https://docs.etebase.com/guides/using_items The Python API handles binary content as `bytes`. You can decode it to a UTF-8 string or set it from a byte array or encoded string. ```python item.content ``` ```python item.content.decode() ``` ```python item.content = b"Some bytes" ``` ```python item.content = "Some bytes".encode() ``` -------------------------------- ### Item Transaction and Batch Operations (Java) Source: https://docs.etebase.com/guides/using_items Demonstrates item management using transactions and batch operations in Java. Shows how to fetch, modify, and synchronize items across devices, including conflict scenarios. ```java // -> On device A: Item item1 = itemManager.fetch(itemUid1); Item item2 = itemManager.fetch(itemUid2); // -> On device B: Item item1 = itemManager.fetch(itemUid1); item1.setContent("Something else for item 1") itemManager.batch(new Item[] {item1}); // -> On device A (using the previously saved item) item1.setContent("New content for item 1"); item2.setContent("New content for item 2"); // Will fail because item1 changed on device B itemManager.transaction(new Item[] {item1, item2}); // Will succeed itemManager.batch(new Item[] {item1, item2}); // Will succeed because item2 hasn't changed on device B itemManager.transaction(new Item[] {item2}); ``` -------------------------------- ### Fetch, Update, and Sync Collections (Java) Source: https://docs.etebase.com/guides/using_collections Demonstrates fetching a collection, updating its metadata, and then attempting to sync (transaction/upload) with and without a stoken. This illustrates scenarios on different devices. ```java // -> On device A: Collection collection = colMgr.fetch(collectionUid); String stoken = collection.stoken // -> On device B: Collection collection = colMgr.fetch(collectionUid); ItemManager itemMgr = colMgr.getItemManager(collection); // Add a new item to tho collection (redacted for simplicity) itemMgr.batch(...) // -> On device A (using the previously saved collection) ItemMetadata meta = collection.getMeta(); meta.setName("Another name"); collection.setMeta(meta); // Will both fail colMgr.transaction(collection, new FetchOptions().stoken(stoken)); colMgr.upload(collection, new FetchOptions().stoken(stoken)); // Will both succeed colMgr.transaction(collection); colMgr.upload(collection); ``` -------------------------------- ### List Collection Items with Fetch Options Source: https://docs.etebase.com/guides/using_items Shows how to list items within a collection, including the collection itself, using specific fetch options. ```java ItemListResponse items = itemManager.list(new FetchOptions().with_collection(true)); ``` ```kotlin val items = itemManager.list(FetchOptions().with_collection(true)) ``` ```c EtebaseFetchOptions *fetch_options = etebase_fetch_options_new(); etebase_fetch_options_set_with_collection(fetch_options, true); etebase_fetch_options_set_limit(fetch_options, 1); EtebaseItemListResponse *item_list = etebase_item_manager_list(item_mgr, fetch_options); etebase_fetch_options_destroy(fetch_options); ``` ```rust let items = item_manager.list(Some(&FetchOptions::new().with_collection(true)))?; ``` -------------------------------- ### Iterate Outgoing Invitations in Rust Source: https://docs.etebase.com/guides/collection_sharing Process outgoing invitations iteratively in Rust. This example uses Rust's Option type for the iterator and handles the loop until all data is fetched. ```rust let mut iterator: Option<&str> = None; let mut invitations: IteratorListResponse; loop { invitations = invitation_manager.list_outgoing( Some(&FetchOptions::new().iterator(iterator).limit(30)) )?; iterator = invitations.iterator(); process_outgoing_invitations(invitations.data()); if invitations.done() { break } } ``` -------------------------------- ### Save and Load Collection (Rust - older API) Source: https://docs.etebase.com/guides/local_cache An older Rust example for saving and loading collections, using base64 encoding for the cache blob and Result for error handling. ```rust // Create a collection let collection = collection_manager.create(...)?; // The cache blob is just a Uint8Array that can be saved for later use let cache_b64 = utils::to_base64(&collection_manager.cache_save(&collection)?)?; // Later on we can load the object back let mut collection = collection_manager.cache_load(&utils::from_base64(&cache_b64)?)?; // And use it like any other object: collection.set_content(b"New content")?; ``` -------------------------------- ### JavaScript: Transaction and Batch with Dependencies Source: https://docs.etebase.com/guides/using_items Demonstrates how to use dependencies in JavaScript for transaction and batch operations. Operations will fail if any of the provided dependency items have changed. ```javascript // -> On device A: const item1 = await.itemManager.fetch(itemUid1); const item2 = await.itemManager.fetch(itemUid2); // -> On device B: const item1 = await.itemManager.fetch(itemUid1); await item1.setContent("something else for item 1"); await itemManagerManager.batch([item1]); // -> On device A (using the previously saved items and stoken) await item2.setContent("new secret content"); // Both will fail because item1 changed await itemManager.transaction([item2], [item1]); await itemManager.batch([item2], [item1]); // Can even use the item in both the list and deps in batch // Will fail because item1 changed on device B await itemManager.batch([item1, item2], [item1]); ``` -------------------------------- ### Include and use Etebase C library Source: https://docs.etebase.com/installation Include the etebase.h header and use the etebase_account_login function in your C/C++ project. ```c #include EtebaseAccount *account = etebase_account_login(...); ``` -------------------------------- ### Rust: Update and Transaction/Batch Operations Source: https://docs.etebase.com/guides/using_items Provides examples of updating an item's content and performing transaction or batch operations in Rust. Operations will fail if a stoken is used in the fetch options. ```rust // -> On device A: let stoken = collection.stoken(); let mut item = item_manager.fetch(item_uid, None)?; // -> On device B: let mut another_item = item_manager.fetch(another_item_uid, None)?; another_item.set_content(b"content for another item")?; item_manager.batch(vec![&another_item].into_iter(), None)?; // -> On device A (using the previously saved item and stoken) item.set_content(b"new secret content")?; // Both will fail let fetch_options = FetchOptions::new().stoken(stoken); item_manager.transaction(vec![&item].into_iter(), Some(&fetch_options))?; item_manager.batch(vec![&item].into_iter(), Some(&fetch_options))?; Both will // Both will succeed item_manager.transaction(vec![&item].into_iter(), None)?; item_manager.batch(vec![&item].into_iter(), None)?; ``` -------------------------------- ### Fetch Collection and Other Items Source: https://docs.etebase.com/guides/using_items Demonstrates fetching updates for a collection along with other items using different language bindings. ```javascript items = item_mgr.fetch_updates([collection.item, item1]); ``` ```java ItemListResponse items = itemManager.fetchUpdates(new Item[] { collection.asItem(), item1 }); ``` ```kotlin val items = itemManager.fetchUpdates(arrayOf(collection.asItem(), item1)) ``` ```c const EtebaseItem *items[] = { col_item, item1 }; EtebaseItemListResponse *item_list = etebase_item_manager_fetch_updates(item_mgr, items, ETEBASE_UTILS_C_ARRAY_LEN(items), NULL); ``` ```rust let items = item_manager.fetch_updates(vec![&collection.item()?, &item1].into_iter(), None); ``` -------------------------------- ### Check Custom Server URL - C/C++ Source: https://docs.etebase.com/guides/basic_authentication Verify if a given URL points to a valid Etebase server. Returns 0 for valid, 1 for invalid, and -1 for errors. ```c EtebaseClient *client = etebase_client_new("client-name", "https://example.com") // Returns 0 if client is pointing an etebase server, 1 if not, -1 on error int32_t is_etebase = etebase_account_check_etebase_server(client) ``` -------------------------------- ### Java API (Alternative Syntax): Get and Set Binary Content Source: https://docs.etebase.com/guides/using_items An alternative syntax in the Java API for accessing and modifying item content. Note that `content` and `contentString` are properties, while `toByteArray()` is a method. ```java item.content ``` ```java item.contentString ``` ```java item.content = "Bla".toByteArray() ``` ```java item.content = "Hello" ``` -------------------------------- ### Create, Encrypt, and Upload a New Item (Java) Source: https://docs.etebase.com/guides/using_items This Java code demonstrates creating a new file item, setting its metadata, encrypting the content, and uploading it. It requires an initialized ItemManager and a Collection object. ```java ItemMetadata meta = new ItemMetadata(); meta.setType("file"); meta.setName("note.txt"); meta.setMtime((new Date()).getTime()); Item item = itemManager.create(meta, "My secret note"); itemManager.batch(new Item[] {item}); ``` -------------------------------- ### Import and use Etebase in Java Source: https://docs.etebase.com/installation Import the Account class from com.etebase.client and use its login method in your Java project. ```java import com.etebase.client.Account; Account etebase = Account.login(...) ``` -------------------------------- ### Item Transaction and Batch Operations (Kotlin) Source: https://docs.etebase.com/guides/using_items Illustrates item management with transactions and batch operations in Kotlin. Covers fetching, updating, and synchronizing items, highlighting potential conflicts. ```kotlin // -> On device A: val item1 = itemManager.fetch(itemUid1) val item2 = itemManager.fetch(itemUid2) // -> On device B: val item1 = itemManager.fetch(itemUid1) item1.content = "Something else for item 1" itemManager.batch(arrayOf(item1)) // -> On device A (using the previously saved item) item1.content = "New content for item 1" item2.content = "New content for item 2" // Will fail because item1 changed on device B itemManager.transaction(arrayOf(item1, item2)) // Will succeed itemManager.batch(arrayOf(item1, item2)) // Will succeed because item2 hasn't changed on device B itemManager.transaction(arrayOf(item2)) ``` -------------------------------- ### Encrypt and Save Session in JavaScript Source: https://docs.etebase.com/guides/basic_authentication Encrypt stored sessions using a randomly generated key for enhanced security. Store the key securely, for example, in the operating system's key store. ```javascript const etebase = await Etebase.Account.login("username", "password"); // Save the key somewhere safe (e.g. the OS's key store) const encryptionKey = Etebase.randomBytes(32); const savedSession = await etebase.save(encryptionKey); // Later on... const etebase = await Etebase.Account.restore(savedSession, encryptionKey); ``` -------------------------------- ### Signup with Etebase Account Source: https://docs.etebase.com/guides/basic_authentication Use this to create a new Etebase account. Ensure your server allows signups or a user exists. ```javascript // serverUrl can be obtained from the dashboard (or omitted for default) const etebase = await Etebase.Account.signup({ username: "username", email: "email" }, "password", serverUrl); ``` ```python from etebase import Client, Account, User # server_url can be obtained from the dashboard (or omitted for default) client = Client("client-name", server_url) user = User("username", "test@example.com") etebase = Account.signup(client, user, "password") ``` ```java import com.etebase.client.*; import okhttp3.OkHttpClient; OkHttpClient httpClient = new OkHttpClient.Builder().build(); User user = new User("username", "text@example.com"); // serverUrl can obtained from the dashboard (or null for default) Client client = Client.create(httpClient, serverUrl); Account etebase = Account.signup(client, user, "password"); ``` ```kotlin import com.etebase.client.* import okhttp3.OkHttpClient; val httpClient: OkHttpClient = Builder().build() val user = User("username", "text@example.com") // serverUrl can obtained from the dashboard (or null for default) val client = Client.create(httpClient, serverUrl) val etebase = Account.signup(client, user, "password") ``` ```c // Your personal server url can be obtained from the dashboard const char *server_url = etebase_get_default_server_url(); EtebaseClient *client = etebase_client_new("client-name", server_url); EtebaseUser *user = etebase_user_new("username", "test@example.com"); EtebaseAccount *etebase = etebase_account_signup(client, user, "password"); ``` ```rust use etebase::{Account, Client, User}; let user = User::new("username", "text@example.com"); let client = Client::new(..., server_url)?; let etebase = Account::signup(client, user, "password")?; ``` -------------------------------- ### Python: Fetching Collection Items Source: https://docs.etebase.com/guides/using_items Demonstrates obtaining an ItemManager for a collection and retrieving items, including the collection itself. Covers listing items with collection data, fetching by UID, and fetching updates. ```python item_mgr = col_mgr.get_item_manager(collection) # Will return the collection item as part of the list: fetch_options = FetchOptions().with_collection(true) items = item_mgr.list(fetch_options); # Assuming the collection is the first item returned: col_item = items.data[0]; assert(col_item.uid == collection.uid) # You can also fetch collection items based on UID: col_item = item_mgr.fetch(collection.uid); ``` -------------------------------- ### Get Collection Content as Null-Terminated String (C API) Source: https://docs.etebase.com/guides/using_collections Demonstrates how to retrieve collection content as a null-terminated string using the C API by manually appending a null terminator after fetching the binary data. ```c // As said above, content is not null terminated. // To get the content as a null terminated string: char tmp[500]; intptr_t len = etebase_collection_get_content(col, tmp, sizeof(tmp)); if (len < 0) { // Error } else { tmp[len] = 0; } ``` -------------------------------- ### Fetch Collections List - Python Source: https://docs.etebase.com/guides/using_collections This Python code demonstrates fetching a list of collections. It requires a logged-in Etebase account and returns an iterator of collections and a sync token. ```python etebase = Account.login(...) col_mgr = etebase.get_collection_manager() collections = col_mgr.list("cyberdyne.calendar") # { # data: iter(etebase.Collection), # Returned iterator of collections # stoken: string, # The sync token for this fetch # ... # More fields we'll cover later # } ``` -------------------------------- ### Kotlin: Batch and Transaction Operations with Dependencies Source: https://docs.etebase.com/guides/using_items Illustrates batch and transaction operations in Kotlin, showing how concurrent changes to an item can lead to operation failures. This is useful for understanding conflict resolution in distributed systems. ```kotlin // -> On device A: val item1 = itemManager.fetch(itemUid1) val item2 = itemManager.fetch(itemUid2) // -> On device B: val item1 = itemManager.fetch(itemUid1) item1.content = "Something else for item1" itemManager.batch(arrayOf(item1)) // -> On device A (using the previously saved collection) item2.content = "New content for item 2" // Both will fail because item1 changed itemManager.transaction(arrayOf(item2), arrayOf(item1)); itemManager.batch(arrayOf(item2), arrayOf(item1)); // Can even use the item in both the list and deps in batch // Will fail because item1 changed on device B itemManager.batch(arrayOf(item1, item2), arrayOf(item1)); ```