@jixo/opendweb-client-sdk 0.1.0 → 0.2.0

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.
Binary file
package/index.d.ts CHANGED
@@ -1,9 +1,30 @@
1
- export interface FabricEventJs {
2
- type: 'peer-connected' | 'peer-disconnected' | 'roster-updated' | 'message' | 'path-changed'
3
- endpointId?: string
4
- from?: string
5
- data?: Buffer
6
- status?: 'direct' | 'relay' | 'unknown'
1
+ /** 事件判别联合:relay-* 事件必携带完整快照 payload(非可选) */
2
+ /** 代理策略:none=直连;from-env=读环境代理;url 形态仅 SDK 使用 */
3
+ export type HttpProxyOptions = 'none' | 'from-env' | { url: string }
4
+
5
+ /** 从 SDK 错误消息的 [<kebab-code>] 前缀派生稳定错误码(SCREAMING_SNAKE);无前缀返回 null */
6
+ export declare function deriveErrorCode(message: string): string | null
7
+
8
+ export type FabricEventJs =
9
+ | {
10
+ type: 'peer-connected' | 'peer-disconnected'
11
+ endpointId: string
12
+ }
13
+ | { type: 'roster-updated' }
14
+ | { type: 'message'; from: string; data: Buffer }
15
+ | { type: 'path-changed'; endpointId: string; status: 'direct' | 'relay' | 'unknown' }
16
+ | { type: 'relay-online' | 'relay-offline'; relay: RelayStatusJs }
17
+
18
+ /** relay 状态快照(relayStatus() 返回值与 relay-* 事件 payload 同构) */
19
+ export interface RelayStatusJs {
20
+ /** 字面量联合(非 string) */
21
+ mode: 'disabled' | 'custom' | 'n0'
22
+ /** 配置的 relay URL 列表(disabled 为空数组;n0 恒为 ["https://relay.iroh.network"]) */
23
+ urls: string[]
24
+ /** null <=> mode === "disabled";否则为任一 relay 已连接 */
25
+ online: boolean | null
26
+ /** 最近一次连接错误类别(脱敏:无凭证段;无错误为 null) */
27
+ lastError: string | null
7
28
  }
8
29
 
9
30
  /* auto-generated by NAPI-RS */
@@ -19,7 +40,11 @@ export declare class Fabric {
19
40
  static open(opts: FabricOptions, secret?: SecretSeedHandle | undefined | null): Promise<Fabric>
20
41
  /** 以加入者身份起步(空名册;随后调用 join 兑换邀请)。 */
21
42
  static attach(opts: FabricOptions, fabricIdHex: string, secret?: SecretSeedHandle | undefined | null): Promise<Fabric>
22
- /** 一步加入:从令牌解析 fabric_id,attach + 兑换 + 持久化名册。 */
43
+ /**
44
+ * 一步加入:从令牌解析 fabric_id,attach + 兑换 + 持久化名册。
45
+ * 令牌前置检查(解码/过期/地址规范化)先于本地数据面加载与身份句柄消费
46
+ * (D11 冻结顺序:令牌自身错误优先于目录检查)。
47
+ */
23
48
  static joinWithToken(opts: FabricOptions, token: string, secret?: SecretSeedHandle | undefined | null): Promise<Fabric>
24
49
  /** 本节点 EndpointId(z-base-32,52 字符) */
25
50
  get endpointId(): string
@@ -29,8 +54,12 @@ export declare class Fabric {
29
54
  members(): Promise<Array<Member>>
30
55
  /** 查询 EndpointId 是否为有效成员 */
31
56
  isMember(endpointId: string): Promise<boolean>
32
- /** 签发邀请令牌(root-only)。返回 dweb1. 前缀的自包含字符串。 */
33
- invite(ttlMs: number, recipient?: string | undefined | null): Promise<string>
57
+ /**
58
+ * 签发邀请令牌(root-only)。返回 dweb1. 前缀的自包含字符串。
59
+ * 第三参 opts 透传签发安全门逃生阀:relay 为空且 advertiseAddrs 为空时,
60
+ * 无 opts 或 allowRelayless !== true => reject([invite-without-relay])。
61
+ */
62
+ invite(ttlMs: number, recipient?: string | undefined | null, opts?: InviteOptions | undefined | null): Promise<string>
34
63
  /** 兑换邀请令牌加入 fabric(issuer-online 单次兑换)。 */
35
64
  join(token: string): Promise<void>
36
65
  /** 连接成员(常规通道;双向门控 + 名册同步)。幂等(活跃连接直接成功)。 */
@@ -45,6 +74,11 @@ export declare class Fabric {
45
74
  setDisplayName(name: string): Promise<void>
46
75
  /** 查询与某成员的当前路径类型:"direct" | "relay" | "unknown" */
47
76
  linkStatus(endpointId: string): Promise<string>
77
+ /**
78
+ * relay 状态快照(零等待,读内核缓存)。快照优先于事件:初始事实一律先查
79
+ * 本方法,事件只承载后续跳变。禁用模式 online 为 null(而非 false)。
80
+ */
81
+ relayStatus(): Promise<RelayStatusJs>
48
82
  /**
49
83
  * 显式导出身份(identity export,不含 roster)为 `dwebkey1.` 加密串。
50
84
  * 交由产品自行安全保存(如账号系统加密托管——密文上云、口令在用户)。
@@ -52,9 +86,11 @@ export declare class Fabric {
52
86
  exportSecretPassphrase(passphrase: string): Promise<string>
53
87
  /**
54
88
  * 注册事件回调(可多次调用,多个回调都会收到全部事件)。
55
- * 事件对象见 FabricEventJs:{ type, endpointId?, from?, data?, status? }
89
+ * 返回句柄 id;off(id) 注销(index.js 包装为取消订阅函数)。
56
90
  */
57
- on(callback: (event: FabricEventJs) => void): void
91
+ on(callback: (event: FabricEventJs) => void): () => void
92
+ /** 注销事件回调(on 返回的 id)。 */
93
+ off(id: number): void
58
94
  /** 优雅关闭:断开全部会话并释放网络资源。幂等。 */
59
95
  shutdown(): Promise<void>
60
96
  }
@@ -77,8 +113,20 @@ export interface FabricOptions {
77
113
  /** 数据目录(名册持久化位置;secret 默认实现也指向此目录) */
78
114
  dataDir: string
79
115
  relay?: RelayOptions
80
- /** 写入邀请令牌的 issuer 直连地址(host:port) */
116
+ /** 写入邀请令牌的 issuer 直连地址(host:port;逐项校验,非法构造 reject) */
81
117
  advertiseAddrs?: Array<string>
118
+ /**
119
+ * HTTP 控制面(relay 连接)代理所有权;缺省 "none"。
120
+ * iroh endpoint 不读进程环境变量;QUIC 数据面永不经代理。
121
+ */
122
+ httpProxy?: 'none' | 'from-env' | { url: string }
123
+ /** join 总时限(毫秒);缺省 30000;值域 [1000, 600000],越界构造 reject */
124
+ joinTimeoutMs?: number
125
+ }
126
+
127
+ /** httpProxy 的 `{ url }` 形态("none" | "from-env" 为字符串形态)。 */
128
+ export interface HttpProxyUrl {
129
+ url: string
82
130
  }
83
131
 
84
132
  /**
@@ -87,6 +135,12 @@ export interface FabricOptions {
87
135
  */
88
136
  export declare function importSecret(token: string, passphrase: string): Promise<SecretSeedHandle>
89
137
 
138
+ /** invite 逃生阀选项(D3)。 */
139
+ export interface InviteOptions {
140
+ /** 允许签发无 relay 令牌;调用方自担可达性责任(带外路径)。 */
141
+ allowRelayless?: boolean
142
+ }
143
+
90
144
  /** 成员信息 */
91
145
  export interface Member {
92
146
  endpointId: string
@@ -97,10 +151,8 @@ export interface Member {
97
151
  /** SDK 原生层版本 */
98
152
  export declare function nativeVersion(): string
99
153
 
100
- /** relay 配置 */
101
- export interface RelayOptions {
102
- /** "disabled" | "custom" | "n0"(默认 "n0") */
103
- mode?: string
104
- /** mode = "custom" 时的 relay URL 列表(自托管 docker 或其它 iroh relay) */
105
- urls?: Array<string>
106
- }
154
+ /** relay 配置(判别联合:非法组合构造期拒绝) */
155
+ export type RelayOptions =
156
+ | { mode?: 'n0' }
157
+ | { mode: 'disabled' }
158
+ | { mode: 'custom'; urls: [string, ...string[]] }
package/index.js CHANGED
@@ -46,10 +46,12 @@ function loadViaTmp() {
46
46
 
47
47
  const Native = loadViaTmp() ?? require(SRC);
48
48
 
49
+ // on() → 取消订阅函数:原生层返回回调 id,off(id) 注销(event_callbacks 移除句柄)。
49
50
  const nativeOn = Native.Fabric.prototype.on;
51
+ const nativeOff = Native.Fabric.prototype.off;
50
52
  Native.Fabric.prototype.on = function onWrapped(callback) {
51
53
  // 原生 TSFN 为 error-first 回调:(err, jsonString)
52
- return nativeOn.call(this, (err, json) => {
54
+ const id = nativeOn.call(this, (err, json) => {
53
55
  if (err) return;
54
56
  const ev = JSON.parse(json);
55
57
  if (typeof ev.dataBase64 === "string") {
@@ -58,6 +60,35 @@ Native.Fabric.prototype.on = function onWrapped(callback) {
58
60
  }
59
61
  callback(ev);
60
62
  });
63
+ return () => nativeOff.call(this, id);
61
64
  };
62
65
 
66
+ /**
67
+ * 从 SDK 错误消息的 [<kebab-code>] 前缀派生稳定错误码(SCREAMING_SNAKE)。
68
+ * napi Error 无自定义 code 通道——前缀约定见 contracts/error-matrix.md。
69
+ * 无前缀时返回 null(未分类的底层错误)。
70
+ */
71
+ function deriveErrorCode(message) {
72
+ if (typeof message !== "string") return null;
73
+ const m = message.match(/^\[([a-z0-9-]+)\]\s/);
74
+ if (!m) return null;
75
+ return m[1].replace(/-/g, "_").toUpperCase();
76
+ }
77
+ Native.deriveErrorCode = deriveErrorCode;
78
+
79
+ // relayStatus():napi Option::None 序列化为 undefined,契约(C0 d.ts)要求 null——
80
+ // 包装归一(事件 payload 的 relay 快照经 JSON.parse 天然是 null,无需处理)。
81
+ const nativeRelayStatus = Native.Fabric.prototype.relayStatus;
82
+ if (typeof nativeRelayStatus === "function") {
83
+ Native.Fabric.prototype.relayStatus = async function relayStatusWrapped() {
84
+ const r = await nativeRelayStatus.call(this);
85
+ return {
86
+ mode: r.mode,
87
+ urls: r.urls ?? [],
88
+ online: r.online ?? null,
89
+ lastError: r.lastError ?? null,
90
+ };
91
+ };
92
+ }
93
+
63
94
  module.exports = Native;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jixo/opendweb-client-sdk",
3
- "version": "0.1.0",
3
+ "version": "0.2.0",
4
4
  "description": "@jixo/opendweb-client-sdk — dweb application-level fabric SDK for Node (napi-rs binding)",
5
5
  "license": "MIT OR Apache-2.0",
6
6
  "main": "index.js",