~ knotless Search/
↑↓ move↵ open⇧↵ all results

johnandersen777.bsky.social/atlibs

0
0
main
98 lines · 2.7 KB Raw History

Write a module

Rust with the wasm target (rustup target add wasm32-unknown-unknown) and the CLI.

atlibs new my-module
my-module/  (cd my-module && cargo test && cargo wasm && atlibs run my-module describe '{"did":"<did>"}')

The SDK is pinned at the commit your CLI was built from:

grep '^abi' my-module/Cargo.toml
abi = { git = "https://knotless.dev/johnandersen777.bsky.social/atlibs", rev = "…" }

The module: one entry, describe, run once per event.

sed -n '1,/^entries!/p' my-module/modules/my-module/src/lib.rs
use abi::{Call, Did, Event, Handle, Run, entries};
use serde::Deserialize;
use serde_json::json;

#[derive(Deserialize)]
struct Args {
    did: Did,
}

// The host calls this once per event. Start: ask the account's PDS. Result: answer.
fn describe_handler(run: Run<Args>) -> Result<Handle, String> {
    Ok(match run.event {
        Event::Start => Handle::new().call(
            Call::new("repo", "com.atproto.repo.describeRepo")
                .params(json!({ "repo": run.args.did }))
                .service(run.args.did.as_str()),
        ),
        Event::Result { id, result, .. } if id == "repo" => {
            let repo = result.output()?;
            let collections = repo["collections"].as_array().map_or(0, Vec::len);
            Handle::new().result(json!({ "handle": repo["handle"], "collections": collections })).done()
        }
        _ => Handle::new(),
    })
}

entries!(describe => describe_handler);

What it may call, the form a host shows for it, and what a composition may set (config):

cat my-module/modules/my-module/module.json
{
	"name": "my-module",
	"description": "Describe an account's repo: its handle and how many collections it has.",
	"actions": [{ "entry": "describe", "label": "Describe", "readOnly": true, "fields": [{ "key": "did", "label": "DID", "required": true }] }],
	"config": [{ "key": "did", "label": "DID", "description": "The account a composition's instance describes." }],
	"calls": ["com.atproto.repo.describeRepo"]
}

Test, build, run

The tests (in lib.rs) feed the handler events; no network.

cd my-module
cargo test 2>&1 | grep '^test ' | LC_ALL=C sort
cargo wasm 2>&1 | tail -1
atlibs run my-module describe '{"did":"did:plc:ocnuqjlzgohypj3zoznermms"}'
test tests::result_counts_collections ... ok
test tests::start_calls_describe_repo ... ok
…
	"result": {
		"collections": …,
		"handle": "bobvmbuilder.bsky.social"
	},

More: the SDK, calls, tests with the real host loop.

Previous: Rust | Next: Publish