Quick Start
This guide walks you through building a simple GraphQL API with queries, mutations, and type-safe arguments.
What We’ll Build
Section titled “What We’ll Build”A basic user API with:
- A
usersquery that returns a list of users - A
user(id)query that returns a single user - A
createUsermutation
-
Define Your Schema
Use Effect Schema to define your data types:
import * as S from "effect/Schema"// User schema with validationconst UserSchema = S.Struct({id: S.String,name: S.String,email: S.String,})// Input for creating usersconst CreateUserInput = S.Struct({name: S.String.pipe(S.minLength(1)),email: S.String.pipe(S.pattern(/@/)),})// TypeScript types are inferred automaticallytype User = S.Schema.Type<typeof UserSchema> -
Build the GraphQL Schema
Use
GraphQLSchemaBuilderto create your schema:import { Effect } from "effect"import { GraphQLSchemaBuilder } from "@effect-gql/core"// Sample dataconst users: User[] = [{ id: "1", name: "Alice", email: "alice@example.com" },{ id: "2", name: "Bob", email: "bob@example.com" },]const schema = GraphQLSchemaBuilder.empty// Register the User type.objectType({ name: "User", schema: UserSchema })// Query: get all users.query("users", {type: S.Array(UserSchema),resolve: () => Effect.succeed(users),})// Query: get user by ID.query("user", {type: UserSchema,args: S.Struct({ id: S.String }),resolve: (args) => {const user = users.find(u => u.id === args.id)return user? Effect.succeed(user): Effect.fail(new Error("User not found"))},})// Mutation: create a new user.mutation("createUser", {type: UserSchema,args: CreateUserInput,resolve: (args) => {const newUser: User = {id: String(users.length + 1),name: args.name,email: args.email,}users.push(newUser)return Effect.succeed(newUser)},})// Build the final GraphQL schema.buildSchema() -
Execute Queries
Use the
executefunction to run GraphQL operations:import { execute } from "@effect-gql/core"import { Layer } from "effect"// Execute a queryconst result = await Effect.runPromise(execute(schema, Layer.empty)(`query {users {idnameemail}}`))console.log(JSON.stringify(result, null, 2))Output:
{"data": {"users": [{ "id": "1", "name": "Alice", "email": "alice@example.com" },{ "id": "2", "name": "Bob", "email": "bob@example.com" }]}} -
Run with Arguments
Pass variables to your queries:
const result = await Effect.runPromise(execute(schema, Layer.empty)(`query GetUser($id: String!) {user(id: $id) {nameemail}}`,{ id: "1" } // variables))
Complete Example
Section titled “Complete Example”Here’s the full code in one file:
import { Effect, Layer } from "effect"import * as S from "effect/Schema"import { GraphQLSchemaBuilder, execute } from "@effect-gql/core"
// Schema definitionsconst UserSchema = S.Struct({ id: S.String, name: S.String, email: S.String,})
type User = S.Schema.Type<typeof UserSchema>
// In-memory data storeconst users: User[] = [ { id: "1", name: "Alice", email: "alice@example.com" }, { id: "2", name: "Bob", email: "bob@example.com" },]
// Build schemaconst schema = GraphQLSchemaBuilder.empty .objectType({ name: "User", schema: UserSchema }) .query("users", { type: S.Array(UserSchema), resolve: () => Effect.succeed(users), }) .query("user", { type: UserSchema, args: S.Struct({ id: S.String }), resolve: (args) => { const user = users.find(u => u.id === args.id) return user ? Effect.succeed(user) : Effect.fail(new Error("User not found")) }, }) .buildSchema()
// Executeconst main = execute(schema, Layer.empty)(` query { users { id name email } }`)
Effect.runPromise(main).then(console.log)Next Steps
Section titled “Next Steps”- Learn about the Schema Builder in detail
- Understand how Resolvers work with services
- Handle errors with Structured Errors