# @nxgt/janus-mongo 中文文档

规范地址：https://npmcn.com/package/%40nxgt/janus-mongo/

版本：0\.13\.0
npm 元数据更新时间：2026-11-02T00:55:46.596Z
中文译文更新时间：2026-11-02T02:16:13.830Z
软件包许可：MIT

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

原始 npm 页面：https://www.npmjs.com/package/%40nxgt/janus-mongo
原文对照：https://npmcn.com/package/%40nxgt/janus-mongo/?lang=original
源码仓库：https://github.com/softistx/nxgt-janus

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

- 包体积（解压后）：176 kB，42 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- 运行依赖：0 个
- peer 依赖：zod \>=4\.6\.5 \<5，mongodb \>=7\.0\.0 \<8，typescript ^6\.0\.3 \|\| ^7\.0\.0，@nxgt/janus ^0\.36\.0，@nxgt/mongo \>=0\.17\.0 \<1
- 首次发布：2026-09-24T10:44:37.811Z
- 最新版本发布：2026-11-02T00:55:46.425Z
- 已发布版本数：41（近 12 个月 41 个）

## 中文简介

用于@nxgt/janus的MongoDB适配器：用户、会话、一次性令牌和权限元组

## 安装

```sh
npm install @nxgt/janus-mongo
```

也可以使用：`pnpm add @nxgt/janus-mongo`、`yarn add @nxgt/janus-mongo`、`bun add @nxgt/janus-mongo`

## README

# @nxgt / janus-mongo

的MongoDB适配器 [`@nxgt/janus`](https://www.npmjs.com/package/@nxgt/janus)：其身份存储- 用户、会话和一次性令牌——的关系存储 `@nxgt/janus/permissions`，以及在一个数据库上的可选API密钥存储 [`@nxgt/mongo`](https://www.npmjs.com/package/@nxgt/mongo).

两者都通过了 `@nxgt/janus/conformance` 套房对一个真正的mongod，停电 包括在内。 `createMongoAdapter(db)` 给出双方的名字 `janus()` 拿起它们，一个人把它们散开；每个也可以单独使用，如 `@nxgt/janus`： `createMongoStores` 的身份, `createMongoRelations` 用于 权限。

```ts
import { janus, scryptHasher } from '@nxgt/janus';
import { permissions } from '@nxgt/janus/permissions';
import { createMongoAdapter, syncMongoAdapter } from '@nxgt/janus-mongo';

await syncMongoAdapter(db); // a deployment step: creates the collections and indexes (API keys: syncMongoApiKeys, apart)

const mongo = createMongoAdapter(db); // { store, relations }

export const auth = janus({
  user: User,
  password: { login: 'email' },
  hasher: scryptHasher(),
  ...mongo, // deleting a user deletes their tuples too
});

export const access = permissions({ model, store: mongo.relations });
```

## 安装

```sh
bun add @nxgt/janus-mongo @nxgt/janus @nxgt/mongo mongodb zod
bun add -d typescript
```

每个peer都是必需的： `@nxgt/janus`， `@nxgt/mongo` （`>=0.17.0 <1`)， `mongodb` (7), `zod` (4.6.5或更高版本，其中 `@nxgt/mongo` 用)和定义集合 `typescript` （6或7）。 `@nxgt/janus` 是一个 **同行**这个包定义了no 错误类并抛出对等方自己的类，所以 `instanceof StoreFailure` 适用于 你的代码。喜欢它，这个包期望 `"moduleResolution": "bundler"`: 声明导入时不需要扩展，所以 `nodenext` 不支持。

这个 `@nxgt/mongo` 地板是经过测试的，而不是声明的：包的规格和它的 运行类型检查 `@nxgt/mongo` 在每个CI上的Floors作业中也是0.17.0 运行。

## API

