
Security News
Browserslist-rs Gets Major Refactor, Cutting Binary Size by Over 1MB
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
graphql-fields-collector
Advanced tools
This package helps to bind client requested grapqhl fields with database queries.
npm install graphql-fields-collector
Typically, when creating a GraphQL resolver, we need to run a query against the database and return the data. However, sometimes the client may only require a subset of the data, which means unnecessary fields are being retrieved and transferred, leading to slower query times.
To address this issue, this package has been developed that can improve query performance. By reducing the number of fields retrieved from the database, the query can be processed more quickly.
To begin, let's create the collector:
import { GraphQLCollector } from "graphql-fields-collector";
type User = {
id: string;
name: string;
};
type Post = {
id: string;
title: string;
content: string;
author: User;
info: {
createdAt: Date;
};
};
type Context = {
select: string[];
leftJoin: string[][];
};
const postCollector = new GraphQLCollector<Context, Post>({
id: (ctx) => ctx.select.push("post.id"),
title: (ctx) => ctx.select.push("post.title"),
content: (ctx) => ctx.select.push("post.content"),
author: (ctx) => {
ctx.jeftJoin.push(["user", "user.id", "post.author_id"]);
return {
id: (ctx) => ctx.select.push("user.id as authorId"),
name: (ctx) => ctx.select.push("user.name as authorName"),
};
},
info: {
createdAt: (ctx) => ctx.select.push("post.createdAt"),
},
});
Next, we can utilize it within the GraphQL resolver:
const resolvers = {
Query: {
// ...
posts(_parent, _args, _context, info: GraphQLResolveInfo): Post[] {
const { select, leftJoin } = postCollector.collect(
{ select: [], leftJoin: [] },
info
);
const query = leftJoin.reduce(
(query, joinArgs) => query.leftJoin(...joinArgs),
orm.select(select).from("post")
);
// execute query, prepare dto and return
},
// ...
},
};
Let's take the following GraphQL query
query {
posts {
id
title
author {
name
}
}
}
Than we get the following from the context:
const select = ["post.id", "post.title", "user.name"];
const leftJoin = [["user", "user.id", "post.author_id"]];
Context and all operations are up to you. Change it freely!
Collect works with array-like fields in context
const postCollector = new GraphQLCollector<Context, Post>({
id: Collect("select", "post.id"),
title: Collect("select", "post.title"),
content: Collect("select", "post.content"),
author: (ctx) => {
Collect("jeftJoin", ["user", "user.id", "post.author_id"])(ctx);
return {
id: Collect("select", "user.id as authorId"),
name: Collect("select", "user.name as authorName"),
};
},
info: {
createdAt: Collect("select", "post.createdAt"),
},
});
Also there are few wrappers to make code readable
Wrap Collect("select", ...selects) into Select(...selects)
const postCollector = new GraphQLCollector<Context, Post>({
id: Select("post.id"),
title: Select("post.title"),
content: Select("post.content"),
author: (ctx) => {
Collect("jeftJoin", ["user", "user.id", "post.author_id"])(ctx);
return {
id: Select("user.id as authorId"),
name: Select("user.name as authorName"),
};
},
info: {
createdAt: Select("post.createdAt"),
},
});
Wrap Collect("jeftJoin", [...leftJoinArgs]) into LeftJoin(...leftJoinArgs)
const postCollector = new GraphQLCollector<Context, Post>({
id: Select("post.id"),
title: Select("post.title"),
content: Select("post.content"),
author: (ctx) => {
LeftJoin("user", "user.id", "post.author_id")(ctx);
return {
id: Select("user.id as authorId"),
name: Select("user.name as authorName"),
};
},
info: {
createdAt: Select("post.createdAt"),
},
});
Compose allows us to call field handlers one by one:
const postCollector = new GraphQLCollector<Context, Post>({
id: Select("post.id"),
title: Select("post.title"),
content: Select("post.content"),
author: Compose(LeftJoin("user", "user.id", "post.author_id"), () => ({
id: Select("user.id as authorId"),
name: Select("user.name as authorName"),
})),
info: {
createdAt: Select("post.createdAt"),
},
});
In addition, if you don't require auxiliary functionality, you can simply use the GraphQLCollectContext with the tools mentioned above.
Remember, you have the option to develop your own tools with customized context. Here's a quick example:
type Ctx = {
query: Knex.QueryBuilder;
};
const Select =
(...selects: string[]) =>
(ctx: Ctx) => {
ctx.query = ctx.query.select(...selects);
};
FAQs
This package helps to bind client requested grapqhl fields with database queries.
The npm package graphql-fields-collector receives a total of 43 weekly downloads. As such, graphql-fields-collector popularity was classified as not popular.
We found that graphql-fields-collector demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
Browserslist-rs now uses static data to reduce binary size by over 1MB, improving memory use and performance for Rust-based frontend tools.
Research
Security News
Eight new malicious Firefox extensions impersonate games, steal OAuth tokens, hijack sessions, and exploit browser permissions to spy on users.
Security News
The official Go SDK for the Model Context Protocol is in development, with a stable, production-ready release expected by August 2025.