# @candoimage/prisma-extension-nested-operations 中文文档

规范地址：https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/

版本：1\.6\.4
npm 元数据更新时间：2026-03-30T13:44:42.999Z
中文译文更新时间：2026-11-09T00:54:47.911Z
软件包许可：Apache-2\.0

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

原始 npm 页面：https://www.npmjs.com/package/%40candoimage/prisma-extension-nested-operations
原文对照：https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/?lang=original
项目主页：https://github.com/CandoImage/prisma-extension-nested-operations#readme
源码仓库：https://github.com/CandoImage/prisma-extension-nested-operations

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

- 包体积（解压后）：163 kB，47 个文件
- 模块格式：ESM + CJS
- TypeScript 类型：包内自带
- 运行依赖：1 个
- peer 依赖：@prisma/client \>=7\.0\.0
- 首次发布：2026-03-02T13:24:34.596Z
- 最新版本发布：2026-03-30T13:44:42.885Z
- 近 30 天下载量：22244（2026-10-09 至 2026-11-07，npm 官方下载统计）
- 已发布版本数：5（近 12 个月 5 个）

## 中文简介

用于创建带有嵌入操作的 Prisma 客户端扩展的 Utils

## 安装

```sh
npm install @candoimage/prisma-extension-nested-operations
```

也可以使用：`pnpm add @candoimage/prisma-extension-nested-operations`、`yarn add @candoimage/prisma-extension-nested-operations`、`bun add @candoimage/prisma-extension-nested-operations`

## README

# Prisma 扩展嵌入操作

Prisma 扩展库允许在 Prisma 查询中修改嵌入关系上的操作 .

