# @carlonicora/nextjs-jsonapi 中文文档

规范地址：https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/

版本：6\.31\.0
npm 元数据更新时间：2026-11-09T10:18:48.335Z
中文译文更新时间：2026-11-09T04:50:35.244Z
软件包许可：GPL-3\.0-or-later

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40carlonicora/nextjs-jsonapi
原文对照：https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/?lang=original
项目主页：https://github.com/carlonicora/nextjs-jsonapi#readme
源码仓库：https://github.com/carlonicora/nextjs-jsonapi

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：23.1 MB，4633 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：57 个
- peer 依赖：yjs ^13\.6\.33，next \>=16\.4\.0，react \>=19\.3\.0，next-intl \>=4\.0\.0，react-dom \>=19\.3\.0，@xyflow/react \>=12\.0\.0，react-hook-form \>=7\.0\.0，@stripe/stripe-js \>=9\.13\.0，@tanstack/react-table \>=8\.0\.0，@stripe/react-stripe-js \>=6\.8\.0
- 首次发布：2025-12-09T23:43:50.475Z
- 最新版本发布：2026-11-09T10:18:48.013Z
- 近 30 天下载量：12509（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：425（近 12 个月 425 个）

## 中文简介

Next.js JSON:API 客户端有服务器/客户端支持并缓存

## 安装

```sh
npm install @carlonicora/nextjs-jsonapi
```

也可以使用：`pnpm add @carlonicora/nextjs-jsonapi`、`yarn add @carlonicora/nextjs-jsonapi`、`bun add @carlonicora/nextjs-jsonapi`

## README

# @carlonicora/nextjs-jsonapi (英语)

一个全面的Next.js软件包为JSON:API兼容客户端提供统一的服务器/客户端支持,自动缓存,以及完整的shadcn/ui组件库.

## 目录

-   [特征](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-features)
-   [4: 0的改变](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-what-changed-in-40)
-   [建筑](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-architecture)
-   [安装](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-installation)
-   [快速启动](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-quick-start)
-   [环境变量](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-environment-variables)
-   [条目点](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-entry-points)
-   [统一 API](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-unified-api)
-   [客户钩](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-client-hooks)
-   [服务器请求](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-server-requests)
-   [权限](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-permissions)
-   [阴影/](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-shadcnui-components)
-   [尾风 CSS 配置](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-tailwind-css-configuration)
-   [CSS 变量](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-css-variables)
-   [许可证](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-license)

## 特征