| 出口 | 它是什么？ |
| --- | --- |
| `createMongoAdapter(db)` | `{ store, relations }`：下面两个，键值为 `janus()` 带走他们，所以 `janus({ …, ...mongo })` 电线。没有任何连接。 |
| `syncMongoAdapter(db, options?)` | `syncMongoStores` 和 `syncMongoRelations` 在一个步骤：四个集合。它不会创造 `apiKeys`. `syncAll(db)` 的 `@nxgt/mongo` 创建 **五个** （`users`， `sessions`， `tokens`， `relations` 和 `apiKeys`)，因为导入包时会注册所有五个定义。 |
| `MongoAdapter` | 什么类型 `createMongoAdapter` 的答案。 |
| `createMongoStores(db)` | 这个 `{ users, sessions, tokens }` 那 `janus()` 需要为 `store`． 没有任何连接。实现可选的 `users.findUsers`,所以 `auth.<type>.findMany(ids)` 是一个 `$in` 查询。 |
| `syncMongoStores(db, options?)` | 创建三个集合、它们的验证器和索引，并回答它所改变的内容。需要 `dbAdmin`;在部署时运行它，而不是每个请求都运行它。 |
| `users`， `sessions`， `tokens` | 这个 `@nxgt/mongo` 定义。定义它们注册它们 `syncAll(db)` 将它们与您自己的集合同步。 |
| `janusCollections` | 这三个定义，按同步顺序排列。 |
| `createMongoRelations(db)` | 这个 `RelationStore` 那 `permissions()` 需要为 `store`, `janus()` 作为 `relations`． 没有任何连接。 |
| `syncMongoRelations(db, options?)` | 创建 `relations` 集合及其索引。另一个步骤：单独使用标识的应用程序不保留元组。 |
| `relations` | 它的 `@nxgt/mongo` 定义。 |
| `createMongoApiKeys(db)` | 这个 `ApiKeyStore` 的 `@nxgt/janus`'可选API密钥端口。选择加入，所以它不是 `createMongoAdapter`． 没有任何连接。 |
| `syncMongoApiKeys(db, options?)` | 创建 `apiKeys` 集合及其索引。一个单独的步骤，比如 `syncMongoRelations`： `syncMongoAdapter` 不运行它。 |
| `apiKeys` | 它的 `@nxgt/mongo` 定义。导入包注册它，所以 `syncAll(db)` 创建它。 |

## 数据库保存了什么

港口的记录，id在 `_id` 没有其他东西被重新命名或 编码。在shell中读取的文档读起来就像代码中的记录。

| 集合 | 索引 |
| --- | --- |
| `users` | `loginUnique` 在 `{ type, logins }`唯一-登录是唯一的 **每个用户类型** · `typeId` 在 `{ type, _id }` 对于清单 |
| `sessions` | `tokenHashUnique` · `userId` · `expiry`， TTL索引 |
| `tokens` | `_id` 令牌的哈希值是· `userId` · `expiry`， TTL索引 |
| `relations` | `_id` **是元组**， `{ object: { type, id }, relation, subject: { type, id, relation? } }` -结构独特· `objectRelation` 向前一跳 `subjectObjects` 用于 `findObjects`，它提供的服务没有内存排序（测量：为10个页面检查11个键）。 |
| `apiKeys` | `_id` 密钥的id是· `userId` 在 `{ userId, _id }`，用于列出用户的键 `expiry`一个TTL索引，每30天删除一个键 **后** `expiresAt` （grace将失效的键保留为“过期”列表） |

没有秘密存储：会话和令牌保留 `sha256` 这个秘密， 密码是自描述散列，也是用户的散列 `secondFactor.secret` 一个你觉得 秘密 `@nxgt/janus` 已经用你的申请钥匙封好了吗 `v1.<key id>.…` -存储以字节为单位保存。它的 `secondFactor.recoveryCodes` 恢复代码的关键散列，从来没有 代码，保持有序；没有字段的因子读为没有。

