@nxgt/janus-mongo

中文文档
0.13.0发布于 2026/11/02MITTypeScriptES Module零依赖

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

中文使用文档
文档目录7 节
  1. 安装
  2. API
  3. 数据库保存了什么
  4. 陷阱
  5. 文档
  6. 类型安全,计数
  7. 执照

@nxgt / janus-mongo

的MongoDB适配器 @nxgt/janus:其身份存储- 用户、会话和一次性令牌——的关系存储 @nxgt/janus/permissions,以及在一个数据库上的可选API密钥存储 @nxgt/mongo.

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

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 });

安装

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中读取的文档读起来就像代码中的记录。

集合索引
usersloginUnique 在 { type, logins }唯一-登录是唯一的 每个用户类型 · typeId 在 { type, _id } 对于清单
sessionstokenHashUnique · 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 这是从主键中读出的 驱动程序的默认值:

    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. 升级 有台阶。

  • 升级到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. 注册和其他每一个写通过,没有文件重写。 同步指南 请听详细报道。

  • 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 +飞行符。

文档

  • 指南 -连接商店,同步收藏品
  • 故障排除 -通过您看到的错误消息
  • 路线图 -下一步是什么,什么是没有计划的

类型安全,计数

编译器拒绝了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 共发布 41 个版本,首次发布于 2026/09/24;过去 12 个月发布了 41 个版本。

版本发布日期距今
0.13.0latest2026/11/021 天前
0.12.02026/11/021 天前
0.11.42026/10/304 天前
0.11.32026/10/276 天前
0.11.22026/10/276 天前
0.11.12026/10/276 天前

关于 @nxgt/janus-mongo 的常见问题

@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 和提交记录判断。