Vanilla Prisma 扩展对修改顶级查询很有帮助,但是 当它们必须处理时仍然难以使用 [筑巢写作](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#nested-writes), (中文(简体) ), `include`s, (中文(简体) ), `select`s, (中文(简体) ), 或修改 `where` 对象的参考关系. 更深入地讨论这个问题 [关于嵌入式中间软件的问题](https://github.com/prisma/prisma/issues/4211),则 同样的问题也适用于扩展.

此库输出 a `withNestedOperations()` 拆分一个 `$allOperations()` 钩入 `$rootOperation()` 财务报告和审定财务报表 `$allNestedOperations()` 钩子.

* * *

[![Build Status](https://github.com/olivierwilkinson/prisma-extension-nested-operations/workflows/prisma-extension-nested-operations/badge.svg)](https://github.com/olivierwilkinson/prisma-extension-nested-operations/actions?query=branch%3Amain+workflow%3Aprisma-extension-nested-operations) [![version](https://img.shields.io/npm/v/@candoimage/prisma-extension-nested-operations.svg?style=flat-square)](https://www.npmjs.com/package/@candoimage/prisma-extension-nested-operations) [![MIT License](https://img.shields.io/npm/l/@candoimage/prisma-extension-nested-operations.svg?style=flat-square)](https://github.com/olivierwilkinson/prisma-extension-nested-operations/blob/master/LICENSE) [![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com/)

## 目录

-   [安装](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-installation)
-   [使用量](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-usage)
    -   [`$rootOperation()`](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-rootoperation)
    -   [`$allNestedOperations()` 参数](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-allnestedoperations-params)
    -   [嵌入式写作](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-nested-writes)
        -   [更改嵌入式写操作](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-changing-nested-write-operations)
        -   [写入结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-write-results)
    -   [何处](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-where)
        -   [成果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-where-results)
    -   [包含](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-include)
        -   [包含结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-include-results)
    -   [选择](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-select)
        -   [选择结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-select-results)
    -   [关系](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-relations)
    -   [修改嵌入式书写参数](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-modifying-nested-write-params)
    -   [修改参数位置](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-modifying-where-params)
    -   [修改结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-modifying-results)
    -   [错误](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-errors)
-   [自由主义](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-license)

## 安装

此模块通过 [无](https://www.npmjs.com/) 与 [节点](https://nodejs.org/) 财务报告和审定财务报表 应当安装为您的项目依赖性之一 :

```
npm install @candoimage/prisma-extension-nested-operations
```

`@prisma/client` 是此库的对等依赖, 因此您需要 如果您还没有安装它 :

```
npm install @prisma/client
```

您必须至少安装了 @ prisma/ 客户端的7. 0.0 版本 .

## 使用量

这个 `withNestedOperations()` 函数取用和反对两个属性, `$rootOperation()` 财务报告和审定财务报表 `$allNestedOperations()`。 。 。 . 返回值为 `$allOperations` 钩子,可以直接传递到扩展 `$allOperations` 钩.

```javascript
import { Prisma } from "@prisma/client";
import { withNestedOperations } from "@candoimage/prisma-extension-nested-operations";

client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          // update root params here
          const result = params.query(params.args);
          // update root result here
          return result;
        },
        async $allNestedOperations(params) {
          // update nested params here
          const result = await params.query(params.args);
          // update nested result here
          return result;
        },
      }),
    },
  },
});
```

### `$rootOperation()`

这个 `$rootOperation()` 钩子叫同一段 `$allOperations()` 钩子,但 `params.args` 对象 已更新 `$allNestedOperations()` 查询功能。 同样的模式适用于 返回结果,它是通过返回结果更新的查询的结果 `$allNestedOperations()` 打电话.

### `$allNestedOperations()` 参数

参数对象传递到 `$allNestedOperations()` 函数与传递到 `$allOperations()`。 。 。 . 它已经 `args`, (中文(简体) ), `model`, (中文(简体) ), `operation`,以及 `query` 字段,但有一些关键差异:

-   页:1 `operation` 字段添加以下选项:"连接 OrCreate","连接","断开","包含","选择"和"在哪里"
    
-   页:1 `query` 字段需要第二个参数,即 `operation` 执行中。 这在巢穴操作的类型应该被改变的地方是有用的.
    
-   还有一个 `scope` 字段,其中包含与嵌入关系相关的特定信息:
    
    -   页:1 `parentParams` 字段包含父关系参数对象
    -   页:1 `modifier` 字段中包含任何修改符,例如包含参数 `some` 或者说 `every`。 。 。 .
    -   页:1 `logicalOperators` 字段包含当前关系与其父关系之间的任何逻辑运算符,例如 `AND` 或者说 `NOT`。 。 。 .
    -   页:1 `relations` 字段包含一个与关系相关的对象 `to` 当前模式和 `from` 模特儿回到父母身边.

详情请查阅 `modifier` 财务报告和审定财务报表 `logicalOperators` 字段见 [何处](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-Where) 节.

详情请查阅 `relations` 见 [关系](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-Relations) 节.

参数对象的类型是:

```typescript
type NestedParams<ExtArgs> = {
  query: (args: any, operation?: NestedOperation) => Prisma.PrismaPromise<any>;
  model: keyof Prisma.TypeMap<ExtArgs>["model"];
  args: any;
  operation: NestedOperation;
  scope?: Scope<ExtArgs>;
};

export type Scope<ExtArgs> = {
  parentParams: Omit<NestedParams<ExtArgs>, "query">;
  relations: { to: Prisma.DMMF.Field; from: Prisma.DMMF.Field };
  modifier?: Modifier;
  logicalOperators?: LogicalOperator[];
};

type Modifier = "is" | "isNot" | "some" | "none" | "every";

type LogicalOperator = "AND" | "OR" | "NOT";

type Operation =
  | "create"
  | "createMany"
  | "update"
  | "updateMany"
  | "upsert"
  | "delete"
  | "deleteMany"
  | "where"
  | "include"
  | "select"
  | "connect"
  | "connectOrCreate"
  | "disconnect";
```

### 嵌入式写作

这个 `$allNestedOperations()` 函数为每个 [嵌入式写作](https://www.prisma.io/docs/concepts/components/prisma-client/relation-queries#nested-writes) 在查询中操作。 这个 `operation` 字段设定为正在执行的操作,例如“创建”或“更新”. 这个 `model` 字段设定为正在运行的模型,例如“用户”或“后”.

例如,请查询如下:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      update: {
        where: { id: 1 },
        data: { title: "Hello World" },
      },
    },
  },
});
```

这个 `$allNestedOperations()` 函数将调用:

```javascript
{
  operation: 'update',
  model: 'Post',
  args: {
    where: { id: 1 },
    data: { title: 'Hello World' }
  },
  relations: {
    to: { kind: 'object', name: 'posts', isList: true, ... },
    from: { kind: 'object', name: 'author', isList: false, ... },
  },
  scope: [root params],
}
```

一些被嵌入的写作可以作为一系列操作来传递. 在这种情况下 `$allNestedOperations()` 对每个函数都要求 在数组中操作。 例如,请查询如下:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      update: [
        { where: { id: 1 }, data: { title: "Hello World" } },
        { where: { id: 2 }, data: { title: "Hello World 2" } },
      ],
    },
  },
});
```

这个 `$allNestedOperations()` 函数将调用:

```javascript
 {
  operation: 'update',
  model: 'Post',
  args: {
    where: { id: 1 },
    data: { title: 'Hello World' }
  },
  relations: {
    to: { kind: 'object', name: 'posts', isList: true, ... },
    from: { kind: 'object', name: 'author', isList: false, ... },
  },
  scope: [root params],
}
```

财务报告和审定财务报表

```javascript
 {
  operation: 'update',
  model: 'Post',
  args: {
    where: { id: 2 },
    data: { title: 'Hello World 2' }
  },
  relations: {
    to: { kind: 'object', name: 'posts', isList: true, ... },
    from: { kind: 'object', name: 'author', isList: false, ... },
  },
  scope: [root params],
}
```

#### 更改嵌入式写操作

这个 `$allNestedOperations()` 函数可以改变模型上的操作。 例如,请查询如下:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      update: {
        where: { id: 1 }
        data: { title: 'Hello World' }
      },
    },
  },
});
```

这个 `$allNestedOperations()` 函数可用于将操作更改为 `upsert`数字 :

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        $rootOperation: (params) => {
          return params.query(params.args);
        },
        $allNestedOperations: (params) => {
          if (params.model === "Post" && params.operation === "update") {
            return params.query(
              {
                where: params.args.where,
                create: params.args.data,
                update: params.args.data,
              },
              "upsert"
            );
          }
          return params.query(params);
        },
      }),
    },
  },
});
```

