Setting the file. One moment.
Subchapter 11.2
references/naming.mdMarkdown7 KBView on GitHub
This reference covers naming conventions for GraphQL schemas. Consistent naming makes APIs intuitive and self-documenting.
createdAt over crtAtUse singular nouns in PascalCase:
# Correct
type User { ... }
type BlogPost { ... }
type ShoppingCart { ... }
type PaymentMethod { ... }
# Incorrect
type user { ... } # lowercase
type Users { ... } # plural
type blog_post { ... } # snake_caseUse adjectives or nouns describing capability:
interface Node { ... }
interface Timestamped { ... }
interface Searchable { ... }
interface Commentable { ... }Use nouns or compound names:
union SearchResult = User | Post | Comment
union MediaContent = Image | Video | Audio
union NotificationTarget = User | Group | ChannelUse camelCase, typically nouns or noun phrases:
type User {
id: ID!
firstName: String!
lastName: String!
emailAddress: String!
createdAt: DateTime!
isActive: Boolean!
}Prefix with is, has, can, or should:
type User {
isActive: Boolean!
isVerified: Boolean!
hasSubscription: Boolean!
canEdit: Boolean!
shouldNotify: Boolean!
}
type Post {
isPublished: Boolean!
isArchived: Boolean!
hasFeaturedImage: Boolean!
}Use plural nouns:
type User {
posts: [Post!]!
followers: [User!]!
notifications: [Notification!]!
}
type Query {
users: [User!]!
allPosts: [Post!]!
}Name based on the relationship:
type Post {
author: User! # Not: user, createdBy
comments: [Comment!]!
tags: [Tag!]!
}
type Comment {
post: Post! # Parent reference
author: User!
replies: [Comment!]! # Child reference
}Name by what they return, not how they’re computed:
type User {
fullName: String! # Not: getFullName, computedName
postCount: Int! # Not: calculatePostCount
recentActivity: [Activity!]!
}type Query {
user(id: ID!): User
users(first: Int, after: String): UserConnection!
search(query: String!, filters: SearchFilters): [SearchResult!]!
}# Single item lookup
user(id: ID!): User
post(slug: String!): Post
# Filtering
users(role: Role, isActive: Boolean): [User!]!
# Pagination
posts(first: Int, after: String): PostConnection!
posts(last: Int, before: String): PostConnection!
# Sorting
posts(orderBy: PostOrderBy): [Post!]!
# Search
search(query: String!): [SearchResult!]!# Avoid
posts(filter: JSON)
users(options: Options)
# Prefer
posts(status: PostStatus, authorId: ID)
users(role: Role, createdAfter: DateTime)enum UserRole { ... }
enum OrderStatus { ... }
enum SortDirection { ... }enum UserRole {
ADMIN
MODERATOR
MEMBER
GUEST
}
enum OrderStatus {
PENDING_PAYMENT
PAYMENT_RECEIVED
PROCESSING
SHIPPED
DELIVERED
CANCELLED
REFUNDED
}
enum SortDirection {
ASC
DESC
}Use action verbs followed by the subject:
type Mutation {
# Create operations
createUser(input: CreateUserInput!): User!
createPost(input: CreatePostInput!): Post!
# Update operations
updateUser(id: ID!, input: UpdateUserInput!): User!
updatePost(id: ID!, input: UpdatePostInput!): Post!
# Delete operations
deleteUser(id: ID!): DeleteUserPayload!
deletePost(id: ID!): DeletePostPayload!
# Domain-specific operations
publishPost(id: ID!): Post!
archivePost(id: ID!): Post!
sendMessage(input: SendMessageInput!): Message!
addItemToCart(input: AddItemInput!): Cart!
removeItemFromCart(itemId: ID!): Cart!
followUser(userId: ID!): FollowPayload!
unfollowUser(userId: ID!): UnfollowPayload!
}| Operation | Verbs |
|---|---|
| Create | create, add, register, submit |
| Read | get, fetch, load (avoid in mutations) |
| Update | update, edit, modify, set |
| Delete | delete, remove, archive |
| State change | publish, approve, reject, cancel |
| Relationships | add, remove, link, unlink |
| Actions | send, invite, follow, like |
Use the mutation name + Input:
input CreateUserInput {
email: String!
name: String!
}
input UpdateUserInput {
email: String
name: String
}
input SendMessageInput {
recipientId: ID!
body: String!
}Use the mutation name + Payload or Result:
type DeleteUserPayload {
success: Boolean!
deletedUserId: ID
}
type FollowUserPayload {
follower: User!
followee: User!
}# Avoid
type TUser { ... }
type UserType { ... }
strName: String!
intAge: Int!
# Prefer
type User { ... }
name: String!
age: Int!# Avoid
type User {
userId: ID!
userName: String!
userEmail: String!
}
# Prefer
type User {
id: ID!
name: String!
email: String!
}# Avoid
type User {
mysql_id: Int!
redis_cache_key: String!
getDerivedStateFromProps: JSON!
}
# Prefer
type User {
id: ID!
# Internal details should not appear in schema
}# Avoid
type Query {
getData: JSON
getInfo(type: String): JSON
fetch(params: JSON): JSON
}
# Prefer
type Query {
userProfile(userId: ID!): UserProfile
orderHistory(first: Int): OrderConnection!
searchProducts(query: String!): [Product!]!
}# Avoid: inconsistent naming
type User {
firstName: String! # camelCase
last_name: String! # snake_case
EmailAddress: String! # PascalCase
}
# Prefer: consistent camelCase
type User {
firstName: String!
lastName: String!
emailAddress: String!
}