@steve02081504/fount-p2p 0.0.3 → 0.0.5

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.
Files changed (57) hide show
  1. package/README.md +1 -1
  2. package/core/bytes_codec.mjs +0 -27
  3. package/core/constants.mjs +0 -31
  4. package/core/hexIds.mjs +0 -13
  5. package/{entity → core}/logical_entity.mjs +2 -1
  6. package/crypto/key.mjs +14 -15
  7. package/dag/index.mjs +0 -73
  8. package/dag/storage.mjs +0 -22
  9. package/federation/entity_key_chain.mjs +0 -9
  10. package/federation/topo_order_memo.mjs +0 -15
  11. package/{entity/files → files}/acl.mjs +3 -3
  12. package/files/assemble.mjs +55 -39
  13. package/files/assemble_stream.mjs +96 -44
  14. package/files/chunk_provider_registry.mjs +0 -6
  15. package/files/chunk_store.mjs +1 -11
  16. package/{entity/files → files}/evfs.mjs +81 -55
  17. package/{entity/files → files}/evfs_ref.mjs +3 -5
  18. package/files/manifest.mjs +11 -2
  19. package/{entity/files → files}/manifest_acl_registry.mjs +4 -10
  20. package/files/manifest_fetch.mjs +2 -2
  21. package/files/public_manifest.mjs +1 -1
  22. package/files/transfer_key.mjs +12 -6
  23. package/files/transfer_key_registry.mjs +0 -7
  24. package/governance/branch.mjs +0 -11
  25. package/link/channel_mux.mjs +2 -0
  26. package/mailbox/importance.mjs +0 -33
  27. package/mailbox/settings.mjs +0 -9
  28. package/node/denylist.mjs +0 -24
  29. package/node/identity.mjs +33 -2
  30. package/node/network.mjs +0 -51
  31. package/node/personal_block.mjs +1 -36
  32. package/node/reputation_store.mjs +0 -9
  33. package/node/retention_policy.mjs +0 -15
  34. package/package.json +1 -3
  35. package/registries/event_type.mjs +0 -12
  36. package/registries/inbound.mjs +0 -22
  37. package/reputation/engine.mjs +0 -11
  38. package/schemas/part_query.mjs +156 -0
  39. package/transport/ice_servers.mjs +0 -8
  40. package/transport/peer_identity_maps.mjs +0 -58
  41. package/transport/remote_user_room.mjs +0 -12
  42. package/transport/rtc_connection_budget.mjs +2 -0
  43. package/transport/user_room.mjs +2 -11
  44. package/trust_graph/cache.mjs +0 -13
  45. package/trust_graph/engine.mjs +0 -24
  46. package/utils/async_mutex.mjs +0 -9
  47. package/wire/part_fanout.mjs +0 -19
  48. package/wire/part_query.mjs +487 -0
  49. package/wire/part_query.tunables.json +14 -0
  50. package/wire/part_query_cache.mjs +94 -0
  51. package/entity/files/replica_host_cache.mjs +0 -46
  52. package/entity/hosting_registry.mjs +0 -47
  53. package/entity/logical_entity_id_registry.mjs +0 -40
  54. package/entity/node_hash.mjs +0 -15
  55. package/entity/replica.mjs +0 -20
  56. package/entity/session_snapshot_registry.mjs +0 -38
  57. package/registries/p2p_viewer.mjs +0 -35
