
Security News
Axios Maintainer Confirms Social Engineering Attack Behind npm Compromise
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.
server-queries
Advanced tools
A powerful TypeScript-first userland implementation of server actions with more flexibility and support for data fetching.
A powerful TypeScript-first userland implementation of server actions with more flexibility and support for data fetching.
This library is not a replacement but rather a powerful addition to the server actions in Next.js.
npm install server-queries
# or
yarn add server-queries
# or
pnpm add server-queries
To use server-queries in your Next.js project, you need to configure the webpack loader. Add the following to your next.config.js:
/** @type {import('next').NextConfig} */
const nextConfig = {
webpack: (config) => {
config.module.rules.push({
test: /\.(ts|tsx)$/,
use: [
{
loader: "server-queries/webpack-loader",
},
],
});
return config;
},
};
module.exports = nextConfig;
// ./src/server/my-query.ts
import { serverQuery } from "server-queries/server";
import { ServerQueryErr, ServerQueryOk } from "server-queries/results";
export const myQuery = serverQuery("my-query", async () => {
const success = doSomethingOnTheServer();
if (!success) {
return ServerQueryErr({
code: "some-error",
title: "A server error occured",
});
}
return ServerQueryOk({
status: "ok",
});
});
Server queries and mutations use Next.js Route Handlers.
Create a new file in ./src/app/query/[id]/route.ts:
import { createRouteHandler } from "server-queries/server";
import { myQuery } from "@/server/my-query";
// Add all queries and mutations in the array.
// The request will only be handled for a query or mutation if it is
// registered in this function.
export const { GET, POST } = createRouteHandler([myQuery]);
[!IMPORTANT] Do not forget the import attributes!
The type is either
server-queryorserver-mutationand the ID MUST match the specified ID of the server query / mutation.
// ./src/app/components/SomeComponent.tsx
import { useServerQuery } from 'server-queries/client';
// IMPORTANT: This library only works by adding the correct import attributes
// when importing the query or mutation in client code!!!
import { myQuery } from '@/server/my-query' with { type: "server-query", id: "my-query" };
export function SomeComponent() {
const { data, isLoading, error } = useServerQuery(myQuery, {
queryKey: ["my-query-key"],
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{data.status}</h1>
</div>
);
}
Server queries can also support input parameters with schema validation.
The input is validated by the specified zod schema. If validation fails, a validation error is automatically returned from the query.
// ./src/server/my-query-with-input.ts
import { z } from "zod";
import { serverQuery } from "server-queries/server";
import { ServerQueryErr, ServerQueryOk } from "server-queries/results";
const schema = z.object({
name: z.string(),
age: z.number(),
});
export const myQueryWithInput = serverQuery(
"my-query-with-input",
async (input) => {
const success = doSomethingOnTheServer({
// Use the data from input.
name: input.name,
age: input.age,
});
if (!success) {
return ServerQueryErr({
code: "some-error",
title: "A server error occured",
});
}
return ServerQueryOk({
status: "ok",
});
}
);
// ./src/app/components/SomeComponent.tsx
import { useServerQuery } from 'server-queries/client';
// IMPORTANT: This library only works by adding the correct import attributes
// when importing the query or mutation in client code!!!
import { myQueryWithInput } from '@/server/my-query-with-input' with { type: "server-query", id: "my-query-with-input" };
export function SomeComponent() {
const { data, isLoading, error } = useServerQuery(myQueryWithInput, {
queryKey: ["my-query-key"],
// Pass the input here, can be state, props, etc.
// But if so, do not forget to add the input to the query key!
input: {
name: "some-name",
age: 40,
},
});
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
return (
<div>
<h1>{data.status}</h1>
</div>
);
}
A Server Query can also be used with infinite loading, by using the
useServerInfiniteQuery hook. Follow the TanStack Query Infinite Query docs for more info.
A server mutation has the same purpose as a server action, except that server mutations can be triggered in parallel. When triggering a data mutation due to user interaction, use of a Server Action (!) is always preferred!
TODO: add documentation
The webpack loader is a crucial part of the server-queries package.
To achieve a good DX similar to server actions, a server query / muation must be importable in the client code in order to directly use it in the desired hook.
This however leads to importing server code in a client component, which is
very dangerous because the server-code will be bundled in the client code if not
using import "server-only"!
The loader checks for all client code that imports a server query / muation
using the correct import attributes (the with statement at the end).
The import is then rewritten to only import the type (this makes sure to not imoprt any actual server code), but keeps type-safety in tact by leaving the needed TypeScript information.
Code for a mock object is then injected into the source code which is asserted to the imported type of the query / mutation and thus making the TypeScript compiler happy. But the object only contains the correct ID and type of the server query / mutation, which is the minimal needed data for the caller to create the request to the route handler.
serverQuery: Factory function to create a server query (GET request).serverMutation: Factory function to create a server mutation (POST request).createRouteHandler: Function to create the GET and POST route handler in Next.js.useServerQuery: React hook for executing server queries.useServerInfiniteQuery: React hook for infinite loading queries.useServerMutation: React hook for executing a server mutation.ServerQueryConfigProvider: Context provider for global configuration.FAQs
A powerful TypeScript-first userland implementation of server actions with more flexibility and support for data fetching.
We found that server-queries demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 2 open source maintainers 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
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.

Security News
The Axios compromise shows how time-dependent dependency resolution makes exposure harder to detect and contain.