以上将修改最后查询 `$allNestedOperations()` 改为:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      upsert: {
        where: { id: 1 },
        create: { title: "Hello World" },
        update: { title: "Hello World" },
      },
    },
  },
});
```

当改变操作时,操作有可能已经存在. 在这种情况下,由此产生的业务将合并. 例如,请查询如下:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      update: {
        where: { id: 1 },
        data: { title: "Hello World" },
      },
      upsert: {
        where: { id: 2 },
        create: { title: "Hello World 2" },
        update: { title: "Hello World 2" },
      },
    },
  },
});
```

使用同样的 `$allNestedOperations()` 在更新操作改为更新操作之前定义,但有 已经是一个上调操作,所以将两个操作合并为上调操作阵列,并添加到新的操作中 数组的结尾。 当现有的操作已经是操作列表时,新的操作会被添加到结尾 名单 在这种情况下,最后的询问是:

```javascript
const result = await client.user.update({
  data: {
    posts: {
      upsert: [
        {
          where: { id: 2 },
          create: { title: "Hello World 2" },
          update: { title: "Hello World 2" },
        },
        {
          where: { id: 1 },
          create: { title: "Hello World" },
          update: { title: "Hello World" },
        },
      ],
    },
  },
});
```

有时无法以这种方式合并操作. 这个 `createMany` 操作不支持 操作阵列 `data` 报告 `createMany` 操作被合并。 例如,请查询如下:

```javascript
const result = await client.user.create({
  data: {
    posts: {
      createMany: {
        data: [{ title: "Hello World" }, { title: "Hello World 2" }],
      },
      create: {
        title: "Hello World 3",
      },
    },
  },
});
```

如果 `create` 操作改为 a `createMany` 操作 `data` 字段将添加到现有 `createMany` 操作。 最后的询问是:

```javascript
const result = await client.user.create({
  data: {
    posts: {
      createMany: {
        data: [
          { title: "Hello World" },
          { title: "Hello World 2" },
          { title: "Hello World 3" },
        ],
      },
    },
  },
});
```

也不可能通过为非列表关系创建一系列操作来将操作合并. 对于 示例如下:

```javascript
const result = await client.user.update({
  data: {
    profile: {
      create: {
        bio: "My personal bio",
        age: 30,
      },
      update: {
        where: { id: 1 },
        data: { bio: "Updated bio" },
      },
    },
  },
});
```

如果 `update` 操作改为 a `create` 使用下列扩展操作:

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        $rootOperation: (params) => {
          return params.query(params.args);
        },
        $allNestedOperations: (params) => {
          if (params.model === "Profile" && params.operation === "update") {
            return params.query(params.args.data, "create");
          }
          return params.query(params);
        },
      }),
    },
  },
});
```

这个 `create` 从操作 `update` 业务需要与现有的 `create` 业务,但自 `profile` 不是一个列表关系, 我们必须合并 最终生成的对象 :

```javascript
const result = await client.user.create({
  data: {
    profile: {
      create: {
        bio: "Updated bio",
        age: 30,
      },
    },
  },
});
```

#### 写入结果

这个 `query` 函数 `$allNestedOperations()` 要求嵌入式写入操作总是返回 `undefined` 因为他们的结果. 这是因为从根查询中返回的结果可能不包括特定嵌入式写入的数据.

例如,请查询如下:

```javascript
const result = await client.user.update({
  data: {
    profile: {
      create: {
        bio: "My personal bio",
        age: 30,
      },
    }
    posts: {
      updateMany: {
        where: {
          published: false,
        },
        data: {
          published: true,
        },
      },
    },
  },
  select: {
    id: true,
    posts: {
      where: {
        title: {
          contains: "Hello",
        },
      },
      select: {
        id: true,
      },
    },
  }
});
```

这个 `profile` 字段不包含在 `select` 对象所以结果 `create` 操作不包含在 根结果。 这个 `posts` 字段包含在 `select` 对象但 `where` 对象仅包含带有 标题中包含“你好”并仅返回“id”字段,在此情况下,无法匹配 `updateMany` 返回的员额.

见 [修改结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-modifying-results) 以了解如何更新查询结果的更多信息.

### 何处

这个 `where` 操作用于在参数内发现对象的任何关系.

注意 `where` 操作不用于对象所在的根, 这是因为您需要根操作来知道 何为对象接受的根属性 。 对于巢穴的物体,这不是一个问题,因为他们总是跟随 同样的模式.

看这里 `where` 操作使用下列查询:

```javascript
const result = await client.user.findMany({
  where: {
    posts: {
      some: {
        published: true,
      },
    },
  },
});
```

上面对象产生在对象所在处发现的"后"关系的调用. 这个 `modifier` 字段设置为 "某"从物体所在"某"字段内.

```javascript
{
  operation: 'where',
  model: 'Post',
  args: {
    published: true,
  },
  scope: {
    parentParams: {...}
    modifier: 'some',
    relations: {...}
  },
}
```

在发现和调用And、OR和NOT逻辑运算符时发现的关系 `$allNestedOperations()` 函数, 不过 `where` 对逻辑运算符本身不要求操作。 例如,请查询如下:

```javascript
const result = await client.user.findMany({
  where: {
    posts: {
      some: {
        published: true,
        AND: [
          {
            title: "Hello World",
          },
          {
            comments: {
              every: {
                text: "Great post!",
              },
            },
          },
        ],
      },
    },
  },
});
```

这个 `$allNestedOperations()` 函数将使用类似“ post” 的参数调用, 但是它也会被调用 附有下列段落:

```javascript
{
  operation: 'where',
  model: 'Comment',
  args: {
    text: "Great post!",
  },
  scope: {
    parentParams: {...}
    modifier: 'every',
    logicalOperators: ['AND'],
    relations: {...}
  },
}
```

由于“注释”关系在“AND”逻辑运算符内找到 要求开展全美行动 这个 `modifier` 字段设置为“每个”,因为对象位于“每个”字段,并且 页:1 `logicalOperators` 字段设置为 `['AND']` 因为物体在“AND”逻辑运算符内.

注意到 `$allNestedOperations()` 函数不为“ AND” 数组中的第一个项目调用, 这是因为第一个项目 不包含任何关系.

这个 `logicalOperators` 字段跟踪在 `parentParams` 和当前参数。 对于 示例如下:

```javascript
const result = await client.user.findMany({
  where: {
    AND: [
      {
        NOT: {
          OR: [
            {
              posts: {
                some: {
                  published: true,
                },
              },
            },
          ],
        },
      },
    ],
  },
});
```

这个 `$allNestedOperations()` 函数将调用以下段落:

```javascript
{
  operation: 'where',
  model: 'Post',
  args: {
    published: true,
  },
  scope: {
    parentParams: {...}
    modifier: 'some',
    logicalOperators: ['AND', 'NOT', 'OR'],
    relations: {...},
  },
}
```

这个 `where` 操作也用于在 `where` 包含和选择区域。 例如:

```javascript
const result = await client.user.findMany({
  select: {
    posts: {
      where: {
        published: true,
      },
    },
  },
});
```

这个 `$allNestedOperations()` 函数将调用以下段落:

```javascript
{
  operation: 'where',
  model: 'Post',
  args: {
    published: true,
  },
  scope: {...}
}
```

#### 成果

这个 `query` a 函数 `where` 操作总是用 `undefined`。 。 。 .

### 包含

这个 `include` 操作需要包含任何关系。 这个 `args` 字段将包含对象或布尔 关系。 例如,请查询如下:

```javascript
const result = await client.user.findMany({
  include: {
    profile: true,
    posts: {
      where: {
        published: true,
      },
    },
  },
});
```

对于"相片"关系 `$allNestedOperations()` 函数将调用:

```javascript
{
  operation: 'include',
  model: 'Profile',
  args: true,
  scope: {...}
}
```

而对于"后"关系 `$allNestedOperations()` 函数将调用:

```javascript
{
  operation: 'include',
  model: 'Post',
  args: {
    where: {
      published: true,
    },
  },
  scope: {...}
}
```

#### 包含结果

这个 `query` 函数 `include` 操作结果 `include` 操作。 举个例子 查询如下:

```javascript
const result = await client.user.findMany({
  include: {
    profile: true,
  },
});
```

这个 `$allNestedOperations()` 用于“ profile” 关系的函数将调用:

```javascript
{
  operation: 'include',
  model: 'Profile',
  args: true,
  scope: {...}
}
```

还有 `query` 函数将随 `include` 操作,在这种情况下,诸如:

```javascript
{
  id: 2,
  bio: 'My personal bio',
  age: 30,
  userId: 1,
}
```

对于被列入父母结果清单的关系 `query` 函数将用平整的阵列解决 每一个母公司的所有模型的结果。 例如,请查询如下:

```javascript
const result = await client.user.findMany({
  include: {
    posts: true,
  },
});
```

如果根结果看起来像如下:

```javascript
[
  {
    id: 1,
    name: "Alice",
    posts: [
      {
        id: 1,
        title: "Hello World",
        published: false,
        userId: 1,
      },
      {
        id: 2,
        title: "My first published post",
        published: true,
        userId: 1,
      },
    ],
  },
  {
    id: 2,
    name: "Bob",
    posts: [
      {
        id: 3,
        title: "Clean Code",
        published: true,
        userId: 2,
      },
    ],
  },
];
```

这个 `query` 函数用于“ posts” 关系,将解决以下问题:

```javascript
[
  {
    id: 1,
    title: "Hello World",
    published: false,
    userId: 1,
  },
  {
    id: 2,
    title: "My first published post",
    published: true,
    userId: 1,
  },
  {
    id: 3,
    title: "Clean Code",
    published: true,
    userId: 2,
  },
];
```

欲了解更多关于如何修改一项公约的结果的信息 `include` 操作参见 [修改结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-modifying-results)

### 选择

与 `include` 操作 `select` 操作将被调用到与 `args` 字段 中包含对象或布尔随关系选择而通过。 例如,请查询如下:

```javascript
const result = await client.user.findMany({
  select: {
    posts: true,
    profile: {
      select: {
        bio: true,
      },
    },
  },
});
```

而对于"后"关系 `$allNestedOperations()` 函数将调用:

```javascript
{
  operation: 'select',
  model: 'Post',
  args: true,
  scope: {...}
}
```

对于"相片"关系 `$allNestedOperations()` 函数将调用:

```javascript
{
  operation: 'select',
  model: 'Profile',
  args: {
    bio: true,
  },
  scope: {...}
}
```

#### 选择结果

这个 `query` a 函数 `select` 操作结果 `select` 操作。 这跟那个一样 `include` 操作。 见 [包含结果](https://npmcn.com/package/%40candoimage/prisma-extension-nested-operations/#readme-include-results) 用于提供更多信息.

### 关系

这个 `relations` 报告 `scope` 对象包含与当前模型相关的关系。 举个例子 查询如下:

```javascript
const result = await client.user.create({
  data: {
    email: "test@test.com",
    profile: {
      create: {
        bio: "Hello World",
      },
    },
    posts: {
      create: {
        title: "Hello World",
      },
    },
  },
});
```

这个 `$allNestedOperations()` 函数将调用“ profile” 关系的下列参数:

```javascript
{
  operation: 'create',
  model: 'Profile',
  args: {
    bio: "Hello World",
  },
  scope: {
    parentParams: {...}
    relations: {
      to: { name: 'profile', kind: 'object', isList: false, ... },
      from: { name: 'user', kind: 'object', isList: false, ... },
    },
  },
}
```

和以下关于“邮政”关系的段落:

```javascript
{
  operation: 'create',
  model: 'Post',
  args: {
    title: "Hello World",
  },
  scope: {
    parentParams: {...}
    relations: {
      to: { name: 'posts', kind: 'object', isList: true, ... },
      from: { name: 'author', kind: 'object', isList: false, ... },
    },
  },
}
```

### 修改嵌入式书写参数

当写入修改查询参数的扩展名时, 您应该首先写入 `$rootOperation()` 像钩子一样 a 一个 `$allOperations()` 钩子,然后添加 `$allNestedOperations()` 钩.

假设您在为特定模型创建模型时正在写入设置默认值的中间软件:

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          // we only want to add default values for the "Invite" model
          if (params.model !== "Invite") {
            return params.query(params.args);
          }

          if (params.operation === "create" && !params.args.data.code) {
            params.args.data.code = createCode();
          }

          if (params.operation === "upsert" && !params.args.create.code) {
            params.args.create.code = createCode();
          }

          if (params.operation === "createMany") {
            params.args.data.forEach((data) => {
              if (!data.code) {
                data.code = createCode();
              }
            });
          }

          return params.query(params.args);
        },
        async $allNestedOperations(params) {
          return params.query(params.args);
        },
      }),
    },
  },
});
```

