mirror of
https://github.com/spacedriveapp/spacedrive.git
synced 2026-02-20 07:37:26 -05:00
4.1 KiB
4.1 KiB
GraphQL API with async-graphql
Spacedrive's new API uses GraphQL with full type safety from Rust to TypeScript.
Type Safety Comparison
rspc (Old Approach)
// Backend
rspc::router! {
pub async fn create_library(name: String) -> Result<Library> {
// implementation
}
}
// Frontend - custom generated types
const library = await client.mutation(['create_library', name]);
async-graphql (New Approach)
// Backend
#[Object]
impl Mutation {
async fn create_library(&self, input: CreateLibraryInput) -> Result<LibraryType> {
// implementation
}
}
// Frontend - standard GraphQL with full types
const { data } = await createLibrary({
variables: { input: { name: "My Library" } }
});
Advantages of async-graphql
1. Better Tooling
- GraphQL Playground for API exploration
- Apollo DevTools for debugging
- VSCode extensions with autocomplete
- Postman/Insomnia support out of the box
2. Flexible Queries
# Frontend can request exactly what it needs
query GetLibrary($id: UUID!) {
library(id: $id) {
name
# Only fetch heavy statistics if needed
statistics {
totalFiles
totalSize
}
}
}
3. Built-in Features
- Field-level permissions
- Automatic N+1 query prevention with DataLoader
- Built-in introspection
- Subscriptions for real-time updates
4. Type Generation
# Simple command generates all TypeScript types
npm run graphql-codegen
# Generates:
# - Types for all queries/mutations
# - React hooks
# - Full TypeScript interfaces
5. Better Error Handling
mutation CreateLibrary($input: CreateLibraryInput!) {
createLibrary(input: $input) {
... on Library {
id
name
}
... on LibraryError {
code
message
field
}
}
}
Migration Benefits
| Feature | rspc | async-graphql |
|---|---|---|
| Type Safety | Custom | Industry Standard |
| Tooling | Limited | Extensive |
| Community | Abandoned | Active |
| Learning Curve | Custom API | Standard GraphQL |
| Code Generation | Custom | graphql-codegen |
| Real-time | Custom | Subscriptions |
| File Upload | Custom | Multipart spec |
| Caching | Manual | Apollo Cache |
Example: Full Type Safety Flow
1. Define in Rust
#[derive(SimpleObject)]
struct LibraryType {
id: Uuid,
name: String,
#[graphql(deprecation = "Use statistics.totalFiles")]
file_count: i64,
}
2. Auto-generated TypeScript
export interface Library {
id: string;
name: string;
/** @deprecated Use statistics.totalFiles */
fileCount: number;
}
3. Use in Frontend
// Full autocomplete and type checking
const { data } = useGetLibraryQuery({
variables: { id: libraryId }
});
// TypeScript knows exactly what fields are available
console.log(data.library.name); // ✅
console.log(data.library.invalid); // Type error!
Performance Benefits
Batching & Caching
// Apollo Client automatically batches and caches
const MultipleLibraryComponent = () => {
// These are automatically batched into one request
const lib1 = useGetLibraryQuery({ variables: { id: id1 } });
const lib2 = useGetLibraryQuery({ variables: { id: id2 } });
const lib3 = useGetLibraryQuery({ variables: { id: id3 } });
};
Optimistic Updates
const [createLibrary] = useCreateLibraryMutation({
optimisticResponse: {
createLibrary: {
id: 'temp-id',
name: input.name,
__typename: 'Library'
}
},
update: (cache, { data }) => {
// UI updates immediately, rolls back on error
}
});
Conclusion
While rspc provided type safety, async-graphql gives us:
- Industry standard that developers already know
- Better tooling and ecosystem
- Active maintenance and updates
- More features out of the box
- Same level of type safety with better DX
The migration from rspc to GraphQL modernizes the API while maintaining the type safety that Spacedrive requires.