# @classytic/mongokit 中文文档

规范地址：https://npmcn.com/package/%40classytic/mongokit/

版本：3\.46\.0
npm 元数据更新时间：2026-11-08T14:49:19.099Z
中文译文更新时间：2026-11-09T23:56:39.503Z
软件包许可：MIT

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

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

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

- 包体积（解压后）：1.4 MB，94 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=22
- 运行依赖：0 个
- peer 依赖：mongoose \>=9\.12\.0，@classytic/repo-core \>=0\.38\.0，mongodb-memory-server \>=11\.3\.0
- 首次发布：2025-11-09T03:48:10.338Z
- 最新版本发布：2026-11-08T14:49:18.903Z
- 近 30 天下载量：2843（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：97（近 12 个月 95 个）

## 中文简介

生产级MongoDB寄存器 - 智能发卡,事件和插件. 建于@classytic/repo-core上.

## 安装

```sh
npm install @classytic/mongokit
```

也可以使用：`pnpm add @classytic/mongokit`、`yarn add @classytic/mongokit`、`bun add @classytic/mongokit`

## README

# @ 经典/ mongokit

[![npm version](https://badge.fury.io/js/@classytic%2Fmongokit.svg)](https://www.npmjs.com/package/@classytic/mongokit) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![Sponsor](https://img.shields.io/github/sponsors/classytic?style=flat-square&label=Sponsor&logo=GitHub&color=EA4AAA)](https://github.com/sponsors/classytic)

Mongoose apps的生产准备寄存层: 租户安全 CRUD, 软删除, pagination, hooks, retries, dealers, change streams, 和插件.

蒙戈克特就是建立在这个基础上的 `@classytic/repo-core` 执行共享 `StandardRepo<TDoc>` 合同,因此控制器代码可以瞄准一个存储器接口跨越MongoDB和SQLite.

## 安装

```bash
npm install @classytic/mongokit @classytic/repo-core mongoose
```

所需经费:

-   节点.js `>=22`
-   乌鸦 `>=9.4.1`
-   `@classytic/repo-core >=0.19.0`
-   `mongodb-memory-server >=10.4.3` —— 说 **选项**,仅需要 `@classytic/mongokit/testkit` 子路径( 被宣布为可选对等点, 所以它是 从来没有为不使用它的消费者安装)

## 快速启动

使用 `createRepository(model, config)` 为了共同的道路。 它为您按安全顺序绘制插件 .

```ts
import { createRepository } from '@classytic/mongokit';
import UserModel from './models/User.js';

const userRepo = createRepository<UserDoc>(UserModel, {
  tenant: { tenantField: 'organizationId' },
  softDelete: true,
  timestamps: true,
  batch: true,
});

const user = await userRepo.create(
  { name: 'Ada', email: 'ada@example.com' },
  { organizationId },
);

const page = await userRepo.getAll({
  page: 1,
  limit: 20,
  filters: { status: 'active' },
  organizationId,
});

await userRepo.update(user._id, { name: 'Ada Lovelace' }, { organizationId });
await userRepo.delete(user._id, { organizationId });
```

对于手动插件控制,请直接使用构造器:

```ts
import {
  Repository,
  methodRegistryPlugin,
  multiTenantPlugin,
  softDeletePlugin,
  timestampPlugin,
} from '@classytic/mongokit';

const userRepo = new Repository(UserModel, [
  methodRegistryPlugin(),
  multiTenantPlugin({ tenantField: 'organizationId' }),
  softDeletePlugin(),
  timestampPlugin(),
]);
```

## 为什么是Mongokit?

-   **房客安全:** 房客过滤器在司机打电话前由政策钩注入.
-   **软删除 :** 默认软删除方式 `restore`, (中文(简体) ), `getDeleted`TTL的支持 和硬去除的逃生舱.
-   **铺设 :** 为不安全的密钥集查询提供索引警告.
-   **钩和中间器皿:** 决定性 `before:*`, (中文(简体) ), `after:*`, (中文(简体) ), `error:*` 钩子外加包装式中件.
-   **检索和取消:** `retryPolicy` 财务报告和审定财务报表 `AbortSignal` 整个存储器表面的支持.
-   **交易 :** 用于单repo和跨repo MongoDB交易的辅助API.
-   **更改流 :** 便携式 `watch()` API过蒙戈变流.
-   **跨吻合同:** 可转让到 `StandardRepo<TDoc>` 从 `@classytic/repo-core`。 。 。 .

## 核心 API

读取:

```ts
await repo.getById(id, options);
await repo.getByQuery({ email }, options);
await repo.getOne({ slug }, options);
await repo.findAll({ status: 'active' }, options);
await repo.getAll({ page: 1, limit: 20, filters });
await repo.count(filters, options);
await repo.exists(filters, options);
await repo.distinct('status', filters, options);
```

写作:

```ts
await repo.create(data, options);
await repo.createMany(rows, options);
await repo.update(id, patch, options);
await repo.updateMany(filter, patch, options);
await repo.delete(id, options);
await repo.deleteMany(filter, options);
await repo.findOneAndUpdate(filter, update, options);
```

语义学小姐跟随 `MinimalRepo` 合同:

-   `getById`, (中文(简体) ), `update`,以及 `delete` 返回时 `null` 关于小姐.
-   无效的对象Id形状输入返回 `null` 而不是冲浪出一只绵羊 `CastError`。 。 。 .
-   过 `{ throwOnNotFound: true }` 选择404式错误.

## 常见食谱

### 多十年读写

```ts
const repo = createRepository(OrderModel, {
  tenant: { tenantField: 'organizationId', required: true },
});

await repo.create({ total: 120 }, { organizationId });
await repo.findAll({ status: 'paid' }, { organizationId });
```

若为 `required: true` 无法解决租户的问题,在任何司机打电话前,电话无法拨打.

### 软删除和硬删除

```ts
const repo = createRepository(UserModel, {
  softDelete: { deletedField: 'deletedAt' },
});

await repo.delete(userId);                    // soft delete
await repo.restore(userId);                   // plugin method
await repo.delete(userId, { mode: 'hard' });  // physical delete
```

硬删除仍然运行着租户,审计,缓存和验证钩.

### 倾斜

```ts
const offsetPage = await repo.getAll({
  mode: 'offset',
  page: 1,
  limit: 25,
  sort: { createdAt: -1 },
});

const first = await repo.getAll({
  mode: 'keyset',
  limit: 25,
  sort: { createdAt: -1 },
});

const next = await repo.getAll({
  mode: 'keyset',
  limit: 25,
  sort: { createdAt: -1 },
  after: first.next,
});
```

每一类都有一个独特的 `_id` 断线器和 `hasNext` 来源于限制+1获取。 偏移页面 报告 `{ total, totalIsEstimate, countedAt }` 每栏下 `countStrategy` (单位:千美元)`exact`, (中文(简体) ), `capped`, (中文(简体) ), `estimated`, (中文(简体) ), `none`, (中文(简体) ), `cached`页:1 `skip` 过去 `maxOffset` (违约10万)以下列方式被拒绝: `mongokit.pagination.offset_too_deep`。光标绑定在它的收藏、过滤器上(租户) 和整理:在其他地方重放 `repo.cursor.scope_mismatch` (对等核心) `CURSOR_ERROR_CODES`页:1 `cursorSecret` 所以篡改也被发现了.

```ts
// Boot: the deployment's list policy.
configurePaginationDefaults({ defaultCountStrategy: 'capped', cursorSecret, maxOffset: 50_000 });
```

### 交易

```ts
import { withTransaction } from '@classytic/mongokit';

await withTransaction(mongoose.connection, async (session) => {
  const order = await orderRepo.create(orderData, { session, organizationId });
  await ledgerRepo.create({ orderId: order._id, amount: order.total }, { session, organizationId });
});
```

单还原便利:

```ts
await orderRepo.withTransaction(async (txRepo) => {
  return txRepo.create(orderData, { organizationId });
});
```

要连载作家,写作必须改变. 将字段设置到它已经拥有的值的更新是无可操作的:它不需要写入锁,所以两个交易在同一瞬间完成,从不冲突. 写有变化的东西( 例如) Name `$inc: { writes: 1 }` 在大门或租赁行.

### 时限和关切`queryDefaults`(中文(简体) )

```ts
// Boot: every command is bounded by a server-side maxTimeMS; the boot check fails without it.
// Do not pass `timeoutMS` to mongoose.connect(): the MongoDB driver ignores it since 7.8 (CVE-2026-119179).
await mongoose.connect(uri);
configureQueryDefaults({ maxTimeMS: 5_000, writeConcern: { w: 'majority' } });
configureAggregateDefaults({ maxTimeMs: 15_000 });
assertQueryDefaultsConfigured();

// Per repository, and per call (per call always wins):
const repo = new Repository(Order, plugins, {}, { queryDefaults: { comment: 'orders' } });
await repo.findAll(filter, { maxTimeMS: 500 });
```

### 加入范围

A 类 `$lookup` 编号 : `$unionWith` 编号 : `$graphLookup` 在自己的仓库下读取已合并的收藏 租户和软删除范围。 拿着 `from` 从 `Model.collection.name`: 没有模型拥有的名称丢出 `mongokit.join.unknown_collection`,没有寄存器支配丢弃 `mongokit.join.ungoverned_collection` (列出一个全公司在 `unscopedJoins`) (中文(简体) ).

### 批量读取( E)`getByIds`(中文(简体) )

```ts
const byId = await repo.getByIds(ids, { select: 'name sku' });              // Map, chunked $in
const rows = await repo.getByIds(ids, { preserveOrder: true, chunkSize: 5_000 }); // aligned, undefined = miss
```

### 读取模型( E)`bulkUpsert`, (中文(简体) ), `@classytic/mongokit/read-model`(中文(简体) )

```ts
const res = await totals.bulkUpsert(rows, { key: ['period', 'rate'], inc: ['tax'], organizationId });
// res.results[i].outcome: 'inserted' | 'updated' | 'unchanged' | 'failed' (+ code). Needs MongoDB 8.0.

import { applyIncrements, rebuildInto, reconcile } from '@classytic/mongokit/read-model';
await applyIncrements(totals, grains, { session, ledger, organizationId }); // inside the posting transaction
await rebuildInto(facts, totals, { pipeline, on: ['organizationId', 'period', 'rate'], scope: { organizationId } });
const { drift } = await reconcile(facts, totals, { pipeline, on, measures: ['tax'], scope: { organizationId } });
```

### 活性扫荡`iterate`(中文(简体) )

```ts
for await (const { docs, checkpoint } of repo.iterate(filter, { batchSize: 1_000, after: saved, organizationId })) {
  await process(docs);
  await saveCheckpoint(checkpoint); // resume later with { after: checkpoint }
}
```

### 改变流

```ts
const ac = new AbortController();

for await (const change of repo.watch({ status: 'pending' }, {
  signal: ac.signal,
  organizationId,
} as { signal: AbortSignal; organizationId: string })) {
  if (change.operation === 'create') enqueue(change.doc);
}
```

`watch()` 与其它读取的一样是插件路由的,所以在蒙戈变流管打开之前,会应用租户和软去除过滤器.

### 查询解析器

```ts
import { QueryParser } from '@classytic/mongokit';

const parser = new QueryParser({
  schema: InvoiceModel.schema,
  allowedFilterFields: ['status', 'total', 'customerId'],
  allowedSortFields: ['createdAt', 'total'],
  searchMode: 'auto',
});

const parsed = parser.parse(req.query); // throws HttpError(400) on invalid/blocked input
const result = await invoiceRepo.getAll(parsed);
```

支持常见的 URL 运算符, 如 `_gt`, (中文(简体) ), `_gte`, (中文(简体) ), `_lt`, (中文(简体) ), `_lte`, (中文(简体) ), `_in`, (中文(简体) ), `_nin`, (中文(简体) ), `_regex`地理过滤器 聚居物 以及有知觉的强迫.

解析器是 **默认关闭失败** (单位:千美元)`invalidInput: 'throw'`: 被封锁 运算符、不允许的字段、错误的值和病理正则输入 提高HTTP 400 (`code: 'INVALID_QUERY_INPUT'`而不是沉默无声 驳回请求 _仅限_ 过滤器会将查询扩展至每个 租户范围记录。 文-语义输入( E)`search`, (中文(简体) ), `like`编号 :`contains`(中文(简体) ) 总是逃避而不是拒绝,所以 `?search=c++` 从来没有400s。 已经信任 迁移/匹配工具可以选择使用遗留的警告和滴放行为 `invalidInput: 'drop'`。 。 。 .

### 前缀搜索( 搜索- as- you- type, 有索引)

`searchMode: 'prefix'` 找到每个查询词开始一个字的文档 `searchFields` (单位:千美元)`moh ali` 找到"Mohammed Al-Ali",由多键索引提供 而不是一个无忧无虑的Regex扫描。 寄存器会写一个普通的单词 键入 `searchKeysField` (默认) `_searchKeys`在每一个写道上. 规范化:小写,有二甲酸盐脱落的NFKD,阿拉伯折叠 (删除了tashkeel/tatweel, `أ إ آ → ا`, (中文(简体) ), `ى → ي`, (中文(简体) ), `ة → ه`),拆分开 白相间/平相.

```ts
import { rebuildSearchKeys, searchKeysIndex, searchKeysPath } from '@classytic/mongokit';

schema.add({ _searchKeys: searchKeysPath() }); // string[], select: false
// Serves getAll({ search }) prefix search.
schema.index(searchKeysIndex().fields, searchKeysIndex().options);

const repo = new Repository(Person, [], {}, { searchMode: 'prefix', searchFields: ['name', 'email'] });
await rebuildSearchKeys(repo, { onlyMissing: true }); // backfill rows written before
await repo.getAll({ search: 'moh', page: 1 }); // composes with filters, tenant scope, keyset/offset, counts
```

客户用同样的规则从无鼠标的子路径突出: `import { findSearchMatches } from '@classytic/mongokit/search'`写着: 绕过寄存器( raw) `Model.updateOne`,更好的奥思的适配器)写出 键为 `buildSearchKeys(doc, fields)`。 。 。 .

## 内建插件

| 插件 | 目的 |
| --- | --- |
| `methodRegistryPlugin` | 安全添加插件分配方法 |
| `multiTenantPlugin` | 租户范围界定和租户盖章 |
| `softDeletePlugin` | 软删除、 恢复、 删除列表查询、 TTL |
| `timestampPlugin` | `createdAt` 编号 : `updatedAt` 管理层 |
| `searchKeysPlugin` | 每个书写上的前缀搜索密钥( 自动安装于 `searchMode: 'prefix'`(中文(简体) ) |
| `batchOperationsPlugin` | `bulkWrite` 和批量帮助者 |
| `cachePlugin` | 可插取读取缓存 |
| `auditLogPlugin` 编号 : `auditTrailPlugin` | 审计线索—— `auditTrailPlugin({ mode: 'transactional' })` 给出内部为原子的会话连接条目 `withTransaction` (遵守级别);默认 `'best-effort'` 模式是防火和遗忘的可观察性。 打电话 `ensureAuditTrailReady()` 因此,在第一次交易中不会发生收藏/索引创建 |
| `observabilityPlugin` | 量子钩点 |
| `cascadePlugin` | Hook 路由级联删除 |
| `customIdPlugin` | 前缀或相继的公共身份证 |
| `fieldFilterPlugin` | 了解作用的外地可见度 |
| `validationChainPlugin` | 分层同步和同步验证 |
| `mongoOperationsPlugin` | Hook- routed Mongo 更新助手 |
| `aggregateHelpersPlugin` | 常见的聚合助手 |
| `subdocumentPlugin` | Nested 阵列文档助手 |
| `changeLogPlugin` | 持久每个文件的改变种子(`@classytic/repo-core/sync`用于离线第一拉出/推出和复制品 |

只导入您使用的插件 .

## 事件和中间软件

每个操作都发出钩子:

```ts
repo.on('before:delete', (context) => {
  if (!context.user) throw new Error('unauthorized');
});

repo.on('after:create', ({ context, result }) => {
  audit.info({ model: context.model, id: result._id });
});
```

Middleward 包裹成功操作执行 :

```ts
repo.useMiddleware(async ({ operation, next }) => {
  const start = performance.now();
  try {
    return await next();
  } finally {
    metrics.record(operation, performance.now() - start);
  }
});
```

使用 `before:*` 安全政策的钩子。 使用中间软件来进行人机组学,如定时,追踪,以及输入/输出成型等.

## 类型脚本

```ts
import type {
  Repository,
  RepositoryContext,
  SoftDeleteMethods,
  BatchOperationsMethods,
} from '@classytic/mongokit';

type UserRepo = Repository<UserDoc> &
  SoftDeleteMethods<UserDoc> &
  BatchOperationsMethods;
```

### 输入您的 Mongoose 模型—— 绝不铸造 `as never`

以医生类型宣布型号 `Model<UserDoc>` 直接流入 `Repository<UserDoc>` 财务报告和审定财务报表 `createMongooseAdapter` 没有铸造物:

```ts
// ✅ Typed — flows cleanly into Repository + the arc adapter
export type UserDoc = InferSchemaType<typeof UserSchema> & { _id: Types.ObjectId };
export const UserModel = model<UserDoc>('User', UserSchema);
export const userRepo = new Repository<UserDoc>(UserModel, [/* plugins */]);

// ❌ Untyped — the inferred doc type diverges from `UserDoc`, and
//    `mongoose.Model<T>` is INVARIANT in T, so it won't unify. The
//    tempting "fix" is `as never` — don't; type the model instead.
export const UserModel = model('User', UserSchema);          // Model<inferred>
new Repository<UserDoc>(UserModel as never, []);             // ⛔ cast smell
```

出品人并不是蒙哥基打字漏洞——是未打字模型的症状. 一个通用的 `model<Doc>(...)` 调用网站将其删除 (单位:千美元)`Repository`, (中文(简体) ), `createMongooseAdapter`,以及任意 `RepositoryLike<Doc>` 网站).

特征- 检测可移植行为 :

```ts
if (repo.capabilities.changeStreams) {
  // repo.watch is available
}
```

## 子路径导入

```ts
import { parseGeoFilter } from '@classytic/mongokit/query/primitives/geo';
import { coerceFieldValue } from '@classytic/mongokit/query/primitives/coercion';
import { extractSchemaIndexes } from '@classytic/mongokit/query/primitives/indexes';
```

可选桥梁 :

```ts
import { createBetterAuthOverlay } from '@classytic/mongokit/better-auth';
```

## 高级文档

GitHub 寄存器包括以下更深入的指南:

-   增强安全性
-   查找和汇总模式
-   类型架构
-   贡献工作流程
-   释放检查

见 `docs/` 这些长式引用的目录.

## 测试

```bash
npm test
npm run typecheck
npm run build
```

测试套房使用 `mongodb-memory-server` 默认。 设定 `MONGODB_URI` 以对抗外部蒙戈DB部署.

## 测试机率—— `@classytic/mongokit/testkit`

装有电池的吊带 用来测试你的储物库 旋转平面 MongoDB( 独立的, 或用于交易的单节点复制件), 打开一个 **单独** 连接,并给你一个活的mongokit `Repository` 在一个电话.

`mongodb-memory-server` 是一个 **选项对等点** ——在使用试样时安装;它从来不是生产依赖性,是动态导入的,因此它从不输入您的应用包:

```bash
npm i -D mongodb-memory-server
```

```ts
import { createTestRepository } from '@classytic/mongokit/testkit';

const t = await createTestRepository({
  name: 'Order',
  schema: orderSchema,
  config: { softDelete: true, timestamps: true }, // full CreateRepositoryConfig
});

await t.repository.create({ total: 10 });
await t.clear();   // empty the collection between tests
await t.close();   // close connection + stop server (idempotent)
```

### 运行于本地或云 DB

传出 a `uri` (或设置) `MONGODB_URI`和 **没有启动模拟服务器** 测试 kit 连接到你真正的数据库和 `close()`编号 :`stop()` 所以它不会放弃它:

```ts
const t = await createTestRepository({
  name: 'Order', schema: orderSchema,
  uri: process.env.ATLAS_TEST_URI ?? 'mongodb://localhost:27017/myapp-test',
});
```

```bash
# or for the whole suite, no code change:
MONGODB_URI="mongodb+srv://…/myapp-test" vitest run
```

> ⚠️ `clear()` 虚空 **每个收藏** 在连接。 在真正的数据库中,总是指向 **专用测试 DB** 从不生产.

### 测试索引

`createTestRepository` 运行 `model.init()`,因此所宣布的指数是真正构建的——独特的约束性执行(`E11000`),TTL,复合物,文本,和地理学索引都真实表现在记忆服务器上. 使用已曝光内容 `model` 用于运行时间索引工作:

```ts
await t.model.syncIndexes();
await t.model.collection.indexes();          // inspect
await t.model.collection.dropIndex('tag_1'); // drop
```

Atlas **`$search` 编号 : `$vectorSearch`** 索引只使用阿特拉斯系统,在任何非阿特拉斯服务器上都不存在 `uri` 在真正的Atlas测试集群.

### 帮助者

| 帮助 | 使用 |
| --- | --- |
| `createTestRepository` | 服务器 + 连接 + 直播 `Repository` 在一个电话中 |
| `createTestConnection` | 孤立连接 + `clear()` 编号 : `close()` |
| `withMongoMemory(fn)` | 设 设 — 运行 — 拆 (`finally`(中文(简体) ) |
| `createMongoMemory` | 原始服务器寿命周期( n)`uri` + 键 `stop`(中文(简体) ) |
| `mongoMemoryBackend()` | (单位:千美元) `TestBackend` 连接 `@classytic/arc-testkit` |

都接受,我们接受 `{ replset?, dbName?, uri? }`。 。 。 .

### 查询计划门

```ts
import { assertQueryPlan } from '@classytic/mongokit/testkit';
// The connection must be opened with { monitorCommands: true }.
await assertQueryPlan(() => repo.getAll({ filters: { status: 'open' }, sort: { at: -1 } }), {
  connection, minDocs: 1_000, leadingKeys: ['status', 'at'],   // fails on COLLSCAN / unindexed SORT
});
```

默认读取有门; 通过 `commands: ['findAndModify', 'update', 'delete']` 写得也一样. `explainCommands(run, { connection, commands?, collections?, verbosity? })` 返回每个字的原始解释 命令 `run` 为插件构建的查询,例如: `leasePlugin` 索赔:

```ts
import { explainCommands } from '@classytic/mongokit/testkit';
const { explains } = await explainCommands(() => jobs.lease({ leaseFor: 30_000, leasedBy }), {
  connection, commands: ['findAndModify'], collections: ['jobs'],
});
explains[0].explain.executionStats; // what the claim examined
```

## 内核配合—— `@classytic/mongokit/kernel-conformance`

一个 **可执行合同套件** 用于构建于 `defineModels()`内核 按描述 ^ 捆绑 → 校验 → 服务 → 关闭寿命周期电线进行自身测试 目录; 传送它符合.

它声称普通内核测试没有做到的: `defineX(shape)` 没有登记,那 `bind` 准确登记SUPPLIED连接上申报的模型,不执行索引 I/O,第二个捆绑扔 `ModelCollisionError`,即提供主机的事件运输 从来没有关闭 当一个内部创建的 `close()` 有天分,没有遗产 `createX`编号 :`destroy`编号 :`dispose` 表面幸存,一个失败的索引同步REJECS 而不是被吞没.

**试跑者注射,从未导入** ——mongokit不需依赖(甚至不需依赖) 在vitest上可选的对等点),套房运行在任何暴露的跑道下无修改 `describe`编号 :`it`请求是内部的,所以没有 `expect` 需要执行.

```ts
import mongoose from 'mongoose';
import { describe, it } from 'vitest';
import { describeKernelConformance } from '@classytic/mongokit/kernel-conformance';
import * as kernel from '../../src/index.js';

describeKernelConformance({
  name: 'party',
  runner: { describe, it },
  // A FACTORY — purity is only observable if the suite can call defineX itself.
  blueprint: () => kernel.defineParty({ multiTenant: false, autoIndex: false }),
  // Never connected: every check is registry-level, so no server is needed.
  connect: async () => mongoose.createConnection(),
  bind: (bp, conn, ctx) => bp.bind(conn, { eventTransport: ctx.transport }),
  expectedModelNames: ['Party'],
  moduleExports: kernel,
  // Opt-outs are explicit, typed, and REQUIRE a reason; each one still emits a
  // visible `[SKIPPED] <id> — <reason>` test. A silent skip is the bug this suite exists
  // to prevent.
  skip: [{ check: 'bind-verifies-requirements', reason: '…' }],
});
```

### 硬化准备: `tenantUniques`

MongoDB 拒绝 `shardCollection` 任何独一无二的指数都缺少这个键作为它的 前缀,所以一个全球独有的索引使得一个收藏被租户无法硬化. 供应 `tenantUniques` 启用 `unique-indexes-tenant-prefixed`: 套房将内核绑起 租借权,阅读每个注册的计划指数,并要求每个独特的指数与 租户田地,或 `allowGlobal` 说明理由和处理时间 部署被硬化或被分解为舱(`shard-key-prefix`, (中文(简体) ), `identity-registry`, (中文(简体) ), `pod-local` 或者说 `drop`) (中文(简体) ). 当没有检查过独特的指数时,它也失败了 `allowGlobal` 输入.

```ts
tenantUniques: {
  tenantField: 'organizationId',
  bindScoped: (conn) => kernel.defineParty({ tenant: { enabled: true }, autoIndex: false }).bind(conn, runtime),
  allowGlobal: [{ index: 'party_site_slug', reason: 'public slug, no tenant', t2: 'identity-registry' }],
},
```

检查 ID 导出为 `KERNEL_CONFORMANCE_CHECKS` 联合国 `const` tu,所以 `skip` 是输入的 union —— 错误的 id 是编译错误,而不是无效的跳过.

## 许可证

麻省理工学院

## 商标

密码是麻省理工学院许可的. **"classytic","arc",并标志为: 经典专卖局长** 并且现在 **没有** 根据麻省理工学院颁发的许可证——见 [贸易商](https://npmcn.com/package/%40classytic/mongokit/TRADEMARK.md)。 。 。 . 叉子必须更名;许可证覆盖了代码,而不是品牌.

## 常见问题

### @classytic/mongokit 是什么？

生产级MongoDB寄存器 - 智能发卡,事件和插件\. 建于@classytic/repo-core上\.

### 如何安装 @classytic/mongokit？

在项目目录运行 npm install @classytic/mongokit，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：mongoose（\>=9\.12\.0）、@classytic/repo-core（\>=0\.38\.0）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @classytic/mongokit 支持 TypeScript 吗？

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

### @classytic/mongokit 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @classytic/mongokit 需要什么版本的 Node\.js？

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

### @classytic/mongokit 可以商用吗？

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

### @classytic/mongokit 的下载量有多少？

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

### @classytic/mongokit 还在维护吗？

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