-   **统一 API**: 自动检测环境(服务器/客户端)并使用适当的请求方法
-   **JSON:API 合规**: 完整的 JSON: API 规格支持与去线化和平面化
-   **下一个.js 16+ 缓存**: 内建支持 `cacheLife()` 财务报告和审定财务报表 `cacheTag()` 通过缓存配置文件
-   **反应钩**数字 : `useJsonApiGet` 财务报告和审定财务报表 `useJsonApiMutation` 用于获取客户端数据
-   **服务器组件**: 直接服务器侧取取数据并自动处理符号
-   **多用途支助**: B2B 应用程序的内建公司ID处理
-   **文件上传**: 无连接文件上传支持, 有多部分请求
-   **阴影/**: 44个预建的UI组件(41个标准+3个自定义)
-   **工具函数**数字 : `cn` 类合并、移动检测和参考组成

## 建筑

图书馆按这些入境点排列 `exports` 地图在 `package.json`:

```
@carlonicora/nextjs-jsonapi
├── (main)               # Unified API, configuration functions, and everything in /core
├── /core                # Interfaces, factories, registries, permissions, feature modules, and utilities
├── /server              # Server-side requests, ServerSession, and cache tag helpers
├── /cached-get          # cachedServerGet: the token-free "use cache" GET (server only)
├── /client              # React hooks and client-side utilities
├── /components          # Library components and the 44 shadcn/ui components
├── /contexts            # React providers (SessionProvider, ViewportProvider, SocketProvider, ...)
├── /contexts/styles.css # Stylesheet for the contexts entry
├── /testing             # Test utilities (mock providers, render helpers)
├── /billing             # Stripe billing components (kept apart so Stripe.js is not loaded globally)
├── /help                # Help feature, client components
├── /help/server         # Help feature, server-safe constants and types
├── /tokenusage          # Token-usage admin feature, client components
├── /analytics           # Analytics feature, client components
├── /analytics/server    # Analytics feature, server page components
└── /next-config         # createNextConfig for next.config.js
```

## 4: 0的改变

4.0使图书馆在下16.4缓存组件下工作. 完整的食谱,随着破碎的改变和工作顺序,在 [文件/迁移至4.0.md](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/docs/migrating-to-4.0.md)简言之:

-   **缓存组件**数字 : `createNextConfig` 打开 `cacheComponents` 财务报告和审定财务报表 `partialPrefetching`。应用程序框架在它后面的会话流出时在静态外壳中制作.
-   **会议**数字 : `ServerSession.read()` (单位:千美元)`/server`返回 a `Promise<SessionSnapshot>` 由饼干和信头建造。 不用等就叫它来 答应我 `SessionProvider` (单位:千美元)`/contexts`(三); `useSession()` 解开它,所以它的召唤者坐在它的后面 `<Suspense>`。 。 。 .
-   **供应商接受 `session`**数字 : `ViewportProvider`, (中文(简体) ), `SocketProvider` (单位:千美元)`/contexts`和 `SidebarProvider` (单位:千美元)`/components`接受 `session?: Promise<SessionSnapshot>`. 旧道具(`token`, (中文(简体) ), `initialIsMobile`, (中文(简体) ), `defaultOpen`还行.
-   **`createNextConfig`** 从 `/next-config`数字 : `cspRemove` 不见了 CSP的第三方来自 `services` (单位:千美元)`"stripe" | "googleMaps" | "turnstile" | "discord" | "googleFonts"`); 任何其它内容 `csp`。 。 。 .
-   **缓存**: 一个模块的 `cache` 值是一个 `cacheLife` 配置文件名称或标签。 缓存服务器通过 `cachedServerGet` (单位:千美元)`/cached-get`页:1 `"use cache"` 函数,从不发送符号。 见 [快取配置文件](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-cache-profiles)。 。 。 .
-   **`configureI18n` 需求 `getLocale`**:通过下一轮 `getLocale` 从 `next-intl/server`; 图书馆不再导入下层 .

## 安装

```bash
pnpm add @carlonicora/nextjs-jsonapi
```

### Git 子模块设置( 替代)

如果您想要将软件包用作git子模块(用于开发或npm发布前):

**1\. 添加子模块**

```bash
cd /path/to/your-project
git submodule add https://github.com/carlonicora/nextjs-jsonapi packages/nextjs-jsonapi
```

**2\. 核实有效**

```bash
git submodule status
# Should show: <commit-sha> packages/nextjs-jsonapi (heads/master)
```

**3\. 提交子模块**

```bash
git add .gitmodules packages/nextjs-jsonapi
git commit -m "Add nextjs-jsonapi as submodule"
```

**4\. 更新您的 `package.json`** (例如, `apps/web/package.json`(中文(简体) )

```json
{
  "dependencies": {
    "@carlonicora/nextjs-jsonapi": "workspace:*"
  }
}
```

**5\. 确保 `pnpm-workspace.yaml` 包括软件包**

```yaml
packages:
  - "apps/*"
  - "packages/*"
```

**6\. 安装和建造**

```bash
pnpm install
cd packages/nextjs-jsonapi && pnpm build && cd ../..
```

**CI/CD(GitHub 动作)**,添加 `submodules: recursive` 到您的退出步骤 :

```yaml
- uses: actions/checkout@v4
  with:
    submodules: recursive
```

**用子模块克隆一个项目:**

```bash
# When cloning fresh
git clone --recurse-submodules https://github.com/your/repo.git

# If already cloned
git submodule update --init --recursive
```

### 同伴依赖关系

| 软件包 | 版本 | 需求 | 目的 |
| --- | --- | --- | --- |
| `next` | \>=16.4.0 | 对 | 下一个框架 |
| `react` | \>=19.3.0 | 对 | 反应库 |
| `react-dom` | \>=19.3.0 | 对 | 反应 DOM |
| `react-hook-form` | 页:1 | 可选 | 表格处理(形式组件) |

## 快速启动

### 1\. 配置API客户端

在您的环境设置文件中配置 JSON: API 客户端 :

```typescript
// src/config/env.ts
import { configureJsonApi } from "@carlonicora/nextjs-jsonapi";
import { bootstrap } from "@/config/Bootstrapper";

configureJsonApi({
  apiUrl: process.env.NEXT_PUBLIC_API_URL!,
  bootstrapper: bootstrap,
});
```

### 2\. 定义您的模块和起步器

为模块注册(用于 `Modules.X` 和 DataClass Registry (用于 JSON: API 响应翻译):

```typescript
// src/config/Bootstrapper.ts
import { DataClassRegistry, FieldSelector, ModuleRegistry } from "@carlonicora/nextjs-jsonapi/core";
import { ModuleWithPermissions } from "@carlonicora/nextjs-jsonapi/core";
import { S3Module } from "@carlonicora/nextjs-jsonapi/core";

// Import your module definitions
import { ArticleModule } from "@/features/article/ArticleModule";
import { UserModule } from "@/features/user/UserModule";
import { Article } from "@/features/article/data/Article";
import { User } from "@/features/user/data/User";

// Module factory helper
const moduleFactory = (params: {
  pageUrl?: string;
  name: string;
  cache?: string;
  model: any;
  feature?: string;
  moduleId?: string;
  inclusions?: Record<string, { types?: string[]; fields?: FieldSelector<any>[] }>;
}): ModuleWithPermissions => ({
  pageUrl: params.pageUrl,
  name: params.name,
  model: params.model,
  feature: params.feature,
  moduleId: params.moduleId,
  cache: params.cache,
  inclusions: params.inclusions ?? {},
});

// Example module definition file (e.g., ArticleModule.ts)
// export const ArticleModule = (factory: ModuleFactory) =>
//   factory({ name: "articles", model: Article, pageUrl: "/articles" });

// Single source of truth for all modules
const allModules = {
  Article: ArticleModule(moduleFactory),
  User: UserModule(moduleFactory),
  S3: S3Module(moduleFactory), // Built-in S3 module from library
} satisfies Record<string, ModuleWithPermissions>;

// Export type for TypeScript autocompletion
export type AllModuleDefinitions = typeof allModules;

let bootstrapped = false;

export function bootstrap(): void {
  if (bootstrapped) return;

  // Register modules for Modules.X access
  Object.entries(allModules).forEach(([name, module]) => {
    ModuleRegistry.register(name, module);
  });

  // Register model classes for JSON:API response translation
  DataClassRegistry.bootstrap(allModules);

  bootstrapped = true;
}
```

### 3\. 在服务器组件中获取数据

```typescript
// src/app/articles/page.tsx
import { JsonApiGet } from "@carlonicora/nextjs-jsonapi";
import { Modules } from "@carlonicora/nextjs-jsonapi/core";

export default async function ArticlesPage() {
  const response = await JsonApiGet({
    classKey: Modules.Article,
    endpoint: "/articles",
    language: "en",
  });

  if (!response.ok) {
    return <div>Error: {response.error}</div>;
  }

  return (
    <ul>
      {response.data.map((article) => (
        <li key={article.id}>{article.title}</li>
      ))}
    </ul>
  );
}
```

### 4\. 在客户端组件中使用钩子

```typescript
"use client";

import { useJsonApiGet, useJsonApiMutation } from "@carlonicora/nextjs-jsonapi/client";
import { Modules } from "@carlonicora/nextjs-jsonapi/core";

export function ArticleList() {
  const { data, loading, error, refetch } = useJsonApiGet({
    classKey: Modules.Article,
    endpoint: "/articles",
  });

  const { mutate, loading: creating } = useJsonApiMutation({
    method: "POST",
    classKey: Modules.Article,
    onSuccess: () => refetch(),
  });

  if (loading) return <div>Loading...</div>;
  if (error) return <div>Error: {error}</div>;

  return (
    <div>
      <button
        onClick={() => mutate({
          endpoint: "/articles",
          body: { title: "New Article" }
        })}
        disabled={creating}
      >
        Create Article
      </button>
      <ul>
        {data.map((article) => (
          <li key={article.id}>{article.title}</li>
        ))}
      </ul>
    </div>
  );
}
```

## 环境变量

```env
# Required
NEXT_PUBLIC_API_URL=http://localhost:3000

# Optional - Token cookie name (default: "token")
# Set this if your API uses a different cookie name for JWT tokens
```

## 条目点

### 主导出( E)`.`(中文(简体) )

默认导出提供了自动检测环境的统一 API :

```typescript
import {
  JsonApiGet,
  JsonApiPost,
  JsonApiPut,
  JsonApiPatch,
  JsonApiDelete,
  configureJsonApi,
} from "@carlonicora/nextjs-jsonapi";
```

### 核心项目`/core`(中文(简体) )

核心接口、工厂、登记册和公用事业:

```typescript
import {
  // Interfaces
  ApiDataInterface,
  ApiRequestDataTypeInterface,
  ApiResponseInterface,

  // Factories
  JsonApiDataFactory,

  // Registries
  ModuleRegistry, // Register modules during bootstrap
  DataClassRegistry, // Register model classes for JSON:API translation
  Modules, // Access registered modules (e.g., Modules.Article)

  // Endpoint builder
  EndpointBuilder,

  // Field selectors
  FieldSelector,

  // Utilities
  translateResponse,
} from "@carlonicora/nextjs-jsonapi/core";
```

### 客户`/client`(中文(简体) )

反应钩和客户端公用事业(要求) `"use client"`:

```typescript
import {
  // Hooks
  useJsonApiGet,
  useJsonApiMutation,
  useRehydration,

  // Context
  JsonApiProvider,
  useJsonApiContext,

  // Request utilities
  directFetch,
  getClientToken,
} from "@carlonicora/nextjs-jsonapi/client";
```

### 服务器( U)`/server`(中文(简体) )

服务器端请求工具 :

```typescript
import {
  serverRequest,
  getServerToken,
  ServerSession, // read(), isLogged(), checkPermission(), ...
  invalidateCacheTag,
  invalidateCacheTags,
  updateCacheTag,
  CACHE_PROFILES,
} from "@carlonicora/nextjs-jsonapi/server";
```

### 缓冲`/cached-get`(中文(简体) )

免签 `"use cache"` 获取。 它决定了真正的功能 `react-server` 仅限条件;其他捆绑都有一个会扔出活塞的活塞. `serverRequest` 召人来见你们 [快取配置文件](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/#readme-cache-profiles)) (中文(简体) ).

```typescript
import { cachedServerGet, statusFromDigest } from "@carlonicora/nextjs-jsonapi/cached-get";
```

### 权限( 在 `/core`(中文(简体) )

权限检查工具输出自 `/core` (并主入道:

```typescript
import {
  checkPermissions,
  Action,
  type PermissionCheck,
  type ModuleWithPermissions,
  type ModuleFactory,
} from "@carlonicora/nextjs-jsonapi/core";
```

### 特性模块(在 `/core`(中文(简体) )

可直接用于应用程序的内建功能模块:

```typescript
import {
  // S3 Module (for file uploads via pre-signed URLs)
  S3Module, // Module definition factory
  S3Service, // Service with getPreSignedUrl, getSignedUrl, deleteFile
  S3, // Data class
  type S3Interface, // Response interface
  type S3Input, // Input parameters
} from "@carlonicora/nextjs-jsonapi/core";

// Usage example:
const s3Response = await S3Service.getPreSignedUrl({
  key: "companies/123/documents/file.pdf",
  contentType: "application/pdf",
  isPublic: true,
});

await fetch(s3Response.url, {
  method: "PUT",
  headers: s3Response.headers,
  body: file,
});
```

### 公用事业 `/core`(中文(简体) )

工具函数 :

```typescript
import {
  cn, // Class name merger (clsx + tailwind-merge)
  composeRefs, // Compose multiple refs
  useComposedRefs, // Hook for composing refs
  useIsMobile, // Mobile detection hook
  type ClassValue, // Type for cn function
} from "@carlonicora/nextjs-jsonapi/core";
```

### 构成部分(`/components`(中文(简体) )

库本身的组件加上所有shadcn/ui组件(需要) `"use client"`:

```typescript
import {
  // UI Components (41)
  Accordion,
  AccordionItem,
  AccordionTrigger,
  AccordionContent,
  Alert,
  AlertTitle,
  AlertDescription,
  AlertDialog,
  AlertDialogTrigger,
  AlertDialogContent /* ... */,
  Avatar,
  AvatarImage,
  AvatarFallback,
  Badge,
  badgeVariants,
  Breadcrumb,
  BreadcrumbList,
  BreadcrumbItem /* ... */,
  Button,
  buttonVariants,
  Calendar,
  Card,
  CardHeader,
  CardTitle,
  CardDescription,
  CardContent,
  CardFooter,
  Carousel,
  CarouselContent,
  CarouselItem,
  CarouselPrevious,
  CarouselNext,
  ChartContainer,
  ChartTooltip,
  ChartTooltipContent,
  ChartLegend /* ... */,
  Checkbox,
  Collapsible,
  CollapsibleTrigger,
  CollapsibleContent,
  Command,
  CommandInput,
  CommandList,
  CommandItem /* ... */,
  ContextMenu,
  ContextMenuTrigger,
  ContextMenuContent /* ... */,
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader /* ... */,
  Drawer,
  DrawerTrigger,
  DrawerContent /* ... */,
  DropdownMenu,
  DropdownMenuTrigger,
  DropdownMenuContent /* ... */,
  Form,
  FormField,
  FormItem,
  FormLabel,
  FormControl /* ... */,
  HoverCard,
  HoverCardTrigger,
  HoverCardContent,
  Input,
  Label,
  NavigationMenu,
  NavigationMenuList,
  NavigationMenuItem /* ... */,
  Popover,
  PopoverTrigger,
  PopoverContent,
  Progress,
  RadioGroup,
  RadioGroupItem,
  ScrollArea,
  ScrollBar,
  Select,
  SelectTrigger,
  SelectValue,
  SelectContent,
  SelectItem /* ... */,
  Separator,
  Sheet,
  SheetTrigger,
  SheetContent,
  SheetHeader /* ... */,
  Sidebar,
  SidebarProvider,
  SidebarContent,
  SidebarMenu /* ... */,
  Skeleton,
  Slider,
  Sonner,
  Toaster,
  toast,
  Switch,
  Table,
  TableHeader,
  TableBody,
  TableRow,
  TableHead,
  TableCell /* ... */,
  Tabs,
  TabsList,
  TabsTrigger,
  TabsContent,
  Textarea,
  Toggle,
  toggleVariants,
  Tooltip,
  TooltipTrigger,
  TooltipContent,
  TooltipProvider,

  // Custom Components (3)
  Kanban,
  KanbanColumn,
  KanbanItem, // Drag-and-drop Kanban board
  Link, // next-intl compatible Link
  MultiSelect, // Multi-select dropdown
} from "@carlonicora/nextjs-jsonapi/components";
```

### 其他条目

| 入境点 | 它所持有的 |
| --- | --- |
| `/contexts` | 反应提供者 : `SessionProvider`编号 :`useSession`, (中文(简体) ), `ViewportProvider`, (中文(简体) ), `SocketProvider`和更多 |
| `/contexts/styles.css` | 随上下文条目一起运出样式表 |
| `/testing` | `MockJsonApiProvider`, (中文(简体) ), `renderWithProviders`, (中文(简体) ), `createMockApiData`, (中文(简体) ), `createMockResponse`,, , , , , , , , . |
| `/billing` | 条纹计费组件和上下文 |
| `/help` | 帮助功能客户端组件( U)`HelpProvider`, (中文(简体) ), `HelpHeader`, (...) (中文(简体) ) |
| `/help/server` | 服务器安全 `HELP_MODES` 和帮助文章类型 |
| `/tokenusage` | Token-usage 附加功能客户端组件 |
| `/analytics` | 分析功能客户端组件( A)`AnalyticsTracker`, (...) (中文(简体) ) |
| `/analytics/server` | `AnalyticsAdminPage`, (中文(简体) ), `AnalyticsJourneyPage` 服务器组件 |
| `/next-config` | `createNextConfig` 页:1 `next.config.js` (见 [文件/迁移至4.0.md](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/docs/migrating-to-4.0.md)(中文(简体) ) |
| `/messages/*` | `en.json`, (中文(简体) ), `it.json`: 图书馆提供的文本(见 [文献/图书馆](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/docs/library-messages.md)(中文(简体) ) |

图书馆自带英文和意大利文;一个应用程序根据自己的信息将其与 `mergeMessages` 说明 [文献/图书馆](https://npmcn.com/package/%40carlonicora/nextjs-jsonapi/docs/library-messages.md)。 。 。 .

## 统一 API

统一的API自动检测代码是否运行在服务器或客户端上,并使用适当的请求方法.

### JsonApiGet (英语)

从 JSON: API 端点获取数据 :

```typescript
const response = await JsonApiGet({
  classKey: Modules.Article, // Module definition
  endpoint: "/articles/123", // API endpoint
  companyId: "company-uuid", // Optional: for multi-tenant apps
  language: "en", // Required: for i18n
});

if (response.ok) {
  console.info(response.data); // Deserialized data
  console.info(response.pagination); // Pagination info

  // Navigate pages
  if (response.next) {
    const nextPage = await response.nextPage();
  }
}
```

### JsonApi 邮局

创建新资源 :

```typescript
const response = await JsonApiPost({
  classKey: Modules.Article,
  endpoint: "/articles",
  body: { title: "New Article", content: "..." },
  language: "en",

  // Optional
  files: { attachment: file }, // File uploads
  overridesJsonApiCreation: false, // Use raw body instead of JSON:API format
  responseType: Modules.OtherType, // If response type differs
});
```

### JsonApiPut / JsonApiPatch 密码

更新资源 :

```typescript
const response = await JsonApiPut({
  classKey: Modules.Article,
  endpoint: "/articles/123",
  body: { title: "Updated Title" },
  language: "en",
});
```

### JsonApiDelete (英语)

删除资源 :

```typescript
const response = await JsonApiDelete({
  classKey: Modules.Article,
  endpoint: "/articles/123",
  language: "en",
});
```

## 客户钩

### 使用 JsonApiGet 软件

自动调试获取数据的钩 :

```typescript
const {
  data, // Fetched data or null
  loading, // Loading state
  error, // Error message or null
  response, // Full API response
  refetch, // Manual refetch function
  hasNextPage, // Pagination: has next page
  hasPreviousPage, // Pagination: has previous page
  fetchNextPage, // Fetch next page
  fetchPreviousPage, // Fetch previous page
} = useJsonApiGet<Article>({
  classKey: Modules.Article,
  endpoint: `/articles/${id}`,
  companyId: companyId,
  options: {
    enabled: !!id, // Conditionally enable
    deps: [someDependency], // Refetch when these change
  },
});
```

### 使用 JsonApi 组合

钩子变异(POST, PUT, PATCH, DELETE):

```typescript
const {
  data, // Result data or null
  loading, // Loading state
  error, // Error message or null
  response, // Full API response
  mutate, // Execute the mutation
  reset, // Reset state
} = useJsonApiMutation<Article>({
  method: "POST",
  classKey: Modules.Article,
  onSuccess: (data) => console.info("Created:", data),
  onError: (error) => console.error("Failed:", error),
});

// Execute mutation
const result = await mutate({
  endpoint: "/articles",
  body: { title: "New Article" },
  files: { image: imageFile },
  companyId: "company-uuid",
});
```

## 服务器请求

对于服务器组件或API路由,直接使用服务器模块:

```typescript
import { serverRequest, getServerToken } from "@carlonicora/nextjs-jsonapi/server";

// Per-user data: no `cache`, so this is a plain uncached fetch that sends the token
export async function getMyArticle(id: string) {
  return serverRequest({
    method: "GET",
    url: `${process.env.NEXT_PUBLIC_API_URL}/articles/${id}`,
    token: await getServerToken(),
    language: "en",
  });
}

// Shared data: a GET with `cache` goes through cachedServerGet and never sends the token
export async function getPublicArticle(id: string) {
  return serverRequest({
    method: "GET",
    url: `${process.env.NEXT_PUBLIC_API_URL}/articles/${id}`,
    cache: "articles", // a cacheLife profile name, or a tag
    language: "en",
  });
}
```

### 快取配置文件

一个模块 `cache` 值决定服务器端 GET 如何被缓存 。 每一个得到一个 `cache` 值在内部运行 `cachedServerGet`页:1 `"use cache"` 函数 :

-   a 内置 `cacheLife` 配置文件名称( e)`"seconds"`, (中文(简体) ), `"minutes"`, (中文(简体) ), `"hours"`, (中文(简体) ), `"days"`, (中文(简体) ), `"weeks"`, (中文(简体) ), `"max"`, (中文(简体) ), `"default"`页:1 `cacheLife(profile)`· ;
-   任何其它值都是标记 ~ `cacheTag(value)` + 键 `cacheLife("max")`,所以该条目将一直存在,直到您取消标记.

```typescript
// In your module definition
const ArticleModule = (factory: ModuleFactory) =>
  factory({ name: "articles", model: Article, cache: "articles" }); // tag

// JsonApiGet on the server applies it automatically, and does not read the token
// cookie for a cached module

// After a write, expire the tag
await updateCacheTag("articles"); // Server Actions: the same request reads fresh data
await invalidateCacheTag("articles"); // elsewhere: stale-while-revalidate
```

缓存路径是无符号的: 参数是缓存密钥, 因此请求会不包含 `Authorization`。需要一个符号的终点是每个用户,其模块不能设置 `cache`。失败的响应被扔出而不是存储;其状态在 `error.digest` 作为 `HTTP_<status>` 财务报告和审定财务报表 `statusFromDigest` 读回.

## 权限

检查保护资源的用户权限 :

```typescript
import { Action, checkPermissions, Modules } from "@carlonicora/nextjs-jsonapi/core";

// Check if user has permission
const canEdit = checkPermissions({
  module: Modules.Article,
  action: Action.Update,
  user: currentUser,
  data: article,
});

if (!canEdit) {
  return <div>Access denied</div>;
}
```

## 阴影/

该包包括44个预建的shadcn/ui组件:

### 标准UI组件(41)

| 构成部分 | 说明 |
| --- | --- |
| `Accordion` | 可折叠的内容部分 |
| `Alert` | 对重要消息的点名 |
| `AlertDialog` | 确认的模块对话框 |
| `Avatar` | 用户配置图像 |
| `Badge` | 状况指标和标签 |
| `Breadcrumb` | 导航面包屑 |
| `Button` | 单击带有变体的动作 |
| `Calendar` | 摘取日期日历 |
| `Card` | 内容容器 |
| `Carousel` | 滑动内容面板 |
| `Chart` | 数据可视化(Recharts) |
| `Checkbox` | 切换选项 |
| `Collapsible` | 可扩展区域 |
| `Command` | 命令调色板( cmdk) |
| `ContextMenu` | 右键菜单 |
| `Dialog` | 模块窗口 |
| `Drawer` | 滑动侧面板(Vaul) |
| `DropdownMenu` | 下放菜单 |
| `Form` | 表格处理(反应- hook-form) |
| `HoverCard` | 交接卡 |
| `Input` | 文本输入字段 |
| `Label` | 表格标签 |
| `NavigationMenu` | 导航菜单 |
| `Popover` | 浮动内容 |
| `Progress` | 进度指标 |
| `RadioGroup` | 无线电按钮组 |
| `ScrollArea` | 自定义滚动条 |
| `Select` | 下拉选择 |
| `Separator` | 视觉分隔符 |
| `Sheet` | 侧面小组讨论 |
| `Sidebar` | 应用程序边栏 |
| `Skeleton` | 正在装入占位符 |
| `Slider` | 区域滑动器 |
| `Sonner` | 托拉斯通知 |
| `Switch` | 切换开关 |
| `Table` | 数据表 |
| `Tabs` | 标签界面 |
| `Textarea` | 多行文本输入 |
| `Toggle` | 切换按钮 |
| `Tooltip` | 隐藏工具提示 |

### 自定义组件(3)

| 构成部分 | 说明 |
| --- | --- |
| `Kanban` | 拖放 Kanban 棋盘( dnd- kit) |
| `Link` | 下个兼容链接包 |
| `MultiSelect` | 多选择带徽章的下拉 |

### 用法示例

```typescript
"use client";

import {
  Button,
  Card,
  CardHeader,
  CardTitle,
  CardContent,
  Dialog,
  DialogTrigger,
  DialogContent,
  DialogHeader,
  DialogTitle,
} from "@carlonicora/nextjs-jsonapi/components";
import { cn } from "@carlonicora/nextjs-jsonapi/core";

export function ArticleCard({ article, className }) {
  return (
    <Card className={cn("hover:shadow-lg transition-shadow", className)}>
      <CardHeader>
        <CardTitle>{article.title}</CardTitle>
      </CardHeader>
      <CardContent>
        <p>{article.excerpt}</p>

        <Dialog>
          <DialogTrigger>
            <Button variant="outline">Read More</Button>
          </DialogTrigger>
          <DialogContent>
            <DialogHeader>
              <DialogTitle>{article.title}</DialogTitle>
            </DialogHeader>
            <p>{article.content}</p>
          </DialogContent>
        </Dialog>
      </CardContent>
    </Card>
  );
}
```

## 尾风 CSS 配置

**对 Tailwind v4 很重要**: 您必须添加 `@source` 给您的指令 `globals.css` 以确保 Tailwind 扫描软件包组件文件 :

```css
/* apps/web/src/app/globals.css */
@import "tailwindcss";
@import "tw-animate-css";

