Skip to content
GQLoom

GraphQL Loom

Build GraphQL server enjoyably and efficiently

GQLoom Logo

The most familiar Schema Library

ts
import { 
field
,
resolver
,
weave
} from "@gqloom/core"
import {
ValibotWeaver
} from "@gqloom/valibot"
import * as
v
from "valibot"
const
Giraffe
=
v
.
object
({
__typename
:
v
.
nullish
(
v
.
literal
("Giraffe")),
name
:
v
.
pipe
(
v
.
string
(),
v
.
description
("The giraffe's name")),
birthday
:
v
.
date
(),
}) const
giraffeResolver
=
resolver
.
of
(
Giraffe
, {
age
:
field
(
v
.
pipe
(
v
.
number
(),
v
.
integer
()))
.
input
({
currentDate
:
v
.
pipe
(
v
.
nullish
(
v
.
string
(), () => new
Date
().
toISOString
()),
v
.
transform
((
x
) => new
Date
(
x
))
), }) .
resolve
((
giraffe
, {
currentDate
}) => {
return
currentDate
.
getFullYear
() -
giraffe
.
birthday
.
getFullYear
()
}), }) export const
schema
=
weave
(
ValibotWeaver
,
giraffeResolver
)
ts
import { 
field
,
resolver
,
weave
} from "@gqloom/core"
import {
ZodWeaver
} from "@gqloom/zod"
import {
z
} from "zod"
const
Giraffe
=
z
.
object
({
__typename
:
z
.
literal
("Giraffe").
nullish
(),
name
:
z
.
string
().
describe
("The giraffe's name"),
birthday
:
z
.
date
(),
}) const
giraffeResolver
=
resolver
.
of
(
Giraffe
, {
age
:
field
(
z
.
number
().
int
())
.
input
({
currentDate
:
z
.
coerce
.
date
()
.
nullish
()
.
transform
((
x
) =>
x
?? new
Date
()),
}) .
resolve
((
giraffe
, {
currentDate
}) => {
return
currentDate
.
getFullYear
() -
giraffe
.
birthday
.
getFullYear
()
}), }) export const
schema
=
weave
(
ZodWeaver
,
giraffeResolver
)
ts
import { 
field
,
resolver
,
weave
} from "@gqloom/core"
import {
yupSilk
} from "@gqloom/yup"
import {
date
,
number
,
object
,
string
} from "yup"
const
Giraffe
=
yupSilk
(
object
({
name
:
string
().
required
().
meta
({
description
: "The giraffe's name" }),
birthday
:
date
().
required
(),
}).
label
("Giraffe")
) const
giraffeResolver
=
resolver
.
of
(
Giraffe
, {
age
:
field
(
yupSilk
(
number
().
integer
().
nonNullable
()))
.
input
({
currentDate
:
yupSilk
(
date
().
default
(() => new
Date
())),
}) .
resolve
((
giraffe
, {
currentDate
}) => {
return
currentDate
.
getFullYear
() -
giraffe
.
birthday
.
getFullYear
()
}), }) export const
schema
=
weave
(
giraffeResolver
)
GraphQL
type Giraffe {
  """The giraffe's name"""
  name: String!
  birthday: String!
  age(currentDate: String): Int!
}
  • 🧩

    Rich Integration

    Use your most familiar validation libraries and ORMs to build your next GraphQL application.

  • 🔒

    Type Safety

    Automatically infer types from the Schema, enjoy intelligent code completion during development, and detect potential problems during compilation.

  • 🔋

    Fully Prepared

    Middleware, context, subscriptions, and federated graphs are ready.

  • 🔮

    No Magic

    Without decorators, metadata, reflection, or code generation, it can run anywhere with just JavaScript/TypeScript.

  • 🧑‍💻

    Development Experience

    Fewer boilerplate codes, semantic API design, and extensive ecosystem integration make development enjoyable.

Full Featured GraphQL

CRUD interfaces are ready for activation

Create CRUD operations with predefined database models from Drizzle, MikroORM, Prisma by using ResolverFactory.

  • Like a skilled weaver, embed precisely defined database tables seamlessly into the GraphQL Schema.
  • With just a few lines of code, easily build a CRUD system and enjoy ORM's convenience.
  • Both resolvers and single operations can be customized with inputs and middleware to meet diverse needs.
  • Using a flexible approach, freely combine resolvers and add operations to the graph for endless potential.
