Select the types of activity you want to include in your feed.
Demonstration bridge between ATproto and GraphQL. Generate schema types and interface with the ATmosphere via GraphQL queries. Includes a TypeScript server with IDE.
···11+# ATProto <=> GraphQL Bridge Rules
22+33+## General
44+- This project bridges ATProto (server-side) and GraphQL (client-side) for efficient UI development in the ATmosphere.
55+- Familiarize yourself with both ATProto (Lexicon) and GraphQL concepts.
66+77+## Schema Generation
88+- Use `schema/generate_lexicon_schema.py` to generate GraphQL schemas from Lexicon definitions.
99+- Initialize standard ATProto definitions in `deps/atproto`.
1010+- Example: `pipenv run python schema/generate_lexicon_schema.py app.bsky.actor.getProfile com.atproto.server.getSession -o schema/schema-generated.graphql`
1111+- Generated schemas include recursive type references (e.g., `Lexicon_app_bsky_actor_defs_profileViewDetailed`).
1212+1313+## Server Development
1414+- The Rust-based GraphQL server serves as a reference implementation.
1515+- API endpoint: `/graphql`
1616+- Interactive interface: GraphiQL (for development)
1717+- Build with: `cd server && cargo run --release`
1818+- Default host: `0.0.0.0`, port: `8080`
1919+- Configure via `.env` (copy from `.env.example`)
2020+2121+## Development Workflow
2222+1. Initialize submodules: `git submodule update --init --recursive`
2323+2. Install dependencies: `pipenv install`
2424+3. Generate schemas as needed
2525+4. Develop server features
2626+2727+## Best Practices
2828+- Maintain clear separation between ATProto (server) and GraphQL (client) concerns.
2929+- Document schema generation steps for new procedures.
3030+- Keep server configuration environment-aware.
3131+3232+## License
3333+MIT - Follow open-source best practices.
···11-# Mothball GraphQL Server
22-33-A simple GraphQL server for the Mothball application, built with Rust, Actix Web, and Juniper.
11+# ATProto <=> GraphQL Bridge
4255-## Features
33+A bridge between ATProto (server-side) and GraphQL (client-side) for developing efficient UIs for the ATmosphere.
6477-- GraphQL API endpoint at `/graphql`
88-- Interactive GraphiQL interface for development
99-- Health check endpoint at `/health`
1010-- Environment-based configuration
1111-- Ready for deployment to Fly.io
55+**Installation:**
1261313-## Installation
77+```
88+git submodule update --init --recursive
99+pipenv install
1010+```
14111515-### Prerequisites
1212+## Schema Generation
16131717-- Rust (latest stable version)
1818-- Cargo
1919-- Fly.io CLI (for deployment)
1414+The `schema/` folder contains scripts to generate a GraphQL schema from Lexicon. Standard ATProto definitions are initialized in the `deps/atproto` folder.
20152121-### Building
1616+Example usage:
22172323-```bash
2424-cd mothball-server
2525-cargo build --release
1818+```
1919+pipenv run python schema/generate_lexicon_schema.py \
2020+ app.bsky.actor.getProfile \
2121+ com.atproto.server.getSession \
2222+ -o schema/schema-generated.graphql
2623```
27242828-### Running Locally
2929-3030-```bash
3131-# Copy the example environment file
3232-cp .env.example .env
2525+This will generate schema definitions for the `getProfile` and `getSession` procedures and recursively import all their referenced types, e.g.
33263434-# Run the server
3535-cargo run
3627```
2828+type Lexicon_app_bsky_actor {
2929+ getProfile(actor: ID!): Lexicon_app_bsky_actor_defs_profileViewDetailed
3030+}
37313838-The server will start on `http://localhost:8080` by default.
3939-4040-## Development
3232+# app.bsky.actor.defs#profileViewDetailed
3333+type Lexicon_app_bsky_actor_defs_profileViewDetailed {
3434+ did: ID!
3535+ handle: ID!
3636+ displayName: String
3737+ description: String
3838+ pronouns: String
3939+ website: String
4040+ avatar: String
4141+ banner: String
4242+ followersCount: Int
4343+ followsCount: Int
4444+ postsCount: Int
4545+ associated: Lexicon_app_bsky_actor_defs_profileAssociated
4646+ joinedViaStarterPack: Lexicon_app_bsky_graph_defs_starterPackViewBasic
4747+ indexedAt: String
4848+ createdAt: String
4949+ viewer: Lexicon_app_bsky_actor_defs_viewerState
5050+ labels: [Lexicon_com_atproto_label_defs_label!]
5151+ pinnedPost: Lexicon_com_atproto_repo_strongRef
5252+ verification: Lexicon_app_bsky_actor_defs_verificationState
5353+ status: Lexicon_app_bsky_actor_defs_statusView
5454+}
41554242-### GraphQL Schema
5656+# ...
5757+```
43584444-The server provides basic queries:
4545-- `hello`: Returns a greeting message
4646-- `health`: Returns server health status
47594848-### Extending the Schema
6060+## Example GraphQL Server
49615050-To add new GraphQL types and queries:
5151-1. Add new types to the `Query` struct in `src/main.rs`
5252-2. Use the `#[juniper::graphql_object]` attribute
5353-3. Add async functions for each query/mutation
5454-5555-## Deployment to Fly.io
5656-5757-### Prerequisites
5858-- Fly.io account
5959-- Fly.io CLI installed
6060-6161-### Deployment Steps
6262-6363-1. **Install Fly.io CLI** (if not already installed):
6464- ```bash
6565- curl -L https://fly.io/install.sh | sh
6666- ```
6262+This repo also contains a Rust GraphQL server that can bridge an exported schema to the AT protocol. You can use this as a reference or even expand it to include non-AT GraphQL types.
67636868-2. **Login to Fly.io**:
6969- ```bash
7070- fly auth login
7171- ```
6464+- GraphQL API endpoint at `/graphql`
6565+- Interactive GraphiQL interface for development
72667373-3. **Create a new Fly.io app**:
7474- ```bash
7575- fly launch
7676- ```
6767+### Building
77687878-4. **Set up PostgreSQL (if needed)**:
7979- ```bash
8080- fly postgres create
8181- ```
6969+```bash
7070+cd server
7171+cargo run --release
7272+```
82738383-5. **Deploy**:
8484- ```bash
8585- fly deploy
8686- ```
7474+The server will start on `http://localhost:8080` by default.
87758876### Environment Configuration
89779078Copy `.env.example` to `.env` and configure as needed for your deployment.
9191-9292-## Configuration
93799480| Variable | Default | Description |
9581|----------|---------|-------------|
9682| `HOST` | `0.0.0.0` | Host to bind the server to |
9783| `PORT` | `8080` | Port to listen on |
9898-| `DATABASE_URL` | (none) | Database connection string |
998410085## License
10186102102-MIT8787+MIT
-16
schema/copy_to_json.py
···11-import json
22-import os
33-44-# Get the absolute path of the script's directory
55-script_dir = os.path.dirname(os.path.abspath(__file__))
66-77-# Load the GraphQL schema from file
88-with open(os.path.join(script_dir, "schema-generated.graphql"), "r") as graphql_file:
99- graphql_schema = graphql_file.read()
1010-1111-# Encode the GraphQL schema as JSON
1212-graphql_json = json.dumps(graphql_schema)
1313-1414-# Save the JSON-encoded schema to a new file
1515-with open(os.path.join(script_dir, "schema-generated.graphql.json"), "w") as json_file:
1616- _ = json_file.write(graphql_json)
+8-8
schema/generate_lexicon_schema.py
···424424 help="List of lexicon identifiers to generate definitions for",
425425 ),
426426 ],
427427- append_schema: Annotated[
428428- list[str],
429429- Option(
430430- "--append-schema",
431431- "-a",
432432- help="Additional GraphQL schema files or folders to append. Can be used multiple times.",
433433- ),
434434- ],
435427 output: Annotated[
436428 str,
437429 Option(
···440432 help="Output file path (default: stdout)",
441433 ),
442434 ],
435435+ append_schema: Annotated[
436436+ list[str] | None,
437437+ Option(
438438+ "--append-schema",
439439+ "-a",
440440+ help="Additional GraphQL schema files or folders to append. Can be used multiple times.",
441441+ ),
442442+ ] = None,
443443) -> None:
444444 """Generate GraphQL schema from lexicon_ids and source files."""
445445