/* Include package source files for Tailwind to scan */
@source "../../../../packages/nextjs-jsonapi/src/**/*.{ts,tsx}";

@custom-variant dark (&:is(.dark *));

@theme inline {
  --color-background: var(--background);
  --color-foreground: var(--foreground);
  /* ... other theme variables */
}
```

这个 `@source` 路径应该是相对的 `globals.css` 切换到软件包 `src` 目录.

## CSS 变量

Shadcn/ui 组件需要您在应用程序中定义 CSS 变量 。 把这些添加到您的 `globals.css`数字 :

```css
:root {
  /* Background & Foreground */
  --background: oklch(1 0 0);
  --foreground: oklch(0.145 0 0);

  /* Primary */
  --primary: oklch(0.205 0 0);
  --primary-foreground: oklch(0.985 0 0);

  /* Secondary */
  --secondary: oklch(0.97 0 0);
  --secondary-foreground: oklch(0.205 0 0);

  /* Muted */
  --muted: oklch(0.97 0 0);
  --muted-foreground: oklch(0.556 0 0);

  /* Accent */
  --accent: oklch(0.97 0 0);
  --accent-foreground: oklch(0.205 0 0);

  /* Destructive */
  --destructive: oklch(0.577 0.245 27.325);
  --destructive-foreground: oklch(0.985 0 0);

  /* Border & Input */
  --border: oklch(0.922 0 0);
  --input: oklch(0.922 0 0);
  --ring: oklch(0.708 0 0);

  /* Card & Popover */
  --card: oklch(1 0 0);
  --card-foreground: oklch(0.145 0 0);
  --popover: oklch(1 0 0);
  --popover-foreground: oklch(0.145 0 0);

  /* Charts */
  --chart-1: oklch(0.646 0.222 41.116);
  --chart-2: oklch(0.6 0.118 184.704);
  --chart-3: oklch(0.398 0.07 227.392);
  --chart-4: oklch(0.828 0.189 84.429);
  --chart-5: oklch(0.769 0.188 70.08);

  /* Sidebar */
  --sidebar: oklch(0.985 0 0);
  --sidebar-foreground: oklch(0.145 0 0);
  --sidebar-primary: oklch(0.205 0 0);
  --sidebar-primary-foreground: oklch(0.985 0 0);
  --sidebar-accent: oklch(0.97 0 0);
  --sidebar-accent-foreground: oklch(0.205 0 0);
  --sidebar-border: oklch(0.922 0 0);
  --sidebar-ring: oklch(0.708 0 0);

  /* Warning */
  --warning: oklch(0.84 0.16 84);
  --warning-foreground: oklch(0.28 0.07 46);

  /* Radius */
  --radius: 0.625rem;
}

