@zvk/next-kit
v0.2.3
Published
Next App Router adapters for server actions, cache invalidation, form data, and route handlers.
Readme
@zvk/next-kit
Next App Router adapters for server actions, cache invalidation, FormData parsing, and route handlers.
import { formDataToObject } from "@zvk/next-kit";
import {
createMappedNextMutationAction,
createNextMutationAction,
parseFormDataActionInput,
parseZodFormDataActionInput,
createPassthroughNextMutationAction,
createPassthroughNextMutationActionFactory,
createZodPassthroughNextMutationAction,
createZodPassthroughNextMutationActionFactory,
type ParseFormDataActionInput,
type ParseZodFormDataActionInput,
} from "@zvk/next-kit/actions";
import { createNextRouteHandler, jsonErrorResponse, parseJsonRequestBody, parseZodJsonRequestBody, readJsonRequestBody, readRequestBody } from "@zvk/next-kit/route-handlers";
import { captureRedirectPath, createJsonRequest, createNextNavigationRedirectMock } from "@zvk/next-kit/test-utils";
import { buildAppUrl, safeNextPath } from "@zvk/next-kit/url";The package keeps its runtime helpers narrow. It depends on @zvk/contracts, @zvk/feature-kit, @zvk/server-kit, server-only, and a Next 15 || 16 peer, but it does not add React components, React Query, Supabase, Drizzle, or app-specific policy.
See ../../docs/package-boundary-matrix.md for the package-family runtime
boundary matrix. The actions, cache, and route-handlers subpaths are
server-only; the root export stays browser-safe.
@zvk/next-kit/actions intentionally keeps both layers of action helpers. Use
createNextMutationAction when you want the canonical contract ActionResult
wrapper from @zvk/contracts, and use the mapped or passthrough helpers when
the app owns the flattened result envelope or needs app-owned wrapper output.
Use @zvk/next-kit/cache for path and tag cache invalidation in Next App
Router server code. Path targets call revalidatePath; tag targets call
revalidateTag. The package expects the Next 15 or 16 next/cache APIs.
Use @zvk/next-kit/url for framework-safe URL construction, next-path
sanitization, and search-param appending. Redirect destinations and route names
remain application policy.
safeNextPath accepts unknown external values, including form-derived values,
and falls back unless the input is a same-origin local path.
Use createMappedNextMutationAction when an application owns a flattened action
result envelope and needs to map shared contract success/error results into that
shape.
Use parseFormDataActionInput when a redirecting or custom server action needs
to convert FormData and validate it through a schema adapter while keeping
redirect destinations, auth policy, and product copy in the app.
Use parseZodFormDataActionInput when the app already validates with Zod-like
schemas and should not compose the schema adapter locally.
Use ParseFormDataActionInput or ParseZodFormDataActionInput for app-local
wrappers that preserve package parser input typing while adding app-owned
redirect policy or response mapping.
Pass values for server-owned fields, such as organization IDs or fixed return
paths, that must override any submitted form values before validation.
Use createPassthroughNextMutationAction when run already returns the
application-owned envelope and package-owned validation, authorization,
dependency, or revalidation failures should be mapped into that same envelope.
Use createZodPassthroughNextMutationAction when the caller already owns a
Zod-like schema and should avoid local schema-adapter glue.
When passing revalidate, also pass shouldRevalidate so app-level error
envelopes do not accidentally invalidate cache targets.
Use createPassthroughNextMutationActionFactory when an app already owns schema
adapters and wants to bind its package-error mapper and default app-envelope
revalidation predicate once.
Use createZodPassthroughNextMutationActionFactory when an app wants to bind
its package-error mapper and default revalidation predicate once, then create
many app-envelope actions without repeating that wiring.
const createAppMutation = createPassthroughNextMutationActionFactory<
AppActionResult<Project>,
AppActionResult<Project>
>({
mapError: actionErrorFromContractError,
shouldRevalidate: (result) => result.status === "ok",
});
export const saveProject = createAppMutation({
schema: projectInputSchemaAdapter,
getContext: requireProjectContext,
run: saveProjectInput,
revalidate: ["/projects"],
});Keep public action envelopes, redirect targets, auth/session policy, product copy, and route-specific revalidation predicates in the application wrapper.
Use readRequestBody when a custom Route Handler needs content-type-aware
JSON, text, form, or empty body parsing while receiving malformed or unsupported
body failures as contract validation errors. Use parseJsonRequestBody for
streaming or custom-response Route Handlers that
cannot use createNextRouteHandler but still need shared JSON parsing and
schema validation before returning an app-owned response. Use
parseZodJsonRequestBody when the route already owns a Zod-like schema. Use
readJsonRequestBody only when the route needs raw body control before
app-owned validation.
Use jsonResponse, jsonErrorResponse, and jsonResultResponse for small
custom JSON Route Handler responses. Pass mapper functions for app-owned
envelopes, product copy, and error details; the package only owns response
serialization, status, and headers.
Use createJsonRequest from @zvk/next-kit/test-utils for App Router tests
that need deterministic JSON Request objects, including raw malformed bodies.
Use createNextNavigationRedirectMock and captureRedirectPath when testing
redirecting actions that import next/navigation. They let tests mock redirects
without adding a dependency on a specific test runner. Use
createRedirectTestDouble only when the redirect function is injected directly.
Repo Skill
Use .codex/skills/use-zvk-next-kit/SKILL.md when maintaining this package.
See ../../docs/package-boundary-matrix.md for the browser-safe and server-only subpaths.
