# @bjoerge/mutiny 中文文档

规范地址：https://npmcn.com/package/%40bjoerge/mutiny/

版本：0\.7\.1
npm 元数据更新时间：2024-08-01T19:42:29.325Z
中文译文更新时间：2026-11-08T05:23:01.360Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：3.4 MB，79 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- Node.js 要求：\>=18
- 运行依赖：6 个
- 首次发布：2023-08-21T00:55:01.081Z
- 最新版本发布：2024-08-01T19:42:29.125Z
- 近 30 天下载量：19886（2026-10-08 至 2026-11-06，npm 官方下载统计）
- 已发布版本数：22（近 12 个月 0 个）

## 中文简介

在 JavaScript 和 TypeScript 中与 Sanity 突变合作的小型工具包

## 安装

```sh
npm install @bjoerge/mutiny
```

也可以使用：`pnpm add @bjoerge/mutiny`、`yarn add @bjoerge/mutiny`、`bun add @bjoerge/mutiny`

## README

# **吴**_细小_

用于工作的小工具箱 [卫生](https://sanity.io/) javaScript 和 TypeScript 中的突变

免责声明: 这项工作正在进行中,要冒着风险使用!

## 看着

-   可声明和可相容突变创建者
-   对内存文件应用突变装置(实验性)
-   支持乐观更新的本地内存数据集复制(实验)

## 特征

-   变异可以使用创建功能宣告,并像任何其他价值观一样相传,被转化和构成 进入涵盖多个文件的大型行动
-   突变只是操作的描述,可以被序列化为紧凑的json格式或Sanity突变 API 请求有效载荷
-   节点可以通过路径作为 JavaScript 值处理,而不是字符串路径
-   与 [Sanity.io 变异格式](https://www.sanity.io/docs/http-mutations)
-   支持自动添加 `_key`'是数组中的对象,所以你不必.
-   实验性支持在记忆文件中应用突变
-   大类型脚本支持

## 用法示例

```ts
import {
  at,
  create,
  createIfNotExists,
  patch,
  SanityEncoder,
  set,
  setIfMissing,
} from '@bjoerge/mutiny'

const mutations = [
  create({_type: 'dog', name: 'Fido'}),
  createIfNotExists({_id: 'document-1', _type: 'someType'}),
  createIfNotExists({_id: 'other-document', _type: 'author'}),
  patch('other-document', [
    at('published', set(true)),
    at('address', setIfMissing({_type: 'address'})),
    at('address.city', set('Oslo')),
  ]),
]

// get a projectId and dataset at sanity.io
const projectId = '<projectId>'
const dataset = '<dataset>'

// Submit mutations to the Sanity API
fetch(`https://${projectId}.api.sanity.io/v2023-08-01/data/mutate/${dataset}`, {
  method: 'POST',
  mode: 'cors',
  credentials: 'include',
  headers: {
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(SanityEncoder.encode(mutations)),
})
  .then(response => response.json())
  .then(result => console.log(result))
```

## 突变创造者

### 变异

-   `create(document: SanityDocument)`: 创建一个新文档
-   `createIfNotExists(document: SanityDocument)`: 如果不存在新文档, 则创建新文档
-   `createOrReplace(document: SanityDocument)`: 创建新文档或替换已存在的文档
-   `delete(documentId: SanityDocument)`: 删除文档(别名: `del`, (中文(简体) ), `destroy`(中文(简体) )
-   `patch(documentId: string, patches: Patch | Patch[], options?: {ifRevision?: string})`: 补丁文档。 可以吗 可选择提供 a `revisionId` 页:1 [乐观锁定](https://www.sanity.io/docs/http-mutations#26600a871378)如果 当前文档修订与指定的修订不匹配,当应用时补丁突变会失败.

### 补丁

补丁是节点路径和操作的组合. 节点路径是一个 简化 [杰森马克](https://www.sanity.io/docs/json-match) 路径或指向 文档中的特定节点。 行动就是其中之一 [下级](https://github.com/bjoerge/mutiny#patch-operations)。 。 。 .

-   `at(path: Path | string, operation: Operation)`: 从路径和操作中创建补丁

#### 实例:

```js
at('foo.bar', set('baz'))

// equivalent to the above
at(['foo', 'bar'], set('baz'))

at(['array[0]'], insert('baz'))

// Set a value deep into an array of objects addressed by `_key`
at(['people', {_key: 'xyz'}, 'name'], set('Bjørge'))

// equivalent to the above, using a serialized path:
at('people[_key=="xyz"].name', set('Bjørge'))
```

### 补丁操作

#### 适用于所有数据类型的补丁操作

-   `set(value: any)`: 将节点的值设定为给定 `value`
-   `setIfMissing(value: any)`: 将节点的值设定为给定 `value` 如果节点没有值
-   `unset()`: 从文档中删除节点

#### 对象操作

-   `assign(value: object)`: 将节点与给定值进行浅重合并. 如果节点是对象,则值会 合并到类似于 `Object.assign(<currentValue>, value)`。 。 。 .
-   `unassign(attributes: string[])`: 从现有值中删除给定属性.

#### 阵列操作

-   `prepend(items: any[])`: 将给定的项目放在数组开头
-   `append(items: any[])`: 将指定项目添加到数组的末尾
-   `insert(items: any | any[], position: "before" | "after", referenceItem: number | {_key: string})`: 插入给定的 给定之前或之后的项目 `before` 或者说 `after` 目 录(续) 若为 `before` 或者说 `after` 未提供,项目将 插入到数组的起始或结尾.
-   `truncate(startIndex: number, endIndex?: number)`: 从数组中删除项目 `startIndex` 结束 时间 `endIndex`如果 `endIndex` 未提供全部项目 `startIndex` 将被删除.
-   `replace(items: any | any[], referenceItem: number | {_key: string})`: 替换 `referenceItem` (电话:1 (212) 963-9084) 索引或键,带有给定 `item` 或者说 `items`如果 `items` 是一个阵列, `referenceItem` 改为: 以及其后出现的任何现有要素 `referenceItem` 将移到右边.
-   `upsert(items: any | any[], position: "before" | "after", referenceItem: number | {_key: string})`: 提升一个或多个项目 输入数组。 如果项目匹配阵列中的现有项目, 现有的项目将被给定的替换 页:1 如果项目与任何现有项目不相匹配,将插入数组。 这个`referenceItem` 指定一个参考项目,将缺失的项目放在相对位置。 若说. 如果不提供,则将在 数组的起始或结尾,取决于 `position`编辑 `position`选项可以用于指定项目在不插入时插入何处 匹配任何现有项目。 如果不提供,项目将在阵列末尾插入.

#### 数量

-   `inc(value: number)`: 按给定值增加数字
-   `dec(value: number)`: 以给定值减少数字

#### 字符串操作

-   `diffMatchPatch(patch: string)`: 在当前字符串中应用增量文本补丁。 更多信息 关于 [diffMatch 选项](https://www.sanity.io/docs/http-patches#aTbJhlAJ)。 。 。 .

## 高级实例

定义一组操作, 并将其变成可以应用到一组文档上的补丁突变

```js
const patches = [
  at("metadata", setIfMissing({})), // make sure metadata object exists
  at("metadata.published", set(true)),
  at("metadata.publishedAt", set(new Date().toISOString())),
]
const mutations = ["document-1", "document-2", "document-3"].map(id =>
  patch(id, patches),
)

// commit mutations to datastore
commitMutations(mutations)
```

## 在本地文档上应用突变( 实验性)

变异可以用于文档的内存集合

```ts
import {applyInCollection} from '@bjoerge/mutiny/_unstable_apply'
import {createIfNotExists, del} from '@bjoerge/mutiny'

const initial = [{_id: 'deleteme', _type: 'foo'}]

const updated = applyInCollection(initial, [
  createIfNotExists({_id: 'mydocument', _type: 'foo'}),
  createIfNotExists({_id: 'anotherDocument', _type: 'foo'}),
  del('deleteme'),
])

console.log(updated)
/*=>
[
  { _id: 'mydocument', _type: 'foo' },
  { _id: 'anotherDocument', _type: 'foo' }
]
*/
```

注:当对收藏物应用突变时,偏好完整性被保留. 这意味着如果一个突变实际上是一个 noop(例如没有实际改变),那么同样的对象引用会被返回.

```ts
import {applyInCollection} from '@bjoerge/mutiny/_unstable_apply'
import {at, createIfNotExists, patch, set} from '@bjoerge/mutiny'

const initial = [
  {
    _id: 'someDoc',
    _type: 'foo',
    value: 'ok',
    nested: {value: 'something'},
    otherNested: {message: 'something else'},
  },
]

const updated = applyInCollection(initial, [
  createIfNotExists({_id: 'someDoc', _type: 'foo'}),
  patch('someDoc', [at('value', set('ok'))]),
  patch('someDoc', [at('nested.value', set('something'))]),
])

// the mutation didn't cause anything to change
console.log(initial === updated)
//=> true
```

情况也是这样: _节点_ 不受变异影响:

```ts
import {applyInCollection} from '@bjoerge/mutiny/_unstable_apply'
import {at, createIfNotExists, patch, set} from '@bjoerge/mutiny'

const initial = [
  {
    _id: 'someDoc',
    _type: 'foo',
    value: 'ok',
    nested: {value: 'something'},
    otherNested: {message: 'something else'},
  },
]

const updated = applyInCollection(initial, [
  createIfNotExists({_id: 'someDoc', _type: 'foo'}),
  patch('someDoc', [at('value', set('ok'))]),
  patch('someDoc', [at('nested.value', set('something'))]),
  patch('someDoc', [at('otherNested.message', set('hello'))]),
])

// the `nested` object unaffected by the mutation
console.log(initial[0].nested === updated[0].nested)
//=> true
```

## 将补丁突变应用到单个文档中

或者,一个补丁突变可以适用于单个文档,只要其id与该突变的文档id相匹配:

```ts
import {applyPatchMutation} from '@bjoerge/mutiny/_unstable_apply'
import {at, insert, patch, setIfMissing} from '@bjoerge/mutiny'

const document = {_id: 'test', _type: 'foo'}

const updated = applyPatchMutation(
  document,
  patch('test', [
    at('title', setIfMissing('Foo')),
    at('cities', setIfMissing([])),
    at('cities', insert(['Oslo', 'San Francisco'], 'after', 0)),
  ]),
)

console.log(updated)
/*=>
{
  _id: 'test',
  _type: 'foo',
  title: 'Foo',
  cities: [ 'Oslo', 'San Francisco' ]
}
*/
```

### 与Sanity API的区别

为了更好地配合严格的类型系统,兵变在应用补丁时与Sanity API略有不同. 虽然您可以用兵变表达出的所有变异类型也可以被表示为"Sanity API变异",但反向并不一定是真实的;"Sanity API"(例如收听者)可能会产生不考虑当前文档的附加转换步骤而不能代表出兵变的补丁. 此外,在兵变中应用一个补丁与在几个账户上使用"Sanity API"应用同一补丁的行为不同:

-   `set` 财务报告和审定财务报表`setIfMissing` 不创建中间空对象 - 使用 Sanity API, `set` 财务报告和审定财务报表 `setIfMissing` 如果沿着给定路径的任何对象已不存在,则会创建中间空对象。 单位 `mutiny`,这些补丁将仅适用于已存在的对象.
-   有限的Json匹配支持. Sanity突变支持一个强大的路径选择语法,用于同时瞄准多个文档节点 [json- match 游戏](https://www.sanity.io/docs/json-match)。为简单起见,一个兵变补丁只能瞄准一个文件节点.

## 常见问题

### @bjoerge/mutiny 是什么？

在 JavaScript 和 TypeScript 中与 Sanity 突变合作的小型工具包

### 如何安装 @bjoerge/mutiny？

在项目目录运行 npm install @bjoerge/mutiny，或使用 pnpm add / yarn add / bun add。

### @bjoerge/mutiny 支持 TypeScript 吗？

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

### @bjoerge/mutiny 支持 ESM 还是 CommonJS？

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

### @bjoerge/mutiny 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @bjoerge/mutiny 可以商用吗？

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

### @bjoerge/mutiny 的下载量有多少？

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

### @bjoerge/mutiny 还在维护吗？

最新版本 0\.7\.1 发布于 2024/08/02（2 年前）；至今共发布 22 个版本，其中过去 12 个月发布了 0 个；首次发布于 2023/08/21。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