ts
import { 
createServer
} from "node:http"
import {
weave
} from "@gqloom/core"
import {
drizzleResolverFactory
} from "@gqloom/drizzle"
import {
drizzle
} from "drizzle-orm/node-postgres"
import {
createYoga
} from "graphql-yoga"
import * as
tables
from "src/schema"
const
db
=
drizzle
(
process
.
env
.
DATABASE_URL
!, {
schema
:
tables
})
const
userResolver
=
drizzleResolverFactory
(
db
,
tables
.
users
).
resolver
()
const
postResolver
=
drizzleResolverFactory
(
db
,
tables
.
posts
).
resolver
()
const
schema
=
weave
(
userResolver
,
postResolver
)
const
yoga
=
createYoga
({
schema
})
const
server
=
createServer
(
yoga
)
server
.
listen
(4000, () => {
console
.
info
("Server is running on http://localhost:4000/graphql")
})
ts
import { 
drizzleSilk
} from "@gqloom/drizzle"
import {
relations
} from "drizzle-orm"
import * as
t
from "drizzle-orm/pg-core"
export const
roleEnum
=
t
.
pgEnum
("role", ["user", "admin"])
export const
users
=
drizzleSilk
(
t
.
pgTable
("users", {
id
:
t
.
serial
().
primaryKey
(),
createdAt
:
t
.
timestamp
().
defaultNow
(),
email
:
t
.
text
().
unique
().
notNull
(),
name
:
t
.
text
(),
role
:
roleEnum
().
default
("user"),
}) ) export const
usersRelations
=
relations
(
users
, ({
many
}) => ({
posts
:
many
(
posts
),
})) export const
posts
=
drizzleSilk
(
t
.
pgTable
("posts", {
id
:
t
.
serial
().
primaryKey
(),
createdAt
:
t
.
timestamp
().
defaultNow
(),
updatedAt
:
t
.
timestamp
()
.
defaultNow
()
.
$onUpdateFn
(() => new
Date
()),
published
:
t
.
boolean
().
default
(false),
title
:
t
.
varchar
({
length
: 255 }).
notNull
(),
authorId
:
t
.
integer
(),
}) ) export const
postsRelations
=
relations
(
posts
, ({
one
}) => ({
author
:
one
(
users
, {
fields
: [
posts
.
authorId
],
references
: [
users
.
id
] }),
}))
GraphQL
type UsersItem {
  id: Int!
  createdAt: String
  email: String!
  name: String
  role: String
  posts: [PostsItem!]!
}

type PostsItem {
  id: Int!
  createdAt: String
  updatedAt: String
  published: Boolean
  title: String!
  authorId: Int
  author: UsersItem
}

type Query {
  users(
    offset: Int
    limit: Int
    orderBy: [UsersOrderBy!]
    where: UsersFilters
  ): [UsersItem!]!
  usersSingle(
    offset: Int
    orderBy: [UsersOrderBy!]
    where: UsersFilters
  ): UsersItem
  posts(
    offset: Int
    limit: Int
    orderBy: [PostsOrderBy!]
    where: PostsFilters
  ): [PostsItem!]!
  postsSingle(
    offset: Int
    orderBy: [PostsOrderBy!]
    where: PostsFilters
  ): PostsItem
}

input UsersOrderBy {
  id: OrderDirection
  createdAt: OrderDirection
  email: OrderDirection
  name: OrderDirection
  role: OrderDirection
}

enum OrderDirection {
  asc
  desc
}

input UsersFilters {
  id: PgSerialFilters
  createdAt: PgTimestampFilters
  email: PgTextFilters
  name: PgTextFilters
  role: PgEnumColumnFilters
  OR: [UsersFiltersOr!]
}

input PgSerialFilters {
  eq: Int
  ne: Int
  lt: Int
  lte: Int
  gt: Int
  gte: Int
  inArray: [Int!]
  notInArray: [Int!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgSerialFiltersOr!]
}

input PgSerialFiltersOr {
  eq: Int
  ne: Int
  lt: Int
  lte: Int
  gt: Int
  gte: Int
  inArray: [Int!]
  notInArray: [Int!]
  isNull: Boolean
  isNotNull: Boolean
}

input PgTimestampFilters {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgTimestampFiltersOr!]
}

input PgTimestampFiltersOr {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
}

input PgTextFilters {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgTextFiltersOr!]
}

input PgTextFiltersOr {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
}

input PgEnumColumnFilters {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgEnumColumnFiltersOr!]
}

input PgEnumColumnFiltersOr {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
}

