# @datocms/cma-client 中文文档

规范地址：https://npmcn.com/package/%40datocms/cma-client/

版本：6\.8\.0
npm 元数据更新时间：2026-10-01T13:37:55.452Z
中文译文更新时间：2026-11-11T15:31:00.958Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40datocms/cma-client
原文对照：https://npmcn.com/package/%40datocms/cma-client/?lang=original
项目主页：https://github.com/datocms/js-rest-api-clients/tree/main/packages/cma-client#readme
源码仓库：https://github.com/datocms/js-rest-api-clients

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

- 包体积（解压后）：5.4 MB，1062 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：3 个
- 首次发布：2022-04-27T06:34:04.622Z
- 最新版本发布：2026-10-01T13:37:55.254Z
- 近 30 天下载量：656266（2026-10-12 至 2026-11-10，npm 官方下载统计）
- 已发布版本数：219（近 12 个月 64 个）

## 中文简介

DatoCMS REST 内容管理API的JS客户端

## 安装

```sh
npm install @datocms/cma-client
```

也可以使用：`pnpm add @datocms/cma-client`、`yarn add @datocms/cma-client`、`bun add @datocms/cma-client`

## README

# DatoCMS 内容管理 API 公用事业

看满了 [API 文档](https://www.datocms.com/docs/content-management-api) 举个例子!

## 字段类型

这个库为所有 DatoCMS 字段类型提供全面的 TypeScript 类型定义和公用事业. 每个字段类型包括类型守护,验证功能,本地化支持,以及编辑器外观配置.

### 还有什么

每一个字段类型都遵循一贯的模式,提供:

-   **字段值类型**: 字段数据结构的TypeScript定义
-   **类型警卫**: 运行时验证字段值的函数
-   **本地化支助**: 处理本地化外地变体的公用事业
-   **验证类型**: 支持的字段类型验证符
-   **外观配置**: 编辑器类型及其配置选项

**示例 `lat_lon` 字段类型**

查看示例

```typescript
import { isLatLonFieldValue, isLocalizedLatLonFieldValue } from '@datocms/cma-client';
import type { LatLonFieldValue, LatLonFieldValidators, LatLonFieldAppearance } from '@datocms/cma-client';

// Field value type - object with latitude/longitude or null
const value: LatLonFieldValue = { latitude: 45.4642, longitude: 9.1900 };

// Type guard functions for validation
if (isLatLonFieldValue(someValue)) {
  // someValue is guaranteed to be { latitude: number; longitude: number } | null
}

if (isLocalizedLatLonFieldValue(localizedValue)) {
  // localizedValue is a localized lat/lon field
}

// Validator and appearance types available for type-safe configuration
type Validators = LatLonFieldValidators;
type Appearance = LatLonFieldAppearance;
```

### 上下文依赖字段类型

一些字段类型根据API上下文(request vs response)或查询参数而有不同的值格式:

#### 请求 vs 响应变化

**文件与图片库字段** 对 API 请求和响应有不同的类型要求 :

查看示例

```typescript
import {
  FileFieldValue,
  FileFieldValueInRequest,
  GalleryFieldValue,
  GalleryFieldValueInRequest,
  // Type guards for runtime validation
  isFileFieldValue,
  isFileFieldValueInRequest,
  isGalleryFieldValue,
  isGalleryFieldValueInRequest
} from '@datocms/cma-client';

// API Response format - all metadata fields present with defaults
const fileResponse: FileFieldValue = {
  upload_id: "12345",
  alt: null,           // Always present (default: null)
  title: null,         // Always present (default: null)
  custom_data: {},     // Always present (default: {})
  focal_point: null    // Always present (default: null)
};

// API Request format - metadata fields are optional
const fileRequest: FileFieldValueInRequest = {
  upload_id: "12345"
  // alt, title, custom_data, focal_point are optional
};

// Runtime validation for different contexts
if (isFileFieldValueInRequest(someFileValue)) {
  // someFileValue has optional metadata fields
}

if (isGalleryFieldValue(someGalleryValue)) {
  // someGalleryValue is array of files with all metadata present
}
```

#### “ 监视模式” 响应变化

**含有块的字段** (单位:千美元)`structured_text`, (中文(简体) ), `single_block`, (中文(简体) ), `rich_text`支持定期答复的不同分组说明,以便 [“监视模式”答复](https://www.datocms.com/docs/content-management-api/resources/item#api-response-modes-regular-vs-nested),并请求:

查看示例

```typescript
import {
  StructuredTextFieldValue,
  StructuredTextFieldValueInRequest,
  StructuredTextFieldValueInNestedResponse,
  // Type guards for all variations (also available for single_block and rich_text)
  isStructuredTextFieldValue,
  isStructuredTextFieldValueInRequest,
  isStructuredTextFieldValueInNestedResponse
} from '@datocms/cma-client';

// Regular response - blocks as string IDs
const standard: StructuredTextFieldValue = {
  document: {
    type: "root",
    children: [
      {
        type: "block",
        // String ID reference
        item: "IdMLV2GJTXyQ0Bfns7R4IQ"
      }
    ]
  }
};

// Nested Mode response (?nested=true) - blocks as full objects
const nested: StructuredTextFieldValueInNestedResponse = {
  document: {
    type: "root",
    children: [
      {
        type: "block",
        // Always full block object
        item: {
          id: "IdMLV2GJTXyQ0Bfns7R4IQ",
          type: "item",
          attributes: { /* ... */ },
          relationships: { /* ... */ }
        }
      }
    ]
  }
};

// Request format - flexible block representation
const request: StructuredTextFieldValueInRequest = {
  document: {
    type: "root",
    children: [
      {
        type: "block",
        // Can be string ID, to keep block unchanged...
        item: "FicV5CxCSQ6yOrgfwRoiKA"
      },
      {
        type: "block",
        // ...or full block object (to create new blocks or update existing ones)
        item: {
          type: "item",
          attributes: { /* ... */ },
          relationships: { /* ... */ }
        }
      }
    ]
  }
};

// Runtime validation for different contexts
if (isStructuredTextFieldValueInNestedResponse(someStructuredText)) {
  // someStructuredText has blocks as full objects
}

if (isStructuredTextFieldValueInRequest(requestData)) {
  // requestData allows flexible block representations
}
```

这些变体确保不同API背景的类型安全,同时保持相同的概念数据结构. 所有本地化的变体也有相应的类型守护(如:, `isLocalizedStructuredTextFieldValueInRequest`, (中文(简体) ), `isLocalizedStructuredTextFieldValueInNestedResponse`(见a/c.5/49/70,附件).

**类型脚本通用支持 :** 为了最大类型安全,所有字段值类型和包含块的字段的类型守护都接受 [`ItemTypeDefinition` 通用软件](https://www.datocms.com/docs/content-management-api/resources/item#type-safe-development-with-typescript) 为您的特定方案提供精确的打字:

查看示例

```typescript
import type { MyArticle, MyArticleSection } from './schema';

// Fully typed structured text with specific block types
const content: StructuredTextFieldValueInRequest<MyArticleSection> = {
  document: {
    type: "root",
    children: [/* ... */]
  }
};

// Type guard with generic for precise validation
if (isStructuredTextFieldValueInNestedResponse<MyArticleSection>(value)) {
  // value is now typed with your specific block schema
}
```

## 块式处理工具

### 检查记录和块

这个 `inspectItem()` 函数在控制台中提供DatoCMS记录的可视化,树状结构化的表示,使调试和理解复杂的内容结构更加容易.

#### 检查项目( )

将 DatoCMS 项(记录或块)格式化为可视树结构,显示每个字段类型有适当格式的所有字段。 对调试模块化内容和结构化文本等嵌入式结构特别有用.

查看细节

**类型脚本签名 :**

```typescript
function inspectItem(
  item: Item,
  options?: InspectItemOptions
): string

type InspectItemOptions = {
  maxWidth?: number; // Maximum width for text fields before truncation (default: 80)
}
```

**参数:**

-   `item`: 任何 DatoCMS 项,包括记录、块或创建/更新格式的项目
-   `options`: 可选配置对象
    -   `maxWidth`: 在切换为"..."之前,文本字段显示的最大字符数

**回返情况:** 将项目格式化的字符串表示为树状结构

**用法示例:**

```typescript
import { inspectItem } from '@datocms/cma-client';

const record = await client.items.find('MgCNaAI0RxSG8CA9sDXCHg');
console.log(inspectItem(record));

// Output:
// Item "MgCNaAI0RxSG8CA9sDXCHg" (item_type: "bJse85JFR0GbA37ey6kA1w")
// ├─ title: "My Blog Post"
// ├─ slug: "my-blog-post"
// └─ content:
//    ├─ en: "This is the English content..."
//    └─ it: "Questo è il contenuto italiano..."
```

### 创建和复制块

#### 构建 Block 记录 ()

将块数据对象转换成 API 请求的正则格式.

查看细节

**类型脚本签名 :**

```typescript
function buildBlockRecord<D extends ItemTypeDefinition>(
  body: ItemUpdateSchema<ToItemDefinitionInRequest<D>>
): NewBlockInRequest<ToItemDefinitionInRequest<D>>
```

**参数:**

-   `body`: 更新计划中的块数据

**回返情况:** 为 API 请求准备格式化块记录

#### 重复的 Block 记录 ()

创建包含所有嵌入区块的区块记录的深层副本,删除ID以创建新实例.

查看细节

**类型脚本签名 :**

```typescript
async function duplicateBlockRecord<D extends ItemTypeDefinition>(
  existingBlock: ItemWithOptionalIdAndMeta<ToItemDefinitionInNestedResponse<D>>,
  schemaRepository: SchemaRepository
): Promise<NewBlockInRequest<ToItemDefinitionInRequest<D>>>
```

**参数:**

-   `existingBlock`: 要复制的块
-   `schemaRepository`: 用于计划检查的仓库

**回返情况:** 新建没有ID的块记录, 准备创建

### 缩小块类型

#### 为 BlockOf Type ()

构建一个类型守护,将块形状的结合缩小到匹配给定模型的组合. 意图 `Array#filter` 编号 : `Array#find` 大于有块的字段—— 或者是嵌入式反应阵列(来自 `client.items.find(..., { nested: true })`)或发送前正在检查的请求负载数组.

TypeScript 不自动限制被埋入巢穴的歧义者, 所以自然的检查 `block.relationships.item_type.data.id === SOME_ID` 不会缩小这个街区的类型。 这名警卫行走并返回一个合适的型号护卫上方.

查看细节

**类型脚本签名 :**

```typescript
// Curried — returns a predicate (use with .filter / .find)
function isBlockOfType<Id extends string>(
  itemTypeId: Id,
): <T>(block: T) => block is NarrowBlockByItemType<T, Id>

// Direct — checks a single block inline (use inside `if`)
function isBlockOfType<T, Id extends string>(
  itemTypeId: Id,
  block: T,
): block is NarrowBlockByItemType<T, Id>

type NarrowBlockByItemType<T, Id extends string> = Extract<
  T,
  { relationships: { item_type: { data: { type: 'item_type'; id: Id } } } }
>
```

**参数:**

-   `itemTypeId`:项目型ID字形. 为了缩小工作范围,必须把论点打成字形——使用 `as const` 在预设的ID常数上。 没有 `ItemTypeDefinition` 需要类型参数 : `Extract` 仅凭身份证明就走进输入联盟.
-   `block` (仅直接形式): 要检查的街区.

**回返情况:**

-   曲线窗体: 上游 `(block) => block is D-typed-block`。 。 。 .
-   直接形式:a `boolean` 也充当了护卫 `block`。 。 。 .

在这两种情况下,警卫:

-   携带的窄块 `relationships.item_type.data.id` - 覆盖 `BlockInNestedResponse<D>` 和对象的变体 `BlockInRequest<D>` (单位:千美元)`UpdatedBlockInRequest`, (中文(简体) ), `NewBlockInRequest`) (中文(简体) ).
-   回返 `false` 用于纯字符串ID(请求的有效载荷中未更改的参考形式)和任何非块输入.

默认(不记名)响应形状,其中块字段为平原字符串ID的数组,是故意不支持的——单从ID中无法恢复该类型.

**用法示例:**

```typescript
import { isBlockOfType } from '@datocms/cma-client';

// ID of the ImageBlock model, one of several allowed inside Article `content`
const IMAGE_BLOCK_ID = 'FJM79jjKRMSVg-fR6k6X2A' as const;

const article = await client.items.find<Schema.Article>(articleId, { nested: true });

// Before: inline === check does not narrow
const images = article.content.filter(
  (b) => b.relationships.item_type.data.id === IMAGE_BLOCK_ID,
);
images[0].attributes.upload_id; // ❌ property does not exist on union

// After (curried): guard narrows the filter result
const images = article.content.filter(isBlockOfType(IMAGE_BLOCK_ID));
images[0].attributes.upload_id; // ✅ narrowed

// After (direct): inline narrowing on a single block
const first = article.content[0];
if (isBlockOfType(IMAGE_BLOCK_ID, first)) {
  first.attributes.upload_id; // ✅ narrowed
}
```

需要上游时使用曲面格式 `.filter` 编号 : `.find`; 一次性使用直接表格 `if` 检查。 这个 `__itemTypeId` 歧视者也可在线使用 `switch` 缩小一个值.

### 递归块操作

DatoCMS支持可以包含块的三种字段类型:模块内容(块阵列),单块字段,和结构化文本(有嵌入块的丰富文本). 这些函数可以抽象去去去去去字段类型之间的区别,并且可以递归地穿行区块,在区块内处理被嵌入区块. 他们需要一个 `SchemaRepository` 实例查找嵌入区块的字段定义.

#### 在非本地化的外地value( )

访问非本地化场值的每个区块,包括嵌入于其他区块内的区块.

查看细节

**类型脚本签名 :**

```typescript
async function visitBlocksInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  visitor: (item: BlockInRequest, path: TreePath) => void | Promise<void>,
): Promise<void>
```

**参数:**

-   `nonLocalizedFieldValue`: 非本地化的字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `visitor`:每个区块的函数调用(包括嵌入)

#### 不本地化的 FieldValue () 地图锁定

在非本地化的字段值中将所有区块进行回转,包括嵌入区块.

查看细节

**类型脚本签名 :**

```typescript
async function mapBlocksInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  mapper: (item: BlockInRequest, path: TreePath) => BlockInRequest | Promise<BlockInRequest>,
): Promise<unknown>
```

**参数:**

-   `nonLocalizedFieldValue`: 非本地化的字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `mapper`: 转换每个块的函数

**回返情况:** 新字段值

#### 在非本地化的 FieldValue () 中过滤锁

过滤块递归,去除任何与上游不相匹配的筑巢级的块.

查看细节

**类型脚本签名 :**

```typescript
async function filterBlocksInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
): Promise<unknown>
```

**参数:**

-   `nonLocalizedFieldValue`: 要过滤的非本地化字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `predicate`: 测试每个块的函数

**回返情况:** 带过滤块的新字段值

**用法示例:**

```typescript
// Remove all video blocks at any nesting level
const noVideos = await filterBlocksInNonLocalizedFieldValue(
  schemaRepository,
  field,
  fieldValue,
  (block) => block.relationships.item_type.data.id !== 'video_block'
);
```

#### 查找 AllBlocks 在非本地化的 FieldValue ()

查找所有匹配上游的区块,通过嵌入区块进行回溯搜索.

查看细节

**类型脚本签名 :**

```typescript
async function findAllBlocksInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
): Promise<Array<{ item: BlockInRequest; path: TreePath }>>
```

**参数:**

-   `nonLocalizedFieldValue`: 搜索的非本地化字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `predicate`: 测试每个块的函数

**回返情况:** 所有匹配的块及其路径的矩阵

#### 在非本地化的 FieldValue () 中

将所有块递归为单个值.

查看细节

**类型脚本签名 :**

```typescript
async function reduceBlocksInNonLocalizedFieldValue<R>(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  reducer: (accumulator: R, item: BlockInRequest, path: TreePath) => R | Promise<R>,
  initialValue: R,
): Promise<R>
```

**参数:**

-   `nonLocalizedFieldValue`: 减少非本地化的字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `reducer`: 处理每个块的函数
-   `initialValue`: 初始累积值

**回返情况:** 最后累计价值

#### 非本地化的 Field Value () 中的一些块

检查是否有任何块(包括有巢)与上游相匹配.

查看细节

**类型脚本签名 :**

```typescript
async function someBlocksInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
): Promise<boolean>
```

**参数:**

-   `nonLocalizedFieldValue`: 要测试的非本地化字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `predicate`: 测试每个块的函数

**回返情况:** 如果区块匹配则为真

#### 无本地化的 FieldValue ()

检查每个区块(包括被巢)是否与上游相匹配.

查看细节

**类型脚本签名 :**

```typescript
async function everyBlockInNonLocalizedFieldValue(
  nonLocalizedFieldValue: unknown,
  fieldType: string,
  schemaRepository: SchemaRepository,
  predicate: (item: BlockInRequest, path: TreePath) => boolean | Promise<boolean>,
): Promise<boolean>
```

**参数:**

-   `nonLocalizedFieldValue`: 要测试的非本地化字段值
-   `fieldType`: DatoCMS 字段的类型(e. `string`, (中文(简体) ), `rich_text`页:1
-   `schemaRepository`: 缓存图样的仓库
-   `predicate`: 测试每个块的函数

**回返情况:** 如果所有块都匹配, 则为真

## 统一外地处理(本地化和非本地化)

这些公用设施为与DatoCMS的可本地化或不可本地化的场值合作提供了一个统一的接口. 它们消除了在可以本地化或非本地化的处理字段时对条件逻辑的需要.

#### 平面图 平面图 平面图 平面图

对字段值应用转换函数,统一处理本地化和非本地化字段.

查看细节

**类型脚本签名 :**

```typescript
function mapNormalizedFieldValues<TInput, TOutput>(
  localizedOrNonLocalizedFieldValue: TInput | LocalizedFieldValue<TInput>,
  field: Field,
  mapFn: (locale: string | undefined, localeValue: TInput) => TOutput
): TOutput | LocalizedFieldValue<TOutput>

async function mapNormalizedFieldValuesAsync<TInput, TOutput>(
  localizedOrNonLocalizedFieldValue: TInput | LocalizedFieldValue<TInput>,
  field: Field,
  mapFn: (locale: string | undefined, localeValue: TInput) => Promise<TOutput>
): Promise<TOutput | LocalizedFieldValue<TOutput>>
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`: 场值(本地化或非本地化)
-   `field`: DatoCMS 字段定义
-   `mapFn`: 转换每个值的函数(本地化字段接收地块,非本地化未定义)

**回返情况:** 不变结构的变值

#### 过滤器

基于上游的过滤字段值,处理本地化和非本地化字段.

查看细节

**类型脚本签名 :**

```typescript
function filterNormalizedFieldValues<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  filterFn: (locale: string | undefined, localeValue: T) => boolean
): T | LocalizedFieldValue<T> | undefined

async function filterNormalizedFieldValuesAsync<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  filterFn: (locale: string | undefined, localeValue: T) => Promise<boolean>
): Promise<T | LocalizedFieldValue<T> | undefined>
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`: 要过滤的字段值
-   `field`: DatoCMS 字段定义
-   `filterFn`: 过滤的预置功能

**回返情况:** 如果全部过滤出, 则过滤出值或未定义

#### 常规值( ) / 常规值( )

访问一个字段的每个值,处理本地化和非本地化字段.

查看细节

**类型脚本签名 :**

```typescript
function visitNormalizedFieldValues<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  visitFn: (locale: string | undefined, localeValue: T) => void
): void

async function visitNormalizedFieldValuesAsync<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  visitFn: (locale: string | undefined, localeValue: T) => Promise<void>
): Promise<void>
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`: 访问的实地价值
-   `field`: DatoCMS 字段定义
-   `visitFn`: 函数调用每个值

#### 某些正态值( ) / 某些正态值值值

检查至少一个字段值是否通过测试 .

查看细节

**类型脚本签名 :**

```typescript
function someNormalizedFieldValues<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  testFn: (locale: string | undefined, localeValue: T) => boolean
): boolean

async function someNormalizedFieldValuesAsync<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  testFn: (locale: string | undefined, localeValue: T) => Promise<boolean>
): Promise<boolean>
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`: 要测试的字段值
-   `field`: DatoCMS 字段定义
-   `testFn`: 优先函数

**回返情况:** 如果有值通过测试, 则为真

#### 每个正态值( ) / 每个正态值值值

检查所有字段值是否通过测试 .

查看细节

**类型脚本签名 :**

```typescript
function everyNormalizedFieldValue<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  testFn: (locale: string | undefined, localeValue: T) => boolean
): boolean

async function everyNormalizedFieldValueAsync<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field,
  testFn: (locale: string | undefined, localeValue: T) => Promise<boolean>
): Promise<boolean>
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`: 要测试的字段值
-   `field`: DatoCMS 字段定义
-   `testFn`: 优先函数

**回返情况:** 如果所有值都通过测试, 则为真

#### 至 Normalized FieldValue Entrys () / 从Normalized FieldValue Entrys ()

将字段值转换为/从一个规范的条目格式进行统一处理.

查看细节

**类型脚本签名 :**

```typescript
function toNormalizedFieldValueEntries<T>(
  localizedOrNonLocalizedFieldValue: T | LocalizedFieldValue<T>,
  field: Field
): NormalizedFieldValueEntry<T>[]

function fromNormalizedFieldValueEntries<T>(
  entries: NormalizedFieldValueEntry<T>[],
  field: Field
): T | LocalizedFieldValue<T>

type NormalizedFieldValueEntry<T> = {
  locale: string | undefined;
  value: T;
}
```

**参数:**

-   `localizedOrNonLocalizedFieldValue`编号 :`entries`: 要从/ 转换到的值
-   `field`: DatoCMS 字段定义

**回返情况:** 规范化的条目数组或重建的字段值

**用法示例:**

```typescript
// Convert to entries for processing
const entries = toNormalizedFieldValueEntries(fieldValue, field);

// Process entries uniformly
const processed = entries.map(({ locale, value }) => ({
  locale,
  value: processValue(value)
}));

// Convert back to field value format
const result = fromNormalizedFieldValueEntries(processed, field);
```

## Schema 仓库

这个 `SchemaRepository` class为 DatoCMS schema 实体(项目类型、字段、字段和插件)提供一个轻量级、内嵌缓存。 它有助于避免在跨多个功能或公用设施工作时出现重复的API呼叫,这些功能或公用设施需要有计划的外观.

**为什么用它?**

-   **缓存一次, 随处重复使用**: 首个API呼叫商店的结果是内存;所有后续的取景都是即时的.
-   **高效计划访问**:通过ID,API密钥来获取实体,或包名而无需再对接.
-   **优化块处理**: 公用事业(如: `mapBlocksInNonLocalizedFieldValue`。 。 。 .
-   **API 调用次数减少**:戏剧性地加速了散装操作和复杂的转弯.

**用法示例:**

查看示例

```typescript
const schemaRepository = new SchemaRepository(client);

// First call: fetches from API and caches result
const blogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
const fields = await schemaRepository.getItemTypeFields(blogPost);

// Next calls: resolved instantly from cache (no API calls)
const sameBlogPost = await schemaRepository.getItemTypeByApiKey('blog_post');
const sameFields = await schemaRepository.getItemTypeFields(blogPost);

// Works seamlessly with block-processing utilities
await mapBlocksInNonLocalizedFieldValue(
  fieldValue,
  fieldType,
  schemaRepository,  // share cached lookups
  async (block) => {
    // transform block here
  }
);
```

**何时使用**

-   反复查询策略的拖转关系
-   散装记录处理脚本
-   需要经常检查的区块处理设施
-   减少 API 调用事项的任何脚本

**不使用时**

-   修改方案(模型、字段等)的脚本
-   长期运行的应用程序( 缓存永远不会过期)
-   在执行期间计划可能改变的情况

**类签名**

```typescript
class SchemaRepository {
  constructor(client: GenericClient)

  // Item Type methods
  async getAllItemTypes(): Promise<ItemType[]>
  async getAllModels(): Promise<ItemType[]>
  async getAllBlockModels(): Promise<ItemType[]>
  async getItemTypeByApiKey(apiKey: string): Promise<ItemType>
  async getItemTypeById(id: string): Promise<ItemType>

  // Field methods
  async getItemTypeFields(itemType: ItemType): Promise<Field[]>
  async getItemTypeFieldsets(itemType: ItemType): Promise<Fieldset[]>

  // Higher-level utilities
  async getModelsEmbeddingBlocks(blocks: ItemType[]): Promise<ItemType[]>
  async getNestedBlocks(itemTypes: ItemType[]): Promise<ItemType[]>
  async getNestedModels(itemTypes: ItemType[]): Promise<ItemType[]>

  // Plugin methods
  async getAllPlugins(): Promise<Plugin[]>
  async getPluginById(id: string): Promise<Plugin>
  async getPluginByPackageName(packageName: string): Promise<Plugin>

  // Raw variants (return API response format)
  async getAllRawItemTypes(): Promise<RawItemType[]>
  async getRawItemTypeByApiKey(apiKey: string): Promise<RawItemType>
  async getRawNestedBlocks(itemTypes: Array<ItemType | RawItemType>): Promise<Array<RawItemType>>
  async getRawNestedModels(itemTypes: Array<ItemType | RawItemType>): Promise<Array<RawItemType>>
  // ... and more raw variants
}
```

## 捐款

GitHub 上欢迎错误报告和拉取请求 [https://github.com/datocms/js-rest-api-客户端 互联网档案馆的存檔,存档日期2013-12-11](https://github.com/datocms/js-rest-api-clients)本项目旨在成为合作的安全和受欢迎的空间,预期捐助者将坚持 [《促进者公约》](http://contributor-covenant.org/) 行为守则.

## 许可证

该软件包可按以下规定作为开源: [MIT 许可证](http://opensource.org/licenses/MIT)。 。 。 .

## 常见问题

### @datocms/cma-client 是什么？

DatoCMS REST 内容管理API的JS客户端

### 如何安装 @datocms/cma-client？

在项目目录运行 npm install @datocms/cma-client，或使用 pnpm add / yarn add / bun add。

### @datocms/cma-client 支持 TypeScript 吗？

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

### @datocms/cma-client 支持 ESM 还是 CommonJS？

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

### @datocms/cma-client 可以商用吗？

@datocms/cma-client 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @datocms/cma-client 的下载量有多少？

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

### @datocms/cma-client 还在维护吗？

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

