Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 7 additions & 11 deletions .llms-snapshots/llms-full.txt
Original file line number Diff line number Diff line change
Expand Up @@ -3287,11 +3287,11 @@ These crates are used to build and extend serverless functions in Rust with Juno
* [junobuild-macros](https://docs.rs/junobuild-macros): Procedural macros for declaratively attaching hooks and assertions.
* [junobuild-utils](https://docs.rs/junobuild-utils): Utility helpers for working with documents, including data encoding, decoding, and assertion context handling.

# Rust Hooks Example
# Mutating Documents with Rust Hooks

This example shows how to use **hooks in Rust** to customize how your Juno **Satellite** behaves. Hooks let you react to things like documents being created or deleted, or assets being uploaded — so you can run custom logic automatically on the backend.
This example demonstrates how to use **hooks in Rust** to modify documents automatically when they're created or updated in your Juno **Satellite**.

The project includes a simple frontend to help you trigger and test the backend logic, but the real focus is on how the Rust serverless function works.
Hooks let you react to events like document creation, deletion, or asset uploads — and run custom backend logic in response.

You can browse the source code here: [github.com/junobuild/examples/tree/main/rust/hooks](https://github.com/junobuild/examples/tree/main/rust/hooks)

Expand Down Expand Up @@ -3321,22 +3321,18 @@ rust/hooks/├── src/│ ├── satellite/ # Rust Satellite s

---

## Example: Hooks in Rust
## Example: Mutating Documents

Here’s the actual Rust logic from `lib.rs`:

```
use ic_cdk::print;use junobuild_macros::{on_delete_doc, on_set_doc, on_set_many_docs, on_upload_asset};use junobuild_satellite::{ include_satellite, set_doc_store, OnDeleteDocContext, OnSetDocContext, OnSetManyDocsContext, OnUploadAssetContext, SetDoc,};use junobuild_utils::{decode_doc_data, encode_doc_data};use junobuild_utils::{DocDataBigInt, DocDataPrincipal};use serde::{Deserialize, Serialize};#[derive(Serialize, Deserialize)]struct Person { yolo: bool, hello: String, principal: DocDataPrincipal, value: DocDataBigInt,}// Hook that runs when a document is set in the "demo" collection#[on_set_doc(collections = ["demo"])]async fn on_set_doc(context: OnSetDocContext) -> Result<(), String> { // Decode the document into our Person struct let mut data: Person = decode_doc_data(&context.data.data.after.data)?; // Log some values for debugging print(format!("[on_set_doc] Caller: {}", context.caller.to_text())); print(format!("[on_set_doc] Collection: {}", context.data.collection)); print(format!("[on_set_doc] Data: {} {}", data.principal.value, data.value.value)); // Modify the document before storing it again data.hello = format!("{} checked", data.hello); data.yolo = false; // Encode and re-store the updated document let encode_data = encode_doc_data(&data)?; let doc: SetDoc = SetDoc { data: encode_data, description: context.data.data.after.description, version: context.data.data.after.version, }; set_doc_store( context.caller, context.data.collection, context.data.key, doc, )?; Ok(())}// Hook that runs when multiple documents are set in the "demo" collection#[on_set_many_docs(collections = ["demo"])]async fn on_set_many_docs(context: OnSetManyDocsContext) -> Result<(), String> { print(format!("Many docs called {}", context.data.len())); Ok(())}// Hook that runs when a document is deleted#[on_delete_doc]async fn on_delete_doc(_context: OnDeleteDocContext) -> Result<(), String> { print("Bye bye"); Ok(())}// Hook that runs when an asset is uploaded to Storage#[on_upload_asset]async fn on_upload_asset(context: OnUploadAssetContext) -> Result<(), String> { print(format!("Asset uploaded {}", context.data.key.full_path)); Ok(())}// A sample query function, accessible via `query` calls#[ic_cdk::query]fn say() { print("Hello");}include_satellite!();
use ic_cdk::print;use junobuild_macros::{on_delete_doc, on_set_doc, on_set_many_docs, on_upload_asset};use junobuild_satellite::{ include_satellite, set_doc_store, OnDeleteDocContext, OnSetDocContext, OnSetManyDocsContext, OnUploadAssetContext, SetDoc,};use junobuild_utils::{decode_doc_data, encode_doc_data};use junobuild_utils::{DocDataBigInt, DocDataPrincipal};use serde::{Deserialize, Serialize};/// Example struct used to demonstrate decode/edit/store flow.#[derive(Serialize, Deserialize)]struct Person { yolo: bool, hello: String, principal: DocDataPrincipal, value: DocDataBigInt,}// Hook that runs when a document is set in the "demo" collection#[on_set_doc(collections = ["demo"])]async fn on_set_doc(context: OnSetDocContext) -> Result<(), String> { // Decode the document into our Person struct let mut data: Person = decode_doc_data(&context.data.data.after.data)?; // Log some values for debugging print(format!("[on_set_doc] Caller: {}", context.caller.to_text())); print(format!("[on_set_doc] Collection: {}", context.data.collection)); print(format!("[on_set_doc] Data: {} {}", data.principal.value, data.value.value)); // Modify the document before storing it again data.hello = format!("{} checked", data.hello); data.yolo = false; // Encode and re-store the updated document let encode_data = encode_doc_data(&data)?; let doc: SetDoc = SetDoc { data: encode_data, description: context.data.data.after.description, version: context.data.data.after.version, }; set_doc_store( context.caller, context.data.collection, context.data.key, doc, )?; Ok(())}include_satellite!();
```

**Explanation:**

* Defines a `Person` struct with fields for demo purposes.
* Uses the `#[on_set_doc]` macro to run logic whenever a document is set in the `demo` collection. Updates the document and saves it back.
* Uses the `#[on_set_many_docs]` macro to react to batch document sets in the `demo` collection.
* Uses the `#[on_delete_doc]` macro to react to document deletions.
* Uses the `#[on_upload_asset]` macro to react to asset uploads.
* Includes a simple query endpoint (`say`) for demonstration.
* `include_satellite!();` brings in the necessary boilerplate for the Juno Satellite runtime.

---
Expand Down Expand Up @@ -3418,8 +3414,8 @@ juno functions buildjuno functions upgrade

## Notes

* This example focuses on the Rust serverless function hooks; the frontend is intentionally minimal and only included for demonstration purposes.
* Use this project as a starting point for writing custom hooks and backend logic in Rust with Juno.
* This example focuses on the Rust serverless function. The frontend is intentionally minimal and included only for demonstration.
* Use this project as a starting point for writing custom backend logic in Rust using Juno hooks.

---

Expand Down
2 changes: 1 addition & 1 deletion .llms-snapshots/llms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ Juno is your self-contained serverless platform for building full-stack web apps
## Examples - Functions - Rust

- [Rust Assertions Example](https://juno.build/docs/examples/functions/rust/assertions.md): An example demonstrating how to write custom assertions in Rust for Juno serverless functions.
- [Rust Hooks Example](https://juno.build/docs/examples/functions/rust/hooks.md): An example demonstrating how to use serverless function hooks in Rust for Juno serverless functions.
- [Mutating Documents with Rust Hooks](https://juno.build/docs/examples/functions/rust/mutating-docs-with-hooks.md): An example demonstrating how to modify and re-save documents in Juno Satellites using Rust hooks.

## Guides

Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
---
title: Rust Hooks Example
description: An example demonstrating how to use serverless function hooks in Rust for Juno serverless functions.
title: Mutating Documents with Rust Hooks
description: An example demonstrating how to modify and re-save documents in Juno Satellites using Rust hooks.
keywords: [rust, hooks, serverless, functions, juno, satellite, example]
sidebar_label: Hooks
sidebar_label: Mutations
---

# Rust Hooks Example
# Mutating Documents with Rust Hooks

This example shows how to use **hooks in Rust** to customize how your Juno **Satellite** behaves. Hooks let you react to things like documents being created or deleted, or assets being uploaded — so you can run custom logic automatically on the backend.
This example demonstrates how to use **hooks in Rust** to modify documents automatically when they're created or updated in your Juno **Satellite**.

The project includes a simple frontend to help you trigger and test the backend logic, but the real focus is on how the Rust serverless function works.
Hooks let you react to events like document creation, deletion, or asset uploads — and run custom backend logic in response.

You can browse the source code here: [github.com/junobuild/examples/tree/main/rust/hooks](https://github.com/junobuild/examples/tree/main/rust/hooks)

Expand Down Expand Up @@ -54,7 +54,7 @@ rust/hooks/

---

## Example: Hooks in Rust
## Example: Mutating Documents

Here’s the actual Rust logic from `lib.rs`:

Expand All @@ -69,6 +69,7 @@ use junobuild_utils::{decode_doc_data, encode_doc_data};
use junobuild_utils::{DocDataBigInt, DocDataPrincipal};
use serde::{Deserialize, Serialize};

/// Example struct used to demonstrate decode/edit/store flow.
#[derive(Serialize, Deserialize)]
struct Person {
yolo: bool,
Expand Down Expand Up @@ -109,44 +110,13 @@ async fn on_set_doc(context: OnSetDocContext) -> Result<(), String> {
Ok(())
}

// Hook that runs when multiple documents are set in the "demo" collection
#[on_set_many_docs(collections = ["demo"])]
async fn on_set_many_docs(context: OnSetManyDocsContext) -> Result<(), String> {
print(format!("Many docs called {}", context.data.len()));
Ok(())
}

// Hook that runs when a document is deleted
#[on_delete_doc]
async fn on_delete_doc(_context: OnDeleteDocContext) -> Result<(), String> {
print("Bye bye");
Ok(())
}

// Hook that runs when an asset is uploaded to Storage
#[on_upload_asset]
async fn on_upload_asset(context: OnUploadAssetContext) -> Result<(), String> {
print(format!("Asset uploaded {}", context.data.key.full_path));
Ok(())
}

// A sample query function, accessible via `query` calls
#[ic_cdk::query]
fn say() {
print("Hello");
}

include_satellite!();
```

**Explanation:**

- Defines a `Person` struct with fields for demo purposes.
- Uses the `#[on_set_doc]` macro to run logic whenever a document is set in the `demo` collection. Updates the document and saves it back.
- Uses the `#[on_set_many_docs]` macro to react to batch document sets in the `demo` collection.
- Uses the `#[on_delete_doc]` macro to react to document deletions.
- Uses the `#[on_upload_asset]` macro to react to asset uploads.
- Includes a simple query endpoint (`say`) for demonstration.
- `include_satellite!();` brings in the necessary boilerplate for the Juno Satellite runtime.

---
Expand Down Expand Up @@ -196,8 +166,8 @@ import ProdDeploy from "../components/prod-deploy.md";

## Notes

- This example focuses on the Rust serverless function hooks; the frontend is intentionally minimal and only included for demonstration purposes.
- Use this project as a starting point for writing custom hooks and backend logic in Rust with Juno.
- This example focuses on the Rust serverless function. The frontend is intentionally minimal and included only for demonstration.
- Use this project as a starting point for writing custom backend logic in Rust using Juno hooks.

---

Expand Down
2 changes: 1 addition & 1 deletion sidebars.ts
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ const sidebars: SidebarsConfig = {
},
items: [
"examples/functions/rust/assertions",
"examples/functions/rust/hooks"
"examples/functions/rust/mutating-docs-with-hooks"
]
}
]
Expand Down