input UsersFiltersOr {
  id: PgSerialFilters
  createdAt: PgTimestampFilters
  email: PgTextFilters
  name: PgTextFilters
  role: PgEnumColumnFilters
}

input PostsOrderBy {
  id: OrderDirection
  createdAt: OrderDirection
  updatedAt: OrderDirection
  published: OrderDirection
  title: OrderDirection
  authorId: OrderDirection
}

input PostsFilters {
  id: PgSerialFilters
  createdAt: PgTimestampFilters
  updatedAt: PgTimestampFilters
  published: PgBooleanFilters
  title: PgVarcharFilters
  authorId: PgIntegerFilters
  OR: [PostsFiltersOr!]
}

input PgBooleanFilters {
  eq: Boolean
  ne: Boolean
  lt: Boolean
  lte: Boolean
  gt: Boolean
  gte: Boolean
  inArray: [Boolean!]
  notInArray: [Boolean!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgBooleanFiltersOr!]
}

input PgBooleanFiltersOr {
  eq: Boolean
  ne: Boolean
  lt: Boolean
  lte: Boolean
  gt: Boolean
  gte: Boolean
  inArray: [Boolean!]
  notInArray: [Boolean!]
  isNull: Boolean
  isNotNull: Boolean
}

input PgVarcharFilters {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgVarcharFiltersOr!]
}

input PgVarcharFiltersOr {
  eq: String
  ne: String
  lt: String
  lte: String
  gt: String
  gte: String
  like: String
  notLike: String
  ilike: String
  notIlike: String
  inArray: [String!]
  notInArray: [String!]
  isNull: Boolean
  isNotNull: Boolean
}

input PgIntegerFilters {
  eq: Int
  ne: Int
  lt: Int
  lte: Int
  gt: Int
  gte: Int
  inArray: [Int!]
  notInArray: [Int!]
  isNull: Boolean
  isNotNull: Boolean
  OR: [PgIntegerFiltersOr!]
}

input PgIntegerFiltersOr {
  eq: Int
  ne: Int
  lt: Int
  lte: Int
  gt: Int
  gte: Int
  inArray: [Int!]
  notInArray: [Int!]
  isNull: Boolean
  isNotNull: Boolean
}

input PostsFiltersOr {
  id: PgSerialFilters
  createdAt: PgTimestampFilters
  updatedAt: PgTimestampFilters
  published: PgBooleanFilters
  title: PgVarcharFilters
  authorId: PgIntegerFilters
}

type Mutation {
  insertIntoUsers(values: [UsersInsertInput!]!): [UsersItem!]!
  insertIntoUsersSingle(value: UsersInsertInput!): UsersItem
  updateUsers(where: UsersFilters, set: UsersUpdateInput!): [UsersItem!]!
  deleteFromUsers(where: UsersFilters): [UsersItem!]!
  insertIntoPosts(values: [PostsInsertInput!]!): [PostsItem!]!
  insertIntoPostsSingle(value: PostsInsertInput!): PostsItem
  updatePosts(where: PostsFilters, set: PostsUpdateInput!): [PostsItem!]!
  deleteFromPosts(where: PostsFilters): [PostsItem!]!
}

input UsersInsertInput {
  id: Int
  createdAt: String
  email: String!
  name: String
  role: String
}

input UsersUpdateInput {
  id: Int
  createdAt: String
  email: String
  name: String
  role: String
}

input PostsInsertInput {
  id: Int
  createdAt: String
  updatedAt: String
  published: Boolean
  title: String!
  authorId: Int
}

input PostsUpdateInput {
  id: Int
  createdAt: String
  updatedAt: String
  published: Boolean
  title: String
  authorId: Int
}

Full Power of GraphQL

  • 🔐

    Type Safety

    Strong type system to ensure the consistency and security of data from the server to the client.

  • 🧩

    Flexible Aggregation

    Automatically aggregate multiple queries, reducing the number of client requests and ensuring the simplicity of the server-side API.

  • 🚀

    Efficient Querying

    The client can specify the required data structure, reducing unnecessary data transfer and improving the performance and maintainability of the API.

  • 🔌

    Easy to Extend

    Extending the API by adding new fields and types without modifying existing code.

  • 👥

    Efficient Collaboration

    Using Schema as documentation, which can reduce communication costs and improve development efficiency in team development.

  • 🌳

    Thriving Ecosystem

    Tools and frameworks are emerging constantly. The active community, with diverse applications, is growing fast and has bright prospects.