@steve02081504/fount-p2p 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/link/link.mjs CHANGED
@@ -73,27 +73,27 @@ function formatErrorReason(error) {
73
73
 
74
74
  /**
75
75
  * 建立 P2P link:WebRTC 双通道、握手、分帧收发与心跳。
76
- * @param {object} opts link 配置
77
- * @param {string | null} [opts.nodeHash] 期望的对端 nodeHash,省略则不校验
78
- * @param {boolean} opts.initiator 是否为连接发起方
79
- * @param {{ send: (message: unknown) => void | Promise<void>, onRemote: (handler: (message: unknown) => void) => (() => void) | void }} opts.signal 信令收发接口
80
- * @param {RTCConfiguration['iceServers']} [opts.iceServers] ICE 服务器列表
81
- * @param {number} [opts.heartbeatMs] 心跳间隔(毫秒)
82
- * @param {number} [opts.idleTimeoutMs] 无入站流量超时(毫秒)
83
- * @param {number} [opts.handshakeTimeoutMs] 握手超时(毫秒)
84
- * @param {{ RTCPeerConnection: typeof RTCPeerConnection } | null} [opts.rtc] RTC 构造器,省略则加载 polyfill
85
- * @param {{ nodeHash?: string, nodePubKey?: string, secretKey?: Uint8Array, nonce?: string } | null} [opts.localIdentity] 本地握手身份
86
- * @returns {Promise<{ ready: Promise<void>, get nodeHash(): string | null, send: (envelope: { scope: string, action: string, payload: unknown }) => Promise<boolean>, onEnvelope: (cb: (envelope: { scope: string, action: string, payload: unknown }, remoteNodeHash: string) => void) => () => void, onDown: (cb: (reason: string) => void) => () => void, close: (reason?: string) => Promise<void>, stats: () => object }>} link 句柄
76
+ * @param {object} options link 配置
77
+ * @param {string | null} [options.nodeHash] 期望的对端 nodeHash,省略则不校验
78
+ * @param {boolean} options.initiator 是否为连接发起方
79
+ * @param {{ send: (message: unknown) => void | Promise<void>, onRemote: (handler: (message: unknown) => void) => (() => void) | void }} options.signal 信令收发接口
80
+ * @param {RTCConfiguration['iceServers']} [options.iceServers] ICE 服务器列表
81
+ * @param {number} [options.heartbeatMs] 心跳间隔(毫秒)
82
+ * @param {number} [options.idleTimeoutMs] 无入站流量超时(毫秒)
83
+ * @param {number} [options.handshakeTimeoutMs] 握手超时(毫秒)
84
+ * @param {{ RTCPeerConnection: typeof RTCPeerConnection } | null} [options.rtc] RTC 构造器,省略则加载 polyfill
85
+ * @param {{ nodeHash?: string, nodePubKey?: string, secretKey?: Uint8Array, nonce?: string } | null} [options.localIdentity] 本地握手身份
86
+ * @returns {Promise<{ ready: Promise<void>, get nodeHash(): string | null, send: (envelope: { scope: string, action: string, payload: unknown }) => Promise<boolean>, onEnvelope: (callback: (envelope: { scope: string, action: string, payload: unknown }, remoteNodeHash: string) => void) => () => void, onDown: (callback: (reason: string) => void) => () => void, close: (reason?: string) => Promise<void>, stats: () => object }>} link 句柄
87
87
  */
88
- export async function createLink(opts) {
89
- const heartbeatMs = Number(opts.heartbeatMs) || ms('15s')
90
- const idleTimeoutMs = Number(opts.idleTimeoutMs) || ms('45s')
91
- const handshakeTimeoutMs = Number(opts.handshakeTimeoutMs) || ms('10s')
88
+ export async function createLink(options) {
89
+ const heartbeatMs = Number(options.heartbeatMs) || ms('15s')
90
+ const idleTimeoutMs = Number(options.idleTimeoutMs) || ms('45s')
91
+ const handshakeTimeoutMs = Number(options.handshakeTimeoutMs) || ms('10s')
92
92
  const channelOpenTimeoutMs = Math.max(handshakeTimeoutMs, ms('30s'))
93
93
  const trickleIceOff = getSignalingRuntimeConfig().trickleIceOff === true
94
- const rtc = opts.rtc ?? await loadNodeRtcPolyfill()
95
- const pc = new rtc.RTCPeerConnection(opts.iceServers?.length ? { iceServers: opts.iceServers } : undefined)
96
- const targetNodeHash = normalizeHex64(opts.nodeHash || '')
94
+ const rtc = options.rtc ?? await loadNodeRtcPolyfill()
95
+ const pc = new rtc.RTCPeerConnection(options.iceServers?.length ? { iceServers: options.iceServers } : undefined)
96
+ const targetNodeHash = normalizeHex64(options.nodeHash || '')
97
97
  const remoteSignalQueue = []
98
98
  const seenRemoteSignals = createLruMap(1024)
99
99
  let remoteDescriptionSet = false
@@ -142,7 +142,7 @@ export async function createLink(opts) {
142
142
  * @returns {Promise<void>}
143
143
  */
144
144
  async function sendSignal(message) {
145
- await Promise.resolve(opts.signal.send(message))
145
+ await Promise.resolve(options.signal.send(message))
146
146
  }
147
147
 
148
148
  /**
@@ -185,7 +185,7 @@ export async function createLink(opts) {
185
185
  const fingerprint = localFingerprint()
186
186
  if (!fingerprint) return
187
187
  authSent = true
188
- await sendRawControl(await buildAuth(remoteHello.nonce, fingerprint, opts.localIdentity ?? {}))
188
+ await sendRawControl(await buildAuth(remoteHello.nonce, fingerprint, options.localIdentity ?? {}))
189
189
  }
190
190
 
191
191
  /**
@@ -446,7 +446,7 @@ export async function createLink(opts) {
446
446
  if (!helloSent) {
447
447
  handshakeTimer = setTimeout(() => { void close('handshake-timeout') }, handshakeTimeoutMs)
448
448
  helloSent = true
449
- localHello = buildHello(opts.localIdentity ?? {})
449
+ localHello = buildHello(options.localIdentity ?? {})
450
450
  await sendRawControl(localHello)
451
451
  }
452
452
  await maybeSendAuth()
@@ -507,7 +507,7 @@ export async function createLink(opts) {
507
507
  emitListeners(downListeners, reason)
508
508
  }
509
509
 
510
- unlistenRemote = opts.signal.onRemote(message => {
510
+ unlistenRemote = options.signal.onRemote(message => {
511
511
  void handleRemoteSignal(message).catch(error => close(`signal-error:${formatErrorReason(error)}`))
512
512
  }) ?? null
513
513
 
@@ -535,7 +535,7 @@ export async function createLink(opts) {
535
535
  }
536
536
  }
537
537
 
538
- if (opts.initiator) {
538
+ if (options.initiator) {
539
539
  await attachChannel(pc.createDataChannel(CHANNEL_CONTROL))
540
540
  await attachChannel(pc.createDataChannel(CHANNEL_BULK))
541
541
  const offer = await pc.createOffer()
@@ -559,25 +559,25 @@ export async function createLink(opts) {
559
559
  * 本端是否为连接发起方。
560
560
  * @returns {boolean} 发起方标志
561
561
  */
562
- get initiator() { return !!opts.initiator },
562
+ get initiator() { return !!options.initiator },
563
563
  send,
564
564
  /**
565
565
  * 订阅业务 envelope 入站。
566
- * @param {(envelope: { scope: string, action: string, payload: unknown }, remoteNodeHash: string) => void} cb 回调
566
+ * @param {(envelope: { scope: string, action: string, payload: unknown }, remoteNodeHash: string) => void} callback 回调
567
567
  * @returns {() => void} 取消订阅函数
568
568
  */
569
- onEnvelope(cb) {
570
- envelopeListeners.add(cb)
571
- return () => envelopeListeners.delete(cb)
569
+ onEnvelope(callback) {
570
+ envelopeListeners.add(callback)
571
+ return () => envelopeListeners.delete(callback)
572
572
  },
573
573
  /**
574
574
  * 订阅 link 断开事件。
575
- * @param {(reason: string) => void} cb 回调
575
+ * @param {(reason: string) => void} callback 回调
576
576
  * @returns {() => void} 取消订阅函数
577
577
  */
578
- onDown(cb) {
579
- downListeners.add(cb)
580
- return () => downListeners.delete(cb)
578
+ onDown(callback) {
579
+ downListeners.add(callback)
580
+ return () => downListeners.delete(callback)
581
581
  },
582
582
  close,
583
583
  /**
@@ -597,7 +597,7 @@ export async function createLink(opts) {
597
597
  ready,
598
598
  nodeHash: remoteNodeHash,
599
599
  targetNodeHash: targetNodeHash || null,
600
- initiator: !!opts.initiator,
600
+ initiator: !!options.initiator,
601
601
  connectionState: pc.connectionState,
602
602
  iceConnectionState: pc.iceConnectionState,
603
603
  lastInboundAt,
@@ -59,26 +59,26 @@ async function resolveRouting(username) {
59
59
 
60
60
  /**
61
61
  * @param {string} username 副本用户名(trust graph 投递上下文)
62
- * @param {object} opts 投递选项
62
+ * @param {object} options 投递选项
63
63
  * @returns {Promise<{ stored: boolean, delivered: boolean, relayed: number }>} 存转结果
64
64
  */
65
- export async function deliverOrStoreMailboxPut(username, opts) {
65
+ export async function deliverOrStoreMailboxPut(username, options) {
66
66
  const routing = await resolveRouting(username)
67
- const toPubKeyHash = normalizeHex64(opts.toPubKeyHash)
67
+ const toPubKeyHash = normalizeHex64(options.toPubKeyHash)
68
68
  if (!toPubKeyHash) return { stored: false, delivered: false, relayed: 0 }
69
- const hop = normalizeMailboxHop(opts.hop)
69
+ const hop = normalizeMailboxHop(options.hop)
70
70
  if (hop >= routing.maxHop) return { stored: false, delivered: false, relayed: 0 }
71
71
  const tier = mailboxTierFromHop(hop)
72
72
  const nodeHash = getNodeHash()
73
73
  const record = {
74
- ...opts.record,
74
+ ...options.record,
75
75
  toPubKeyHash,
76
76
  hop,
77
77
  tier,
78
- fromNodeHash: opts.record?.fromNodeHash || nodeHash,
78
+ fromNodeHash: options.record?.fromNodeHash || nodeHash,
79
79
  }
80
80
  const stored = await storeMailboxRecord(record)
81
- const toNodeHash = opts.toNodeHash?.trim().toLowerCase()
81
+ const toNodeHash = options.toNodeHash?.trim().toLowerCase()
82
82
  const delivered = toNodeHash && isMailboxRecordWithinSizeLimit(record)
83
83
  ? await requireTrustGraphProvider(DEFAULT_TRUST_GRAPH_OWNER).sendToNode(username, toNodeHash, 'mailbox_put', { nodeHash, record })
84
84
  : false
@@ -108,17 +108,17 @@ export async function publishMailboxRecord(username, toPubKeyHash, record, toNod
108
108
  }
109
109
 
110
110
  /**
111
- * @param {{ replicaUsername?: string }} ctx 入站上下文
111
+ * @param {{ replicaUsername?: string }} wireContext 入站上下文
112
112
  * @param {object} put 入站 mailbox_put
113
113
  * @param {string} [peerId] Trystero 对端 id(有则校验 nodeHash 绑定)
114
114
  * @returns {Promise<void>}
115
115
  */
116
- export async function ingestMailboxPut(ctx, put, peerId = '') {
116
+ export async function ingestMailboxPut(wireContext, put, peerId = '') {
117
117
  const { record } = put
118
118
  if (!record?.envelope || !record?.toPubKeyHash) return
119
119
  const fromNode = normalizeHex64(put.nodeHash)
120
120
  if (!fromNode || !takeIncomingMailboxPutSlot(fromNode)) return
121
- const username = String(ctx?.replicaUsername || '').trim()
121
+ const username = String(wireContext.replicaUsername || '').trim()
122
122
  if (!username) return
123
123
  if (peerId) {
124
124
  const remote = await resolveRemoteNodeHashForPeer(username, peerId)
@@ -157,14 +157,14 @@ export async function respondMailboxWant(want, sendGive, peerId) {
157
157
  }
158
158
 
159
159
  /**
160
- * @param {{ replicaUsername?: string }} ctx 入站上下文
160
+ * @param {{ replicaUsername?: string }} wireContext 入站上下文
161
161
  * @param {object} give mailbox_give 载荷
162
162
  * @returns {Promise<number>} 投递给消费者的记录数
163
163
  */
164
- export async function ingestMailboxGive(ctx, give) {
164
+ export async function ingestMailboxGive(wireContext, give) {
165
165
  const records = (give.records || []).filter(isDeliverableMailboxRecord)
166
166
  if (!records.length) return 0
167
- const username = String(ctx?.replicaUsername || '').trim()
167
+ const username = String(wireContext.replicaUsername || '').trim()
168
168
  if (!username) return 0
169
169
  const { dispatchMailboxRecordsToConsumers } = await import('./consumer_registry.mjs')
170
170
  const { deleteMailboxRecords } = await import('./store.mjs')
package/mailbox/wire.mjs CHANGED
@@ -10,15 +10,15 @@ import { parseMailboxGive, parseMailboxPut, parseMailboxWant } from './parse.mjs
10
10
  */
11
11
 
12
12
  /**
13
- * @param {MailboxWireContext} ctx 入站上下文
13
+ * @param {MailboxWireContext} wireContext 入站上下文
14
14
  * @param {{ on: (name: string, handler: (payload: unknown, peerId: string) => void) => void, send: (name: string, payload: unknown, peerId: string | null) => void }} wire Trystero 适配器
15
15
  * @returns {void}
16
16
  */
17
- export function attachMailboxWire(ctx, wire) {
17
+ export function attachMailboxWire(wireContext, wire) {
18
18
  wire.on('mailbox_put', (payload, peerId) => {
19
19
  const put = parseMailboxPut(payload)
20
20
  if (!put.ok) return
21
- void ingestMailboxPut(ctx, put.value, peerId).catch(err => console.error('mailbox: put ingest failed', err))
21
+ void ingestMailboxPut(wireContext, put.value, peerId).catch(err => console.error('mailbox: put ingest failed', err))
22
22
  })
23
23
 
24
24
  wire.on('mailbox_want', (payload, peerId) => {
@@ -35,6 +35,6 @@ export function attachMailboxWire(ctx, wire) {
35
35
  wire.on('mailbox_give', payload => {
36
36
  const give = parseMailboxGive(payload)
37
37
  if (!give.ok) return
38
- void ingestMailboxGive(ctx, give.value).catch(err => console.error('mailbox: give ingest failed', err))
38
+ void ingestMailboxGive(wireContext, give.value).catch(err => console.error('mailbox: give ingest failed', err))
39
39
  })
40
40
  }
@@ -26,12 +26,12 @@ import { readNodeJsonSync, writeNodeJsonSync } from './storage.mjs'
26
26
 
27
27
  const DATA_NAME = 'reputation'
28
28
 
29
- /** @type {((opts: object) => Promise<boolean>) | null} */
29
+ /** @type {((options: object) => Promise<boolean>) | null} */
30
30
  let blockReputationHandler = null
31
31
 
32
32
  /**
33
33
  * Shell Load 时注册:公开 block/unblock → 信誉传导。
34
- * @param {(opts: object) => Promise<boolean>} handler block/unblock 信誉传导回调
34
+ * @param {(options: object) => Promise<boolean>} handler block/unblock 信誉传导回调
35
35
  * @returns {void}
36
36
  */
37
37
  export function registerBlockReputationHandler(handler) {
@@ -308,10 +308,10 @@ export function pickNodeScore(nodeId) {
308
308
  }
309
309
 
310
310
  /**
311
- * @param {object} opts applyFollowedBlockSignal 参数
311
+ * @param {object} options applyFollowedBlockSignal 参数
312
312
  * @returns {Promise<boolean>} 是否已应用
313
313
  */
314
- export async function applyBlockReputationSignal(opts) {
314
+ export async function applyBlockReputationSignal(options) {
315
315
  if (!blockReputationHandler) return false
316
- return blockReputationHandler(opts)
316
+ return blockReputationHandler(options)
317
317
  }
@@ -8,16 +8,16 @@ import {
8
8
  * 在共识分支上计算须保留的事件 id(连通子图,不用拓扑下标切片)。
9
9
  * @param {string[]} order 规范拓扑序
10
10
  * @param {Map<string, object>} byId id → 事件
11
- * @param {object} opts 保留策略
12
- * @param {number} opts.maxDepth 分支上最大事件深度
13
- * @param {number} opts.cutoffWall 最早保留的 HLC wall
14
- * @param {Set<string>} opts.anchorTypes 权限锚点事件类型
15
- * @param {string | null} [opts.checkpointTipId] checkpoint 尖
16
- * @param {string | null} [opts.branchTipId] 共识分支尖
11
+ * @param {object} options 保留策略
12
+ * @param {number} options.maxDepth 分支上最大事件深度
13
+ * @param {number} options.cutoffWall 最早保留的 HLC wall
14
+ * @param {Set<string>} options.anchorTypes 权限锚点事件类型
15
+ * @param {string | null} [options.checkpointTipId] checkpoint 尖
16
+ * @param {string | null} [options.branchTipId] 共识分支尖
17
17
  * @returns {Set<string>} 保留 id
18
18
  */
19
- export function computeRetentionKeepIds(order, byId, opts) {
20
- const { maxDepth, cutoffWall, anchorTypes, checkpointTipId, branchTipId } = opts
19
+ export function computeRetentionKeepIds(order, byId, options) {
20
+ const { maxDepth, cutoffWall, anchorTypes, checkpointTipId, branchTipId } = options
21
21
  const branchOrder = authzFoldOrderIds(order, byId, branchTipId)
22
22
  const branchSet = new Set(branchOrder)
23
23
  if (!branchSet.size) return new Set()
package/overlay/index.mjs CHANGED
@@ -131,15 +131,15 @@ export function createOverlayRouter(registry, ttl = 3) {
131
131
  /**
132
132
  * 发现到目标节点的签名路由路径。
133
133
  * @param {string} targetNodeHash 目标节点 64 hex
134
- * @param {object} [opts] 选项
135
- * @param {number} [opts.ttl] 路由 TTL
136
- * @param {number} [opts.timeoutMs] 超时毫秒
134
+ * @param {object} [options] 选项
135
+ * @param {number} [options.ttl] 路由 TTL
136
+ * @param {number} [options.timeoutMs] 超时毫秒
137
137
  * @returns {Promise<string[]>} 从本节点到目标的 nodeHash 路径
138
138
  */
139
- async discoverRoute(targetNodeHash, opts = {}) {
139
+ async discoverRoute(targetNodeHash, options = {}) {
140
140
  const reqId = randomMsgIdHex()
141
- const maxTtl = Number(opts.ttl) || ttl
142
- const timeoutMs = Number(opts.timeoutMs) || 10_000
141
+ const maxTtl = Number(options.ttl) || ttl
142
+ const timeoutMs = Number(options.timeoutMs) || 10_000
143
143
  const promise = new Promise((resolve, reject) => {
144
144
  const timer = setTimeout(() => {
145
145
  pendingRoutes.delete(reqId)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@steve02081504/fount-p2p",
3
- "version": "0.0.5",
3
+ "version": "0.0.6",
4
4
  "description": "fount federation P2P layer — link, trust graph, mailbox, DAG, EVFS.",
5
5
  "keywords": [
6
6
  "network",
@@ -10,11 +10,11 @@
10
10
  */
11
11
 
12
12
  /**
13
- * @typedef {(ctx: InboundContext, message: object) => Promise<PartInvokeResponse | null>} RpcInboundHandler
13
+ * @typedef {(inboundContext: InboundContext, message: object) => Promise<PartInvokeResponse | null>} RpcInboundHandler
14
14
  */
15
15
 
16
16
  /**
17
- * @typedef {(ctx: InboundContext, message: object) => Promise<void>} DeliveryInboundHandler
17
+ * @typedef {(inboundContext: InboundContext, message: object) => Promise<void>} DeliveryInboundHandler
18
18
  */
19
19
 
20
20
  /** @type {Map<string, RpcInboundHandler>} */
@@ -42,27 +42,27 @@ export function registerDeliveryInboundHandler(type, handler) {
42
42
  }
43
43
 
44
44
  /**
45
- * @param {InboundContext} ctx 入站上下文
45
+ * @param {InboundContext} inboundContext 入站上下文
46
46
  * @param {object} message 已校验的线载荷(含 type)
47
47
  * @returns {Promise<PartInvokeResponse | null>} 处理器返回值
48
48
  */
49
- export async function dispatchRpcInbound(ctx, message) {
49
+ export async function dispatchRpcInbound(inboundContext, message) {
50
50
  const type = String(message?.type || '').trim()
51
51
  if (!type) return null
52
52
  const handler = rpcHandlers.get(type)
53
53
  if (!handler) return null
54
- return handler(ctx, message)
54
+ return handler(inboundContext, message)
55
55
  }
56
56
 
57
57
  /**
58
- * @param {InboundContext} ctx 入站上下文
58
+ * @param {InboundContext} inboundContext 入站上下文
59
59
  * @param {object} message 已校验的线载荷(含 type)
60
60
  * @returns {Promise<void>}
61
61
  */
62
- export async function dispatchDeliveryInbound(ctx, message) {
62
+ export async function dispatchDeliveryInbound(inboundContext, message) {
63
63
  const type = String(message?.type || '').trim()
64
64
  if (!type) return
65
65
  const handler = deliveryHandlers.get(type)
66
66
  if (!handler) return
67
- await handler(ctx, message)
67
+ await handler(inboundContext, message)
68
68
  }
@@ -9,17 +9,17 @@ import {
9
9
 
10
10
  /**
11
11
  * 在指定 scope 与 roomSecret 下创建 link 层房间(discovery + registry 转发)。
12
- * @param {object} opts 房间选项
13
- * @param {string} opts.scope link registry scope(如 `group:{id}`)
14
- * @param {string} opts.roomSecret 房间 rendezvous 密钥
15
- * @param {(nodeHash: string) => boolean} [opts.allowNode] 是否允许与某 nodeHash 通信
16
- * @returns {{ start: () => Promise<void>, leave: () => Promise<void>, makeAction: (name: string) => [(payload: unknown, peerId?: string | string[] | null) => Promise<void>, (handler: (payload: unknown, peerId: string) => void) => void], onPeerJoin: (cb: (peerId: string) => void) => () => void, onPeerLeave: (cb: (peerId: string) => void) => () => void, getPeers: () => Record<string, true> }} 房间句柄
12
+ * @param {object} options 房间选项
13
+ * @param {string} options.scope link registry scope(如 `group:{id}`)
14
+ * @param {string} options.roomSecret 房间 rendezvous 密钥
15
+ * @param {(nodeHash: string) => boolean} [options.allowNode] 是否允许与某 nodeHash 通信
16
+ * @returns {{ start: () => Promise<void>, leave: () => Promise<void>, makeAction: (name: string) => [(payload: unknown, peerId?: string | string[] | null) => Promise<void>, (handler: (payload: unknown, peerId: string) => void) => void], onPeerJoin: (callback: (peerId: string) => void) => () => void, onPeerLeave: (callback: (peerId: string) => void) => () => void, getPeers: () => Record<string, true> }} 房间句柄
17
17
  */
18
- export function createScopedLinkRoom(opts) {
18
+ export function createScopedLinkRoom(options) {
19
19
  const registry = getLinkRegistry()
20
- const scope = String(opts.scope)
21
- const topic = groupRendezvousTopic(opts.roomSecret)
22
- const allowNode = typeof opts.allowNode === 'function' ? opts.allowNode : () => true
20
+ const scope = String(options.scope)
21
+ const topic = groupRendezvousTopic(options.roomSecret)
22
+ const allowNode = typeof options.allowNode === 'function' ? options.allowNode : () => true
23
23
  /** @type {Set<string>} */
24
24
  const discoveredPeers = new Set()
25
25
  /** @type {Set<string>} */
@@ -156,24 +156,24 @@ export function createScopedLinkRoom(opts) {
156
156
  ]
157
157
  },
158
158
  /**
159
- * @param {(peerId: string) => void} cb 新 peer 上线回调
159
+ * @param {(peerId: string) => void} callback 新 peer 上线回调
160
160
  * @returns {() => void} 取消订阅
161
161
  */
162
- onPeerJoin(cb) {
163
- joinListeners.add(cb)
162
+ onPeerJoin(callback) {
163
+ joinListeners.add(callback)
164
164
  for (const peerId of activePeerIds())
165
165
  announcedPeers.add(peerId)
166
166
  for (const peerId of announcedPeers)
167
- try { cb(peerId) } catch { /* ignore */ }
168
- return () => joinListeners.delete(cb)
167
+ try { callback(peerId) } catch { /* ignore */ }
168
+ return () => joinListeners.delete(callback)
169
169
  },
170
170
  /**
171
- * @param {(peerId: string) => void} cb peer 离线回调
171
+ * @param {(peerId: string) => void} callback peer 离线回调
172
172
  * @returns {() => void} 取消订阅
173
173
  */
174
- onPeerLeave(cb) {
175
- leaveListeners.add(cb)
176
- return () => leaveListeners.delete(cb)
174
+ onPeerLeave(callback) {
175
+ leaveListeners.add(callback)
176
+ return () => leaveListeners.delete(callback)
177
177
  },
178
178
  /**
179
179
  * @returns {Record<string, true>} 当前活跃 peer 的 nodeHash 集合
@@ -14,17 +14,17 @@ import { computeDagTipIdsFromEvents } from '../governance/branch.mjs'
14
14
  * 为追加事件计算 HLC 与 DAG 前驱(chat 群与 social 时间线共用)。
15
15
  * @param {object[]} previous 已有事件
16
16
  * @param {object} event 待追加事件
17
- * @param {{ multiTip?: boolean }} [opts] chat 在多 tip 时连接全部 tip
17
+ * @param {{ multiTip?: boolean }} [options] chat 在多 tip 时连接全部 tip
18
18
  * @returns {{ hlc: object, prev_event_ids: string[], last: object | undefined }} HLC、前驱与末条事件
19
19
  */
20
- export function computeAppendHlcAndPrev(previous, event, opts = {}) {
20
+ export function computeAppendHlcAndPrev(previous, event, options = {}) {
21
21
  const last = previous[previous.length - 1]
22
22
  const hlc = nextHlc(last?.hlc, event.timestamp ?? Date.now())
23
23
  const tips = computeDagTipIdsFromEvents(previous)
24
24
  let prev_event_ids
25
25
  if (event.prev_event_ids?.length)
26
26
  prev_event_ids = sortedPrevEventIds(event.prev_event_ids)
27
- else if (opts.multiTip && tips.length > 1)
27
+ else if (options.multiTip && tips.length > 1)
28
28
  prev_event_ids = sortedPrevEventIds(tips)
29
29
  else if (tips.length)
30
30
  prev_event_ids = sortedPrevEventIds(tips)
@@ -14,22 +14,22 @@ import { resolveFederationPoolLimits, selectLinkTargetsFromMembers } from './pee
14
14
 
15
15
  /**
16
16
  * 创建基于 link registry 的群组联邦房间。
17
- * @param {object} opts 选项
18
- * @param {string} opts.groupId 群组 id
19
- * @param {string} opts.roomSecret 房间密钥(用于 rendezvous topic)
20
- * @param {string[]} opts.members 初始成员 nodeHash 列表
21
- * @param {object} [opts.groupSettings] 群设置(连接预算:trustedPeerSlots/explorePeerSlots/maxPeers 等)
22
- * @returns {{ groupId: string, scope: string, start: () => Promise<void>, leave: () => Promise<void>, getRoster: () => Array<{ peerId: string, remoteNodeHash: string }>, getPeerIdByNodeHash: (nodeHash: string) => string | null, sendToPeer: (peerId: string, actionName: string, payload: unknown) => Promise<boolean>, send: (actionName: string, payload: unknown, peerId?: string | null) => Promise<number>, onEnvelope: (cb: (senderNodeHash: string, envelope: object) => void) => () => void, onPeerJoin: (cb: (peerId: string) => void) => () => void, onPeerLeave: (cb: (peerId: string) => void) => () => void, getPeers: () => Record<string, true>, makeAction: (name: string) => [(payload: unknown, peerId?: string | string[] | null) => Promise<void>, (handler: (payload: unknown, peerId: string) => void) => void], registerCleanup: (fn: () => void) => void, isActive: () => boolean }} 群组 link set 接口
17
+ * @param {object} options 选项
18
+ * @param {string} options.groupId 群组 id
19
+ * @param {string} options.roomSecret 房间密钥(用于 rendezvous topic)
20
+ * @param {string[]} options.members 初始成员 nodeHash 列表
21
+ * @param {object} [options.groupSettings] 群设置(连接预算:trustedPeerSlots/explorePeerSlots/maxPeers 等)
22
+ * @returns {{ groupId: string, scope: string, start: () => Promise<void>, leave: () => Promise<void>, getRoster: () => Array<{ peerId: string, remoteNodeHash: string }>, getPeerIdByNodeHash: (nodeHash: string) => string | null, sendToPeer: (peerId: string, actionName: string, payload: unknown) => Promise<boolean>, send: (actionName: string, payload: unknown, peerId?: string | null) => Promise<number>, onEnvelope: (callback: (senderNodeHash: string, envelope: object) => void) => () => void, onPeerJoin: (callback: (peerId: string) => void) => () => void, onPeerLeave: (callback: (peerId: string) => void) => () => void, getPeers: () => Record<string, true>, makeAction: (name: string) => [(payload: unknown, peerId?: string | string[] | null) => Promise<void>, (handler: (payload: unknown, peerId: string) => void) => void], registerCleanup: (cleanup: () => void) => void, isActive: () => boolean }} 群组 link set 接口
23
23
  */
24
- export function createGroupLinkSet(opts) {
25
- const registry = opts.registry ?? getLinkRegistry()
26
- const autoconnect = opts.autoconnect !== false
27
- const groupId = String(opts.groupId)
24
+ export function createGroupLinkSet(options) {
25
+ const registry = options.registry ?? getLinkRegistry()
26
+ const autoconnect = options.autoconnect !== false
27
+ const groupId = String(options.groupId)
28
28
  const scope = `group:${groupId}`
29
- const topic = groupRendezvousTopic(opts.roomSecret)
30
- const members = new Set((Array.isArray(opts.members) ? opts.members : []).map(String))
29
+ const topic = groupRendezvousTopic(options.roomSecret)
30
+ const members = new Set((Array.isArray(options.members) ? options.members : []).map(String))
31
31
  const selfNodeHash = registry.localIdentity.nodeHash
32
- const groupSettings = opts.groupSettings ?? {}
32
+ const groupSettings = options.groupSettings ?? {}
33
33
  // 初始成员是调用方明确知道的引导集合(如 introducer/creator/seed),作为必连锚点保证引导期连通。
34
34
  const initialAnchors = new Set(members)
35
35
  /** @type {ReturnType<typeof setTimeout> | null} */
@@ -50,12 +50,12 @@ export function createGroupLinkSet(opts) {
50
50
 
51
51
  /**
52
52
  * 注册 leave 时执行的清理回调。
53
- * @param {() => void} fn 清理函数
53
+ * @param {() => void} cleanup 清理函数
54
54
  * @returns {void}
55
55
  */
56
- function registerCleanup(fn) {
57
- if (typeof fn !== 'function') return
58
- cleanups.add(fn)
56
+ function registerCleanup(cleanup) {
57
+ if (typeof cleanup !== 'function') return
58
+ cleanups.add(cleanup)
59
59
  }
60
60
 
61
61
  /**
@@ -255,34 +255,34 @@ export function createGroupLinkSet(opts) {
255
255
  },
256
256
  /**
257
257
  * 订阅入站 envelope。
258
- * @param {(senderNodeHash: string, envelope: object) => void} cb 回调
258
+ * @param {(senderNodeHash: string, envelope: object) => void} callback 回调
259
259
  * @returns {() => void} 取消订阅函数
260
260
  */
261
- onEnvelope(cb) {
262
- envelopeListeners.add(cb)
263
- return () => envelopeListeners.delete(cb)
261
+ onEnvelope(callback) {
262
+ envelopeListeners.add(callback)
263
+ return () => envelopeListeners.delete(callback)
264
264
  },
265
265
  /**
266
266
  * 订阅 peer 加入事件(含当前已在线 peer 的即时回调)。
267
- * @param {(peerId: string) => void} cb 回调
267
+ * @param {(peerId: string) => void} callback 回调
268
268
  * @returns {() => void} 取消订阅函数
269
269
  */
270
- onPeerJoin(cb) {
271
- peerJoinListeners.add(cb)
270
+ onPeerJoin(callback) {
271
+ peerJoinListeners.add(callback)
272
272
  for (const { peerId } of activeRoster())
273
273
  if (peerId) announcedPeers.add(peerId)
274
274
  for (const peerId of announcedPeers)
275
- try { cb(peerId) } catch { /* ignore */ }
276
- return () => peerJoinListeners.delete(cb)
275
+ try { callback(peerId) } catch { /* ignore */ }
276
+ return () => peerJoinListeners.delete(callback)
277
277
  },
278
278
  /**
279
279
  * 订阅 peer 离开事件。
280
- * @param {(peerId: string) => void} cb 回调
280
+ * @param {(peerId: string) => void} callback 回调
281
281
  * @returns {() => void} 取消订阅函数
282
282
  */
283
- onPeerLeave(cb) {
284
- peerLeaveListeners.add(cb)
285
- return () => peerLeaveListeners.delete(cb)
283
+ onPeerLeave(callback) {
284
+ peerLeaveListeners.add(callback)
285
+ return () => peerLeaveListeners.delete(callback)
286
286
  },
287
287
  /**
288
288
  * 返回当前在线 peer 的 Record 映射。
@@ -187,20 +187,20 @@ function subscribeBucket(buckets, key, listener) {
187
187
 
188
188
  /**
189
189
  * 创建 P2P 链路注册表(discovery、信令、直连与 overlay relay)。
190
- * @param {object} [opts] 选项
191
- * @param {{ nodeHash?: string, nodePubKey?: string, secretKey?: Uint8Array }} [opts.localIdentity] 本地身份
192
- * @param {typeof createLink} [opts.createLink] 链路工厂(可注入 mock)
193
- * @param {RTCConfiguration['iceServers']} [opts.iceServers] ICE 服务器列表
194
- * @param {number} [opts.maxActive] 最大并发活跃链路数
195
- * @param {boolean} [opts.autoRegisterDiscoveryProviders] 是否自动注册 discovery provider
190
+ * @param {object} [options] 选项
191
+ * @param {{ nodeHash?: string, nodePubKey?: string, secretKey?: Uint8Array }} [options.localIdentity] 本地身份
192
+ * @param {typeof createLink} [options.createLink] 链路工厂(可注入 mock)
193
+ * @param {RTCConfiguration['iceServers']} [options.iceServers] ICE 服务器列表
194
+ * @param {number} [options.maxActive] 最大并发活跃链路数
195
+ * @param {boolean} [options.autoRegisterDiscoveryProviders] 是否自动注册 discovery provider
196
196
  * @returns {object} link registry 接口
197
197
  */
198
- export function createLinkRegistry(opts = {}) {
199
- const localIdentity = resolveLocalIdentity(opts.localIdentity)
200
- const createLinkImpl = opts.createLink ?? createLink
201
- const iceServers = opts.iceServers?.length ? opts.iceServers : DEFAULT_ICE_SERVERS
202
- const maxActive = Math.max(4, Number(opts.maxActive) || 32)
203
- const autoRegisterDiscoveryProviders = opts.autoRegisterDiscoveryProviders !== false
198
+ export function createLinkRegistry(options = {}) {
199
+ const localIdentity = resolveLocalIdentity(options.localIdentity)
200
+ const createLinkImpl = options.createLink ?? createLink
201
+ const iceServers = options.iceServers?.length ? options.iceServers : DEFAULT_ICE_SERVERS
202
+ const maxActive = Math.max(4, Number(options.maxActive) || 32)
203
+ const autoRegisterDiscoveryProviders = options.autoRegisterDiscoveryProviders !== false
204
204
  const selfTopic = nodeRendezvousTopic(localIdentity.nodeHash)
205
205
  /** @type {Map<string, Awaited<ReturnType<typeof createLinkImpl>>>} */
206
206
  const links = new Map()
@@ -348,7 +348,7 @@ export function createLinkRegistry(opts = {}) {
348
348
  /**
349
349
  * 为一条 connId 会话建 PC 并走 glare 择一:建 link → 绑 onDown 清 session → ready → registerResolvedLink。
350
350
  * initiator 侧建链前先 trimToBudget 腾预算。出错则清理该 connId 会话。
351
- * @param {{ remoteNodeHash: string, connId: string, session: ReturnType<typeof createBufferedSignalSession>, initiator: boolean }} opts 建链参数
351
+ * @param {{ remoteNodeHash: string, connId: string, session: ReturnType<typeof createBufferedSignalSession>, initiator: boolean }} options 建链参数
352
352
  * @returns {Promise<Awaited<ReturnType<typeof createLinkImpl>> | null>} 当前规范链(本条可能因 glare 被关,取 links 现值);失败 null
353
353
  */
354
354
  async function buildConnLink({ remoteNodeHash, connId, session, initiator }) {
@@ -141,7 +141,7 @@ export function selectExploreWithSourceQuota(exploreIds, exploreSources, k, maxP
141
141
  * selfNodeHash: string,
142
142
  * inRoomNodeHashes?: Set<string> | string[] 群内在线 node_id;有则优先,仅全不可达时用 explore 中非房内节点
143
143
  * hintSources?: Map<string, string> explore 节点来源(用于配额)
144
- * }} opts 选取参数(roster、peers、rep、limits、selfNodeHash)
144
+ * }} options 选取参数(roster、peers、rep、limits、selfNodeHash)
145
145
  * @returns {string[]} 目标 Trystero peerId 列表(去重,长度 ≤ maxPeers)
146
146
  */
147
147
  export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash, inRoomNodeHashes, hintSources }) {
@@ -212,7 +212,7 @@ export function selectPeerIdsFromPool({ roster, peers, rep, limits, selfNodeHash
212
212
  * peers: { trustedPeers: string[], explorePeers: string[], blockedPeers: string[], hintSources?: Map<string, string> },
213
213
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
214
214
  * anchors?: Iterable<string>,
215
- * }} opts 选取参数(members、selfNodeHash、rep、peers、limits、anchors)
215
+ * }} options 选取参数(members、selfNodeHash、rep、peers、limits、anchors)
216
216
  * @returns {string[]} 应建链的 nodeHash 列表(去重)
217
217
  */
218
218
  export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers, limits, anchors = [] }) {
@@ -245,7 +245,7 @@ export function selectLinkTargetsFromMembers({ members, selfNodeHash, rep, peers
245
245
  * rep: { byNodeHash?: Record<string, { score?: number }> },
246
246
  * hints: string[],
247
247
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
248
- * }} opts 合并参数(peers、rep、hints、limits)
248
+ * }} options 合并参数(peers、rep、hints、limits)
249
249
  * @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
250
250
  */
251
251
  export function applyPexHints({ peers, rep, hints, limits }) {
@@ -275,7 +275,7 @@ export function applyPexHints({ peers, rep, hints, limits }) {
275
275
  * rep: { byNodeHash?: Record<string, { score?: number }> },
276
276
  * roster: Array<{ remoteNodeHash?: string }>,
277
277
  * limits: ReturnType<typeof resolveFederationPoolLimits>,
278
- * }} opts roster 更新参数(peers、rep、roster、limits)
278
+ * }} options roster 更新参数(peers、rep、roster、limits)
279
279
  * @returns {{ trustedPeers: string[], explorePeers: string[] }} 更新后的 trusted/explore 列表
280
280
  */
281
281
  export function applyRosterToPeerPool({ peers, rep, roster, limits }) {