`countAttempt` 对代码的尝试计数为一次 `findOneAndUpdate` 与 `$inc`，因此，同时进行的20次尝试回答了20种不同的计数。 `spendUserTokens` 是一个 `updateMany` 在 `{ userId, kind, spentAt: null }` - - - - - - 和 `_id: { $ne: except }` 当 `except` 给出- 通过索引 `deleteUserTokens` 已经读取：它花费的每个令牌是 在一个步骤中完成匹配和书写，所以这是一种快速的救赎，而不是两者兼而有之 花同样的钱。

## 陷阱

-   **阅读原文。** `@nxgt/janus` 看每一个 在它完成之前写：一个登录重新读取用户以捕获一个 在运行时写入密码。一个 `db` 谁的客户机从辅助服务器读取数据 （`readPreference: 'secondaryPreferred'`)错过了，写，和 登录成功。把适配器递给我 `db` 这是从主键中读出的 驱动程序的默认值：
    
    ```ts
    import { MongoClient } from 'mongodb';
    
    const client = new MongoClient(url); // readPreference 'primary' by default
    const adapter = createMongoAdapter(client.db('app'));
    ```
    
-   **升级到0.3：在部署之前运行同步。** 没有文件 重写-用户没有 `secondFactor` 读取为none，这是一个标记 没有 `codeHash` 和 `attempts` 作为 `null` 和 `0` -但是验证器 先前的同步写入拒绝新字段。直到 `syncMongoAdapter(db)` 有 运行，每次注册和一次性令牌都会失败 `STORE_FAILED`， 引起的 `Document failed validation`. [升级](https://npmcn.com/package/%40nxgt/janus-mongo/docs/guide/sync.md#upgrading-sync-before-you-deploy) 有台阶。
    
-   **升级到0.5：再次在部署之前运行同步。** 没有文件 重写-第二个因素没有 `recoveryCodes` 读起来好像没有- 但是前一个同步写入的验证器拒绝新字段。直到 `syncMongoAdapter(db)` 已经跑了，每次写第二个因素—— `enroll`， `activate`，一个确认的代码-失败 `STORE_FAILED`，由…引起 `Document failed validation`． 并在用户等待之前完成rollout 恢复代码：仍处于0.4状态的实例将未写入的因子写回来 当它接受代码时。
    
-   **升级到0.6：再次在部署前运行同步。** 这个 令牌类型 `stepUp` 是新的，又是 `kind` 枚举上一个同步写入的内容 拒绝：直到 `syncMongoAdapter(db)` 跑了吗，每一个升级请求 失败与 `STORE_FAILED`，由…引起 `Document failed validation`． 否 文档被重写。
    
-   **升级到0.7：出于同样的原因，再次进行同步。** 象征性的 `magicLink` - - - - - - `@nxgt/janus` 0.15的登录链接-是新的：直到同步 跑过了，每一次 `magicLink.request` 失败与 `STORE_FAILED`，由…引起 `Document failed validation`． 不重写文档。
    
-   **升级到0.9：出于同样的原因，再次进行同步。** 象征性的 `changeEmail` - - - - - - `@nxgt/janus` 0.23的链接到一个新的地址-是新的：直到 同步已运行，此类令牌的第一次写入失败 `STORE_FAILED`，由…引起 `Document failed validation`． 没有文件 重写。
    
-   **升级到0.10：在部署之前运行同步。** 这个 `avatar` 槽, `@nxgt/janus` 0.29的-是新的，严格的验证器之前的同步 写了拒绝它：直到 `syncMongoAdapter(db)` 跑了，只写那一套 化身失败，与 `STORE_FAILED`，由…引起 `Document failed validation`. 注册和其他每一个写通过，没有文件重写。 [同步指南](https://npmcn.com/package/%40nxgt/janus-mongo/docs/guide/sync.md) 请听详细报道。
    
-   **TTL索引是存储卫生，而不是过期。** MongoDB的TTL监视器 每60秒运行一次，因此失效的会话最多可以在60秒内保持可读 分钟。核心比较 `expiresAt` 每读一次，就会过期 它。
    
-   **`auth.collectExpired()` 答案 `UNSUPPORTED`** 用这个适配器。的TTL 索引已经删除了失效的会话和令牌，所以 `deleteExpiredSessions` 和 `deleteExpiredTokens` 都是故意不实现的。
    
-   **没有为您调用同步函数** - - - - - - `syncMongoAdapter`，或者 `syncMongoStores` 对于恒等式。核心从不管理模式。 没有它，就没有唯一索引，也没有什么可以阻止两个并发注册 只需一次登录。
    
-   **在登录索引以外的索引上的重复键是 `StoreFailure`,而不是 `LOGIN_TAKEN`.** 这样的重复是一个适配器错误，并且 将其报告为被占用的登录将告诉某人他们的电子邮件正在使用 事实并非如此。
    
-   **一个以上元组的关系写入是一个事务**， MongoDB运行 仅在副本集上执行事务。 `grant` 和 `revoke` 写一个元组和 到处运行;在独立的mongod上，多元写入失败 `STORE_FAILED`． 交易不会重试：是司机的 `withTransaction` 在回答之前，将重试停机两分钟，并且写入是 幂等的，所以自己再试一次。
    
-   **`findObjects` 订单id作为MongoDB，通过UTF-8字节。** `list()` 排序 它自己收集，所以它的页面不依赖于它；一个打电话的人 store直接看到字节顺序，这与JavaScript不同 `<` 只有过去 U +飞行符。
    

## 文档

-   [指南](https://npmcn.com/package/%40nxgt/janus-mongo/docs/README.md) -连接商店，同步收藏品
-   [故障排除](https://npmcn.com/package/%40nxgt/janus-mongo/docs/troubleshooting.md) -通过您看到的错误消息
-   [路线图](https://npmcn.com/package/%40nxgt/janus-mongo/docs/roadmap.md) -下一步是什么，什么是没有计划的

## 类型安全，计数

编译器拒绝了11个貌似合理的错误，每个错误都有一个 `@ts-expect-error` 在 `test/types/adapter.ts`：

-   连接字符串而不是数据库；
-   `@nxgt/mongo`的连接，而不是它的 `db`, `createMongoAdapter`；
-   司机的 `MongoClient` 而不是它的一个数据库；
-   `@nxgt/mongo`的连接，而不是它的 `db`, `syncMongoAdapter`；
-   同样的， `syncMongoRelations`；
-   承诺 `connectMongo` 没有等待的答案；
-   错误情况下的同步选项： `dryrun` 用于 `dryRun`；
-   整个适配器为 `janus()`的 `store`，而不是传播；
-   关系存储为 `janus()`的 `store`；
-   整个适配器为 `permissions()`的 `store`，而不是 `mongo.relations`；
-   标识存储为 `permissions()`的 `store`.

## 执照

麻省理工学院

## 常见问题

### @nxgt/janus-mongo 是什么？

用于@nxgt/janus的MongoDB适配器：用户、会话、一次性令牌和权限元组

### 如何安装 @nxgt/janus-mongo？

在项目目录运行 npm install @nxgt/janus-mongo，或使用 pnpm add / yarn add / bun add。它还需要宿主项目提供 peer 依赖：zod（\>=4\.6\.5 \<5）、mongodb（\>=7\.0\.0 \<8）、typescript（^6\.0\.3 \|\| ^7\.0\.0）、@nxgt/janus（^0\.36\.0）、@nxgt/mongo（\>=0\.17\.0 \<1）。npm 7 及以上与 pnpm 8 及以上默认会自动安装必需的 peer 依赖，Yarn 需要手动安装。

### @nxgt/janus-mongo 支持 TypeScript 吗？

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

### @nxgt/janus-mongo 支持 ESM 还是 CommonJS？

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

### @nxgt/janus-mongo 可以商用吗？

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

### @nxgt/janus-mongo 还在维护吗？

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