@@ -0,0 +1,94 @@
1
+ import { sha256Hex } from '../crypto/crypto.mjs'
2
+ import { normalizePartQueryCacheMaterial } from '../schemas/part_query.mjs'
3
+ import { createLruMap } from '../utils/lru.mjs'
4
+
5
+ import partQueryTunables from './part_query.tunables.json' with { type: 'json' }
6
+
7
+ /**
8
+ * @typedef {{ rows: unknown[], storedAt: number }} PartQueryCacheEntry
9
+ */
10
+
11
+ /**
12
+ * @param {string} partpath part 路径
13
+ * @param {string} kind 查询标签
14
+ * @param {unknown} query 不透明查询
15
+ * @returns {string | null} sha256 hex 缓存键
16
+ */
17
+ export function partQueryCacheKey(partpath, kind, query) {
18
+ const material = normalizePartQueryCacheMaterial(partpath, kind, query)
19
+ if (!material) return null
20
+ return sha256Hex(material)
21
+ }
22
+
23
+ /**
24
+ * LRU + TTL 中继缓存(未验证线索;发起端仍需验签复核)。
25
+ */
26
+ export function createPartQueryCache(options = {}) {
27
+ const maxKeys = Math.max(1, Math.floor(Number(options.maxKeys) || partQueryTunables.cacheMaxKeys))
28
+ const ttlMs = Math.max(1, Math.floor(Number(options.ttlMs) || partQueryTunables.cacheTtlMs))
29
+ const maxHits = Math.max(1, Math.floor(Number(options.maxHits) || partQueryTunables.maxHits))
30
+ /** @type {ReturnType<typeof createLruMap<string, PartQueryCacheEntry>>} */
31
+ const map = createLruMap(maxKeys)
32
+
33
+ /**
34
+ * @param {number} [now=Date.now()] 当前时间
35
+ * @returns {void}
36
+ */
37
+ const sweep = (now = Date.now()) => {
38
+ for (const [key, entry] of map)
39
+ if (now - entry.storedAt >= ttlMs) map.delete(key)
40
+ }
41
+
42
+ return {
43
+ /**
44
+ * @param {string} partpath part 路径
45
+ * @param {string} kind 查询标签
46
+ * @param {unknown} query 查询体
47
+ * @param {number} [now=Date.now()] 当前时间
48
+ * @returns {unknown[] | null} 未过期 rows
49
+ */
50
+ get(partpath, kind, query, now = Date.now()) {
51
+ const key = partQueryCacheKey(partpath, kind, query)
52
+ if (!key) return null
53
+ const entry = map.get(key)
54
+ if (!entry) return null
55
+ if (now - entry.storedAt >= ttlMs) {
56
+ map.delete(key)
57
+ return null
58
+ }
59
+ map.touch(key, entry)
60
+ return entry.rows.slice()
61
+ },
62
+
63
+ /**
64
+ * @param {string} partpath part 路径
65
+ * @param {string} kind 查询标签
66
+ * @param {unknown} query 查询体
67
+ * @param {unknown[]} rows 聚合 rows
68
+ * @param {number} [now=Date.now()] 当前时间
69
+ * @returns {void}
70
+ */
71
+ set(partpath, kind, query, rows, now = Date.now()) {
72
+ const key = partQueryCacheKey(partpath, kind, query)
73
+ if (!key || !Array.isArray(rows)) return
74
+ sweep(now)
75
+ map.touch(key, {
76
+ rows: rows.slice(0, maxHits),
77
+ storedAt: now,
78
+ })
79
+ },
80
+
81
+ /** @returns {void} */
82
+ clear() {
83
+ map.clear()
84
+ },
85
+
86
+ /** @returns {number} 当前条目数 */
87
+ get size() {
88
+ return map.size
89
+ },
90
+ }
91
+ }
92
+
93
+ /** 进程内默认中继缓存 */
94
+ export const partQueryCache = createPartQueryCache()
@@ -1,46 +0,0 @@
1
- import { getEntityStore } from '../../node/instance.mjs'
2
-
3
- /** @type {Map<string, { replica: string | null, at: number }>} */
4
- const replicaHostCache = new Map()
5
-
6
- const REPLICA_HOST_CACHE_MS = 60_000
7
-
8
- /**
9
- * @param {string | string[]} [entityHash] owner(单个或批量)
10
- * @returns {void}
11
- */
12
- export function invalidateReplicaHostCache(entityHash) {
13
- if (Array.isArray(entityHash)) {
14
- for (const eh of entityHash)
15
- replicaHostCache.delete(String(eh).trim().toLowerCase())
16
- return
17
- }
18
- if (entityHash) {
19
- replicaHostCache.delete(String(entityHash).trim().toLowerCase())
20
- return
21
- }
22
- replicaHostCache.clear()
23
- }
24
-
25
- /**
26
- * @param {string} ownerEntityHash 所有者
27
- * @returns {Promise<string | null>} 托管 manifest 的 replica
28
- */
29
- export async function findReplicaHostingEntityFiles(ownerEntityHash) {
30
- const eh = String(ownerEntityHash).trim().toLowerCase()
31
- const cached = replicaHostCache.get(eh)
32
- if (cached && Date.now() - cached.at < REPLICA_HOST_CACHE_MS)
33
- return cached.replica
34
-
35
- const store = getEntityStore()
36
- if (typeof store.findHostingUser === 'function') {
37
- const replica = await store.findHostingUser(eh)
38
- replicaHostCache.set(eh, { replica, at: Date.now() })
39
- return replica
40
- }
41
-
42
- const files = await store.listEntityFiles(eh)
43
- const replica = files.length ? '__node__' : null
44
- replicaHostCache.set(eh, { replica, at: Date.now() })
45
- return replica
46
- }
@@ -1,47 +0,0 @@
1
- /** @type {((username: string, entityHash: string) => string | null) | null} */
2
- let resolveAgentCharPartName = null
3
-
4
- /** @type {((username: string) => { entityHash: string, charPartName: string }[]) | null} */
5
- let listLocalAgents = null
6
-
7
- /**
8
- * Chat Load 时注册:解析本地 agent 的 chars 目录名。
9
- * @param {(username: string, entityHash: string) => string | null} resolver 解析函数
10
- * @returns {void}
11
- */
12
- export function registerAgentCharResolver(resolver) {
13
- resolveAgentCharPartName = resolver
14
- }
15
-
16
- /**
17
- * Chat Load 时注册:枚举 replica 下本地 agent 实体。
18
- * @param {(username: string) => { entityHash: string, charPartName: string }[]} provider 枚举函数
19
- * @returns {void}
20
- */
21
- export function registerListLocalAgentsProvider(provider) {
22
- listLocalAgents = provider
23
- }
24
-
25
- /** @returns {void} */
26
- export function unregisterAgentCharResolver() {
27
- resolveAgentCharPartName = null
28
- }
29
-
30
- /** @returns {void} */
31
- export function unregisterListLocalAgentsProvider() {
32
- listLocalAgents = null
33
- }
34
-
35
- /**
36
- * @returns {((username: string, entityHash: string) => string | null) | null} 已注册解析器
37
- */
38
- export function getAgentCharResolver() {
39
- return resolveAgentCharPartName
40
- }
41
-
42
- /**
43
- * @returns {((username: string) => { entityHash: string, charPartName: string }[]) | null} 已注册枚举器
44
- */
45
- export function getListLocalAgentsProvider() {
46
- return listLocalAgents
47
- }
@@ -1,40 +0,0 @@
1
- /** @type {Map<string, (username: string, entityHash: string) => Promise<string | null>>} */
2
- const resolversByOwner = new Map()
3
-
4
- /**
5
- * @param {string} ownerId 注册方
6
- * @param {(username: string, entityHash: string) => Promise<string | null>} resolver logical entity id 反查
7
- * @returns {void}
8
- */
9
- export function registerLogicalEntityIdResolver(ownerId, resolver) {
10
- resolversByOwner.set(String(ownerId), resolver)
11
- }
12
-
13
- /**
14
- * @param {string} ownerId 注册方
15
- * @returns {void}
16
- */
17
- export function unregisterLogicalEntityIdResolver(ownerId) {
18
- resolversByOwner.delete(String(ownerId))
19
- }
20
-
21
- /** @returns {void} */
22
- export function clearLogicalEntityIdRegistry() {
23
- resolversByOwner.clear()
24
- }
25
-
26
- /**
27
- * @param {string} username 副本用户名
28
- * @param {string} entityHash 128 位十六进制 logical entity
29
- * @returns {Promise<string | null>} 逻辑实体 id
30
- */
31
- export async function resolveLogicalEntityId(username, entityHash) {
32
- for (const resolver of resolversByOwner.values())
33
- try {
34
- const id = await resolver(username, entityHash)
35
- if (id) return id
36
- }
37
- catch { /* next */ }
38
-
39
- return null
40
- }
@@ -1,15 +0,0 @@
1
- import { Buffer } from 'node:buffer'
2
-
3
- import { keyPairFromSeed, pubKeyHash } from '../crypto/crypto.mjs'
4
-
5
- /**
6
- * 由持久化 nodeSeed 派生 nodeHash(64 hex)。
7
- * @param {string} seedHex 32 字节 hex
8
- * @returns {string} 节点哈希
9
- */
10
- export function nodeHashFromSeed(seedHex) {
11
- const seed = Buffer.from(String(seedHex).trim(), 'hex')
12
- if (seed.length !== 32) throw new Error('invalid node seed')
13
- const { publicKey } = keyPairFromSeed(seed)
14
- return pubKeyHash(publicKey)
15
- }
@@ -1,20 +0,0 @@
1
- import { parseEntityHash } from '../core/entity_id.mjs'
2
- import { entityHashFromKeys, getNodeHash } from '../node/identity.mjs'
3
-
4
- /**
5
- * @param {string} recoveryPubKeyHex 64 位十六进制 recovery 公钥
6
- * @returns {string | null} 本节点 entityHash
7
- */
8
- export function resolveLocalEntityHashFromRecoveryPubKeyHex(recoveryPubKeyHex) {
9
- return entityHashFromKeys(getNodeHash(), recoveryPubKeyHex)
10
- }
11
-
12
- /**
13
- * @param {string} entityHash 目标 entityHash
14
- * @returns {boolean} 是否为本节点可写实体
15
- */
16
- export function isWritableLocalEntity(entityHash) {
17
- const parsed = parseEntityHash(entityHash)
18
- if (!parsed) return false
19
- return parsed.nodeHash === getNodeHash()
20
- }
@@ -1,38 +0,0 @@
1
- /** @type {Map<string, (replicaUsername: string, groupId: string) => Promise<object | null>>} */
2
- const providersByOwner = new Map()
3
-
4
- /**
5
- * @param {string} ownerId 注册方
6
- * @param {(replicaUsername: string, groupId: string) => Promise<object | null>} provider 物化会话
7
- * @returns {void}
8
- */
9
- export function registerMaterializedSessionProvider(ownerId, provider) {
10
- providersByOwner.set(String(ownerId), provider)
11
- }
12
-
13
- /**
14
- * @param {string} ownerId 注册方
15
- * @returns {void}
16
- */
17
- export function unregisterMaterializedSessionProvider(ownerId) {
18
- providersByOwner.delete(String(ownerId))
19
- }
20
-
21
- /**
22
- * @param {string} replicaUsername 副本用户名
23
- * @param {string} groupId 群 ID
24
- * @param {string} [ownerId] 注册方 id;省略时遍历所有 provider
25
- * @returns {Promise<object | null>} 物化会话
26
- */
27
- export async function getMaterializedSession(replicaUsername, groupId, ownerId) {
28
- if (ownerId != null) {
29
- const provider = providersByOwner.get(String(ownerId))
30
- if (!provider) return null
31
- return provider(replicaUsername, groupId)
32
- }
33
- for (const provider of providersByOwner.values()) {
34
- const session = await provider(replicaUsername, groupId)
35
- if (session) return session
36
- }
37
- return null
38
- }
@@ -1,35 +0,0 @@
1
- /** @type {Map<string, (replicaUsername: string, groupId: string) => Promise<string>>} */
2
- const groupMemberEntityByOwner = new Map()
3
-
4
- /**
5
- * @param {string} ownerId 注册方
6
- * @param {(replicaUsername: string, groupId: string) => Promise<string>} resolver 群成员 entityHash
7
- * @returns {void}
8
- */
9
- export function registerGroupMemberEntityResolver(ownerId, resolver) {
10
- groupMemberEntityByOwner.set(String(ownerId), resolver)
11
- }
12
-
13
- /**
14
- * @param {string} ownerId 注册方
15
- * @returns {void}
16
- */
17
- export function unregisterGroupMemberEntityResolver(ownerId) {
18
- groupMemberEntityByOwner.delete(String(ownerId))
19
- }
20
-
21
- /**
22
- * @param {string} replicaUsername 副本用户名
23
- * @param {string} groupId 群 ID
24
- * @returns {Promise<string | null>} entityHash;无注册方时 null
25
- */
26
- export async function resolveGroupMemberEntityHash(replicaUsername, groupId) {
27
- for (const resolver of groupMemberEntityByOwner.values())
28
- try {
29
- const eh = await resolver(replicaUsername, groupId)
30
- if (eh) return eh
31
- }
32
- catch { /* next */ }
33
-
34
- return null
35
- }