@scp-dev/hub 0.3.1 → 0.4.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 +24 -1
- package/dist/index.js +27 -1
- package/package.json +1 -1
- package/src/hub.ts +37 -0
- package/src/index.ts +2 -0
package/dist/index.d.ts
CHANGED
|
@@ -593,6 +593,26 @@ interface HubGraph {
|
|
|
593
593
|
/** the default and widest window of message edges; the core keeps an hour of sender and recipient pairs */
|
|
594
594
|
declare const GRAPH_MINUTES = 15;
|
|
595
595
|
declare const GRAPH_MINUTES_MAX = 60;
|
|
596
|
+
/** what a read-only dashboard stream sees as it happens: addresses, kinds and presence, never a body, note, summary or label */
|
|
597
|
+
type DashboardEvent = {
|
|
598
|
+
type: "presence";
|
|
599
|
+
at: string;
|
|
600
|
+
machine: string | null;
|
|
601
|
+
endpoint: string;
|
|
602
|
+
presence: Presence;
|
|
603
|
+
} | {
|
|
604
|
+
type: "message";
|
|
605
|
+
at: string;
|
|
606
|
+
kind: string;
|
|
607
|
+
from: string;
|
|
608
|
+
to: string[];
|
|
609
|
+
} | {
|
|
610
|
+
type: "endpoints";
|
|
611
|
+
at: string;
|
|
612
|
+
machine: string;
|
|
613
|
+
};
|
|
614
|
+
/** a watcher's fleet event as a dashboard sees it, field by field; null for the kinds a dashboard does not stream */
|
|
615
|
+
declare function dashboardEvent(event: Record<string, unknown>, at: string): DashboardEvent | null;
|
|
596
616
|
interface HubSocket {
|
|
597
617
|
conn: HubConn;
|
|
598
618
|
send(text: string): void;
|
|
@@ -611,6 +631,8 @@ interface HubDeps {
|
|
|
611
631
|
save(socket: HubSocket): void;
|
|
612
632
|
/** structured log line, e.g. relay_action; never bodies or tokens */
|
|
613
633
|
log?: (event: string, fields: Record<string, unknown>) => void;
|
|
634
|
+
/** live presence, endpoint and message metadata for a read-only dashboard; never a body */
|
|
635
|
+
dashboard?: (event: DashboardEvent) => void;
|
|
614
636
|
/** overrides of {@link HUB_LIMITS}; `Infinity` disables a cap, count or byte limit, durations stay finite */
|
|
615
637
|
limits?: Partial<HubLimits>;
|
|
616
638
|
/** the link to other accounts' relays; without it an address of another account is not found */
|
|
@@ -793,6 +815,7 @@ declare class RelayHub {
|
|
|
793
815
|
/** the machines of other members than the grant's, which a bridge shows under the account handle */
|
|
794
816
|
private othersOf;
|
|
795
817
|
private fleet;
|
|
818
|
+
private dash;
|
|
796
819
|
private write;
|
|
797
820
|
private save;
|
|
798
821
|
private waitMs;
|
|
@@ -842,4 +865,4 @@ declare class RelayHub {
|
|
|
842
865
|
xnotice(endpoint: string, text: string): void;
|
|
843
866
|
}
|
|
844
867
|
|
|
845
|
-
export { type Deliver, type Delivery, FederatedCore, type FederatedOptions, GRAPH_MINUTES, GRAPH_MINUTES_MAX, type GraphEdge, type GraphNode, HUB_LIMITS, type HoldView, type HubAuth, type HubConn, type HubDeps, type HubGrant, type HubGraph, type HubJudgeOptions, type HubLimits, type HubRole, type HubSocket, JUDGE_LIMITS, type JudgeClientFactory, JudgeGate, type JudgeGateOptions, type JudgeLimits, type Origin as JudgeOrigin, MACHINE_NAME, type MachineRow, type MirrorCaps, type MirrorChange, type MirrorRules, type MirrorScope, type MirrorView, type RelayAuth, RelayHub, type RemoteView, type XEndpoint };
|
|
868
|
+
export { type DashboardEvent, type Deliver, type Delivery, FederatedCore, type FederatedOptions, GRAPH_MINUTES, GRAPH_MINUTES_MAX, type GraphEdge, type GraphNode, HUB_LIMITS, type HoldView, type HubAuth, type HubConn, type HubDeps, type HubGrant, type HubGraph, type HubJudgeOptions, type HubLimits, type HubRole, type HubSocket, JUDGE_LIMITS, type JudgeClientFactory, JudgeGate, type JudgeGateOptions, type JudgeLimits, type Origin as JudgeOrigin, MACHINE_NAME, type MachineRow, type MirrorCaps, type MirrorChange, type MirrorRules, type MirrorScope, type MirrorView, type RelayAuth, RelayHub, type RemoteView, type XEndpoint, dashboardEvent };
|
package/dist/index.js
CHANGED
|
@@ -2012,6 +2012,20 @@ function heldResult(id, params) {
|
|
|
2012
2012
|
// src/hub.ts
|
|
2013
2013
|
var GRAPH_MINUTES = 15;
|
|
2014
2014
|
var GRAPH_MINUTES_MAX = 60;
|
|
2015
|
+
var str = (v) => typeof v === "string" ? v : null;
|
|
2016
|
+
function dashboardEvent(event, at) {
|
|
2017
|
+
if (event.type === "message") {
|
|
2018
|
+
const from = str(event.from);
|
|
2019
|
+
const to = Array.isArray(event.to) ? event.to.filter((a) => typeof a === "string") : [];
|
|
2020
|
+
return from && to.length ? { type: "message", at, kind: str(event.kind) ?? "message", from, to } : null;
|
|
2021
|
+
}
|
|
2022
|
+
if (event.type === "presence") {
|
|
2023
|
+
const endpoint = str(event.endpoint);
|
|
2024
|
+
const presence = event.presence === "online" || event.presence === "idle" || event.presence === "offline" ? event.presence : null;
|
|
2025
|
+
return endpoint && presence ? { type: "presence", at, machine: str(event.machine), endpoint, presence } : null;
|
|
2026
|
+
}
|
|
2027
|
+
return null;
|
|
2028
|
+
}
|
|
2015
2029
|
var HUB_LIMITS = {
|
|
2016
2030
|
machines: 16,
|
|
2017
2031
|
endpoints: 512,
|
|
@@ -3170,6 +3184,7 @@ var RelayHub = class _RelayHub {
|
|
|
3170
3184
|
this.fleet({ type: "presence", machine, endpoint: view.address, presence: view.presence, harness: view.harness, labels: view.labels });
|
|
3171
3185
|
if (change.status && !change.added) this.fleet({ type: "status", machine, endpoint: view.address, status: view.status });
|
|
3172
3186
|
}
|
|
3187
|
+
if (full || changes.some((c) => c.added || c.was !== void 0)) this.dash({ type: "endpoints", at: new Date(this.now()).toISOString(), machine });
|
|
3173
3188
|
}
|
|
3174
3189
|
/** a direct client's endpoint changed: the other bridges mirror it */
|
|
3175
3190
|
announceEndpoint(endpoint) {
|
|
@@ -3194,6 +3209,15 @@ var RelayHub = class _RelayHub {
|
|
|
3194
3209
|
fleet(event) {
|
|
3195
3210
|
const at = new Date(this.now()).toISOString();
|
|
3196
3211
|
for (const socket of this.deps.sockets()) if (socket.conn.watching) this.write(socket, { jsonrpc: "2.0", method: "fleet", params: { at, ...event } });
|
|
3212
|
+
const dash = this.deps.dashboard ? dashboardEvent(event, at) : null;
|
|
3213
|
+
if (dash) this.dash(dash);
|
|
3214
|
+
}
|
|
3215
|
+
dash(event) {
|
|
3216
|
+
try {
|
|
3217
|
+
this.deps.dashboard?.(event);
|
|
3218
|
+
} catch {
|
|
3219
|
+
this.deps.log?.("relay_dashboard_failed", { account: this.account });
|
|
3220
|
+
}
|
|
3197
3221
|
}
|
|
3198
3222
|
write(socket, value) {
|
|
3199
3223
|
if (this.gone.has(socket.conn.id)) return;
|
|
@@ -3386,6 +3410,7 @@ var RelayHub = class _RelayHub {
|
|
|
3386
3410
|
});
|
|
3387
3411
|
this.stored = null;
|
|
3388
3412
|
this.toBridges(name, { machine: name, endpoints: [], full: true });
|
|
3413
|
+
this.dash({ type: "endpoints", at: new Date(this.now()).toISOString(), machine: name });
|
|
3389
3414
|
this.deps.log?.("relay_action", { account: this.account, machine: name, method: "machine_release", code: "ok" });
|
|
3390
3415
|
return { removed: name, endpoints: dropped };
|
|
3391
3416
|
}
|
|
@@ -3498,5 +3523,6 @@ export {
|
|
|
3498
3523
|
JUDGE_LIMITS,
|
|
3499
3524
|
JudgeGate,
|
|
3500
3525
|
MACHINE_NAME,
|
|
3501
|
-
RelayHub
|
|
3526
|
+
RelayHub,
|
|
3527
|
+
dashboardEvent
|
|
3502
3528
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scp-dev/hub",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Swarm Communication Protocol federation and account hub: mirrored endpoints across machines, bridges, direct clients and cross-account delivery.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"homepage": "https://scp.dev",
|
package/src/hub.ts
CHANGED
|
@@ -123,6 +123,29 @@ export interface HubGraph {
|
|
|
123
123
|
export const GRAPH_MINUTES = 15
|
|
124
124
|
export const GRAPH_MINUTES_MAX = 60
|
|
125
125
|
|
|
126
|
+
/** what a read-only dashboard stream sees as it happens: addresses, kinds and presence, never a body, note, summary or label */
|
|
127
|
+
export type DashboardEvent =
|
|
128
|
+
| { type: "presence"; at: string; machine: string | null; endpoint: string; presence: Presence }
|
|
129
|
+
| { type: "message"; at: string; kind: string; from: string; to: string[] }
|
|
130
|
+
| { type: "endpoints"; at: string; machine: string }
|
|
131
|
+
|
|
132
|
+
const str = (v: unknown): string | null => (typeof v === "string" ? v : null)
|
|
133
|
+
|
|
134
|
+
/** a watcher's fleet event as a dashboard sees it, field by field; null for the kinds a dashboard does not stream */
|
|
135
|
+
export function dashboardEvent(event: Record<string, unknown>, at: string): DashboardEvent | null {
|
|
136
|
+
if (event.type === "message") {
|
|
137
|
+
const from = str(event.from)
|
|
138
|
+
const to = Array.isArray(event.to) ? event.to.filter((a): a is string => typeof a === "string") : []
|
|
139
|
+
return from && to.length ? { type: "message", at, kind: str(event.kind) ?? "message", from, to } : null
|
|
140
|
+
}
|
|
141
|
+
if (event.type === "presence") {
|
|
142
|
+
const endpoint = str(event.endpoint)
|
|
143
|
+
const presence = event.presence === "online" || event.presence === "idle" || event.presence === "offline" ? event.presence : null
|
|
144
|
+
return endpoint && presence ? { type: "presence", at, machine: str(event.machine), endpoint, presence } : null
|
|
145
|
+
}
|
|
146
|
+
return null
|
|
147
|
+
}
|
|
148
|
+
|
|
126
149
|
export interface HubSocket {
|
|
127
150
|
conn: HubConn
|
|
128
151
|
send(text: string): void
|
|
@@ -142,6 +165,8 @@ export interface HubDeps {
|
|
|
142
165
|
save(socket: HubSocket): void
|
|
143
166
|
/** structured log line, e.g. relay_action; never bodies or tokens */
|
|
144
167
|
log?: (event: string, fields: Record<string, unknown>) => void
|
|
168
|
+
/** live presence, endpoint and message metadata for a read-only dashboard; never a body */
|
|
169
|
+
dashboard?: (event: DashboardEvent) => void
|
|
145
170
|
/** overrides of {@link HUB_LIMITS}; `Infinity` disables a cap, count or byte limit, durations stay finite */
|
|
146
171
|
limits?: Partial<HubLimits>
|
|
147
172
|
/** the link to other accounts' relays; without it an address of another account is not found */
|
|
@@ -1431,6 +1456,7 @@ export class RelayHub {
|
|
|
1431
1456
|
this.fleet({ type: "presence", machine, endpoint: view.address, presence: view.presence, harness: view.harness, labels: view.labels })
|
|
1432
1457
|
if (change.status && !change.added) this.fleet({ type: "status", machine, endpoint: view.address, status: view.status })
|
|
1433
1458
|
}
|
|
1459
|
+
if (full || changes.some((c) => c.added || c.was !== undefined)) this.dash({ type: "endpoints", at: new Date(this.now()).toISOString(), machine })
|
|
1434
1460
|
}
|
|
1435
1461
|
|
|
1436
1462
|
/** a direct client's endpoint changed: the other bridges mirror it */
|
|
@@ -1461,6 +1487,16 @@ export class RelayHub {
|
|
|
1461
1487
|
private fleet(event: Record<string, unknown>): void {
|
|
1462
1488
|
const at = new Date(this.now()).toISOString()
|
|
1463
1489
|
for (const socket of this.deps.sockets()) if (socket.conn.watching) this.write(socket, { jsonrpc: "2.0", method: "fleet", params: { at, ...event } })
|
|
1490
|
+
const dash = this.deps.dashboard ? dashboardEvent(event, at) : null
|
|
1491
|
+
if (dash) this.dash(dash)
|
|
1492
|
+
}
|
|
1493
|
+
|
|
1494
|
+
private dash(event: DashboardEvent): void {
|
|
1495
|
+
try {
|
|
1496
|
+
this.deps.dashboard?.(event)
|
|
1497
|
+
} catch {
|
|
1498
|
+
this.deps.log?.("relay_dashboard_failed", { account: this.account })
|
|
1499
|
+
}
|
|
1464
1500
|
}
|
|
1465
1501
|
|
|
1466
1502
|
private write(socket: HubSocket, value: unknown): void {
|
|
@@ -1673,6 +1709,7 @@ export class RelayHub {
|
|
|
1673
1709
|
})
|
|
1674
1710
|
this.stored = null
|
|
1675
1711
|
this.toBridges(name, { machine: name, endpoints: [], full: true })
|
|
1712
|
+
this.dash({ type: "endpoints", at: new Date(this.now()).toISOString(), machine: name })
|
|
1676
1713
|
this.deps.log?.("relay_action", { account: this.account, machine: name, method: "machine_release", code: "ok" })
|
|
1677
1714
|
return { removed: name, endpoints: dropped }
|
|
1678
1715
|
}
|