
Security News
AI Agent Lands PRs in Major OSS Projects, Targets Maintainers via Cold Outreach
An AI agent is merging PRs into major OSS projects and cold-emailing maintainers to drum up more work.
@appgeist/restful-next-api
Advanced tools
Build restful API methods for Next.js > 9 and validate the incoming requests with yup

Build restful API methods for Next.js > 9 and validate the incoming requests with yup.
Next.js brought API routes support in v9, but you have to provide your own implementation of handling different rest methods (GET, POST, PUT, PATCH, DELETE). This helper enables you to clearly structure your method handling and validation.
npm i @appgeist/restful-next-api or yarn add @appgeist/restful-next-api;npx install-peerdeps -do @appgeist/restful-next-api to make sure you have the necessary peerDependencies (yup and of course next) in your project.In /pages/api/products.js:
import { object, number, string } from 'yup';
import methods from '@appgeist/restful-next-api';
import { Product, User } from '~/models';
import { log } from '~/utils';
export default methods({
get: ({ query: { page } }) => Product.browse({ page }),
post: {
bodySchema: object({
name: string()
.min(5)
.max(20)
.required(),
description: string()
.min(5)
.max(1000),
price: number()
.positive()
.max(9999)
.required(),
inventoryItems: number()
.integer()
.positive()
.max(999)
.required()
}).noUnknown(),
onRequest: async ({ body, req }) => {
const product = await Product.create(body);
await log(`Product ${product.id} created at ${new Date()} by user ${req.userId}`);
return product;
}
}
});
In /pages/api/products/[id].js:
import { object, number, string } from 'yup';
import { FORBIDDEN } from 'http-status-codes';
import methods, { ApiError } from '@appgeist/restful-next-api';
import { Product } from '~/models';
import { log } from '~/utilities';
export default methods({
patch: {
querySchema: {
id: number()
.integer()
.positive()
.required()
},
bodySchema: object({
name: string()
.min(5)
.max(20)
.required(),
description: string()
.min(5)
.max(1000),
price: number()
.positive()
.max(9999)
.required(),
inventoryItems: number()
.integer()
.positive()
.max(999)
.required()
}).noUnknown(),
onRequest: async ({ body, req }) => {
const product = await Product.create(body);
await log(`Product ${product.id} updated at ${new Date()} by user ${req.userId}`);
return product;
}
},
delete: {
querySchema: {
id: number()
.integer()
.positive()
.required()
},
onRequest: async ({ query: { id }, req }) => {
const { userId } = req;
const acl = await User.getACL(userId);
if (!acl.includes('deleteProduct')) throw new ApiError(FORBIDDEN);
await Product.destroy(id);
await log(`Product ${id} deleted at ${new Date()} by user ${userId}`);
}
}
});
Each method can be:
{ querySchema, bodySchema, handler, errorHandler }.A querySchema/bodySchema definition can be:
.noUnknown() modifier)For each request, the beforeRequest handler is invoked if present:
import methods from '@appgeist/restful-next-api';
export default methods({
get: {
beforeRequest: () => {
console.log('Before GET');
},
onRequest: () => {
console.log('On GET request');
}
},
delete: () => {
console.log('On DELETE request');
},
beforeRequest: () => {
// ...
console.log('Before REQUEST');
// ...
}
});
If beforeRequest completes without throwing an error, the data for each request is validated (and transformed) according to the specified querySchema and bodySchema definitions. See yup readme for more information on data validation and transformation.
400 (BAD_REQUEST) response is sent to the client with a JSON body type structured like so:{
"message": "There were 2 validation errors",
"errors": ["body.price must be an integer", "body.inventoryItems is required"]
}
onRequest handler will be invoked.The onRequest handler:
function onRequest({ query, body, req }) => { /* do work and return data */ };
...or
async function onRequest({ query, body, req }) => { /* do work and return Promise which resolves to data */ };
This method can return an object or a Promise resolving to an object that will be serialized to JSON and sent back to the client with a 200 (OK) status code. If onRequest returns undefined or null, an empty response will be sent with a 201 (CREATED) header for POST requests and 204 (NO_CONTENT) for non-POST request.
Default error handling
If beforeRequest or onRequest throws an ApiError (also exported by @appgeist/restful-next-api), a specific http status code is returned to the client. For instance, the following code will result in a 403 (FORBIDDEN) being sent to the client:
import methods, { ApiError } from '@appgeist/restful-next-api';
import { FORBIDDEN } from 'http-status-codes';
export default methods({
get: {
// ...
onRequest: () => {
// ...
throw new ApiError(FORBIDDEN);
// ...
}
// ...
}
});
Other error types are treated as 500 / INTERNAL_SERVER_ERROR and are also logged to the console.
You can override the default error handling mechanism by providing a custom error handling function like so:
export default methods({
patch: {
// querySchema: ..., bodySchema: ...,
onRequest: ({ body, req }) => {
/* handle patch request */
},
// Error handler for patch requests
onError: ({ res, err }) => {
res.status(500).send('Error while trying to patch');
}
},
delete: {
// querySchema: ...,
onRequest: ({ query: { id }, req }) => {
/* handle delete request */
}
},
// Generic error handler - this will also handle errors for delete requests
onError: ({ res, err }) => {
res.status(500).send('Error');
}
});
A specific method error handler takes precedence over the generic error handler.
JsDocs are provided for IDE support for now; an index.d.ts will be provided at some point in the future.
The ISC License.
FAQs
Build restful API methods for Next.js > 9 and validate the incoming requests with yup
We found that @appgeist/restful-next-api 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
An AI agent is merging PRs into major OSS projects and cold-emailing maintainers to drum up more work.

Research
/Security News
Chrome extension CL Suite by @CLMasters neutralizes 2FA for Facebook and Meta Business accounts while exfiltrating Business Manager contact and analytics data.

Security News
After Matplotlib rejected an AI-written PR, the agent fired back with a blog post, igniting debate over AI contributions and maintainer burden.