然后加入在巢中可以找到的不同参数和操作的条件:

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          [...]
        },
        async $allNestedOperations(params) {
          // we only want to add default values for the "Invite" model
          if (params.model !== "Invite") {
            return params.query(params.args);
          }

          // when the "create" operation is from a nested write the data is not in the "data" field
          if (params.operation === "create" && !params.args.code) {
            params.args.code = createCode();
          }

          // handle the "connectOrCreate" operation
          if (params.operation === "connectOrCreate" && !params.args.create.code) {
            params.args.create.code = createCode();
          }

          // pass args to query
          return params.query(params.args);
        },
      }),
    },
  },
});
```

### 修改参数位置

当写入修改查询参数的扩展时, 您应当首先写入 `$rootOperation()` 钩为 如果它是一个 `$allOperations()` 钩子,这是因为 `where` 操作不用于对象所在的根, 因此您 需要手动处理.

假设你正在写一个扩展, 排除模型与特定的领域, 让我们称之为"隐形"而不是 "取出"使这更不熟悉:

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          // don't handle operations that only accept unique fields such as findUnique or upsert
          if (
            params.operation === "findFirst" ||
            params.operation === "findFirstOrThrow" ||
            params.operation === "findMany" ||
            params.operation === "updateMany" ||
            params.operation === "deleteMany" ||
            params.operation === "count" ||
            params.operation === "aggregate"
          ) {
            return params.query({
              ...params.args,
              where: {
                ...params.args.where,
                invisible: false,
              },
            });
          }

          return params.query(params.args);
        },
        async $allNestedOperations(params) {
          return params.query(params.args);
        },
      }),
    },
  },
});
```

