@wearesage/schema
Version:
A flexible schema definition and validation system for TypeScript with multi-database support
136 lines (98 loc) • 3.38 kB
Markdown
This example demonstrates how to integrate the SAGE schema system with GraphQL, automatically generating a complete API from your entity definitions.
The example shows how to:
1. Generate a GraphQL schema from your entity metadata
2. Create GraphQL resolvers backed by your entity repositories
3. Support multiple database types through a unified GraphQL API
- Node.js v14+ and npm/yarn
- MongoDB, Neo4j, and PostgreSQL for the underlying datastores
```bash
npm install
npm run build
node dist/examples/graphql/index.js
```
This will output the generated GraphQL schema and resolver structure.
The example automatically generates a GraphQL schema from your entity metadata, including:
- Types for each entity with fields matching your properties
- Query resolvers for fetching entities
- Mutation resolvers for creating, updating, and deleting entities
- Input types for mutations
- Proper handling of relationships
The generated resolvers use your repositories to:
- Fetch entities from the appropriate database
- Create and update entities with proper validation
- Handle relationships across different databases
The example supports entities stored in different databases:
- Users in MongoDB
- Posts in Neo4j
- Tags in PostgreSQL
All accessible through a single GraphQL API!
To use this in a production environment, you would:
1. **Set up a GraphQL server** (e.g., Apollo Server):
```typescript
import { ApolloServer } from 'apollo-server';
import { generateGraphQLTypes, generateResolvers } from './graphql-generator';
const typeDefs = generateGraphQLTypes(registry);
const resolvers = generateResolvers(registry, repositories);
const server = new ApolloServer({
typeDefs,
resolvers,
context: ({ req }) => ({
// Add authentication, etc.
})
});
server.listen().then(({ url }) => {
console.log(`🚀 Server ready at ${url}`);
});
```
2. **Add authentication and authorization**:
```typescript
// In your context builder
const context = ({ req }) => {
const token = req.headers.authorization || '';
const user = verifyToken(token);
return { user };
};
// In your resolvers
const resolvers = {
Query: {
post: (_, { id }, { user }) => {
if (!user) throw new Error('Not authenticated');
return postRepo.findById(id);
}
}
};
```
3. **Add data loaders for performance**:
```typescript
import DataLoader from 'dataloader';
const context = () => {
return {
loaders: {
user: new DataLoader(ids => userRepo.findByIds(ids)),
post: new DataLoader(ids => postRepo.findByIds(ids)),
tag: new DataLoader(ids => tagRepo.findByIds(ids))
}
};
};
// In your resolvers
Post: {
author: (post, _, { loaders }) => {
return loaders.user.load(post.authorId);
}
}
```
- **Zero-Boilerplate API**: Your GraphQL API is automatically generated from your entity definitions
- **Type Safety**: Full TypeScript support ensures type safety across your entire stack
- **Database Flexibility**: Use the right database for each entity type
- **Unified API**: Clients access a single, coherent API regardless of the underlying database structure