.dark {
  --background: oklch(0.145 0 0);
  --foreground: oklch(0.985 0 0);
  --card: oklch(0.205 0 0);
  --card-foreground: oklch(0.985 0 0);
  --popover: oklch(0.269 0 0);
  --popover-foreground: oklch(0.985 0 0);
  --primary: oklch(0.922 0 0);
  --primary-foreground: oklch(0.205 0 0);
  --secondary: oklch(0.269 0 0);
  --secondary-foreground: oklch(0.985 0 0);
  --muted: oklch(0.269 0 0);
  --muted-foreground: oklch(0.708 0 0);
  --accent: oklch(0.269 0 0);
  --accent-foreground: oklch(0.985 0 0);
  --destructive: oklch(0.704 0.191 22.216);
  --destructive-foreground: oklch(0.985 0 0);
  --border: oklch(1 0 0 / 10%);
  --input: oklch(1 0 0 / 15%);
  --ring: oklch(0.556 0 0);
  /* ... other dark mode values */
}
```

## 许可证

此项目在GPL v3下获得开源使用许可.

商业/封闭源码许可证,联系: [@卡尔隆科拉](https://github.com/carlonicora)

## 作者

卡罗・尼科拉 [@卡尔隆科拉](https://github.com/carlonicora)

## 常见问题

### @carlonicora/nextjs-jsonapi 是什么？

Next\.js JSON:API 客户端有服务器/客户端支持并缓存

### 如何安装 @carlonicora/nextjs-jsonapi？

在项目目录运行 npm install @carlonicora/nextjs-jsonapi，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：next（\>=16\.4\.0）、react（\>=19\.3\.0）、react-dom（\>=19\.3\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。它还提供命令行工具 generate-web-module，可以用 npx generate-web-module 直接运行。

### @carlonicora/nextjs-jsonapi 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @carlonicora/nextjs-jsonapi 支持 ESM 还是 CommonJS？

同时提供 ES Module 与 CommonJS 入口，import 和 require\(\) 都可以使用，打包工具会自动选择合适的版本。

### @carlonicora/nextjs-jsonapi 可以商用吗？

@carlonicora/nextjs-jsonapi 使用 GPL-3\.0-or-later 许可。强 Copyleft：分发包含该代码的软件时，整个作品需以 GPL-3\.0 兼容许可开源，并附带专利与反锁定条款。仅内部使用不触发此义务。以上为概括，不构成法律意见，请以许可原文为准。

### @carlonicora/nextjs-jsonapi 的下载量有多少？

根据 npm 官方下载统计，@carlonicora/nextjs-jsonapi 在 2026/10/09 – 2026/11/07 这 30 天内被下载 12,509 次，日均约 417 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @carlonicora/nextjs-jsonapi 还在维护吗？

最新版本 6\.31\.0 发布于 2026/11/09（今天）；至今共发布 425 个版本，其中过去 12 个月发布了 425 个；首次发布于 2025/12/10。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

