DEV Community

Alex Spinov
Alex Spinov

Posted on

GraphQL (Apollo) Has a Free API — Here's How to Build Type-Safe APIs

Apollo GraphQL provides a complete ecosystem for building GraphQL APIs and consuming them in frontend apps — all open-source and free.

Apollo Server Setup

npm install @apollo/server graphql
Enter fullscreen mode Exit fullscreen mode
import { ApolloServer } from "@apollo/server";
import { startStandaloneServer } from "@apollo/server/standalone";

const typeDefs = `#graphql
  type Post {
    id: ID!
    title: String!
    content: String!
    author: User!
    tags: [String!]!
    createdAt: String!
  }

  type User {
    id: ID!
    name: String!
    email: String!
    posts: [Post!]!
  }

  type Query {
    posts(limit: Int, offset: Int): [Post!]!
    post(id: ID!): Post
    user(id: ID!): User
  }

  type Mutation {
    createPost(title: String!, content: String!, tags: [String!]): Post!
    updatePost(id: ID!, title: String, content: String): Post!
    deletePost(id: ID!): Boolean!
  }
`;

const resolvers = {
  Query: {
    posts: (_, { limit = 10, offset = 0 }) => db.posts.slice(offset, offset + limit),
    post: (_, { id }) => db.posts.find(p => p.id === id),
    user: (_, { id }) => db.users.find(u => u.id === id)
  },
  Mutation: {
    createPost: (_, args) => {
      const post = { id: crypto.randomUUID(), ...args, createdAt: new Date().toISOString() };
      db.posts.push(post);
      return post;
    }
  },
  Post: {
    author: (post) => db.users.find(u => u.id === post.authorId)
  },
  User: {
    posts: (user) => db.posts.filter(p => p.authorId === user.id)
  }
};

const server = new ApolloServer({ typeDefs, resolvers });
const { url } = await startStandaloneServer(server, { listen: { port: 4000 } });
console.log(`Server ready at ${url}`);
Enter fullscreen mode Exit fullscreen mode

Apollo Client (React)

npm install @apollo/client graphql
Enter fullscreen mode Exit fullscreen mode
import { ApolloClient, InMemoryCache, ApolloProvider, useQuery, gql } from "@apollo/client";

const client = new ApolloClient({
  uri: "http://localhost:4000/graphql",
  cache: new InMemoryCache()
});

const GET_POSTS = gql`
  query GetPosts($limit: Int) {
    posts(limit: $limit) {
      id
      title
      author { name }
      tags
    }
  }
`;

function Posts() {
  const { loading, error, data } = useQuery(GET_POSTS, { variables: { limit: 10 } });
  if (loading) return <p>Loading...</p>;
  if (error) return <p>Error: {error.message}</p>;
  return (
    <ul>
      {data.posts.map(post => (
        <li key={post.id}>{post.title} by {post.author.name}</li>
      ))}
    </ul>
  );
}
Enter fullscreen mode Exit fullscreen mode

Mutations

import { useMutation, gql } from "@apollo/client";

const CREATE_POST = gql`
  mutation CreatePost($title: String!, $content: String!) {
    createPost(title: $title, content: $content) { id title }
  }
`;

function CreatePostForm() {
  const [createPost, { loading }] = useMutation(CREATE_POST, {
    refetchQueries: ["GetPosts"]
  });

  const handleSubmit = (e) => {
    e.preventDefault();
    createPost({ variables: { title: e.target.title.value, content: e.target.content.value } });
  };

  return <form onSubmit={handleSubmit}>...</form>;
}
Enter fullscreen mode Exit fullscreen mode

Need to extract or automate web content at scale? Check out my web scraping tools on Apify — no coding required. Or email me at spinov001@gmail.com for custom solutions.

Top comments (0)