@takosjp/yurucommu-api 3.2.0 → 3.3.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.
- package/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +624 -4
- package/dist/lib/api/browser-push.d.ts +8 -0
- package/dist/lib/api/browser-push.d.ts.map +1 -1
- package/dist/lib/api/gateway-url-fixtures.d.ts +18 -0
- package/dist/lib/api/gateway-url-fixtures.d.ts.map +1 -0
- package/dist/lib/api/normalize.d.ts.map +1 -1
- package/dist/lib/api/notification-target.d.ts +26 -0
- package/dist/lib/api/notification-target.d.ts.map +1 -0
- package/dist/lib/api/push-config.d.ts +57 -0
- package/dist/lib/api/push-config.d.ts.map +1 -0
- package/dist/lib/api.d.ts +2 -0
- package/dist/lib/api.d.ts.map +1 -1
- package/dist/lib/rtc-client.d.ts +84 -0
- package/dist/lib/rtc-client.d.ts.map +1 -0
- package/dist/social-server.d.ts +7 -0
- package/dist/social-server.d.ts.map +1 -1
- package/dist/types/call.d.ts +199 -0
- package/dist/types/call.d.ts.map +1 -0
- package/dist/types/index.d.ts +12 -4
- package/dist/types/index.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,cAAc,CAAC;AAC7B,cAAc,oBAAoB,CAAC;AACnC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC;AACnC,cAAc,kBAAkB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -154,6 +154,63 @@ async function createAccount(username, name) {
|
|
|
154
154
|
return data.account;
|
|
155
155
|
}
|
|
156
156
|
|
|
157
|
+
// src/lib/api/notification-target.ts
|
|
158
|
+
function hasControlChar(value) {
|
|
159
|
+
for (let index = 0;index < value.length; index += 1) {
|
|
160
|
+
if (value.charCodeAt(index) < 32)
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
return false;
|
|
164
|
+
}
|
|
165
|
+
function safeNotificationPath(value) {
|
|
166
|
+
if (!value || !value.startsWith("/") || value.startsWith("//") || value.includes("\\") || hasControlChar(value)) {
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
return value;
|
|
170
|
+
}
|
|
171
|
+
function isStoryNotification(notification) {
|
|
172
|
+
return notification.target_kind === "story" || !!notification.object_ap_id?.includes("/ap/stories/");
|
|
173
|
+
}
|
|
174
|
+
function resolveNotificationTarget(notification) {
|
|
175
|
+
const declaredKind = notification.target_kind;
|
|
176
|
+
const declaredUrl = safeNotificationPath(notification.target_url);
|
|
177
|
+
if (declaredKind && declaredUrl) {
|
|
178
|
+
return {
|
|
179
|
+
target_kind: declaredKind,
|
|
180
|
+
target_id: notification.target_id ?? null,
|
|
181
|
+
target_url: declaredUrl
|
|
182
|
+
};
|
|
183
|
+
}
|
|
184
|
+
if (notification.type === "follow" || notification.type === "follow_request") {
|
|
185
|
+
const actorApId = notification.actor?.ap_id ?? null;
|
|
186
|
+
return {
|
|
187
|
+
target_kind: "profile",
|
|
188
|
+
target_id: actorApId,
|
|
189
|
+
target_url: actorApId ? `/profile/${encodeURIComponent(actorApId)}` : "/notifications"
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
const objectApId = notification.object_ap_id;
|
|
193
|
+
if (objectApId && isStoryNotification(notification)) {
|
|
194
|
+
return {
|
|
195
|
+
target_kind: "story",
|
|
196
|
+
target_id: objectApId,
|
|
197
|
+
target_url: `/?story=${encodeURIComponent(objectApId)}`
|
|
198
|
+
};
|
|
199
|
+
}
|
|
200
|
+
if (objectApId) {
|
|
201
|
+
return {
|
|
202
|
+
target_kind: "post",
|
|
203
|
+
target_id: objectApId,
|
|
204
|
+
target_url: `/post/${encodeURIComponent(objectApId)}`
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
return {
|
|
208
|
+
target_kind: "notifications",
|
|
209
|
+
target_id: null,
|
|
210
|
+
target_url: "/notifications"
|
|
211
|
+
};
|
|
212
|
+
}
|
|
213
|
+
|
|
157
214
|
// src/lib/api/normalize.ts
|
|
158
215
|
function formatUsernameFromApId(apId, preferred) {
|
|
159
216
|
try {
|
|
@@ -195,10 +252,16 @@ var normalizeActorNote = (note) => ({
|
|
|
195
252
|
...note,
|
|
196
253
|
actor: normalizeActor(note.actor)
|
|
197
254
|
});
|
|
198
|
-
var normalizeNotification = (notification) =>
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
255
|
+
var normalizeNotification = (notification) => {
|
|
256
|
+
const target = resolveNotificationTarget(notification);
|
|
257
|
+
return {
|
|
258
|
+
...notification,
|
|
259
|
+
actor: normalizeActor(notification.actor),
|
|
260
|
+
target_kind: target.target_kind,
|
|
261
|
+
target_id: target.target_id,
|
|
262
|
+
target_url: target.target_url
|
|
263
|
+
};
|
|
264
|
+
};
|
|
202
265
|
|
|
203
266
|
// src/lib/api/actors.ts
|
|
204
267
|
async function fetchActor(identifier) {
|
|
@@ -853,6 +916,9 @@ function normalizeServerOrigin(value) {
|
|
|
853
916
|
return null;
|
|
854
917
|
}
|
|
855
918
|
}
|
|
919
|
+
function normalizeBrowserPushGatewayUrl(value) {
|
|
920
|
+
return normalizeGatewayUrl(value);
|
|
921
|
+
}
|
|
856
922
|
function normalizeGatewayUrl(value) {
|
|
857
923
|
try {
|
|
858
924
|
const url = new URL(value.trim());
|
|
@@ -1005,6 +1071,59 @@ async function retireBrowserSubscription(config, subscription, runtime, unregist
|
|
|
1005
1071
|
}
|
|
1006
1072
|
}
|
|
1007
1073
|
|
|
1074
|
+
// src/lib/api/push-config.ts
|
|
1075
|
+
function createBrowserPushConfigResolver(options) {
|
|
1076
|
+
const { identity, resolveServerOrigin, buildTimeValues } = options;
|
|
1077
|
+
const build = (values) => {
|
|
1078
|
+
const gatewayUrl = values?.gatewayUrl?.trim();
|
|
1079
|
+
const vapidPublicKey = values?.vapidPublicKey?.trim();
|
|
1080
|
+
if (!gatewayUrl || !vapidPublicKey)
|
|
1081
|
+
return null;
|
|
1082
|
+
const serverOrigin = resolveServerOrigin();
|
|
1083
|
+
if (!serverOrigin)
|
|
1084
|
+
return null;
|
|
1085
|
+
return {
|
|
1086
|
+
product: identity.product,
|
|
1087
|
+
appId: identity.appId,
|
|
1088
|
+
appDisplayName: identity.appDisplayName,
|
|
1089
|
+
serverOrigin,
|
|
1090
|
+
gatewayUrl,
|
|
1091
|
+
vapidPublicKey,
|
|
1092
|
+
serviceWorkerPath: identity.serviceWorkerPath,
|
|
1093
|
+
...identity.scope ? { scope: identity.scope } : {},
|
|
1094
|
+
...identity.lang ? { lang: identity.lang } : {}
|
|
1095
|
+
};
|
|
1096
|
+
};
|
|
1097
|
+
const buildTimeConfig = () => build(buildTimeValues?.() ?? null);
|
|
1098
|
+
const resolveConfig = async () => {
|
|
1099
|
+
try {
|
|
1100
|
+
const runtime = await fetchNotificationPusherPublicConfig();
|
|
1101
|
+
if (!runtime.enabled || !runtime.gateway_url || !runtime.web_push_public_key) {
|
|
1102
|
+
return null;
|
|
1103
|
+
}
|
|
1104
|
+
return build({
|
|
1105
|
+
gatewayUrl: runtime.gateway_url,
|
|
1106
|
+
vapidPublicKey: runtime.web_push_public_key
|
|
1107
|
+
});
|
|
1108
|
+
} catch {
|
|
1109
|
+
return buildTimeConfig();
|
|
1110
|
+
}
|
|
1111
|
+
};
|
|
1112
|
+
const clearBeforeSignOut = async () => {
|
|
1113
|
+
const config = await resolveConfig().catch(() => null);
|
|
1114
|
+
if (config) {
|
|
1115
|
+
try {
|
|
1116
|
+
await disableBrowserNotificationPush(config);
|
|
1117
|
+
return;
|
|
1118
|
+
} catch {}
|
|
1119
|
+
}
|
|
1120
|
+
await clearBrowserNotificationPush(identity).catch(() => {
|
|
1121
|
+
return;
|
|
1122
|
+
});
|
|
1123
|
+
};
|
|
1124
|
+
return { buildTimeConfig, resolveConfig, clearBeforeSignOut };
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1008
1127
|
// src/lib/api/search.ts
|
|
1009
1128
|
function pageParams(query, opts) {
|
|
1010
1129
|
const params = new URLSearchParams({ q: query });
|
|
@@ -1236,6 +1355,402 @@ async function reportContent(input) {
|
|
|
1236
1355
|
});
|
|
1237
1356
|
await assertOk(res, "Failed to submit report");
|
|
1238
1357
|
}
|
|
1358
|
+
// src/lib/rtc-client.ts
|
|
1359
|
+
var CANDIDATE_FLUSH_MS = 200;
|
|
1360
|
+
|
|
1361
|
+
class CallClient {
|
|
1362
|
+
options;
|
|
1363
|
+
ws = null;
|
|
1364
|
+
wantConnected = false;
|
|
1365
|
+
backoff = 500;
|
|
1366
|
+
reconnectTimer = null;
|
|
1367
|
+
listeners = new Map;
|
|
1368
|
+
call = null;
|
|
1369
|
+
localStream = null;
|
|
1370
|
+
state = "idle";
|
|
1371
|
+
constructor(options = {}) {
|
|
1372
|
+
this.options = options;
|
|
1373
|
+
}
|
|
1374
|
+
on(event, listener) {
|
|
1375
|
+
let set = this.listeners.get(event);
|
|
1376
|
+
if (!set) {
|
|
1377
|
+
set = new Set;
|
|
1378
|
+
this.listeners.set(event, set);
|
|
1379
|
+
}
|
|
1380
|
+
set.add(listener);
|
|
1381
|
+
return () => set?.delete(listener);
|
|
1382
|
+
}
|
|
1383
|
+
emit(event, ...args) {
|
|
1384
|
+
for (const l of this.listeners.get(event) ?? []) {
|
|
1385
|
+
l(...args);
|
|
1386
|
+
}
|
|
1387
|
+
}
|
|
1388
|
+
setState(state) {
|
|
1389
|
+
if (this.state === state)
|
|
1390
|
+
return;
|
|
1391
|
+
this.state = state;
|
|
1392
|
+
this.emit("state", state);
|
|
1393
|
+
}
|
|
1394
|
+
getState() {
|
|
1395
|
+
return this.state;
|
|
1396
|
+
}
|
|
1397
|
+
origin() {
|
|
1398
|
+
return this.options.origin ?? (typeof location !== "undefined" ? location.origin : "");
|
|
1399
|
+
}
|
|
1400
|
+
socketUrl() {
|
|
1401
|
+
const o = this.origin();
|
|
1402
|
+
return `${o.replace(/^http/, "ws")}/api/rtc/socket`;
|
|
1403
|
+
}
|
|
1404
|
+
connect() {
|
|
1405
|
+
this.wantConnected = true;
|
|
1406
|
+
this.openSocket();
|
|
1407
|
+
}
|
|
1408
|
+
disconnect() {
|
|
1409
|
+
this.wantConnected = false;
|
|
1410
|
+
if (this.reconnectTimer)
|
|
1411
|
+
clearTimeout(this.reconnectTimer);
|
|
1412
|
+
this.reconnectTimer = null;
|
|
1413
|
+
this.ws?.close();
|
|
1414
|
+
this.ws = null;
|
|
1415
|
+
}
|
|
1416
|
+
openSocket() {
|
|
1417
|
+
if (this.ws && this.ws.readyState <= WebSocket.OPEN)
|
|
1418
|
+
return;
|
|
1419
|
+
let socket;
|
|
1420
|
+
try {
|
|
1421
|
+
socket = new WebSocket(this.socketUrl());
|
|
1422
|
+
} catch (err) {
|
|
1423
|
+
this.emit("error", "socket_open_failed", String(err));
|
|
1424
|
+
this.scheduleReconnect();
|
|
1425
|
+
return;
|
|
1426
|
+
}
|
|
1427
|
+
this.ws = socket;
|
|
1428
|
+
socket.onopen = () => {
|
|
1429
|
+
this.backoff = 500;
|
|
1430
|
+
this.send({ t: "hello" });
|
|
1431
|
+
if (this.call)
|
|
1432
|
+
this.send({ t: "resume", callId: this.call.callId });
|
|
1433
|
+
};
|
|
1434
|
+
socket.onmessage = (ev) => {
|
|
1435
|
+
this.onFrame(ev.data);
|
|
1436
|
+
};
|
|
1437
|
+
socket.onclose = () => {
|
|
1438
|
+
if (this.ws === socket)
|
|
1439
|
+
this.ws = null;
|
|
1440
|
+
if (this.wantConnected)
|
|
1441
|
+
this.scheduleReconnect();
|
|
1442
|
+
};
|
|
1443
|
+
socket.onerror = () => {
|
|
1444
|
+
socket.close();
|
|
1445
|
+
};
|
|
1446
|
+
}
|
|
1447
|
+
scheduleReconnect() {
|
|
1448
|
+
if (!this.wantConnected || this.reconnectTimer)
|
|
1449
|
+
return;
|
|
1450
|
+
const max = this.options.maxBackoffMs ?? 15000;
|
|
1451
|
+
const delay = Math.min(this.backoff, max);
|
|
1452
|
+
this.backoff = Math.min(this.backoff * 2, max);
|
|
1453
|
+
this.reconnectTimer = setTimeout(() => {
|
|
1454
|
+
this.reconnectTimer = null;
|
|
1455
|
+
this.openSocket();
|
|
1456
|
+
}, delay);
|
|
1457
|
+
}
|
|
1458
|
+
send(frame) {
|
|
1459
|
+
if (this.ws && this.ws.readyState === WebSocket.OPEN) {
|
|
1460
|
+
this.ws.send(JSON.stringify(frame));
|
|
1461
|
+
}
|
|
1462
|
+
}
|
|
1463
|
+
async startCall(peer, media) {
|
|
1464
|
+
if (this.call)
|
|
1465
|
+
throw new Error("already in a call");
|
|
1466
|
+
const res = await fetch(`${this.origin()}/api/rtc/calls`, {
|
|
1467
|
+
method: "POST",
|
|
1468
|
+
credentials: "include",
|
|
1469
|
+
headers: { "Content-Type": "application/json" },
|
|
1470
|
+
body: JSON.stringify({ to: peer, media })
|
|
1471
|
+
});
|
|
1472
|
+
if (!res.ok) {
|
|
1473
|
+
const code = res.status === 403 ? "blocked" : "start_failed";
|
|
1474
|
+
this.emit("error", code);
|
|
1475
|
+
throw new Error(code);
|
|
1476
|
+
}
|
|
1477
|
+
const data = await res.json();
|
|
1478
|
+
this.call = this.newCall(data.callId, peer, media, "caller", data.iceServers);
|
|
1479
|
+
this.setState("calling");
|
|
1480
|
+
this.connect();
|
|
1481
|
+
this.send({ t: "invite", callId: data.callId, to: peer, media });
|
|
1482
|
+
await this.setupMedia(this.call);
|
|
1483
|
+
await this.makeOffer(this.call);
|
|
1484
|
+
}
|
|
1485
|
+
async accept() {
|
|
1486
|
+
const call = this.call;
|
|
1487
|
+
if (!call || call.role !== "callee")
|
|
1488
|
+
return;
|
|
1489
|
+
this.setState("connecting");
|
|
1490
|
+
this.send({ t: "accept", callId: call.callId });
|
|
1491
|
+
await this.setupMedia(call);
|
|
1492
|
+
if (call.pc && call.remoteDescriptionSet) {
|
|
1493
|
+
const answer = await call.pc.createAnswer();
|
|
1494
|
+
await call.pc.setLocalDescription(answer);
|
|
1495
|
+
this.send({ t: "answer", callId: call.callId, sdp: answer.sdp ?? "" });
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
reject(reason = "declined") {
|
|
1499
|
+
const call = this.call;
|
|
1500
|
+
if (!call)
|
|
1501
|
+
return;
|
|
1502
|
+
this.send({ t: "reject", callId: call.callId, reason });
|
|
1503
|
+
this.teardown("ended");
|
|
1504
|
+
}
|
|
1505
|
+
hangup(reason = "hangup") {
|
|
1506
|
+
const call = this.call;
|
|
1507
|
+
if (!call)
|
|
1508
|
+
return;
|
|
1509
|
+
this.send({ t: "hangup", callId: call.callId, reason });
|
|
1510
|
+
this.teardown("ended");
|
|
1511
|
+
}
|
|
1512
|
+
setMuted(muted) {
|
|
1513
|
+
for (const track of this.localStream?.getAudioTracks() ?? []) {
|
|
1514
|
+
track.enabled = !muted;
|
|
1515
|
+
}
|
|
1516
|
+
this.emit("muted", muted);
|
|
1517
|
+
}
|
|
1518
|
+
setCameraEnabled(enabled) {
|
|
1519
|
+
for (const track of this.localStream?.getVideoTracks() ?? []) {
|
|
1520
|
+
track.enabled = enabled;
|
|
1521
|
+
}
|
|
1522
|
+
this.emit("cameraoff", !enabled);
|
|
1523
|
+
}
|
|
1524
|
+
async onFrame(raw) {
|
|
1525
|
+
if (typeof raw !== "string")
|
|
1526
|
+
return;
|
|
1527
|
+
let frame;
|
|
1528
|
+
try {
|
|
1529
|
+
frame = JSON.parse(raw);
|
|
1530
|
+
} catch {
|
|
1531
|
+
return;
|
|
1532
|
+
}
|
|
1533
|
+
switch (frame.t) {
|
|
1534
|
+
case "ready":
|
|
1535
|
+
case "pong":
|
|
1536
|
+
return;
|
|
1537
|
+
case "ringing":
|
|
1538
|
+
this.onRinging(frame);
|
|
1539
|
+
return;
|
|
1540
|
+
case "ice-servers":
|
|
1541
|
+
if (this.call && this.call.callId === frame.callId) {
|
|
1542
|
+
this.call.iceServers = frame.iceServers;
|
|
1543
|
+
}
|
|
1544
|
+
return;
|
|
1545
|
+
case "offer":
|
|
1546
|
+
await this.onRemoteOffer(frame);
|
|
1547
|
+
return;
|
|
1548
|
+
case "answer":
|
|
1549
|
+
await this.onRemoteAnswer(frame);
|
|
1550
|
+
return;
|
|
1551
|
+
case "candidates":
|
|
1552
|
+
await this.onRemoteCandidates(frame);
|
|
1553
|
+
return;
|
|
1554
|
+
case "peer-accepted":
|
|
1555
|
+
if (this.state === "calling")
|
|
1556
|
+
this.setState("connecting");
|
|
1557
|
+
return;
|
|
1558
|
+
case "peer-rejected":
|
|
1559
|
+
this.emit("error", "declined", frame.reason);
|
|
1560
|
+
this.teardown("ended");
|
|
1561
|
+
return;
|
|
1562
|
+
case "peer-hangup":
|
|
1563
|
+
this.teardown("ended");
|
|
1564
|
+
return;
|
|
1565
|
+
case "call-state":
|
|
1566
|
+
this.onCallState(frame);
|
|
1567
|
+
return;
|
|
1568
|
+
case "error":
|
|
1569
|
+
this.emit("error", frame.code, frame.message);
|
|
1570
|
+
if (frame.code === "peer_unreachable")
|
|
1571
|
+
this.teardown("ended");
|
|
1572
|
+
return;
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1575
|
+
onRinging(frame) {
|
|
1576
|
+
if (this.call) {
|
|
1577
|
+
this.send({ t: "reject", callId: frame.callId, reason: "busy" });
|
|
1578
|
+
return;
|
|
1579
|
+
}
|
|
1580
|
+
this.call = this.newCall(frame.callId, frame.from, frame.media, "callee", []);
|
|
1581
|
+
this.setState("incoming");
|
|
1582
|
+
this.emit("incoming", {
|
|
1583
|
+
callId: frame.callId,
|
|
1584
|
+
from: frame.from,
|
|
1585
|
+
media: frame.media
|
|
1586
|
+
});
|
|
1587
|
+
}
|
|
1588
|
+
onCallState(frame) {
|
|
1589
|
+
if (!this.call || this.call.callId !== frame.callId)
|
|
1590
|
+
return;
|
|
1591
|
+
if (frame.state === "missed" || frame.state === "cancelled" || frame.state === "rejected" || frame.state === "failed" || frame.state === "ended") {
|
|
1592
|
+
this.teardown("ended");
|
|
1593
|
+
}
|
|
1594
|
+
}
|
|
1595
|
+
async onRemoteOffer(frame) {
|
|
1596
|
+
let call = this.call;
|
|
1597
|
+
if (!call || call.callId !== frame.callId) {
|
|
1598
|
+
call = this.newCall(frame.callId, "unknown", frame.media ?? { audio: true, video: false }, "callee", []);
|
|
1599
|
+
this.call = call;
|
|
1600
|
+
this.setState("incoming");
|
|
1601
|
+
}
|
|
1602
|
+
if (!call.pc)
|
|
1603
|
+
this.buildPeerConnection(call);
|
|
1604
|
+
await call.pc?.setRemoteDescription({ type: "offer", sdp: frame.sdp });
|
|
1605
|
+
call.remoteDescriptionSet = true;
|
|
1606
|
+
await this.drainRemoteCandidates(call);
|
|
1607
|
+
}
|
|
1608
|
+
async onRemoteAnswer(frame) {
|
|
1609
|
+
const call = this.call;
|
|
1610
|
+
if (!call || call.callId !== frame.callId || !call.pc)
|
|
1611
|
+
return;
|
|
1612
|
+
await call.pc.setRemoteDescription({ type: "answer", sdp: frame.sdp });
|
|
1613
|
+
call.remoteDescriptionSet = true;
|
|
1614
|
+
await this.drainRemoteCandidates(call);
|
|
1615
|
+
}
|
|
1616
|
+
async onRemoteCandidates(frame) {
|
|
1617
|
+
const call = this.call;
|
|
1618
|
+
if (!call || call.callId !== frame.callId)
|
|
1619
|
+
return;
|
|
1620
|
+
for (const cand of frame.candidates) {
|
|
1621
|
+
if (call.pc && call.remoteDescriptionSet) {
|
|
1622
|
+
try {
|
|
1623
|
+
await call.pc.addIceCandidate(cand);
|
|
1624
|
+
} catch {}
|
|
1625
|
+
} else {
|
|
1626
|
+
call.pendingRemoteCandidates.push(cand);
|
|
1627
|
+
}
|
|
1628
|
+
}
|
|
1629
|
+
}
|
|
1630
|
+
async drainRemoteCandidates(call) {
|
|
1631
|
+
if (!call.pc)
|
|
1632
|
+
return;
|
|
1633
|
+
const pending = call.pendingRemoteCandidates.splice(0);
|
|
1634
|
+
for (const cand of pending) {
|
|
1635
|
+
try {
|
|
1636
|
+
await call.pc.addIceCandidate(cand);
|
|
1637
|
+
} catch {}
|
|
1638
|
+
}
|
|
1639
|
+
}
|
|
1640
|
+
async setupMedia(call) {
|
|
1641
|
+
if (!this.localStream) {
|
|
1642
|
+
try {
|
|
1643
|
+
this.localStream = await navigator.mediaDevices.getUserMedia({
|
|
1644
|
+
audio: call.media.audio,
|
|
1645
|
+
video: call.media.video
|
|
1646
|
+
});
|
|
1647
|
+
} catch (err) {
|
|
1648
|
+
this.emit("error", "media_denied", String(err));
|
|
1649
|
+
this.hangup("media_denied");
|
|
1650
|
+
return;
|
|
1651
|
+
}
|
|
1652
|
+
this.emit("localstream", this.localStream);
|
|
1653
|
+
}
|
|
1654
|
+
if (!call.pc)
|
|
1655
|
+
this.buildPeerConnection(call);
|
|
1656
|
+
for (const track of this.localStream.getTracks()) {
|
|
1657
|
+
call.pc?.addTrack(track, this.localStream);
|
|
1658
|
+
}
|
|
1659
|
+
}
|
|
1660
|
+
buildPeerConnection(call) {
|
|
1661
|
+
const pc = new RTCPeerConnection({
|
|
1662
|
+
iceServers: call.iceServers.map((s) => ({
|
|
1663
|
+
urls: s.urls,
|
|
1664
|
+
username: s.username,
|
|
1665
|
+
credential: s.credential
|
|
1666
|
+
}))
|
|
1667
|
+
});
|
|
1668
|
+
pc.onicecandidate = (ev) => {
|
|
1669
|
+
if (ev.candidate)
|
|
1670
|
+
this.bufferCandidate(call, ev.candidate.toJSON());
|
|
1671
|
+
else
|
|
1672
|
+
this.flushCandidates(call);
|
|
1673
|
+
};
|
|
1674
|
+
pc.ontrack = (ev) => {
|
|
1675
|
+
this.emit("remotestream", ev.streams[0] ?? null);
|
|
1676
|
+
};
|
|
1677
|
+
pc.onconnectionstatechange = () => {
|
|
1678
|
+
if (pc.connectionState === "connected")
|
|
1679
|
+
this.setState("connected");
|
|
1680
|
+
else if (pc.connectionState === "failed" || pc.connectionState === "closed") {
|
|
1681
|
+
this.teardown("ended");
|
|
1682
|
+
}
|
|
1683
|
+
};
|
|
1684
|
+
call.pc = pc;
|
|
1685
|
+
}
|
|
1686
|
+
async makeOffer(call) {
|
|
1687
|
+
if (!call.pc)
|
|
1688
|
+
this.buildPeerConnection(call);
|
|
1689
|
+
const offer = await call.pc.createOffer();
|
|
1690
|
+
await call.pc.setLocalDescription(offer);
|
|
1691
|
+
this.send({ t: "offer", callId: call.callId, sdp: offer.sdp ?? "" });
|
|
1692
|
+
}
|
|
1693
|
+
bufferCandidate(call, cand) {
|
|
1694
|
+
call.candidateBuffer.push(cand);
|
|
1695
|
+
if (call.flushTimer)
|
|
1696
|
+
return;
|
|
1697
|
+
call.flushTimer = setTimeout(() => this.flushCandidates(call), CANDIDATE_FLUSH_MS);
|
|
1698
|
+
}
|
|
1699
|
+
flushCandidates(call) {
|
|
1700
|
+
if (call.flushTimer) {
|
|
1701
|
+
clearTimeout(call.flushTimer);
|
|
1702
|
+
call.flushTimer = null;
|
|
1703
|
+
}
|
|
1704
|
+
if (call.candidateBuffer.length === 0)
|
|
1705
|
+
return;
|
|
1706
|
+
const candidates = call.candidateBuffer.splice(0).map((c) => ({
|
|
1707
|
+
candidate: c.candidate ?? "",
|
|
1708
|
+
sdpMid: c.sdpMid ?? null,
|
|
1709
|
+
sdpMLineIndex: c.sdpMLineIndex ?? null,
|
|
1710
|
+
usernameFragment: c.usernameFragment ?? null
|
|
1711
|
+
}));
|
|
1712
|
+
this.send({ t: "candidates", callId: call.callId, candidates });
|
|
1713
|
+
}
|
|
1714
|
+
newCall(callId, peer, media, role, iceServers) {
|
|
1715
|
+
return {
|
|
1716
|
+
callId,
|
|
1717
|
+
peer,
|
|
1718
|
+
media,
|
|
1719
|
+
role,
|
|
1720
|
+
pc: null,
|
|
1721
|
+
iceServers,
|
|
1722
|
+
pendingRemoteCandidates: [],
|
|
1723
|
+
candidateBuffer: [],
|
|
1724
|
+
flushTimer: null,
|
|
1725
|
+
remoteDescriptionSet: false
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
teardown(finalState) {
|
|
1729
|
+
const call = this.call;
|
|
1730
|
+
if (call) {
|
|
1731
|
+
if (call.flushTimer)
|
|
1732
|
+
clearTimeout(call.flushTimer);
|
|
1733
|
+
call.pc?.getSenders().forEach((s) => s.track?.stop());
|
|
1734
|
+
try {
|
|
1735
|
+
call.pc?.close();
|
|
1736
|
+
} catch {}
|
|
1737
|
+
}
|
|
1738
|
+
if (this.localStream) {
|
|
1739
|
+
this.localStream.getTracks().forEach((t) => t.stop());
|
|
1740
|
+
this.localStream = null;
|
|
1741
|
+
this.emit("localstream", null);
|
|
1742
|
+
}
|
|
1743
|
+
this.emit("remotestream", null);
|
|
1744
|
+
this.call = null;
|
|
1745
|
+
this.setState(finalState);
|
|
1746
|
+
if (finalState === "ended") {
|
|
1747
|
+
setTimeout(() => {
|
|
1748
|
+
if (!this.call)
|
|
1749
|
+
this.setState("idle");
|
|
1750
|
+
}, 400);
|
|
1751
|
+
}
|
|
1752
|
+
}
|
|
1753
|
+
}
|
|
1239
1754
|
// src/social-server.ts
|
|
1240
1755
|
async function fetchCurrentActor() {
|
|
1241
1756
|
const res = await apiFetch("/api/auth/me");
|
|
@@ -1250,6 +1765,101 @@ async function fetchSocialServerDiscovery() {
|
|
|
1250
1765
|
await assertOk(res, "Failed to load social server discovery");
|
|
1251
1766
|
return await res.json();
|
|
1252
1767
|
}
|
|
1768
|
+
// src/types/call.ts
|
|
1769
|
+
var RTC_SIGNAL_ENVELOPE_VERSION = 1;
|
|
1770
|
+
var TERMINAL_CALL_STATES = [
|
|
1771
|
+
"ended",
|
|
1772
|
+
"rejected",
|
|
1773
|
+
"missed",
|
|
1774
|
+
"failed",
|
|
1775
|
+
"cancelled"
|
|
1776
|
+
];
|
|
1777
|
+
function isTerminalCallState(state) {
|
|
1778
|
+
return TERMINAL_CALL_STATES.includes(state);
|
|
1779
|
+
}
|
|
1780
|
+
var SIGNAL_TYPES = [
|
|
1781
|
+
"offer",
|
|
1782
|
+
"answer",
|
|
1783
|
+
"candidate",
|
|
1784
|
+
"accept",
|
|
1785
|
+
"reject",
|
|
1786
|
+
"hangup",
|
|
1787
|
+
"cancel"
|
|
1788
|
+
];
|
|
1789
|
+
function isPlainObject(value) {
|
|
1790
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
1791
|
+
}
|
|
1792
|
+
function isCallMediaKind(value) {
|
|
1793
|
+
return isPlainObject(value) && typeof value.audio === "boolean" && typeof value.video === "boolean";
|
|
1794
|
+
}
|
|
1795
|
+
function parseCandidates(value) {
|
|
1796
|
+
if (value === undefined)
|
|
1797
|
+
return;
|
|
1798
|
+
if (!Array.isArray(value))
|
|
1799
|
+
return;
|
|
1800
|
+
const out = [];
|
|
1801
|
+
for (const raw of value) {
|
|
1802
|
+
if (!isPlainObject(raw) || typeof raw.candidate !== "string")
|
|
1803
|
+
continue;
|
|
1804
|
+
out.push({
|
|
1805
|
+
candidate: raw.candidate,
|
|
1806
|
+
sdpMid: typeof raw.sdpMid === "string" ? raw.sdpMid : null,
|
|
1807
|
+
sdpMLineIndex: typeof raw.sdpMLineIndex === "number" ? raw.sdpMLineIndex : null,
|
|
1808
|
+
usernameFragment: typeof raw.usernameFragment === "string" ? raw.usernameFragment : null
|
|
1809
|
+
});
|
|
1810
|
+
}
|
|
1811
|
+
return out;
|
|
1812
|
+
}
|
|
1813
|
+
function parseSfuFocus(value) {
|
|
1814
|
+
if (value === undefined)
|
|
1815
|
+
return;
|
|
1816
|
+
if (value === null)
|
|
1817
|
+
return null;
|
|
1818
|
+
if (!isPlainObject(value))
|
|
1819
|
+
return;
|
|
1820
|
+
if (typeof value.kind !== "string" || typeof value.url !== "string") {
|
|
1821
|
+
return;
|
|
1822
|
+
}
|
|
1823
|
+
return {
|
|
1824
|
+
kind: value.kind,
|
|
1825
|
+
url: value.url,
|
|
1826
|
+
token: typeof value.token === "string" ? value.token : undefined,
|
|
1827
|
+
room: typeof value.room === "string" ? value.room : undefined
|
|
1828
|
+
};
|
|
1829
|
+
}
|
|
1830
|
+
function parseRtcSignalEnvelope(input) {
|
|
1831
|
+
if (!isPlainObject(input))
|
|
1832
|
+
return null;
|
|
1833
|
+
if (input.v !== RTC_SIGNAL_ENVELOPE_VERSION)
|
|
1834
|
+
return null;
|
|
1835
|
+
const { callId, from, to, type, ts, ttlMs } = input;
|
|
1836
|
+
if (typeof callId !== "string" || callId.length === 0 || callId.length > 200 || typeof from !== "string" || from.length === 0 || typeof to !== "string" || to.length === 0 || typeof type !== "string" || !SIGNAL_TYPES.includes(type) || typeof ts !== "number" || !Number.isFinite(ts) || typeof ttlMs !== "number" || !Number.isFinite(ttlMs) || ttlMs < 0) {
|
|
1837
|
+
return null;
|
|
1838
|
+
}
|
|
1839
|
+
const sdp = typeof input.sdp === "string" ? input.sdp : undefined;
|
|
1840
|
+
if (sdp !== undefined && sdp.length > 1e5)
|
|
1841
|
+
return null;
|
|
1842
|
+
return {
|
|
1843
|
+
v: RTC_SIGNAL_ENVELOPE_VERSION,
|
|
1844
|
+
callId,
|
|
1845
|
+
from,
|
|
1846
|
+
to,
|
|
1847
|
+
type,
|
|
1848
|
+
media: isCallMediaKind(input.media) ? input.media : undefined,
|
|
1849
|
+
sdp,
|
|
1850
|
+
candidates: parseCandidates(input.candidates),
|
|
1851
|
+
sfuFocus: parseSfuFocus(input.sfuFocus),
|
|
1852
|
+
reason: typeof input.reason === "string" ? input.reason.slice(0, 200) : undefined,
|
|
1853
|
+
ts,
|
|
1854
|
+
ttlMs
|
|
1855
|
+
};
|
|
1856
|
+
}
|
|
1857
|
+
function isEnvelopeFresh(envelope, now) {
|
|
1858
|
+
const skewToleranceMs = 30000;
|
|
1859
|
+
if (envelope.ts - now > skewToleranceMs)
|
|
1860
|
+
return false;
|
|
1861
|
+
return now - envelope.ts <= envelope.ttlMs;
|
|
1862
|
+
}
|
|
1253
1863
|
export {
|
|
1254
1864
|
voteOnStory,
|
|
1255
1865
|
validateFile,
|
|
@@ -1281,8 +1891,10 @@ export {
|
|
|
1281
1891
|
searchPosts,
|
|
1282
1892
|
searchHashtag,
|
|
1283
1893
|
searchActors,
|
|
1894
|
+
safeNotificationPath,
|
|
1284
1895
|
revokeCommunityInvite,
|
|
1285
1896
|
resolveReport,
|
|
1897
|
+
resolveNotificationTarget,
|
|
1286
1898
|
repostPost,
|
|
1287
1899
|
reportContent,
|
|
1288
1900
|
removeCommunityMember,
|
|
@@ -1291,9 +1903,11 @@ export {
|
|
|
1291
1903
|
rejectCommunityJoinRequest,
|
|
1292
1904
|
registerNotificationPusher,
|
|
1293
1905
|
refreshBrowserNotificationPush,
|
|
1906
|
+
parseRtcSignalEnvelope,
|
|
1294
1907
|
normalizeStory,
|
|
1295
1908
|
normalizePost,
|
|
1296
1909
|
normalizeNotification,
|
|
1910
|
+
normalizeBrowserPushGatewayUrl,
|
|
1297
1911
|
normalizeActorStories,
|
|
1298
1912
|
normalizeActorNote,
|
|
1299
1913
|
normalizeActor,
|
|
@@ -1311,6 +1925,8 @@ export {
|
|
|
1311
1925
|
likePost,
|
|
1312
1926
|
leaveCommunity,
|
|
1313
1927
|
joinCommunity,
|
|
1928
|
+
isTerminalCallState,
|
|
1929
|
+
isEnvelopeFresh,
|
|
1314
1930
|
getYurucommuApiTransport,
|
|
1315
1931
|
getStoryViewers,
|
|
1316
1932
|
getBrowserNotificationPushState,
|
|
@@ -1366,6 +1982,7 @@ export {
|
|
|
1366
1982
|
createNote,
|
|
1367
1983
|
createCommunityInvite,
|
|
1368
1984
|
createCommunity,
|
|
1985
|
+
createBrowserPushConfigResolver,
|
|
1369
1986
|
createAccount,
|
|
1370
1987
|
clearYurucommuApiTransport,
|
|
1371
1988
|
clearBrowserNotificationPush,
|
|
@@ -1385,6 +2002,9 @@ export {
|
|
|
1385
2002
|
allowedMimeTypes,
|
|
1386
2003
|
acceptFollowRequest,
|
|
1387
2004
|
acceptCommunityJoinRequest,
|
|
2005
|
+
TERMINAL_CALL_STATES,
|
|
2006
|
+
RTC_SIGNAL_ENVELOPE_VERSION,
|
|
1388
2007
|
FileValidationError,
|
|
2008
|
+
CallClient,
|
|
1389
2009
|
ApiError
|
|
1390
2010
|
};
|
|
@@ -66,5 +66,13 @@ export declare function disableBrowserNotificationPush(config: BrowserNotificati
|
|
|
66
66
|
* temporarily unavailable server cannot keep waking a signed-out device.
|
|
67
67
|
*/
|
|
68
68
|
export declare function clearBrowserNotificationPush(identity: Pick<BrowserNotificationPushConfig, "product" | "appId" | "serviceWorkerPath">, runtime?: BrowserNotificationPushRuntime): Promise<BrowserNotificationPushState>;
|
|
69
|
+
/**
|
|
70
|
+
* Client-side gateway URL policy. MUST stay behaviorally equivalent to the
|
|
71
|
+
* server's `normalizeGatewayUrl` in the notification pusher contract — a
|
|
72
|
+
* client-accepted / server-rejected URL yields a confusing "registers but
|
|
73
|
+
* 400s" failure. The equivalence is pinned by a shared-fixture drift test.
|
|
74
|
+
* Exported for that test; app code calls the higher-level helpers above.
|
|
75
|
+
*/
|
|
76
|
+
export declare function normalizeBrowserPushGatewayUrl(value: string): string | null;
|
|
69
77
|
export {};
|
|
70
78
|
//# sourceMappingURL=browser-push.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"browser-push.d.ts","sourceRoot":"","sources":["../../../src/lib/api/browser-push.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"browser-push.d.ts","sourceRoot":"","sources":["../../../src/lib/api/browser-push.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared gateway-URL acceptance table.
|
|
3
|
+
*
|
|
4
|
+
* Consumed by BOTH the browser-push validator (this package) and the server's
|
|
5
|
+
* notification pusher contract (backend), each in an equivalence test, so the
|
|
6
|
+
* two independent copies of the URL policy cannot silently diverge into a
|
|
7
|
+
* "client accepts / server rejects" mismatch.
|
|
8
|
+
*
|
|
9
|
+
* `valid` is whether the URL is an acceptable gateway. Bound-length-only cases
|
|
10
|
+
* are omitted because only the server enforces the 2048-char cap.
|
|
11
|
+
*/
|
|
12
|
+
export interface GatewayUrlCase {
|
|
13
|
+
readonly url: string;
|
|
14
|
+
readonly valid: boolean;
|
|
15
|
+
readonly note: string;
|
|
16
|
+
}
|
|
17
|
+
export declare const GATEWAY_URL_CASES: readonly GatewayUrlCase[];
|
|
18
|
+
//# sourceMappingURL=gateway-url-fixtures.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"gateway-url-fixtures.d.ts","sourceRoot":"","sources":["../../../src/lib/api/gateway-url-fixtures.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,eAAO,MAAM,iBAAiB,EAAE,SAAS,cAAc,EAmDtD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/lib/api/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,IAAI,EACJ,KAAK,EACN,MAAM,sBAAsB,CAAC;
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../../src/lib/api/normalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,IAAI,EACJ,KAAK,EACN,MAAM,sBAAsB,CAAC;AAG9B,KAAK,SAAS,GAAG;IACf,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAiBF,wBAAgB,cAAc,CAAC,CAAC,SAAS,SAAS,EAAE,KAAK,EAAE,CAAC,GAAG,CAAC,CAkB/D;AAED,eAAO,MAAM,aAAa,GAAI,MAAM,IAAI,KAAG,IAGzC,CAAC;AAEH,eAAO,MAAM,cAAc,GAAI,OAAO,KAAK,KAAG,KAG5C,CAAC;AAEH,eAAO,MAAM,qBAAqB,GAAI,SAAS,YAAY,KAAG,YAI5D,CAAC;AAEH,eAAO,MAAM,kBAAkB,GAAI,MAAM,SAAS,KAAG,SAGnD,CAAC;AAEH,eAAO,MAAM,qBAAqB,GAChC,cAAc,YAAY,KACzB,YAaF,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import type { Notification, NotificationTargetKind } from "../../types/index.js";
|
|
2
|
+
export interface NotificationTarget {
|
|
3
|
+
readonly target_kind: NotificationTargetKind;
|
|
4
|
+
readonly target_id: string | null;
|
|
5
|
+
/**
|
|
6
|
+
* Same-origin in-app path shaped for the yurucommu web client's routing.
|
|
7
|
+
* Other clients should prefer `target_kind` + `target_id` and build their own
|
|
8
|
+
* path. Never treat this as an external URL.
|
|
9
|
+
*/
|
|
10
|
+
readonly target_url: string;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Guard an in-app navigation path against open-redirect / protocol-relative /
|
|
14
|
+
* control-character abuse. Returns the value only if it is a plain same-origin
|
|
15
|
+
* absolute path (`/...`, not `//...`), else null. Promoted from the yurucommu
|
|
16
|
+
* and yurume web clients, which each carried an identical copy.
|
|
17
|
+
*/
|
|
18
|
+
export declare function safeNotificationPath(value: string | null | undefined): string | null;
|
|
19
|
+
/**
|
|
20
|
+
* Resolve the navigation target for a notification. Prefers the server-provided
|
|
21
|
+
* `target_*` fields (3.2.0+) after re-validating `target_url`; when a server
|
|
22
|
+
* older than 3.2.0 omitted them, synthesizes the same mapping the server uses
|
|
23
|
+
* from `type` + `object_ap_id`. Always returns a safe same-origin path.
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveNotificationTarget(notification: Notification): NotificationTarget;
|
|
26
|
+
//# sourceMappingURL=notification-target.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"notification-target.d.ts","sourceRoot":"","sources":["../../../src/lib/api/notification-target.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,YAAY,EACZ,sBAAsB,EACvB,MAAM,sBAAsB,CAAC;AAE9B,MAAM,WAAW,kBAAkB;IACjC,QAAQ,CAAC,WAAW,EAAE,sBAAsB,CAAC;IAC7C,QAAQ,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IAClC;;;;OAIG;IACH,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;CAC7B;AAUD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC/B,MAAM,GAAG,IAAI,CAWf;AASD;;;;;GAKG;AACH,wBAAgB,yBAAyB,CACvC,YAAY,EAAE,YAAY,GACzB,kBAAkB,CA6CpB"}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import type { NotificationPusherProduct } from "../../types/index.js";
|
|
2
|
+
import { type BrowserNotificationPushConfig } from "./browser-push.js";
|
|
3
|
+
/**
|
|
4
|
+
* Stable identity of a browser/PWA push client. Everything here is a per-app
|
|
5
|
+
* constant; only the gateway URL, VAPID key, and server origin are resolved at
|
|
6
|
+
* runtime.
|
|
7
|
+
*/
|
|
8
|
+
export interface BrowserPushClientIdentity {
|
|
9
|
+
readonly product: NotificationPusherProduct;
|
|
10
|
+
readonly appId: string;
|
|
11
|
+
readonly appDisplayName: string;
|
|
12
|
+
/** Root-relative service worker script path (e.g. "/notification-push-sw.js"). */
|
|
13
|
+
readonly serviceWorkerPath: string;
|
|
14
|
+
readonly scope?: string;
|
|
15
|
+
readonly lang?: string;
|
|
16
|
+
}
|
|
17
|
+
/** Non-secret runtime gateway values, from a fetch or build-time fallback. */
|
|
18
|
+
export interface BrowserPushRuntimeValues {
|
|
19
|
+
readonly gatewayUrl?: string | null;
|
|
20
|
+
readonly vapidPublicKey?: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface BrowserPushConfigResolverOptions {
|
|
23
|
+
readonly identity: BrowserPushClientIdentity;
|
|
24
|
+
/**
|
|
25
|
+
* Origin of the yurucommu-compatible API that owns the registration. Returns
|
|
26
|
+
* null when it cannot be determined (e.g. SSR, or an unconfigured shell), in
|
|
27
|
+
* which case config resolution yields null.
|
|
28
|
+
*/
|
|
29
|
+
readonly resolveServerOrigin: () => string | null;
|
|
30
|
+
/**
|
|
31
|
+
* Build-time fallback used only while a server rolls forward to 3.2.0; a
|
|
32
|
+
* responding runtime config always wins.
|
|
33
|
+
*/
|
|
34
|
+
readonly buildTimeValues?: () => BrowserPushRuntimeValues | null;
|
|
35
|
+
}
|
|
36
|
+
export interface BrowserPushConfigResolver {
|
|
37
|
+
/** Build config from build-time values only (no network). */
|
|
38
|
+
readonly buildTimeConfig: () => BrowserNotificationPushConfig | null;
|
|
39
|
+
/**
|
|
40
|
+
* Resolve config from the server's runtime pusher config, falling back to
|
|
41
|
+
* build-time values if the server is unreachable or has push disabled.
|
|
42
|
+
*/
|
|
43
|
+
readonly resolveConfig: () => Promise<BrowserNotificationPushConfig | null>;
|
|
44
|
+
/**
|
|
45
|
+
* Invalidate this device's endpoint before sign-out / account teardown,
|
|
46
|
+
* disabling via the resolved config when possible and always clearing the
|
|
47
|
+
* local subscription so a signed-out device is never woken.
|
|
48
|
+
*/
|
|
49
|
+
readonly clearBeforeSignOut: () => Promise<void>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Build a browser push config resolver for a single client identity. Promoted
|
|
53
|
+
* from the near-identical per-app resolvers in the yurucommu and yurume web
|
|
54
|
+
* clients so the fetch/fallback/clear flow lives in one place.
|
|
55
|
+
*/
|
|
56
|
+
export declare function createBrowserPushConfigResolver(options: BrowserPushConfigResolverOptions): BrowserPushConfigResolver;
|
|
57
|
+
//# sourceMappingURL=push-config.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-config.d.ts","sourceRoot":"","sources":["../../../src/lib/api/push-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,yBAAyB,EAAE,MAAM,sBAAsB,CAAC;AACtE,OAAO,EAGL,KAAK,6BAA6B,EACnC,MAAM,mBAAmB,CAAC;AAG3B;;;;GAIG;AACH,MAAM,WAAW,yBAAyB;IACxC,QAAQ,CAAC,OAAO,EAAE,yBAAyB,CAAC;IAC5C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,kFAAkF;IAClF,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;CACxB;AAED,8EAA8E;AAC9E,MAAM,WAAW,wBAAwB;IACvC,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACpC,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CACzC;AAED,MAAM,WAAW,gCAAgC;IAC/C,QAAQ,CAAC,QAAQ,EAAE,yBAAyB,CAAC;IAC7C;;;;OAIG;IACH,QAAQ,CAAC,mBAAmB,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAClD;;;OAGG;IACH,QAAQ,CAAC,eAAe,CAAC,EAAE,MAAM,wBAAwB,GAAG,IAAI,CAAC;CAClE;AAED,MAAM,WAAW,yBAAyB;IACxC,6DAA6D;IAC7D,QAAQ,CAAC,eAAe,EAAE,MAAM,6BAA6B,GAAG,IAAI,CAAC;IACrE;;;OAGG;IACH,QAAQ,CAAC,aAAa,EAAE,MAAM,OAAO,CAAC,6BAA6B,GAAG,IAAI,CAAC,CAAC;IAC5E;;;;OAIG;IACH,QAAQ,CAAC,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CAClD;AAED;;;;GAIG;AACH,wBAAgB,+BAA+B,CAC7C,OAAO,EAAE,gCAAgC,GACxC,yBAAyB,CAgE3B"}
|
package/dist/lib/api.d.ts
CHANGED
|
@@ -7,7 +7,9 @@ export * from "./api/posts.js";
|
|
|
7
7
|
export * from "./api/communities.js";
|
|
8
8
|
export * from "./api/dm.js";
|
|
9
9
|
export * from "./api/notifications.js";
|
|
10
|
+
export * from "./api/notification-target.js";
|
|
10
11
|
export * from "./api/browser-push.js";
|
|
12
|
+
export * from "./api/push-config.js";
|
|
11
13
|
export * from "./api/search.js";
|
|
12
14
|
export * from "./api/media.js";
|
|
13
15
|
export * from "./api/stories.js";
|
package/dist/lib/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/lib/api.ts"],"names":[],"mappings":"AAAA,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,eAAe,CAAC;AAC9B,cAAc,iBAAiB,CAAC;AAChC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC;AACrC,cAAc,aAAa,CAAC;AAC5B,cAAc,wBAAwB,CAAC;AACvC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,iBAAiB,CAAC;AAChC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,kBAAkB,CAAC;AACjC,cAAc,gBAAgB,CAAC;AAC/B,cAAc,0BAA0B,CAAC;AACzC,cAAc,qBAAqB,CAAC;AACpC,cAAc,oBAAoB,CAAC"}
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* CallClient — framework-agnostic browser WebRTC engine for the call feature.
|
|
3
|
+
*
|
|
4
|
+
* Owns the WebSocket to the per-user signaling hub (`/api/rtc/socket`), the
|
|
5
|
+
* `RTCPeerConnection` lifecycle, `getUserMedia`, half-trickle ICE, and the call
|
|
6
|
+
* state machine as the browser sees it. Both products (yurucommu / yurumeet)
|
|
7
|
+
* wrap this with their own reactive state layer (SolidJS signals / jotai) — no
|
|
8
|
+
* WebRTC logic is duplicated per product, and the wire protocol is single-
|
|
9
|
+
* sourced with the backend via `./types/call.ts`.
|
|
10
|
+
*
|
|
11
|
+
* 1:1 only for now: the caller offers, the callee answers, media is P2P over the
|
|
12
|
+
* server-provided ICE (STUN/TURN) servers. Camera on/off toggles the existing
|
|
13
|
+
* video track (no mid-call renegotiation, so no glare at the PC level).
|
|
14
|
+
*/
|
|
15
|
+
import type { CallMediaKind } from "../types/call.js";
|
|
16
|
+
export type CallUiState = "idle" | "calling" | "incoming" | "connecting" | "connected" | "ended";
|
|
17
|
+
export interface IncomingCallInfo {
|
|
18
|
+
callId: string;
|
|
19
|
+
from: string;
|
|
20
|
+
media: CallMediaKind;
|
|
21
|
+
}
|
|
22
|
+
export interface CallClientEvents {
|
|
23
|
+
state: (state: CallUiState) => void;
|
|
24
|
+
incoming: (info: IncomingCallInfo) => void;
|
|
25
|
+
localstream: (stream: MediaStream | null) => void;
|
|
26
|
+
remotestream: (stream: MediaStream | null) => void;
|
|
27
|
+
muted: (muted: boolean) => void;
|
|
28
|
+
cameraoff: (off: boolean) => void;
|
|
29
|
+
error: (code: string, message?: string) => void;
|
|
30
|
+
}
|
|
31
|
+
export interface CallClientOptions {
|
|
32
|
+
/** Origin the app is served from (defaults to the page origin). */
|
|
33
|
+
origin?: string;
|
|
34
|
+
/** WebSocket reconnect backoff ceiling (ms). */
|
|
35
|
+
maxBackoffMs?: number;
|
|
36
|
+
}
|
|
37
|
+
export declare class CallClient {
|
|
38
|
+
private readonly options;
|
|
39
|
+
private ws;
|
|
40
|
+
private wantConnected;
|
|
41
|
+
private backoff;
|
|
42
|
+
private reconnectTimer;
|
|
43
|
+
private readonly listeners;
|
|
44
|
+
private call;
|
|
45
|
+
private localStream;
|
|
46
|
+
private state;
|
|
47
|
+
constructor(options?: CallClientOptions);
|
|
48
|
+
on<K extends keyof CallClientEvents>(event: K, listener: CallClientEvents[K]): () => void;
|
|
49
|
+
private emit;
|
|
50
|
+
private setState;
|
|
51
|
+
getState(): CallUiState;
|
|
52
|
+
private origin;
|
|
53
|
+
private socketUrl;
|
|
54
|
+
connect(): void;
|
|
55
|
+
disconnect(): void;
|
|
56
|
+
private openSocket;
|
|
57
|
+
private scheduleReconnect;
|
|
58
|
+
private send;
|
|
59
|
+
/** Place an outgoing call. Fetches a callId + ICE, then rings the peer. */
|
|
60
|
+
startCall(peer: string, media: CallMediaKind): Promise<void>;
|
|
61
|
+
/** Accept the current incoming call. */
|
|
62
|
+
accept(): Promise<void>;
|
|
63
|
+
/** Decline the current incoming call. */
|
|
64
|
+
reject(reason?: string): void;
|
|
65
|
+
/** Hang up / cancel the active call. */
|
|
66
|
+
hangup(reason?: string): void;
|
|
67
|
+
setMuted(muted: boolean): void;
|
|
68
|
+
setCameraEnabled(enabled: boolean): void;
|
|
69
|
+
private onFrame;
|
|
70
|
+
private onRinging;
|
|
71
|
+
private onCallState;
|
|
72
|
+
private onRemoteOffer;
|
|
73
|
+
private onRemoteAnswer;
|
|
74
|
+
private onRemoteCandidates;
|
|
75
|
+
private drainRemoteCandidates;
|
|
76
|
+
private setupMedia;
|
|
77
|
+
private buildPeerConnection;
|
|
78
|
+
private makeOffer;
|
|
79
|
+
private bufferCandidate;
|
|
80
|
+
private flushCandidates;
|
|
81
|
+
private newCall;
|
|
82
|
+
private teardown;
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=rtc-client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rtc-client.d.ts","sourceRoot":"","sources":["../../src/lib/rtc-client.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,KAAK,EACV,aAAa,EAId,MAAM,kBAAkB,CAAC;AAE1B,MAAM,MAAM,WAAW,GACnB,MAAM,GACN,SAAS,GACT,UAAU,GACV,YAAY,GACZ,WAAW,GACX,OAAO,CAAC;AAEZ,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,aAAa,CAAC;CACtB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,CAAC,KAAK,EAAE,WAAW,KAAK,IAAI,CAAC;IACpC,QAAQ,EAAE,CAAC,IAAI,EAAE,gBAAgB,KAAK,IAAI,CAAC;IAC3C,WAAW,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IAClD,YAAY,EAAE,CAAC,MAAM,EAAE,WAAW,GAAG,IAAI,KAAK,IAAI,CAAC;IACnD,KAAK,EAAE,CAAC,KAAK,EAAE,OAAO,KAAK,IAAI,CAAC;IAChC,SAAS,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAClC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,KAAK,IAAI,CAAC;CACjD;AAED,MAAM,WAAW,iBAAiB;IAChC,mEAAmE;IACnE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,gDAAgD;IAChD,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAmBD,qBAAa,UAAU;IAUT,OAAO,CAAC,QAAQ,CAAC,OAAO;IATpC,OAAO,CAAC,EAAE,CAA0B;IACpC,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAO;IACtB,OAAO,CAAC,cAAc,CAA8C;IACpE,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAoD;IAC9E,OAAO,CAAC,IAAI,CAA2B;IACvC,OAAO,CAAC,WAAW,CAA4B;IAC/C,OAAO,CAAC,KAAK,CAAuB;gBAEP,OAAO,GAAE,iBAAsB;IAG5D,EAAE,CAAC,CAAC,SAAS,MAAM,gBAAgB,EACjC,KAAK,EAAE,CAAC,EACR,QAAQ,EAAE,gBAAgB,CAAC,CAAC,CAAC,GAC5B,MAAM,IAAI;IAUb,OAAO,CAAC,IAAI;IASZ,OAAO,CAAC,QAAQ;IAMhB,QAAQ,IAAI,WAAW;IAKvB,OAAO,CAAC,MAAM;IAOd,OAAO,CAAC,SAAS;IAKjB,OAAO,IAAI,IAAI;IAKf,UAAU,IAAI,IAAI;IAQlB,OAAO,CAAC,UAAU;IA4BlB,OAAO,CAAC,iBAAiB;IAWzB,OAAO,CAAC,IAAI;IAQZ,2EAA2E;IACrE,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IA+BlE,wCAAwC;IAClC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAc7B,yCAAyC;IACzC,MAAM,CAAC,MAAM,SAAa,GAAG,IAAI;IAOjC,wCAAwC;IACxC,MAAM,CAAC,MAAM,SAAW,GAAG,IAAI;IAO/B,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,IAAI;IAO9B,gBAAgB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI;YAQ1B,OAAO;IAiDrB,OAAO,CAAC,SAAS;IAuBjB,OAAO,CAAC,WAAW;YAeL,aAAa;YAsBb,cAAc;YAUd,kBAAkB;YAkBlB,qBAAqB;YAarB,UAAU;IAoBxB,OAAO,CAAC,mBAAmB;YA2Bb,SAAS;IAOvB,OAAO,CAAC,eAAe;IASvB,OAAO,CAAC,eAAe;IAevB,OAAO,CAAC,OAAO;IAqBf,OAAO,CAAC,QAAQ;CA0BjB"}
|
package/dist/social-server.d.ts
CHANGED
|
@@ -14,6 +14,11 @@ export interface SocialServerDiscovery {
|
|
|
14
14
|
readonly defaultEntry: "feed" | "messages";
|
|
15
15
|
}[];
|
|
16
16
|
readonly issuer: string;
|
|
17
|
+
readonly oidcClientId?: string;
|
|
18
|
+
readonly auth?: {
|
|
19
|
+
readonly oidc: boolean;
|
|
20
|
+
readonly password: boolean;
|
|
21
|
+
};
|
|
17
22
|
readonly apiBaseUrl: string;
|
|
18
23
|
readonly activitypubOrigin: string;
|
|
19
24
|
readonly mediaOrigin: string;
|
|
@@ -22,6 +27,8 @@ export interface SocialServerDiscovery {
|
|
|
22
27
|
readonly endpoints: {
|
|
23
28
|
readonly api: string;
|
|
24
29
|
readonly authProviders: string;
|
|
30
|
+
readonly mobilePasswordLogin: string;
|
|
31
|
+
readonly mobileOidcExchange: string;
|
|
25
32
|
readonly currentUser: string;
|
|
26
33
|
readonly timeline: string;
|
|
27
34
|
readonly conversations: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"social-server.d.ts","sourceRoot":"","sources":["../src/social-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,EAAE,EAAE,kBAAkB,CAAC;QAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;KACpC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,QAAQ,CAAC;QACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAAC;KAC5C,EAAE,CAAC;IACJ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;QACrC,2CAA2C;QAC3C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;KAC1C,CAAC;CACH;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAM/D;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAIjF"}
|
|
1
|
+
{"version":3,"file":"social-server.d.ts","sourceRoot":"","sources":["../src/social-server.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,MAAM,EAAE;QACf,QAAQ,CAAC,EAAE,EAAE,kBAAkB,CAAC;QAChC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;QACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;KACpC,CAAC;IACF,QAAQ,CAAC,OAAO,EAAE,SAAS;QACzB,QAAQ,CAAC,EAAE,EAAE,WAAW,GAAG,QAAQ,CAAC;QACpC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;QACtB,QAAQ,CAAC,YAAY,EAAE,MAAM,GAAG,UAAU,CAAC;KAC5C,EAAE,CAAC;IACJ,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,IAAI,CAAC,EAAE;QACd,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;QACvB,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;KAC5B,CAAC;IACF,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;IAC7B,QAAQ,CAAC,2BAA2B,EAAE,MAAM,CAAC;IAC7C,QAAQ,CAAC,YAAY,EAAE,SAAS,MAAM,EAAE,CAAC;IACzC,QAAQ,CAAC,SAAS,EAAE;QAClB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;QACrC,QAAQ,CAAC,kBAAkB,EAAE,MAAM,CAAC;QACpC,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAC;QAC7B,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;QAC1B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;QAC/B,QAAQ,CAAC,mBAAmB,EAAE,MAAM,CAAC;QACrC,2CAA2C;QAC3C,QAAQ,CAAC,uBAAuB,EAAE,MAAM,CAAC;KAC1C,CAAC;CACH;AAED,wBAAsB,iBAAiB,IAAI,OAAO,CAAC,KAAK,GAAG,IAAI,CAAC,CAM/D;AAED,wBAAsB,0BAA0B,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAIjF"}
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Call signaling wire contract (voice + video).
|
|
3
|
+
*
|
|
4
|
+
* SINGLE SOURCE OF TRUTH shared by:
|
|
5
|
+
* - the backend cross-instance signaling ingest (`/ap/rtc/signal`) + the
|
|
6
|
+
* Signaling Durable Object (server-to-server + browser fan-out), and
|
|
7
|
+
* - the browser `CallClient` (`../lib/rtc-client.ts`).
|
|
8
|
+
*
|
|
9
|
+
* Kept deliberately DOM-structural (no `RTCIceCandidateInit` / `RTCIceServer`
|
|
10
|
+
* imports) so the same file type-checks in the server context (which never runs
|
|
11
|
+
* the browser WebRTC APIs) and the browser bundle. The `CallClient` maps these
|
|
12
|
+
* structural shapes to/from the real DOM `RTCSessionDescriptionInit` /
|
|
13
|
+
* `RTCIceCandidateInit` / `RTCIceServer`, which are structurally compatible.
|
|
14
|
+
*
|
|
15
|
+
* Design: signaling travels over federation (server-to-server, HTTP-Signature
|
|
16
|
+
* authenticated) as `RtcSignalEnvelopeV1`; media is P2P WebRTC + STUN/TURN for
|
|
17
|
+
* 1:1 (`sfuFocus: null`) and a pluggable WHIP/WHEP SFU focus for group calls.
|
|
18
|
+
*/
|
|
19
|
+
export declare const RTC_SIGNAL_ENVELOPE_VERSION: 1;
|
|
20
|
+
/** Which media tracks a call carries. `video:false` => audio-only call. */
|
|
21
|
+
export interface CallMediaKind {
|
|
22
|
+
audio: boolean;
|
|
23
|
+
video: boolean;
|
|
24
|
+
}
|
|
25
|
+
/** Cross-instance signaling message kinds (Matrix-VoIP inspired). */
|
|
26
|
+
export type RtcSignalType = "offer" | "answer" | "candidate" | "accept" | "reject" | "hangup" | "cancel";
|
|
27
|
+
/**
|
|
28
|
+
* Selected SFU focus for a group call. `null`/absent means pure P2P (1:1).
|
|
29
|
+
* `kind` names the adapter (`whip` / `livekit` / `cloudflare-realtime` / ...);
|
|
30
|
+
* the client talks WHIP/WHEP so the SFU backend stays vendor-neutral.
|
|
31
|
+
*/
|
|
32
|
+
export interface SfuFocus {
|
|
33
|
+
kind: string;
|
|
34
|
+
/** WHIP (publish) / WHEP (subscribe) endpoint base, or SFU signaling URL. */
|
|
35
|
+
url: string;
|
|
36
|
+
/** Short-lived join token when the adapter requires one. */
|
|
37
|
+
token?: string;
|
|
38
|
+
room?: string;
|
|
39
|
+
}
|
|
40
|
+
/** Structural mirror of `RTCIceCandidateInit` (no DOM dependency). */
|
|
41
|
+
export interface CallIceCandidate {
|
|
42
|
+
candidate: string;
|
|
43
|
+
sdpMid?: string | null;
|
|
44
|
+
sdpMLineIndex?: number | null;
|
|
45
|
+
usernameFragment?: string | null;
|
|
46
|
+
}
|
|
47
|
+
/** Structural mirror of `RTCIceServer` (no DOM dependency). */
|
|
48
|
+
export interface IceServerConfig {
|
|
49
|
+
urls: string | string[];
|
|
50
|
+
username?: string;
|
|
51
|
+
credential?: string;
|
|
52
|
+
}
|
|
53
|
+
/**
|
|
54
|
+
* Server-to-server signaling envelope. Delivered by the sending instance to the
|
|
55
|
+
* recipient instance's `/ap/rtc/signal` endpoint, signed with the sender actor's
|
|
56
|
+
* HTTP Signature key (keyId-owner === `from`). `callId` doubles as the anti-
|
|
57
|
+
* replay nonce; `ts`/`ttlMs` bound its freshness (the DO drops stale frames).
|
|
58
|
+
*/
|
|
59
|
+
export interface RtcSignalEnvelopeV1 {
|
|
60
|
+
v: typeof RTC_SIGNAL_ENVELOPE_VERSION;
|
|
61
|
+
callId: string;
|
|
62
|
+
from: string;
|
|
63
|
+
to: string;
|
|
64
|
+
type: RtcSignalType;
|
|
65
|
+
media?: CallMediaKind;
|
|
66
|
+
/** SDP for `offer` / `answer`. */
|
|
67
|
+
sdp?: string;
|
|
68
|
+
/** Half-trickle ICE bundle for `offer` / `answer` / `candidate`. */
|
|
69
|
+
candidates?: CallIceCandidate[];
|
|
70
|
+
sfuFocus?: SfuFocus | null;
|
|
71
|
+
/** Free-text end/reject reason (`busy`, `declined`, `timeout`, ...). */
|
|
72
|
+
reason?: string;
|
|
73
|
+
ts: number;
|
|
74
|
+
ttlMs: number;
|
|
75
|
+
}
|
|
76
|
+
/** Lifecycle of a single call, mirrored client-side and in `call_sessions`. */
|
|
77
|
+
export type CallState = "idle" | "ringing" | "connecting" | "connected" | "ended" | "rejected" | "missed" | "failed" | "cancelled";
|
|
78
|
+
export type CallDirection = "incoming" | "outgoing";
|
|
79
|
+
/** Terminal states — a call in one of these is over and not resumable. */
|
|
80
|
+
export declare const TERMINAL_CALL_STATES: readonly CallState[];
|
|
81
|
+
export declare function isTerminalCallState(state: CallState): boolean;
|
|
82
|
+
/** Frames the browser sends up to its own instance's Signaling DO. */
|
|
83
|
+
export type ClientToHubFrame = {
|
|
84
|
+
t: "hello";
|
|
85
|
+
} | {
|
|
86
|
+
t: "invite";
|
|
87
|
+
callId: string;
|
|
88
|
+
to: string;
|
|
89
|
+
media: CallMediaKind;
|
|
90
|
+
} | {
|
|
91
|
+
t: "offer";
|
|
92
|
+
callId: string;
|
|
93
|
+
sdp: string;
|
|
94
|
+
} | {
|
|
95
|
+
t: "answer";
|
|
96
|
+
callId: string;
|
|
97
|
+
sdp: string;
|
|
98
|
+
} | {
|
|
99
|
+
t: "candidates";
|
|
100
|
+
callId: string;
|
|
101
|
+
candidates: CallIceCandidate[];
|
|
102
|
+
} | {
|
|
103
|
+
t: "accept";
|
|
104
|
+
callId: string;
|
|
105
|
+
} | {
|
|
106
|
+
t: "reject";
|
|
107
|
+
callId: string;
|
|
108
|
+
reason?: string;
|
|
109
|
+
} | {
|
|
110
|
+
t: "hangup";
|
|
111
|
+
callId: string;
|
|
112
|
+
reason?: string;
|
|
113
|
+
} | {
|
|
114
|
+
t: "resume";
|
|
115
|
+
callId: string;
|
|
116
|
+
} | {
|
|
117
|
+
t: "ping";
|
|
118
|
+
};
|
|
119
|
+
/** Frames the Signaling DO pushes down to the browser. */
|
|
120
|
+
export type HubToClientFrame = {
|
|
121
|
+
t: "ready";
|
|
122
|
+
} | {
|
|
123
|
+
t: "ringing";
|
|
124
|
+
callId: string;
|
|
125
|
+
from: string;
|
|
126
|
+
media: CallMediaKind;
|
|
127
|
+
} | {
|
|
128
|
+
t: "offer";
|
|
129
|
+
callId: string;
|
|
130
|
+
sdp: string;
|
|
131
|
+
media?: CallMediaKind;
|
|
132
|
+
} | {
|
|
133
|
+
t: "answer";
|
|
134
|
+
callId: string;
|
|
135
|
+
sdp: string;
|
|
136
|
+
} | {
|
|
137
|
+
t: "candidates";
|
|
138
|
+
callId: string;
|
|
139
|
+
candidates: CallIceCandidate[];
|
|
140
|
+
} | {
|
|
141
|
+
t: "peer-accepted";
|
|
142
|
+
callId: string;
|
|
143
|
+
} | {
|
|
144
|
+
t: "peer-rejected";
|
|
145
|
+
callId: string;
|
|
146
|
+
reason?: string;
|
|
147
|
+
} | {
|
|
148
|
+
t: "peer-hangup";
|
|
149
|
+
callId: string;
|
|
150
|
+
reason?: string;
|
|
151
|
+
} | {
|
|
152
|
+
t: "ice-servers";
|
|
153
|
+
callId: string;
|
|
154
|
+
iceServers: IceServerConfig[];
|
|
155
|
+
sfuFocus?: SfuFocus | null;
|
|
156
|
+
} | {
|
|
157
|
+
t: "call-state";
|
|
158
|
+
callId: string;
|
|
159
|
+
state: CallState;
|
|
160
|
+
} | {
|
|
161
|
+
t: "pong";
|
|
162
|
+
} | {
|
|
163
|
+
t: "error";
|
|
164
|
+
code: string;
|
|
165
|
+
message?: string;
|
|
166
|
+
};
|
|
167
|
+
export interface StartCallRequest {
|
|
168
|
+
to: string;
|
|
169
|
+
media: CallMediaKind;
|
|
170
|
+
}
|
|
171
|
+
export interface StartCallResponse {
|
|
172
|
+
callId: string;
|
|
173
|
+
iceServers: IceServerConfig[];
|
|
174
|
+
sfuFocus?: SfuFocus | null;
|
|
175
|
+
}
|
|
176
|
+
export interface IceServersResponse {
|
|
177
|
+
iceServers: IceServerConfig[];
|
|
178
|
+
}
|
|
179
|
+
export interface CallSessionSummary {
|
|
180
|
+
id: string;
|
|
181
|
+
peer: string;
|
|
182
|
+
direction: CallDirection;
|
|
183
|
+
state: CallState;
|
|
184
|
+
media: CallMediaKind;
|
|
185
|
+
createdAt: string;
|
|
186
|
+
connectedAt?: string | null;
|
|
187
|
+
endedAt?: string | null;
|
|
188
|
+
endReason?: string | null;
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Parse + validate an inbound cross-instance signaling envelope. Returns the
|
|
192
|
+
* normalized envelope or `null` when the shape is invalid. Callers additionally
|
|
193
|
+
* enforce that the HTTP-Signature signer equals `from` and that the recipient
|
|
194
|
+
* (`to`) is a local actor.
|
|
195
|
+
*/
|
|
196
|
+
export declare function parseRtcSignalEnvelope(input: unknown): RtcSignalEnvelopeV1 | null;
|
|
197
|
+
/** True when the envelope is still within its freshness window. */
|
|
198
|
+
export declare function isEnvelopeFresh(envelope: RtcSignalEnvelopeV1, now: number): boolean;
|
|
199
|
+
//# sourceMappingURL=call.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"call.d.ts","sourceRoot":"","sources":["../../src/types/call.ts"],"names":[],"mappings":"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"}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export * from "./call.js";
|
|
1
2
|
export interface Actor {
|
|
2
3
|
ap_id: string;
|
|
3
4
|
username: string;
|
|
@@ -97,13 +98,20 @@ export interface Notification {
|
|
|
97
98
|
type: "follow" | "follow_request" | "like" | "announce" | "reply" | "mention";
|
|
98
99
|
actor: NotificationActor;
|
|
99
100
|
object_ap_id: string | null;
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
101
|
+
/**
|
|
102
|
+
* Navigation target for the notification. OPTIONAL: a server older than
|
|
103
|
+
* 3.2.0 omits these fields, and `normalizeNotification` then synthesizes them
|
|
104
|
+
* from `object_ap_id`. Prefer `target_kind` + `target_id` and build your own
|
|
105
|
+
* in-app path; `target_url` is shaped for the yurucommu web client's routing
|
|
106
|
+
* and is same-origin only — never treat it as an external URL.
|
|
107
|
+
*/
|
|
108
|
+
target_kind?: NotificationTargetKind;
|
|
109
|
+
target_id?: string | null;
|
|
110
|
+
target_url?: string;
|
|
104
111
|
read: boolean;
|
|
105
112
|
created_at: string;
|
|
106
113
|
}
|
|
114
|
+
export type NotificationTargetKind = "post" | "story" | "profile" | "notifications";
|
|
107
115
|
export type NotificationPusherProduct = "yurucommu" | "yurume";
|
|
108
116
|
export interface NotificationPusherInput {
|
|
109
117
|
kind: "http";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/types/index.ts"],"names":[],"mappings":"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"}
|