@scp-dev/hub 0.3.0 → 0.3.1
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 +4 -2
- package/dist/index.js +5 -2
- package/package.json +2 -2
- package/src/federation.ts +8 -1
- package/src/hub.ts +3 -2
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as _scp_dev_core from '@scp-dev/core';
|
|
2
|
-
import { Envelope, RelayCore, CoreOptions, EndpointRow, PolicySubject, ScopeSubject, ScopeNode, ScopeDirection, Admission, MessageRow, EndpointView, ScopeCap, ScopeEntry, Claim, SendParams, SendResult, EndpointKind, Presence, StatusState, Verdict, JudgeModelConfig, JudgeClient, Sql, JudgePolicy, CrossAccountLink, XDelivered, XListed, ActivityRow, XRelease } from '@scp-dev/core';
|
|
2
|
+
import { Envelope, RelayCore, CoreOptions, EndpointRow, PolicySubject, ScopeSubject, ScopeNode, ScopeDirection, Admission, MessageRow, EndpointView, ScopeCap, ScopeEntry, Claim, SendParams, SendResult, EndpointKind, Presence, StatusState, Verdict, JudgeModelConfig, JudgeClient, Sql, JudgePolicy, Wake, CrossAccountLink, XDelivered, XListed, ActivityRow, XRelease } from '@scp-dev/core';
|
|
3
3
|
|
|
4
4
|
type RelayAuth = Envelope["from"]["auth"];
|
|
5
5
|
/** a machine name: one relay host of an account */
|
|
@@ -59,6 +59,8 @@ interface MirrorView extends MirrorScope {
|
|
|
59
59
|
presence?: Presence;
|
|
60
60
|
last_seen?: string | null;
|
|
61
61
|
title?: string | null;
|
|
62
|
+
/** an agent's {@link Wake}; a value this hub does not know is kept as none */
|
|
63
|
+
wake?: string | null;
|
|
62
64
|
/** the handle the endpoint had before a rename: its mirror is renamed in place */
|
|
63
65
|
was?: string;
|
|
64
66
|
}
|
|
@@ -567,7 +569,7 @@ interface GraphNode {
|
|
|
567
569
|
status: EndpointView["status"];
|
|
568
570
|
last_seen: string | null;
|
|
569
571
|
parent: string | null;
|
|
570
|
-
wake?:
|
|
572
|
+
wake?: Wake | null;
|
|
571
573
|
}
|
|
572
574
|
/** `spawn`: parent to child; `message`: sender to recipient, with the count and newest send in the graph's window */
|
|
573
575
|
type GraphEdge = {
|
package/dist/index.js
CHANGED
|
@@ -22,7 +22,8 @@ import {
|
|
|
22
22
|
unreachable,
|
|
23
23
|
validHandle,
|
|
24
24
|
validHarness,
|
|
25
|
-
validSelector
|
|
25
|
+
validSelector,
|
|
26
|
+
WAKES
|
|
26
27
|
} from "@scp-dev/core";
|
|
27
28
|
var MACHINE_NAME = /^[a-z0-9][a-z0-9-]{0,31}$/;
|
|
28
29
|
var REMOTE = /^[a-z0-9][a-z0-9._-]{0,63}\/([a-z0-9][a-z0-9._-]{0,62})?$/;
|
|
@@ -1283,7 +1284,7 @@ var FederatedCore = class extends RelayCore {
|
|
|
1283
1284
|
const was = this.view(before);
|
|
1284
1285
|
const presence = was.presence !== view.presence;
|
|
1285
1286
|
const status = before.status_state !== after.status_state || before.status_note !== after.status_note;
|
|
1286
|
-
const other = ["kind", "harness", "model", "cwd", "labels", "title", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"].some(
|
|
1287
|
+
const other = ["kind", "harness", "model", "cwd", "labels", "title", "wake", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"].some(
|
|
1287
1288
|
(field) => before[field] !== after[field]
|
|
1288
1289
|
);
|
|
1289
1290
|
return presence || status || other ? { view, added: false, presence, status } : null;
|
|
@@ -1351,6 +1352,7 @@ var FederatedCore = class extends RelayCore {
|
|
|
1351
1352
|
rules: rules === void 0 ? row.rules : rules && (rules.in || rules.out) ? JSON.stringify(rules) : null,
|
|
1352
1353
|
caps,
|
|
1353
1354
|
title: scope.title !== void 0 ? scope.title : fresh ? null : row.title,
|
|
1355
|
+
wake: scope.wake !== void 0 ? scope.wake : fresh ? null : row.wake,
|
|
1354
1356
|
incarnation: scope.incarnation ?? row.incarnation
|
|
1355
1357
|
};
|
|
1356
1358
|
}
|
|
@@ -1504,6 +1506,7 @@ function parseScope(view) {
|
|
|
1504
1506
|
throw new RelayError("too_large", `an endpoint's rules and caps are more than ${SCOPE_BYTES} bytes`);
|
|
1505
1507
|
if (given("title"))
|
|
1506
1508
|
out.title = view.title === null ? null : cleanText(typeof view.title === "string" ? view.title.replace(/\s+/g, " ") : view.title, "title", 64) || null;
|
|
1509
|
+
if (given("wake")) out.wake = typeof view.wake === "string" && view.wake !== "none" && WAKES.includes(view.wake) ? view.wake : null;
|
|
1507
1510
|
if (given("incarnation")) {
|
|
1508
1511
|
if (view.incarnation !== null && (typeof view.incarnation !== "string" || !INCARNATION.test(view.incarnation))) throw bad("incarnation");
|
|
1509
1512
|
out.incarnation = view.incarnation ?? null;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scp-dev/hub",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.1",
|
|
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",
|
|
@@ -29,7 +29,7 @@
|
|
|
29
29
|
"typecheck": "tsc -p ."
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@scp-dev/core": "0.1.
|
|
32
|
+
"@scp-dev/core": "0.1.4"
|
|
33
33
|
},
|
|
34
34
|
"devDependencies": {
|
|
35
35
|
"tsup": "^8.5.1"
|
package/src/federation.ts
CHANGED
|
@@ -43,6 +43,8 @@ import {
|
|
|
43
43
|
validHandle,
|
|
44
44
|
validHarness,
|
|
45
45
|
validSelector,
|
|
46
|
+
type Wake,
|
|
47
|
+
WAKES,
|
|
46
48
|
} from "@scp-dev/core"
|
|
47
49
|
|
|
48
50
|
export type RelayAuth = Envelope["from"]["auth"]
|
|
@@ -121,6 +123,8 @@ export interface MirrorView extends MirrorScope {
|
|
|
121
123
|
presence?: Presence
|
|
122
124
|
last_seen?: string | null
|
|
123
125
|
title?: string | null
|
|
126
|
+
/** an agent's {@link Wake}; a value this hub does not know is kept as none */
|
|
127
|
+
wake?: string | null
|
|
124
128
|
/** the handle the endpoint had before a rename: its mirror is renamed in place */
|
|
125
129
|
was?: string
|
|
126
130
|
}
|
|
@@ -142,6 +146,7 @@ interface ParsedScope {
|
|
|
142
146
|
rules?: MirrorRules | null
|
|
143
147
|
caps?: ScopeCaps | null
|
|
144
148
|
title?: string | null
|
|
149
|
+
wake?: Wake | null
|
|
145
150
|
incarnation?: string | null
|
|
146
151
|
}
|
|
147
152
|
|
|
@@ -1609,7 +1614,7 @@ export class FederatedCore extends RelayCore {
|
|
|
1609
1614
|
const was = this.view(before)
|
|
1610
1615
|
const presence = was.presence !== view.presence
|
|
1611
1616
|
const status = before.status_state !== after.status_state || before.status_note !== after.status_note
|
|
1612
|
-
const other = (["kind", "harness", "model", "cwd", "labels", "title", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"] as const).some(
|
|
1617
|
+
const other = (["kind", "harness", "model", "cwd", "labels", "title", "wake", "tree", "parent_ep", "depth", "rules", "caps", "incarnation"] as const).some(
|
|
1613
1618
|
(field) => before[field] !== (after as FederatedRow)[field],
|
|
1614
1619
|
)
|
|
1615
1620
|
return presence || status || other ? { view, added: false, presence, status } : null
|
|
@@ -1682,6 +1687,7 @@ export class FederatedCore extends RelayCore {
|
|
|
1682
1687
|
rules: rules === undefined ? row.rules : rules && (rules.in || rules.out) ? JSON.stringify(rules) : null,
|
|
1683
1688
|
caps,
|
|
1684
1689
|
title: scope.title !== undefined ? scope.title : fresh ? null : row.title,
|
|
1690
|
+
wake: scope.wake !== undefined ? scope.wake : fresh ? null : row.wake,
|
|
1685
1691
|
incarnation: scope.incarnation ?? row.incarnation,
|
|
1686
1692
|
}
|
|
1687
1693
|
}
|
|
@@ -1860,6 +1866,7 @@ function parseScope(view: Partial<MirrorView>): ParsedScope {
|
|
|
1860
1866
|
throw new RelayError("too_large", `an endpoint's rules and caps are more than ${SCOPE_BYTES} bytes`)
|
|
1861
1867
|
if (given("title"))
|
|
1862
1868
|
out.title = view.title === null ? null : cleanText(typeof view.title === "string" ? view.title.replace(/\s+/g, " ") : view.title, "title", 64) || null
|
|
1869
|
+
if (given("wake")) out.wake = typeof view.wake === "string" && view.wake !== "none" && WAKES.includes(view.wake as Wake) ? (view.wake as Wake) : null
|
|
1863
1870
|
if (given("incarnation")) {
|
|
1864
1871
|
if (view.incarnation !== null && (typeof view.incarnation !== "string" || !INCARNATION.test(view.incarnation))) throw bad("incarnation")
|
|
1865
1872
|
out.incarnation = view.incarnation ?? null
|
package/src/hub.ts
CHANGED
|
@@ -38,6 +38,7 @@ import {
|
|
|
38
38
|
SYSTEM_HANDLE,
|
|
39
39
|
sameSecret,
|
|
40
40
|
untilTomorrow,
|
|
41
|
+
type Wake,
|
|
41
42
|
type XContact,
|
|
42
43
|
XCounters,
|
|
43
44
|
type XDelivered,
|
|
@@ -104,7 +105,7 @@ export interface GraphNode {
|
|
|
104
105
|
status: EndpointView["status"]
|
|
105
106
|
last_seen: string | null
|
|
106
107
|
parent: string | null
|
|
107
|
-
wake?:
|
|
108
|
+
wake?: Wake | null
|
|
108
109
|
}
|
|
109
110
|
|
|
110
111
|
/** `spawn`: parent to child; `message`: sender to recipient, with the count and newest send in the graph's window */
|
|
@@ -1593,7 +1594,7 @@ export class RelayHub {
|
|
|
1593
1594
|
/** a read-only graph for a dashboard: listed endpoints, spawn edges among them, and message counts per sender and recipient; never a body */
|
|
1594
1595
|
graph(minutes = GRAPH_MINUTES): HubGraph {
|
|
1595
1596
|
const window = Math.min(Math.max(1, Math.floor(Number.isFinite(minutes) ? minutes : GRAPH_MINUTES)), GRAPH_MINUTES_MAX)
|
|
1596
|
-
const endpoints = this.relay.list()
|
|
1597
|
+
const endpoints = this.relay.list()
|
|
1597
1598
|
const byId = new Map(endpoints.map((e) => [e.id, e.address]))
|
|
1598
1599
|
const listed = new Set(byId.values())
|
|
1599
1600
|
const nodes: GraphNode[] = endpoints.map((e) => ({
|