@yeying-community/web3-bs 1.0.6 → 1.0.7
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/README.md +107 -106
- package/dist/auth/central.d.ts +1 -0
- package/dist/dapp.d.ts +8 -0
- package/dist/web3-bs.esm.js +107 -14
- package/dist/web3-bs.esm.js.map +1 -1
- package/dist/web3-bs.umd.js +109 -13
- package/dist/web3-bs.umd.js.map +1 -1
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -1,15 +1,14 @@
|
|
|
1
1
|
# YeYing Browser DApp Access SDK
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
它优先面向 EIP-1193 / EIP-6963 钱包生态,可对接 YeYing、MetaMask 等浏览器钱包;也可对接能暴露 EIP-1193 能力的 App 钱包或中心化认证服务。仅支持浏览器环境(依赖 `window` / `localStorage` / `fetch`)。
|
|
3
|
+
`web3-bs` 是浏览器端 DApp 接入 SDK,用于统一封装:
|
|
5
4
|
|
|
6
|
-
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
|
|
12
|
-
|
|
5
|
+
- 钱包连接(EIP-1193 / EIP-6963)
|
|
6
|
+
- SIWE challenge 登录与 JWT 鉴权请求
|
|
7
|
+
- UCAN 多后端授权(钱包 UCAN RPC 优先,失败可回退本地 Ed25519 session)
|
|
8
|
+
- 中心化 UCAN 发行服务接入
|
|
9
|
+
- WebDAV 文件访问与应用目录初始化
|
|
10
|
+
|
|
11
|
+
仅支持浏览器环境(依赖 `window` / `localStorage` / `fetch`)。
|
|
13
12
|
|
|
14
13
|
## 安装
|
|
15
14
|
|
|
@@ -17,82 +16,112 @@
|
|
|
17
16
|
npm install @yeying-community/web3-bs
|
|
18
17
|
```
|
|
19
18
|
|
|
20
|
-
|
|
21
|
-
推荐先读:
|
|
22
|
-
- `docs/README.md`
|
|
23
|
-
- `docs/positioning.md`
|
|
24
|
-
- `docs/quickstart.md`
|
|
25
|
-
- `docs/capability-matrix.md`
|
|
19
|
+
## 能力概览
|
|
26
20
|
|
|
27
|
-
|
|
21
|
+
### 1) Provider 与账户
|
|
28
22
|
|
|
29
|
-
-
|
|
30
|
-
-
|
|
31
|
-
-
|
|
23
|
+
- `getProvider` / `requireProvider`
|
|
24
|
+
- `requestAccounts` / `getAccounts` / `getPreferredAccount` / `watchAccounts`
|
|
25
|
+
- `getChainId` / `getBalance`
|
|
26
|
+
- `onAccountsChanged` / `onChainChanged`
|
|
32
27
|
|
|
33
|
-
|
|
28
|
+
### 2) SIWE + JWT
|
|
34
29
|
|
|
35
|
-
|
|
30
|
+
- `signMessage`
|
|
31
|
+
- `loginWithChallenge`
|
|
32
|
+
- `authFetch`
|
|
33
|
+
- `refreshAccessToken`
|
|
34
|
+
- `logout`
|
|
35
|
+
- `getAccessToken` / `setAccessToken` / `clearAccessToken`
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
- Frontend Mobile Central UCAN Demo: `examples/frontend/mobile-central-ucan.html`
|
|
39
|
-
- Frontend Dapp (TS module): `examples/frontend/main.ts`
|
|
40
|
-
- Backend server (Node): `examples/backend/node/server.js`
|
|
41
|
-
- Backend server (Go): `examples/backend/go/main.go`
|
|
42
|
-
- Backend server (Python): `examples/backend/python/app.py`
|
|
43
|
-
- Backend server (Java): `examples/backend/java/src/main/java/com/yeying/demo/AuthServer.java`
|
|
37
|
+
### 3) UCAN(钱包优先 + 本地回退)
|
|
44
38
|
|
|
45
|
-
|
|
39
|
+
- `createUcanSession` / `getUcanSession`
|
|
40
|
+
- `getOrCreateUcanRoot` / `createRootUcan`
|
|
41
|
+
- `createDelegationUcan` / `createInvocationUcan`
|
|
42
|
+
- `authUcanFetch`
|
|
43
|
+
- `normalizeUcanCapabilities`
|
|
46
44
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
4. 访问:`http://127.0.0.1:8001/examples/frontend/dapp.html`
|
|
51
|
-
5. 确保安装 YeYing 钱包扩展插件
|
|
52
|
-
6. 点击:`Detect Provider` → `Connect Wallet` → `Login`
|
|
45
|
+
说明:
|
|
46
|
+
- 能调用 `yeying_ucan_session` / `yeying_ucan_sign` 时,优先用钱包侧 UCAN session 签名。
|
|
47
|
+
- 不支持上述钱包 RPC 时,SDK 会回退到浏览器本地 Ed25519 session(IndexedDB 持久化)。
|
|
53
48
|
|
|
54
|
-
|
|
55
|
-
`COOKIE_SAMESITE=none` 且 `COOKIE_SECURE=true` 并使用 HTTPS,
|
|
56
|
-
以便 `refresh_token` Cookie 能随 `credentials: 'include'` 发送。
|
|
49
|
+
### 4) 中心化 UCAN
|
|
57
50
|
|
|
58
|
-
|
|
51
|
+
- `getCentralIssuerInfo`
|
|
52
|
+
- `createCentralSession`
|
|
53
|
+
- `issueCentralUcan`
|
|
54
|
+
- `createAndIssueCentralUcan`
|
|
55
|
+
- `authCentralUcanFetch`
|
|
56
|
+
- `getCentralSessionToken` / `setCentralSessionToken` / `clearCentralSessionToken`
|
|
59
57
|
|
|
60
|
-
|
|
61
|
-
`./scripts/backend.sh <start|stop|restart|status> <node|go|python|java|all> [--setup] [--no-stop]`
|
|
58
|
+
### 5) WebDAV 与 DApp 会话编排
|
|
62
59
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
60
|
+
- `createWebDavClient`
|
|
61
|
+
- `initWebDavStorage`(自动生成/复用 WebDAV Invocation UCAN,可自动创建应用目录)
|
|
62
|
+
- `initDappSession`(SIWE 登录 + WebDAV UCAN 初始化)
|
|
63
|
+
- `deriveAppIdFromLocation` / `deriveAppIdFromHost`
|
|
67
64
|
|
|
68
|
-
|
|
69
|
-
./scripts/backend.sh start go --setup
|
|
65
|
+
## 常见接入方式
|
|
70
66
|
|
|
71
|
-
|
|
72
|
-
./scripts/backend.sh status all
|
|
67
|
+
### 单后端登录(SIWE + JWT)
|
|
73
68
|
|
|
74
|
-
|
|
75
|
-
|
|
69
|
+
```ts
|
|
70
|
+
import { loginWithChallenge, authFetch } from '@yeying-community/web3-bs';
|
|
76
71
|
|
|
77
|
-
|
|
78
|
-
|
|
72
|
+
await loginWithChallenge({
|
|
73
|
+
baseUrl: 'http://localhost:3203/api/v1/public/auth',
|
|
74
|
+
storeToken: false,
|
|
75
|
+
});
|
|
79
76
|
|
|
80
|
-
|
|
81
|
-
|
|
77
|
+
const res = await authFetch(
|
|
78
|
+
'http://localhost:3203/api/v1/public/profile',
|
|
79
|
+
{ method: 'GET' },
|
|
80
|
+
{ baseUrl: 'http://localhost:3203/api/v1/public/auth', storeToken: false }
|
|
81
|
+
);
|
|
82
82
|
```
|
|
83
83
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
84
|
+
### 多后端 UCAN + WebDAV
|
|
85
|
+
|
|
86
|
+
```ts
|
|
87
|
+
import { initWebDavStorage, deriveAppIdFromLocation } from '@yeying-community/web3-bs';
|
|
88
|
+
|
|
89
|
+
const appId = deriveAppIdFromLocation(window.location) || 'localhost-8001';
|
|
90
|
+
const webdav = await initWebDavStorage({
|
|
91
|
+
baseUrl: 'http://localhost:6065',
|
|
92
|
+
audience: 'did:web:localhost:6065',
|
|
93
|
+
appId,
|
|
94
|
+
capabilities: [{ with: `app:all:${appId}`, can: 'write' }],
|
|
95
|
+
});
|
|
96
|
+
|
|
97
|
+
await webdav.client.upload(`${webdav.appDir}/hello.txt`, 'Hello WebDAV');
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
## Demo
|
|
101
|
+
|
|
102
|
+
- 前端 Demo(双 Tab:单后端 SIWE / 多后端 UCAN+WebDAV):
|
|
103
|
+
`examples/frontend/dapp.html`
|
|
104
|
+
- 前端 TS 示例:`examples/frontend/main.ts`
|
|
105
|
+
- 多语言后端示例:
|
|
106
|
+
- Node: `examples/backend/node/server.js`
|
|
107
|
+
- Go: `examples/backend/go/main.go`
|
|
108
|
+
- Java: `examples/backend/java/src/main/java/com/yeying/demo/AuthServer.java`
|
|
109
|
+
- Python: `examples/backend/python/app.py`
|
|
110
|
+
|
|
111
|
+
## 本地联调
|
|
88
112
|
|
|
89
|
-
|
|
113
|
+
1. 构建 SDK:`npm run build`
|
|
114
|
+
2. 启动后端(示例):
|
|
115
|
+
`./scripts/backend.sh start nodejs`
|
|
116
|
+
3. 启动前端:
|
|
117
|
+
`python3 -m http.server 8001 --bind 127.0.0.1`
|
|
118
|
+
4. 打开:
|
|
119
|
+
`http://127.0.0.1:8001/examples/frontend/dapp.html`
|
|
90
120
|
|
|
91
|
-
|
|
121
|
+
多后端联调:
|
|
92
122
|
|
|
93
123
|
```bash
|
|
94
124
|
./scripts/backend.sh start all
|
|
95
|
-
./scripts/backend.sh start all --setup
|
|
96
125
|
```
|
|
97
126
|
|
|
98
127
|
默认端口:
|
|
@@ -101,56 +130,28 @@ npm install @yeying-community/web3-bs
|
|
|
101
130
|
- Node `3203`
|
|
102
131
|
- Python `3204`
|
|
103
132
|
|
|
104
|
-
|
|
105
|
-
- 将前端 Origin 加入 `CORS_ORIGINS`(例如 `http://127.0.0.1:3203`)
|
|
106
|
-
- UCAN 调用的 `audience` 与后端 `UCAN_AUD` 一致(如 `did:web:127.0.0.1:3202`)
|
|
107
|
-
|
|
108
|
-
提示:`examples/frontend/dapp.html` 已内置多后端列表,可在一次 UCAN 授权后依次调用多个服务。
|
|
109
|
-
提示:Demo 的 UCAN 流程按协议链路实现为 `Root(SIWE) -> Delegation -> Invocation`,便于按步骤理解多后端授权。
|
|
110
|
-
|
|
111
|
-
## 常见问题
|
|
133
|
+
## CORS 注意事项
|
|
112
134
|
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
执行:
|
|
135
|
+
若你用 `http://[::]:8001` 打开页面,请确保后端 CORS 白名单包含该 Origin。
|
|
136
|
+
建议统一加入:
|
|
116
137
|
|
|
117
138
|
```bash
|
|
118
|
-
|
|
139
|
+
CORS_ORIGINS=http://localhost:8001,http://127.0.0.1:8001,http://[::]:8001
|
|
119
140
|
```
|
|
120
141
|
|
|
121
|
-
|
|
122
|
-
- 钱包 UCAN RPC 路径(`createUcanSession` 返回 `source=wallet`)
|
|
123
|
-
- UCAN 本地回退路径(钱包不支持 `yeying_ucan_*` 时 `source=local`)
|
|
124
|
-
- `createRootUcan` + `createInvocationUcan` 两条链路
|
|
125
|
-
- `initWebDavStorage` 的 UCAN 自动初始化
|
|
126
|
-
- 中心化 UCAN API 是否已导出(`createCentralSession` / `issueCentralUcan` / `authCentralUcanFetch`)
|
|
127
|
-
|
|
128
|
-
### 刷新token失败
|
|
129
|
-
|
|
130
|
-
清理旧 Cookie 后重新登录:在浏览器 DevTools → Application → Cookies → http://127.0.0.1:8001 删除 refresh_token,再点 Login 后再点 Refresh Token。
|
|
142
|
+
## 本地软链接(开发)
|
|
131
143
|
|
|
132
|
-
|
|
144
|
+
将本仓库作为本地依赖链接到你的 DApp:
|
|
133
145
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
- 确认 `baseUrl` 指向 WebDAV 服务(默认 `http://127.0.0.1:6065`),不要误用 320x 认证后端。
|
|
138
|
-
- `baseUrl` 不应包含任何路径;若服务挂载在子路径,请用 `prefix` 指定(例如 `/dav`)。
|
|
139
|
-
- `audience` 必须与 WebDAV 服务端 `web3.ucan.audience` 一致(例如 `did:web:127.0.0.1:6065`)。
|
|
140
|
-
- `capabilities` 与服务端要求一致(优先 `web3.ucan.required_capabilities`,兼容 `required_resource/required_action`)。
|
|
141
|
-
- SDK 推荐使用 `with/can`(兼容 `resource/action`),例如:`{ with: "app:all:<appId>", can: "read,write" }`。
|
|
142
|
-
- 推荐资源统一使用 `app:<scope>:<appId>`,常用为 `with=app:all:<appId>`;请确保路径在 `/apps/<appId>/`(或 `app_scope.path_prefix`)下。
|
|
143
|
-
- Token 过期或缓存异常时,清理 UCAN 会话并重新登录/生成 Root + Invocation。
|
|
144
|
-
|
|
145
|
-
### UCAN audience mismatch
|
|
146
|
-
|
|
147
|
-
日志示例:
|
|
148
|
-
```
|
|
149
|
-
[2026-01-31T05:19:44.478Z] UCAN profile failed { error: 'UCAN audience mismatch' }
|
|
146
|
+
```bash
|
|
147
|
+
mkdir -p /path/to/your-dapp/node_modules/@yeying-community
|
|
148
|
+
ln -s /path/to/web3-bs /path/to/your-dapp/node_modules/@yeying-community/web3-bs
|
|
150
149
|
```
|
|
151
150
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
-
|
|
151
|
+
## 文档导航
|
|
152
|
+
|
|
153
|
+
- [文档导航](./docs/文档导航.md)
|
|
154
|
+
- [快速上手](./docs/快速上手.md)
|
|
155
|
+
- [SDK能力](./docs/SDK能力.md)
|
|
156
|
+
- [移动端认证与授权选型指南](./docs/移动端认证与授权选型指南.md)
|
|
157
|
+
- [接口规范(OpenAPI)](./docs/开放接口规范.yaml)
|
package/dist/auth/central.d.ts
CHANGED
package/dist/dapp.d.ts
CHANGED
|
@@ -45,5 +45,13 @@ export type InitDappSessionResult = {
|
|
|
45
45
|
webdavToken?: string;
|
|
46
46
|
webdavAppDir?: string;
|
|
47
47
|
};
|
|
48
|
+
export type AppIdLocationLike = {
|
|
49
|
+
host?: string | null;
|
|
50
|
+
hostname?: string | null;
|
|
51
|
+
port?: string | number | null;
|
|
52
|
+
};
|
|
53
|
+
export declare function normalizeAppHostnameForAppId(hostname: string): string;
|
|
54
|
+
export declare function deriveAppIdFromHost(host: string): string;
|
|
55
|
+
export declare function deriveAppIdFromLocation(locationLike?: AppIdLocationLike): string;
|
|
48
56
|
export declare function initWebDavStorage(options: InitWebDavStorageOptions): Promise<InitWebDavStorageResult>;
|
|
49
57
|
export declare function initDappSession(options: InitDappSessionOptions): Promise<InitDappSessionResult>;
|
package/dist/web3-bs.esm.js
CHANGED
|
@@ -1131,6 +1131,16 @@ function resolveCredentials(options) {
|
|
|
1131
1131
|
function resolveSessionTokenKey(options) {
|
|
1132
1132
|
return options?.sessionTokenStorageKey || DEFAULT_SESSION_TOKEN_KEY;
|
|
1133
1133
|
}
|
|
1134
|
+
function resolveAccessToken(options) {
|
|
1135
|
+
if (typeof options?.accessToken === 'string') {
|
|
1136
|
+
const token = options.accessToken.trim();
|
|
1137
|
+
return token || null;
|
|
1138
|
+
}
|
|
1139
|
+
if (options?.accessToken === null) {
|
|
1140
|
+
return null;
|
|
1141
|
+
}
|
|
1142
|
+
return getAccessToken(options);
|
|
1143
|
+
}
|
|
1134
1144
|
function shouldStoreSessionToken(options) {
|
|
1135
1145
|
return options?.storeSessionToken !== false;
|
|
1136
1146
|
}
|
|
@@ -1178,6 +1188,9 @@ function parseCapabilitiesField(obj, keys) {
|
|
|
1178
1188
|
}
|
|
1179
1189
|
return undefined;
|
|
1180
1190
|
}
|
|
1191
|
+
function parseIssuerDidField(obj) {
|
|
1192
|
+
return parseStringField(obj, ['issuerDid', 'issuer', 'did']);
|
|
1193
|
+
}
|
|
1181
1194
|
function readStoredSessionToken(options) {
|
|
1182
1195
|
if (!shouldStoreSessionToken(options))
|
|
1183
1196
|
return null;
|
|
@@ -1234,11 +1247,16 @@ async function getCentralIssuerInfo(options = {}) {
|
|
|
1234
1247
|
const fetcher = resolveFetcher(options);
|
|
1235
1248
|
const credentials = resolveCredentials(options);
|
|
1236
1249
|
const url = joinUrl$1(resolveBaseUrl(options), options.issuerPath || DEFAULT_ISSUER_PATH);
|
|
1250
|
+
const token = resolveAccessToken(options);
|
|
1251
|
+
const headers = new Headers({
|
|
1252
|
+
accept: 'application/json',
|
|
1253
|
+
});
|
|
1254
|
+
if (token) {
|
|
1255
|
+
headers.set('Authorization', `Bearer ${token}`);
|
|
1256
|
+
}
|
|
1237
1257
|
const response = await fetcher(url, {
|
|
1238
1258
|
method: 'GET',
|
|
1239
|
-
headers
|
|
1240
|
-
accept: 'application/json',
|
|
1241
|
-
},
|
|
1259
|
+
headers,
|
|
1242
1260
|
credentials,
|
|
1243
1261
|
});
|
|
1244
1262
|
const payload = await parseJsonBody(response);
|
|
@@ -1248,7 +1266,7 @@ async function getCentralIssuerInfo(options = {}) {
|
|
|
1248
1266
|
const data = parseEnvelopeData(payload);
|
|
1249
1267
|
return {
|
|
1250
1268
|
enabled: typeof data.enabled === 'boolean' ? data.enabled : undefined,
|
|
1251
|
-
issuerDid:
|
|
1269
|
+
issuerDid: parseIssuerDidField(data),
|
|
1252
1270
|
defaultAudience: parseStringField(data, ['defaultAudience']),
|
|
1253
1271
|
defaultCapabilities: parseCapabilitiesField(data, ['defaultCapabilities']),
|
|
1254
1272
|
response: payload,
|
|
@@ -1261,13 +1279,18 @@ async function createCentralSession(options) {
|
|
|
1261
1279
|
}
|
|
1262
1280
|
const fetcher = resolveFetcher(options);
|
|
1263
1281
|
const credentials = resolveCredentials(options);
|
|
1282
|
+
const accessToken = resolveAccessToken(options);
|
|
1264
1283
|
const url = joinUrl$1(resolveBaseUrl(options), options.sessionPath || DEFAULT_SESSION_PATH);
|
|
1284
|
+
const headers = new Headers({
|
|
1285
|
+
'Content-Type': 'application/json',
|
|
1286
|
+
accept: 'application/json',
|
|
1287
|
+
});
|
|
1288
|
+
if (accessToken) {
|
|
1289
|
+
headers.set('Authorization', `Bearer ${accessToken}`);
|
|
1290
|
+
}
|
|
1265
1291
|
const response = await fetcher(url, {
|
|
1266
1292
|
method: 'POST',
|
|
1267
|
-
headers
|
|
1268
|
-
'Content-Type': 'application/json',
|
|
1269
|
-
accept: 'application/json',
|
|
1270
|
-
},
|
|
1293
|
+
headers,
|
|
1271
1294
|
credentials,
|
|
1272
1295
|
body: JSON.stringify({
|
|
1273
1296
|
subject,
|
|
@@ -1288,7 +1311,7 @@ async function createCentralSession(options) {
|
|
|
1288
1311
|
subject: parseStringField(data, ['subject']) || subject,
|
|
1289
1312
|
sessionToken,
|
|
1290
1313
|
expiresAt: parseNumberField(data, ['expiresAt']),
|
|
1291
|
-
issuerDid:
|
|
1314
|
+
issuerDid: parseIssuerDidField(data),
|
|
1292
1315
|
response: payload,
|
|
1293
1316
|
};
|
|
1294
1317
|
}
|
|
@@ -1329,13 +1352,13 @@ async function issueCentralUcan(options = {}) {
|
|
|
1329
1352
|
}
|
|
1330
1353
|
return {
|
|
1331
1354
|
ucan,
|
|
1332
|
-
issuerDid:
|
|
1355
|
+
issuerDid: parseIssuerDidField(data),
|
|
1333
1356
|
subject: parseStringField(data, ['subject']),
|
|
1334
1357
|
audience: parseStringField(data, ['audience']),
|
|
1335
1358
|
capabilities: parseCapabilitiesField(data, ['capabilities']),
|
|
1336
|
-
exp: parseNumberField(data, ['exp']),
|
|
1337
|
-
nbf: parseNumberField(data, ['nbf']),
|
|
1338
|
-
iat: parseNumberField(data, ['iat']),
|
|
1359
|
+
exp: parseNumberField(data, ['exp', 'expiresAt']),
|
|
1360
|
+
nbf: parseNumberField(data, ['nbf', 'notBefore']),
|
|
1361
|
+
iat: parseNumberField(data, ['iat', 'issuedAt']),
|
|
1339
1362
|
response: payload,
|
|
1340
1363
|
};
|
|
1341
1364
|
}
|
|
@@ -1608,6 +1631,13 @@ function createWebDavClient(options) {
|
|
|
1608
1631
|
const tokenCache = new Map();
|
|
1609
1632
|
const TOKEN_SKEW_MS = 5000;
|
|
1610
1633
|
const DEFAULT_APP_ACTION = 'write';
|
|
1634
|
+
const LOOPBACK_HOST_ALIASES = new Set([
|
|
1635
|
+
'localhost',
|
|
1636
|
+
'127.0.0.1',
|
|
1637
|
+
'::1',
|
|
1638
|
+
'0:0:0:0:0:0:0:1',
|
|
1639
|
+
'0.0.0.0',
|
|
1640
|
+
]);
|
|
1611
1641
|
function normalizeAppDir(path) {
|
|
1612
1642
|
const trimmed = path.trim();
|
|
1613
1643
|
if (!trimmed)
|
|
@@ -1619,6 +1649,69 @@ function normalizeAppDir(path) {
|
|
|
1619
1649
|
function sanitizeAppId(appId) {
|
|
1620
1650
|
return appId.trim().replace(/[^a-zA-Z0-9._-]/g, '-');
|
|
1621
1651
|
}
|
|
1652
|
+
function parseHostPort(rawHost) {
|
|
1653
|
+
const host = rawHost.trim();
|
|
1654
|
+
if (!host)
|
|
1655
|
+
return { hostname: '', port: '' };
|
|
1656
|
+
const bracketMatch = host.match(/^\[([^\]]+)\](?::([0-9]+))?$/);
|
|
1657
|
+
if (bracketMatch) {
|
|
1658
|
+
return {
|
|
1659
|
+
hostname: bracketMatch[1] || '',
|
|
1660
|
+
port: bracketMatch[2] || '',
|
|
1661
|
+
};
|
|
1662
|
+
}
|
|
1663
|
+
const firstColon = host.indexOf(':');
|
|
1664
|
+
const lastColon = host.lastIndexOf(':');
|
|
1665
|
+
if (firstColon > -1 && firstColon === lastColon) {
|
|
1666
|
+
const hostname = host.slice(0, firstColon).trim();
|
|
1667
|
+
const port = host.slice(firstColon + 1).trim();
|
|
1668
|
+
if (/^[0-9]+$/.test(port)) {
|
|
1669
|
+
return { hostname, port };
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
return { hostname: host, port: '' };
|
|
1673
|
+
}
|
|
1674
|
+
function normalizeAppHostnameForAppId(hostname) {
|
|
1675
|
+
const normalized = (hostname || '').trim().toLowerCase();
|
|
1676
|
+
if (!normalized)
|
|
1677
|
+
return '';
|
|
1678
|
+
const bare = normalized.replace(/^\[(.*)\]$/, '$1');
|
|
1679
|
+
if (LOOPBACK_HOST_ALIASES.has(normalized) || LOOPBACK_HOST_ALIASES.has(bare)) {
|
|
1680
|
+
return 'localhost';
|
|
1681
|
+
}
|
|
1682
|
+
return bare;
|
|
1683
|
+
}
|
|
1684
|
+
function buildSanitizedAppId(hostname, port) {
|
|
1685
|
+
const normalizedHostname = normalizeAppHostnameForAppId(hostname);
|
|
1686
|
+
if (!normalizedHostname)
|
|
1687
|
+
return '';
|
|
1688
|
+
const normalizedPort = port === undefined || port === null ? '' : String(port).trim();
|
|
1689
|
+
const host = normalizedPort
|
|
1690
|
+
? `${normalizedHostname}:${normalizedPort}`
|
|
1691
|
+
: normalizedHostname;
|
|
1692
|
+
return sanitizeAppId(host);
|
|
1693
|
+
}
|
|
1694
|
+
function deriveAppIdFromHost(host) {
|
|
1695
|
+
const parsed = parseHostPort(host || '');
|
|
1696
|
+
return buildSanitizedAppId(parsed.hostname, parsed.port);
|
|
1697
|
+
}
|
|
1698
|
+
function deriveAppIdFromLocation(locationLike) {
|
|
1699
|
+
const source = locationLike ||
|
|
1700
|
+
(typeof window !== 'undefined' ? window.location : undefined);
|
|
1701
|
+
if (!source)
|
|
1702
|
+
return '';
|
|
1703
|
+
const hostname = typeof source.hostname === 'string' ? source.hostname : '';
|
|
1704
|
+
const port = source.port;
|
|
1705
|
+
if (hostname) {
|
|
1706
|
+
const appId = buildSanitizedAppId(hostname, port);
|
|
1707
|
+
if (appId)
|
|
1708
|
+
return appId;
|
|
1709
|
+
}
|
|
1710
|
+
if (typeof source.host === 'string') {
|
|
1711
|
+
return deriveAppIdFromHost(source.host);
|
|
1712
|
+
}
|
|
1713
|
+
return '';
|
|
1714
|
+
}
|
|
1622
1715
|
function normalizeAction(action) {
|
|
1623
1716
|
const trimmed = (action || '').trim();
|
|
1624
1717
|
return trimmed ? trimmed : null;
|
|
@@ -1842,5 +1935,5 @@ async function initDappSession(options) {
|
|
|
1842
1935
|
return result;
|
|
1843
1936
|
}
|
|
1844
1937
|
|
|
1845
|
-
export { WebDavClient, authCentralUcanFetch, authFetch, authUcanFetch, clearAccessToken, clearCentralSessionToken, clearUcanSession, createAndIssueCentralUcan, createCentralSession, createDelegationUcan, createInvocationUcan, createRootUcan, createUcanSession, createWebDavClient, getAccessToken, getAccounts, getBalance, getCapabilityAction, getCapabilityResource, getCentralIssuerInfo, getCentralSessionToken, getChainId, getOrCreateUcanRoot, getPreferredAccount, getProvider, getStoredUcanRoot, getUcanSession, initDappSession, initWebDavStorage, isYeYingProvider, issueCentralUcan, loginWithChallenge, logout, normalizeUcanCapabilities, normalizeUcanCapability, onAccountsChanged, onChainChanged, refreshAccessToken, requestAccounts, requireProvider, setAccessToken, setCentralSessionToken, signMessage, storeUcanRoot, watchAccounts };
|
|
1938
|
+
export { WebDavClient, authCentralUcanFetch, authFetch, authUcanFetch, clearAccessToken, clearCentralSessionToken, clearUcanSession, createAndIssueCentralUcan, createCentralSession, createDelegationUcan, createInvocationUcan, createRootUcan, createUcanSession, createWebDavClient, deriveAppIdFromHost, deriveAppIdFromLocation, getAccessToken, getAccounts, getBalance, getCapabilityAction, getCapabilityResource, getCentralIssuerInfo, getCentralSessionToken, getChainId, getOrCreateUcanRoot, getPreferredAccount, getProvider, getStoredUcanRoot, getUcanSession, initDappSession, initWebDavStorage, isYeYingProvider, issueCentralUcan, loginWithChallenge, logout, normalizeAppHostnameForAppId, normalizeUcanCapabilities, normalizeUcanCapability, onAccountsChanged, onChainChanged, refreshAccessToken, requestAccounts, requireProvider, setAccessToken, setCentralSessionToken, signMessage, storeUcanRoot, watchAccounts };
|
|
1846
1939
|
//# sourceMappingURL=web3-bs.esm.js.map
|