SuperAPI AI Directory

api-graphql-grpc

Coding & development

View repository

Updated 10-16 06:22

About this skill

GraphQL & gRPC Skill

Design schemas, resolvers, and service definitions for GraphQL and gRPC APIs.


GraphQL Schema Design

# Scalars
scalar DateTime
scalar UUID
scalar JSON

# Enums
enum OrderStatus { PENDING PAID SHIPPED DELIVERED CANCELLED }
enum UserRole { ADMIN EDITOR VIEWER }
Types

type User { id: UUID! name: String! email: String! role: UserRole! orders(first: Int, after: String): OrderConnection! createdAt: DateTime! }

type Order { id: UUID! status: OrderStatus! total: Float! items: [OrderItem!]! user: User! createdAt: DateTime! }

type OrderItem { id: UUID! product: Product! quantity: Int! price: Float! }

Pagination (Relay cursor spec)

type OrderConnection { edges: [OrderEdge!]! pageInfo: PageInfo! totalCount: Int! } type OrderEdge { node: Order!; cursor: String! } type PageInfo { hasNextPage: Boolean! hasPreviousPage: Boolean! startCursor: String endCursor: String }

Queries

type Query { me: User user(id: UUID!): User users(first: Int, after: String, role: UserRole): UserConnection! order(id: UUID!): Order orders(status: OrderStatus, first: Int, after: String): OrderConnection! }

Mutations

type Mutation { createUser(input: CreateUserInput!): CreateUserPayload! updateUser(id: UUID!, input: UpdateUserInput!): UpdateUserPayload! deleteUser(id: UUID!): DeletePayload! createOrder(input: CreateOrderInput!): CreateOrderPayload! cancelOrder(id: UUID!): CancelOrderPayload! }

Subscriptions

type Subscription { orderStatusChanged(orderId: UUID!): Order! newOrder: Order! }

Inputs & Payloads

input CreateUserInput { name: String!; email: String!; role: UserRole } type CreateUserPayload { user: User; errors: [UserError!] } type UserError { field: String; message: String! }


---

## Resolver Pattern (DataLoader — solves N+1)

```javascript
// Without DataLoader: N+1 queries
// With DataLoader: batch all user IDs into one SQL IN(...)

const userLoader = new DataLoader(async (userIds) => {
  const users = await db.query(`SELECT * FROM users WHERE id = ANY($1)`, [userIds]);
  // Return in same order as input IDs
  return userIds.map(id => users.find(u => u.id === id) || null);
});

const resolvers = {
  Order: {
    user: (order, _, { loaders }) => loaders.user.load(order.userId),
  },
  Query: {
    orders: async (_, { status, first = 20, after }) => {
      return paginatedQuery('orders', { status, first, after });
    }
  }
};

Error Handling in GraphQL

{
  "data": { "createUser": null },
  "errors": [
    {
      "message": "Email already in use",
      "locations": [{ "line": 2, "column": 3 }],
      "path": ["createUser"],
      "extensions": {
        "code": "USER_EMAIL_TAKEN",
        "field": "email"
      }
    }
  ]
}

gRPC Proto Definition

syntax = "proto3";
package users.v1;
option go_package = "github.com/example/api/users/v1";

import "google/protobuf/timestamp.proto";
import "google/protobuf/empty.proto";

service UsersService {
  // Unary RPCs
  rpc GetUser(GetUserRequest) returns (User);
  rpc CreateUser(CreateUserRequest) returns (User);
  rpc UpdateUser(UpdateUserRequest) returns (User);
  rpc DeleteUser(DeleteUserRequest) returns (google.protobuf.Empty);
  rpc ListUsers(ListUsersRequest) returns (ListUsersResponse);

  // Server streaming
  rpc WatchUser(GetUserRequest) returns (stream User);

  // Bidirectional streaming
  rpc SyncUsers(stream SyncRequest) returns (stream SyncResponse);
}

message User {
  string id = 1;
  string name = 2;
  string email = 3;
  string role = 4;
  google.protobuf.Timestamp created_at = 5;
}

message GetUserRequest { string id = 1; }
message CreateUserRequest { string name = 1; string email = 2; string role = 3; }
message UpdateUserRequest { string id = 1; string name = 2; string email = 3; }
message DeleteUserRequest { string id = 1; }
message ListUsersRequest { int32 page = 1; int32 limit = 2; string role = 3; }
message ListUsersResponse { repeated User users = 1; int32 total = 2; }

REST vs GraphQL vs gRPC Decision Matrix

Factor REST GraphQL gRPC
Public API ✓ Best ✓ Good ✗
Mobile clients (bandwidth) ✗ Over-fetch ✓ Best ✓
Microservices (internal) ✓ ✗ ✓ Best
Streaming / real-time ✗ ✓ Subscriptions ✓ Best
Complex queries ✗ N endpoints ✓ Best ✗
Caching ✓ HTTP cache ✗ Complex ✗
Browser native ✓ ✓ ✗ (needs proxy)

After Completing the API Design

Once the graphql/grpc design output is delivered, ask the user:

"Would you like me to generate API documentation for this design? (yes/no)"

If the user says yes:

  • Check if the API Documentation skill is available in the installed skills list
  • If the skill is available:
    • Read and follow the instructions in the API Documentation skill
    • Use the API design output above as the input
  • If the skill is NOT available:
    • Inform the user: "It looks like the API Documentation skill isn't installed. You can install it and re-run.

If the user says no:

  • End the task here