然后添加条件 `where` 操作 :

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          [...]
        },
        async $allNestedOperations(params) {
          // handle the "where" operation
          if (params.operation === "where") {
            return params.query({
              ...params.args,
              invisible: false,
            });
          }

          return params.query(params.args);
        },
      }),
    },
  },
});
```

### 修改结果

在写入修改查询结果的扩展名时,您应当遵循以下程序:

-   处理 `$rootOperation()` 钩一样,你会与一个 `$allOperations()` 钩.
-   使用 `include` 财务报告和审定财务报表 `select` 业务活动 `$allNestedOperations()` 钩.

说你正在写中间软件 给查询结果添加了时间戳 你将首先处理根源案件:

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          const result = await params.query(params.args);

          // ensure result is defined
          if (!result) return result;

          // handle root operations
          if (
            params.operation === "findFirst" ||
            params.operation === "findFirstOrThrow" ||
            params.operation === "findUnique" ||
            params.operation === "findUniqueOrThrow" ||
            params.operation === "create" ||
            params.operation === "update" ||
            params.operation === "upsert" ||
            params.operation === "delete"
          ) {
            result.timestamp = Date.now();
            return result;
          }

          if (params.operation === "findMany") {
            const result = await params.query(params.args);
            result.forEach((model) => {
              model.timestamp = Date.now();
            });
            return result;
          }

          return result;
        },
        async $allNestedOperations(params) {
          return params.query(params.args);
        },
      }),
    },
  },
});
```

然后,你会处理 巢的结果使用 `include` 财务报告和审定财务报表 `select` 操作 :

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          [...]
        },
        async $allNestedOperations(params) {
          const result = await next(params);

          // ensure result is defined
          if (!result) return result;

          // handle nested operations
          if (params.operation === "include" || params.operation === "select") {
            if (Array.isArray(result)) {
              result.forEach((model) => {
                model.timestamp = Date.now();
              });
            } else {
              result.timestamp = Date.now();
            }
            return result;
          }

          return result;
        },
      }),
    },
  },
});
```

您也可以通过为每个结果创建新对象来写入上面的中间软件,而不是改变现有的 对象 :

```javascript
const client = _client.$extends({
  query: {
    $allModels: {
      $allOperations: withNestedOperations({
        dmmf: Prisma.dmmf,
        inlineSchema: (client as any)._engineConfig?.inlineSchema,
        async $rootOperation(params) {
          [...]
        },
        async $allNestedOperations(params) {
          const result = await next(params);

          // ensure result is defined
          if (!result) return result;

          // handle nested operations
          if (params.operation === "include" || params.operation === "select") {
            if (Array.isArray(result)) {
              return result.map((model) => ({
                ...model,
                timestamp: Date.now(),
              });
            }

            return {
              ...result,
              timestamp: Date.now(),
            };
          }

          return result;
        },
      }),
    },
  },
});
```

注:当修改结果来自 `include` 或者说 `select` 操作中必须变换现有对象或 将已有对象扩展为新对象。 这是因为 `createNestedMiddleware` 需要从 原始对象以修正更新根结果.

### 错误

如果任何中间软件在任何一点投出出出错,则根查询会随该出错一起投出. 任何中间软件 等待会让承诺在那时遭到拒绝.

## 自由主义

Apache 2.0 (英语)

## 常见问题

### @candoimage/prisma-extension-nested-operations 是什么？

用于创建带有嵌入操作的 Prisma 客户端扩展的 Utils

### 如何安装 @candoimage/prisma-extension-nested-operations？

在项目目录运行 npm install @candoimage/prisma-extension-nested-operations，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：@prisma/client（\>=7\.0\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @candoimage/prisma-extension-nested-operations 支持 TypeScript 吗？

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

### @candoimage/prisma-extension-nested-operations 支持 ESM 还是 CommonJS？

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

### @candoimage/prisma-extension-nested-operations 可以商用吗？

@candoimage/prisma-extension-nested-operations 使用 Apache-2\.0 许可。宽松许可：允许商业使用、修改和再分发，并附带明确的专利授权；分发时需保留许可与 NOTICE 文件，修改过的文件要注明改动。以上为概括，不构成法律意见，请以许可原文为准。

### @candoimage/prisma-extension-nested-operations 的下载量有多少？

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

### @candoimage/prisma-extension-nested-operations 还在维护吗？

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

