Simplify gatekeeper client-side protocols
This commit is contained in:
parent
f45ab47175
commit
6fb100ee60
|
@ -1,10 +1,10 @@
|
||||||
/// SPDX-License-Identifier: GPL-3.0-or-later
|
/// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
/// SPDX-FileCopyrightText: Copyright © 2016-2021 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
|
|
||||||
import { fromJS, Bytes, Dataspace, Ref, Sturdy, AnyValue, Reader, Schemas, stringify } from "@syndicate-lang/core";
|
import { fromJS, Bytes, Dataspace, Ref, AnyValue, Reader, Schemas, stringify } from "@syndicate-lang/core";
|
||||||
import { boot as bootHtml, Anchor, template as html, HtmlFragments, GlobalEvent, UIAttribute, UIChangeableProperty } from "@syndicate-lang/html";
|
import { boot as bootHtml, Anchor, template as html, HtmlFragments, GlobalEvent, UIAttribute, UIChangeableProperty } from "@syndicate-lang/html";
|
||||||
import { boot as bootWakeDetector, WakeEvent } from "./wake-detector";
|
import { boot as bootWakeDetector, WakeEvent } from "./wake-detector";
|
||||||
import { boot as bootWsRelay } from "@syndicate-lang/ws-relay";
|
import { boot as bootWsRelay, contactRemote } from "@syndicate-lang/ws-relay";
|
||||||
import { Present, Says } from './gen/simpleChatProtocol';
|
import { Present, Says } from './gen/simpleChatProtocol';
|
||||||
import G = Schemas.gatekeeper;
|
import G = Schemas.gatekeeper;
|
||||||
import N = Schemas.noise;
|
import N = Schemas.noise;
|
||||||
|
@ -38,47 +38,40 @@ function bootChat(ds: Ref) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
}
|
}
|
||||||
assert UIAttribute('#route', 'class', 'invalid') when (!route);
|
assert UIAttribute('#route', 'class', 'invalid') when (!route);
|
||||||
if (route) contactRemote(route);
|
if (route) {
|
||||||
}
|
console.log('contactRemote', route);
|
||||||
|
contactRemote(route, (remoteDs, control, addr) => {
|
||||||
|
on message WakeEvent() => at control {
|
||||||
|
send message G.ForceDisconnect();
|
||||||
|
}
|
||||||
|
|
||||||
function contactRemote(route: G.Route<Ref>) {
|
outputState('connected', 'connected to ' + stringify(addr));
|
||||||
console.log('contactRemote', route);
|
on stop outputState('disconnected', 'disconnected from ' + stringify(addr));
|
||||||
during G.ResolvePath({
|
|
||||||
"route": route,
|
|
||||||
"addr": $addr,
|
|
||||||
"control": $control: Ref,
|
|
||||||
"resolved": G.Resolved.accepted($remoteDs: Ref),
|
|
||||||
}) => {
|
|
||||||
on message WakeEvent() => at control {
|
|
||||||
send message G.ForceDisconnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
outputState('connected', 'connected to ' + stringify(addr));
|
on message GlobalEvent('#send_chat', 'click', _) => {
|
||||||
on stop outputState('disconnected', 'disconnected from ' + stringify(addr));
|
const inp = document.getElementById("chat_input") as HTMLInputElement;
|
||||||
|
var utterance = inp.value;
|
||||||
on message GlobalEvent('#send_chat', 'click', _) => {
|
inp.value = '';
|
||||||
const inp = document.getElementById("chat_input") as HTMLInputElement;
|
if (utterance) {
|
||||||
var utterance = inp.value;
|
at remoteDs {
|
||||||
inp.value = '';
|
send message Says({ who: nym.value, what: utterance });
|
||||||
if (utterance) {
|
}
|
||||||
at remoteDs {
|
|
||||||
send message Says({ who: nym.value, what: utterance });
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
at remoteDs {
|
at remoteDs {
|
||||||
assert Present(nym.value);
|
assert Present(nym.value);
|
||||||
|
|
||||||
const ui = new Anchor();
|
const ui = new Anchor();
|
||||||
during Present($who: string) => at ds {
|
during Present($who: string) => at ds {
|
||||||
assert ui.context(who).html('#nymlist', html`<li>${who}</li>`);
|
assert ui.context(who).html('#nymlist', html`<li>${who}</li>`);
|
||||||
|
}
|
||||||
|
|
||||||
|
on message Says({ "who": $who: string, "what": $what: string }) => {
|
||||||
|
outputUtterance(who, what);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}, ds);
|
||||||
on message Says({ "who": $who: string, "what": $what: string }) => {
|
|
||||||
outputUtterance(who, what);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,30 +2,35 @@
|
||||||
# yarn lockfile v1
|
# yarn lockfile v1
|
||||||
|
|
||||||
|
|
||||||
"@preserves/core@0.995.200", "@preserves/core@^0.995.200":
|
"@preserves/core@^0.995.200":
|
||||||
version "0.995.200"
|
version "0.995.200"
|
||||||
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
|
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.200.tgz#65575cf8f9320e73b5d37fa9ac9d6881a33fd3a6"
|
||||||
integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
|
integrity sha512-htZ2x+hltUpKoPsviWSuelzZW96po9zVSsN0RZEih60FahNX0R2LCqFJ6v5lyATuQ9oHALVi0w8w4rtf8oiAJw==
|
||||||
|
|
||||||
"@preserves/schema-cli@0.995.201":
|
"@preserves/core@^0.995.206":
|
||||||
version "0.995.201"
|
version "0.995.206"
|
||||||
resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.995.201.tgz#e87cb7ba51b225ff6ea96f177c5388907adf6717"
|
resolved "https://registry.yarnpkg.com/@preserves/core/-/core-0.995.206.tgz#f13507aa39dbc8cbd5d10ac18d107c06e92bf519"
|
||||||
integrity sha512-n/lpVgWBY1UTRySPXIwWG4Yu87OrQ9b7Xo8zPPQzD/DJDTEDT3y3SUujY7UTF1pQn09xRGnfPnDu1RoRCv2J3w==
|
integrity sha512-Uc4SSSXHQG6xYER9cCc0bkbLYM8fGVbO4kXw3DI8BaQjeUFPOX3yYNYPAvRNzmaF4MuMOZY+jSJpjJ9o5g6A0w==
|
||||||
|
|
||||||
|
"@preserves/schema-cli@>=0.995.201":
|
||||||
|
version "0.995.206"
|
||||||
|
resolved "https://registry.yarnpkg.com/@preserves/schema-cli/-/schema-cli-0.995.206.tgz#709c96d938dce3bf5b132a3da1304ca3c84bbe2e"
|
||||||
|
integrity sha512-870rwjKtQHA8huwt8MpMImnKC2cBHKYzcJi4811k5RuYs/HdbT9B81NMSiSn+Hq19/v9fEBicwwEmao3oM7hJw==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@preserves/core" "^0.995.200"
|
"@preserves/core" "^0.995.206"
|
||||||
"@preserves/schema" "^0.995.201"
|
"@preserves/schema" "^0.995.206"
|
||||||
chalk "^4.1"
|
chalk "^4.1"
|
||||||
chokidar "^3.5"
|
chokidar "^3.5"
|
||||||
commander "^7.2"
|
commander "^7.2"
|
||||||
glob "^7.1"
|
glob "^7.1"
|
||||||
minimatch "^3.0"
|
minimatch "^3.0"
|
||||||
|
|
||||||
"@preserves/schema@^0.995.201":
|
"@preserves/schema@^0.995.206":
|
||||||
version "0.995.201"
|
version "0.995.206"
|
||||||
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.201.tgz#827ad539afb0fdf68ba885ee3ff43db0fd473aa5"
|
resolved "https://registry.yarnpkg.com/@preserves/schema/-/schema-0.995.206.tgz#8e35a7db5363374f6794009d394510871f86746e"
|
||||||
integrity sha512-0SuhwOEAfxtrAeOTZ8V1yNEcHHHEbfUmoFawrF+vzTQFNZRz/X3LF1FM6wOiJlHtb7tBr4B+rHXX8jfNrqrdkA==
|
integrity sha512-JmXGxSqsNSEzZNpvOYPupSZhffvMIvgnUmKE+Yt5oiPiD/8H52EbKRrqBUQuVpvI4hvwgThWAtNIg3+q42vI2w==
|
||||||
dependencies:
|
dependencies:
|
||||||
"@preserves/core" "^0.995.200"
|
"@preserves/core" "^0.995.206"
|
||||||
|
|
||||||
"@rollup/pluginutils@^3.0.9":
|
"@rollup/pluginutils@^3.0.9":
|
||||||
version "3.1.0"
|
version "3.1.0"
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
´³bundle·µ³tcp„´³schema·³version°³definitions·³TcpLocal´³rec´³lit³ tcp-local„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³ TcpRemote´³rec´³lit³
|
´³bundle·µ³rpc„´³schema·³version°³definitions·³Answer´³rec´³lit³a„´³tupleµ´³named³request³any„´³named³response³any„„„„³Result´³orµµ±ok´³rec´³lit³ok„´³tupleµ´³named³value³any„„„„„µ±error´³rec´³lit³error„´³tupleµ´³named³error³any„„„„„„„³Question´³rec´³lit³q„´³tupleµ´³named³request³any„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³tcp„´³schema·³version°³definitions·³TcpLocal´³rec´³lit³ tcp-local„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³ TcpRemote´³rec´³lit³
|
||||||
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
|
tcp-remote„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³TcpPeerInfo´³rec´³lit³tcp-peer„´³tupleµ´³named³handle´³embedded³any„„´³named³local´³refµ„³TcpLocal„„´³named³remote´³refµ„³ TcpRemote„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³http„´³schema·³version°³definitions·³Chunk´³orµµ±string´³atom³String„„µ±bytes´³atom³
|
||||||
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
|
ByteString„„„„³Headers´³dictof´³atom³Symbol„´³atom³String„„³MimeType´³atom³Symbol„³
|
||||||
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
|
QueryValue´³orµµ±string´³atom³String„„µ±file´³rec´³lit³file„´³tupleµ´³named³filename´³atom³String„„´³named³headers´³refµ„³Headers„„´³named³body´³atom³
|
||||||
|
@ -40,5 +40,5 @@ ByteString
|
||||||
RunService´³rec´³lit³run-service„´³tupleµ´³named³serviceName³any„„„„³ServiceState´³rec´³lit³
service-state„´³tupleµ´³named³serviceName³any„´³named³state´³refµ„³State„„„„„³
ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³serviceName³any„„„„³ServiceDependency´³rec´³lit³
|
RunService´³rec´³lit³run-service„´³tupleµ´³named³serviceName³any„„„„³ServiceState´³rec´³lit³
service-state„´³tupleµ´³named³serviceName³any„´³named³state´³refµ„³State„„„„„³
ServiceObject´³rec´³lit³service-object„´³tupleµ´³named³serviceName³any„´³named³object³any„„„„³RequireService´³rec´³lit³require-service„´³tupleµ´³named³serviceName³any„„„„³RestartService´³rec´³lit³restart-service„´³tupleµ´³named³serviceName³any„„„„³ServiceDependency´³rec´³lit³
|
||||||
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ServiceState„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³definitions·³Nop´³lit€„³Oid´³atom³
SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³
SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„µ±Nop´³refµ„³Nop„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³embeddedType€„„µ³ dataspace„´³schema·³version°³definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³
|
depends-on„´³tupleµ´³named³depender³any„´³named³dependee´³refµ„³ServiceState„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³protocol„´³schema·³version°³definitions·³Nop´³lit€„³Oid´³atom³
SignedInteger„³Sync´³rec´³lit³S„´³tupleµ´³named³peer´³embedded´³lit<69>„„„„„„³Turn´³seqof´³refµ„³ TurnEvent„„³Error´³rec´³lit³error„´³tupleµ´³named³message´³atom³String„„´³named³detail³any„„„„³Event´³orµµ±Assert´³refµ„³Assert„„µ±Retract´³refµ„³Retract„„µ±Message´³refµ„³Message„„µ±Sync´³refµ„³Sync„„„„³Assert´³rec´³lit³A„´³tupleµ´³named³ assertion´³refµ„³ Assertion„„´³named³handle´³refµ„³Handle„„„„„³Handle´³atom³
SignedInteger„³Packet´³orµµ±Turn´³refµ„³Turn„„µ±Error´³refµ„³Error„„µ± Extension´³refµ„³ Extension„„µ±Nop´³refµ„³Nop„„„„³Message´³rec´³lit³M„´³tupleµ´³named³body´³refµ„³ Assertion„„„„„³Retract´³rec´³lit³R„´³tupleµ´³named³handle´³refµ„³Handle„„„„„³ Assertion³any³ Extension´³rec´³named³label³any„´³named³fields´³seqof³any„„„³ TurnEvent´³tupleµ´³named³oid´³refµ„³Oid„„´³named³event´³refµ„³Event„„„„„³embeddedType€„„µ³ dataspace„´³schema·³version°³definitions·³Observe´³rec´³lit³Observe„´³tupleµ´³named³pattern´³refµ³dataspacePatterns„³Pattern„„´³named³observer´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³
|
||||||
gatekeeper„´³schema·³version°³definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³description´³refµ„³Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³tuplePrefixµ´³named³
|
gatekeeper„´³schema·³version°³definitions·³Bind´³rec´³lit³bind„´³tupleµ´³named³description´³refµ„³Description„„´³named³target´³embedded³any„„´³named³observer´³refµ„³BindObserver„„„„„³Step´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Bound´³orµµ±bound´³rec´³lit³bound„´³tupleµ´³named³pathStep´³refµ„³PathStep„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Route´³rec´³lit³route„´³tuplePrefixµ´³named³
|
||||||
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ResolvePath´³rec´³lit³resolve-path„´³tupleµ´³named³route´³refµ„³Route„„´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„³BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvedPathStep´³rec´³lit³ path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„´³named³resolved´³refµ„³Resolved„„„„„³TransportControl´³refµ„³ForceDisconnect„³TransportConnection´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³resolved´³refµ„³Resolved„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³embeddedType€„„µ³dataspacePatterns„´³schema·³version°³definitions·³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³
SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
|
transports´³seqof³any„„„´³named³ pathSteps´³seqof´³refµ„³PathStep„„„„„³Resolve´³rec´³lit³resolve„´³tupleµ´³named³step´³refµ„³Step„„´³named³observer´³embedded´³refµ„³Resolved„„„„„„³PathStep´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³Rejected´³rec´³lit³rejected„´³tupleµ´³named³detail³any„„„„³Resolved´³orµµ±accepted´³rec´³lit³accepted„´³tupleµ´³named³responderSession´³embedded³any„„„„„„µ±Rejected´³refµ„³Rejected„„„„³Description´³rec´³named³stepType´³atom³Symbol„„´³tupleµ´³named³detail³any„„„„³ResolvePath´³rec´³lit³resolve-path„´³tupleµ´³named³route´³refµ„³Route„„„„„³BindObserver´³orµµ±present´³embedded´³refµ„³Bound„„„µ±absent´³lit€„„„„³ResolvedPath´³rec´³lit³
resolved-path„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³responderSession´³embedded³any„„„„„³ForceDisconnect´³rec´³lit³force-disconnect„´³tupleµ„„„³ResolvePathStep´³rec´³lit³resolve-path-step„´³tupleµ´³named³origin´³embedded´³refµ„³Resolve„„„´³named³pathStep´³refµ„³PathStep„„„„„³ConnectTransport´³rec´³lit³connect-transport„´³tupleµ´³named³addr³any„„„„³ResolvedPathStep´³embedded³any„³TransportControl´³refµ„³ForceDisconnect„³ConnectedTransport´³rec´³lit³connected-transport„´³tupleµ´³named³addr³any„´³named³control´³embedded´³refµ„³TransportControl„„„´³named³responderSession´³embedded³any„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„µ³transportAddress„´³schema·³version°³definitions·³Tcp´³rec´³lit³tcp„´³tupleµ´³named³host´³atom³String„„´³named³port´³atom³
SignedInteger„„„„„³Unix´³rec´³lit³unix„´³tupleµ´³named³path´³atom³String„„„„„³Stdio´³rec´³lit³stdio„´³tupleµ„„„³ WebSocket´³rec´³lit³ws„´³tupleµ´³named³url´³atom³String„„„„„„³embeddedType€„„µ³dataspacePatterns„´³schema·³version°³definitions·³AnyAtom´³orµµ±bool´³atom³Boolean„„µ±double´³atom³Double„„µ±int´³atom³
SignedInteger„„µ±string´³atom³String„„µ±bytes´³atom³
|
||||||
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±discard´³rec´³lit³_„´³tupleµ„„„„µ±bind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„„µ±group´³rec´³lit³group„´³tupleµ´³named³type´³refµ„³ GroupType„„´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ GroupType´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„„„„„µ±arr´³rec´³lit³arr„´³tupleµ„„„„µ±dict´³rec´³lit³dict„´³tupleµ„„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„„„
|
ByteString„„µ±symbol´³atom³Symbol„„µ±embedded´³embedded³any„„„„³Pattern´³orµµ±discard´³rec´³lit³_„´³tupleµ„„„„µ±bind´³rec´³lit³bind„´³tupleµ´³named³pattern´³refµ„³Pattern„„„„„„µ±lit´³rec´³lit³lit„´³tupleµ´³named³value´³refµ„³AnyAtom„„„„„„µ±group´³rec´³lit³group„´³tupleµ´³named³type´³refµ„³ GroupType„„´³named³entries´³dictof³any´³refµ„³Pattern„„„„„„„„„³ GroupType´³orµµ±rec´³rec´³lit³rec„´³tupleµ´³named³label³any„„„„„µ±arr´³rec´³lit³arr„´³tupleµ„„„„µ±dict´³rec´³lit³dict„´³tupleµ„„„„„„„³embeddedType´³refµ³ EntityRef„³Cap„„„„„
|
|
@ -52,14 +52,23 @@ Bound = <bound @pathStep PathStep> / Rejected .
|
||||||
# ---------------------------------------------------------------------------
|
# ---------------------------------------------------------------------------
|
||||||
# Protocol at client-side dataspaces, for resolution utilities
|
# Protocol at client-side dataspaces, for resolution utilities
|
||||||
|
|
||||||
# Assertion. In response to observation of this with appropriate captures/wildcards in `addr`
|
# The client-side operates using `rpc.Question`s and `rpc.Answer`s.
|
||||||
# and `resolved`, respondent will follow `route.pathSteps` starting from one of the
|
|
||||||
# `route.transports`, asserting `ResolvePath` with the final `Resolved` as well as the selected
|
|
||||||
# transport `addr` and a `control` for it.
|
|
||||||
ResolvePath = <resolve-path @route Route @addr any @control #:TransportControl @resolved Resolved> .
|
|
||||||
|
|
||||||
TransportConnection = <connect-transport @addr any @control #:TransportControl @resolved Resolved> .
|
# Assert `rpc.Question` with `ResolvePath` to request resolution of `Route`. The resolution
|
||||||
ResolvedPathStep = <path-step @origin #:Resolve @pathStep PathStep @resolved Resolved> .
|
# utility will continuously try to satisfy the request, following `route.pathSteps` starting
|
||||||
|
# from one of the `route.transports`, ultimately asserting `rpc.Answer` with an `rpc.Result` in
|
||||||
|
# response. If the process completes successfully, the `rpc.Result.ok` will carry a
|
||||||
|
# `ResolvedPath`.
|
||||||
|
ResolvePath = <resolve-path @route Route> .
|
||||||
|
ResolvedPath = <resolved-path @addr any @control #:TransportControl @responderSession #:any> .
|
||||||
|
|
||||||
|
# Assertions. As `ResolvePath`/`ResolvedPath`, but just for an initial transport link setup.
|
||||||
|
ConnectTransport = <connect-transport @addr any> .
|
||||||
|
ConnectedTransport = <connected-transport @addr any @control #:TransportControl @responderSession #:any> .
|
||||||
|
|
||||||
|
# Assertions. Like `ResolvePath`/`ResolvedPath`, but for incremental resolution along a route.
|
||||||
|
ResolvePathStep = <resolve-path-step @origin #:Resolve @pathStep PathStep> .
|
||||||
|
ResolvedPathStep = #:any .
|
||||||
PathStep = <<rec> @stepType symbol [@detail any]> .
|
PathStep = <<rec> @stepType symbol [@detail any]> .
|
||||||
|
|
||||||
# A `Route` describes a network path that can be followed to reach some target entity.
|
# A `Route` describes a network path that can be followed to reach some target entity.
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
version 1 .
|
||||||
|
embeddedType EntityRef.Cap .
|
||||||
|
|
||||||
|
# Assertion. Establishes a frame for a request.
|
||||||
|
Question = <q @request any> .
|
||||||
|
|
||||||
|
# Assertion or message. Responds to a question.
|
||||||
|
Answer = <a @request any @response any> .
|
||||||
|
|
||||||
|
# Value. Captures a common "ok-or-error" pattern as seen in e.g. Rust.
|
||||||
|
Result = <ok @value any> / <error @error any> .
|
|
@ -16,6 +16,8 @@ export * as Pattern from './runtime/pattern.js';
|
||||||
export * as QuasiValue from './runtime/quasivalue.js';
|
export * as QuasiValue from './runtime/quasivalue.js';
|
||||||
export * from './runtime/randomid.js';
|
export * from './runtime/randomid.js';
|
||||||
export * as Rewrite from './runtime/rewrite.js';
|
export * as Rewrite from './runtime/rewrite.js';
|
||||||
|
export * from './runtime/rpc.js';
|
||||||
|
export * as Rpc from './runtime/rpc.js';
|
||||||
export * as Skeleton from './runtime/skeleton.js';
|
export * as Skeleton from './runtime/skeleton.js';
|
||||||
export * from './runtime/space.js';
|
export * from './runtime/space.js';
|
||||||
export * from './runtime/supervise.js';
|
export * from './runtime/supervise.js';
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
/// SPDX-FileCopyrightText: Copyright © 2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
|
|
||||||
|
import { Assertable, Ref } from './actor.js';
|
||||||
|
import { ctor, dict, QuasiValue } from './quasivalue.js';
|
||||||
|
import * as R from '../gen/rpc.js';
|
||||||
|
import { fromJS } from '@preserves/core';
|
||||||
|
|
||||||
|
export { Result } from '../gen/rpc.js';
|
||||||
|
|
||||||
|
export function Question<Q extends Assertable>(q: Q): R.Question<Ref> {
|
||||||
|
return R.Question(fromJS<Ref>(q));
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Question {
|
||||||
|
export function quasiValue(q: QuasiValue): QuasiValue {
|
||||||
|
return ctor(R.Question, q);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Answer<Q extends Assertable, A extends Assertable>(q: Q, a: A): R.Answer<Ref> {
|
||||||
|
return R.Answer({ request: fromJS<Ref>(q), response: fromJS<Ref>(a) });
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace Answer {
|
||||||
|
export function quasiValue(q: QuasiValue, a: QuasiValue): QuasiValue {
|
||||||
|
return ctor(R.Answer, dict(
|
||||||
|
["request", q],
|
||||||
|
["response", a]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resultOk<V extends Assertable>(v: V): R.Result<Ref> {
|
||||||
|
return R.Result.ok(fromJS<Ref>(v));
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace resultOk {
|
||||||
|
export function quasiValue(v: QuasiValue): QuasiValue {
|
||||||
|
return ctor(R.Result.ok, v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export function resultError<E extends Assertable>(e: E): R.Result<Ref> {
|
||||||
|
return R.Result.error(fromJS<Ref>(e));
|
||||||
|
}
|
||||||
|
|
||||||
|
export namespace resultError {
|
||||||
|
export function quasiValue(e: QuasiValue): QuasiValue {
|
||||||
|
return ctor(R.Result.error, e);
|
||||||
|
}
|
||||||
|
}
|
|
@ -6,6 +6,7 @@ export * as dataspace from './gen/dataspace.js';
|
||||||
export * as gatekeeper from './gen/gatekeeper.js';
|
export * as gatekeeper from './gen/gatekeeper.js';
|
||||||
export * as protocol from './gen/protocol.js';
|
export * as protocol from './gen/protocol.js';
|
||||||
export * as noise from './gen/noise.js';
|
export * as noise from './gen/noise.js';
|
||||||
|
export * as rpc from './gen/rpc.js';
|
||||||
export * as service from './gen/service.js';
|
export * as service from './gen/service.js';
|
||||||
export * as stdenv from './gen/stdenv.js';
|
export * as stdenv from './gen/stdenv.js';
|
||||||
export * as stream from './gen/stream.js';
|
export * as stream from './gen/stream.js';
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
/// SPDX-License-Identifier: GPL-3.0-or-later
|
/// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
/// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
/// SPDX-FileCopyrightText: Copyright © 2023-2024 Tony Garnock-Jones <tonyg@leastfixedpoint.com>
|
||||||
|
|
||||||
import { Dataspace, Ref, Sturdy, Reader, Schemas, Embedded, randomId, fromJS } from "@syndicate-lang/core";
|
import { Dataspace, Ref, Sturdy, Reader, Schemas, Embedded, randomId, fromJS, Question, resultOk, Answer } from "@syndicate-lang/core";
|
||||||
import { boot as bootHtml, Widget } from "@syndicate-lang/html2";
|
import { boot as bootHtml, Widget } from "@syndicate-lang/html2";
|
||||||
import wsRelay from "@syndicate-lang/ws-relay";
|
import wsRelay from "@syndicate-lang/ws-relay";
|
||||||
import { ExampleDefinition } from './gen/example';
|
import { ExampleDefinition } from './gen/example';
|
||||||
|
@ -34,11 +34,10 @@ function bootApp(ds: Ref) {
|
||||||
'<ref {oid: "syndicate" sig: #[acowDB2/oI+6aSEC3YIxGg==]}>').next())))],
|
'<ref {oid: "syndicate" sig: #[acowDB2/oI+6aSEC3YIxGg==]}>').next())))],
|
||||||
});
|
});
|
||||||
|
|
||||||
during G.ResolvePath({
|
assert Question(G.ResolvePath(route));
|
||||||
"route": route,
|
during Answer(G.ResolvePath(route), resultOk(G.ResolvedPath({
|
||||||
"resolved": G.Resolved.accepted($remoteDs_e: Embedded),
|
responderSession: $remoteDs: Ref,
|
||||||
}) => {
|
}))) => {
|
||||||
const remoteDs = remoteDs_e.embeddedValue;
|
|
||||||
at remoteDs {
|
at remoteDs {
|
||||||
assert ExampleDefinition(this_instance);
|
assert ExampleDefinition(this_instance);
|
||||||
during ExampleDefinition($who: string) => {
|
during ExampleDefinition($who: string) => {
|
||||||
|
|
|
@ -7,7 +7,6 @@ import {
|
||||||
Bytes,
|
Bytes,
|
||||||
Dataspace,
|
Dataspace,
|
||||||
IdentitySet,
|
IdentitySet,
|
||||||
Observe,
|
|
||||||
QuasiValue as Q,
|
QuasiValue as Q,
|
||||||
Record,
|
Record,
|
||||||
Ref,
|
Ref,
|
||||||
|
@ -19,23 +18,28 @@ import {
|
||||||
canonicalEncode,
|
canonicalEncode,
|
||||||
decode,
|
decode,
|
||||||
fromJS,
|
fromJS,
|
||||||
isEmbedded,
|
|
||||||
parse,
|
parse,
|
||||||
stringify,
|
stringify,
|
||||||
underlying,
|
underlying,
|
||||||
Embeddable,
|
Embeddable,
|
||||||
SaltyCrypto,
|
SaltyCrypto,
|
||||||
|
Question,
|
||||||
|
Answer,
|
||||||
|
Result,
|
||||||
|
resultOk,
|
||||||
|
resultError,
|
||||||
} from "@syndicate-lang/core";
|
} from "@syndicate-lang/core";
|
||||||
import G = Schemas.gatekeeper;
|
import G = Schemas.gatekeeper;
|
||||||
import S = Schemas.sturdy;
|
import S = Schemas.sturdy;
|
||||||
import N = Schemas.noise;
|
import N = Schemas.noise;
|
||||||
import T = Schemas.transportAddress;
|
import T = Schemas.transportAddress;
|
||||||
import E = Schemas.stdenv;
|
import E = Schemas.stdenv;
|
||||||
|
import R = Schemas.rpc;
|
||||||
|
|
||||||
export * from './seal.js';
|
export * from './seal.js';
|
||||||
|
|
||||||
type TransportState = {
|
type TransportState = {
|
||||||
addr: T.WebSocket,
|
addr: AnyValue,
|
||||||
control: Ref,
|
control: Ref,
|
||||||
peer: Ref,
|
peer: Ref,
|
||||||
};
|
};
|
||||||
|
@ -43,23 +47,17 @@ type TransportState = {
|
||||||
export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketConstructor?: typeof WebSocket) {
|
export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketConstructor?: typeof WebSocket) {
|
||||||
spawn named 'transportConnector' {
|
spawn named 'transportConnector' {
|
||||||
at ds {
|
at ds {
|
||||||
during Observe({ "pattern": :pattern G.TransportConnection({
|
during Question(G.ConnectTransport(T.WebSocket($url: string))) => {
|
||||||
"addr": \$addrPatValue,
|
|
||||||
"control": \_,
|
|
||||||
"resolved": \_,
|
|
||||||
}) }) => {
|
|
||||||
const addr = Q.drop_lit(addrPatValue, T.toWebSocket);
|
|
||||||
if (!addr) return;
|
|
||||||
let counter =0;
|
let counter =0;
|
||||||
Supervisor.always(() => ['transportConnector', fromJS(addr), counter++], () => {
|
Supervisor.always(() => ['wsTransport', fromJS(url), counter++], () => {
|
||||||
console.log('connecting', addr.url, counter);
|
console.log('connecting', url, counter);
|
||||||
connectTo(addr);
|
connectWs(url);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function connectTo(addr: T.WebSocket) {
|
function connectWs(url: string) {
|
||||||
const facet = Turn.activeFacet;
|
const facet = Turn.activeFacet;
|
||||||
facet.preventInertCheck();
|
facet.preventInertCheck();
|
||||||
const controlEntity = {
|
const controlEntity = {
|
||||||
|
@ -73,9 +71,9 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
function succeed(ws: WebSocket) {
|
function succeed(ws: WebSocket) {
|
||||||
if (final) return;
|
if (final) return;
|
||||||
final = true;
|
final = true;
|
||||||
console.log('opened', addr.url);
|
console.log('opened', url);
|
||||||
on stop {
|
on stop {
|
||||||
console.log('closing', addr.url);
|
console.log('closing', url);
|
||||||
ws.close();
|
ws.close();
|
||||||
}
|
}
|
||||||
ws.onclose = () => facet.turn(() => { stop facet; });
|
ws.onclose = () => facet.turn(() => { stop facet; });
|
||||||
|
@ -87,60 +85,50 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
setup: r => ws.onmessage = e => r.accept(new Uint8Array(e.data)),
|
setup: r => ws.onmessage = e => r.accept(new Uint8Array(e.data)),
|
||||||
initialOid: 0,
|
initialOid: 0,
|
||||||
});
|
});
|
||||||
console.log('succeed', addr.url);
|
console.log('succeed', url);
|
||||||
at ds {
|
at ds {
|
||||||
assert G.TransportConnection<Ref>({
|
assert Answer(G.ConnectTransport(fromJS<Ref>(T.WebSocket(url))), resultOk(G.ConnectedTransport({
|
||||||
"addr": fromJS(addr),
|
"addr": fromJS<Ref>(T.WebSocket(url)),
|
||||||
"control": create controlEntity,
|
"control": create controlEntity,
|
||||||
"resolved": G.Resolved.accepted(relay.peer!),
|
"responderSession": relay.peer!,
|
||||||
});
|
})));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function fail(detail: Assertion) {
|
function fail(detail: Assertion) {
|
||||||
if (final) return;
|
if (final) return;
|
||||||
final = true;
|
final = true;
|
||||||
console.log('fail', addr.url, detail);
|
console.log('fail', url, detail);
|
||||||
at ds {
|
at ds {
|
||||||
assert G.TransportConnection<Ref>({
|
assert Answer(G.ConnectTransport(fromJS<Ref>(T.WebSocket(url))), resultError(detail));
|
||||||
"addr": fromJS(addr),
|
|
||||||
"control": create controlEntity,
|
|
||||||
"resolved": G.Resolved.Rejected(G.Rejected(detail)),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
setTimeout(() => facet.turn(() => { stop facet; }), 10000);
|
setTimeout(() => facet.turn(() => { stop facet; }), 10000);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
const ws = new (WebSocketConstructor ?? WebSocket)(addr.url);
|
const ws = new (WebSocketConstructor ?? WebSocket)(url);
|
||||||
ws.binaryType = 'arraybuffer';
|
ws.binaryType = 'arraybuffer';
|
||||||
ws.onopen = () => facet.turn(() => succeed(ws));
|
ws.onopen = () => facet.turn(() => succeed(ws));
|
||||||
ws.onclose = () => facet.turn(() => fail(Symbol.for('closed')));
|
ws.onclose = () => facet.turn(() => fail(Symbol.for('closed')));
|
||||||
ws.onerror = () => facet.turn(() => fail(Symbol.for('websocket-error-event')));
|
ws.onerror = () => facet.turn(() => fail(Symbol.for('websocket-error-event')));
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error('Failed opening websocket', addr.url, e);
|
console.error('Failed opening websocket', url, e);
|
||||||
fail(Symbol.for('websocket-exception'));
|
fail(Symbol.for('websocket-exception'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spawn named 'pathResolver' {
|
spawn named 'pathResolver' {
|
||||||
at ds {
|
at ds {
|
||||||
during Observe({ "pattern": :pattern G.ResolvePath({
|
during Question(G.ResolvePath($route0)) => {
|
||||||
"route": \$routePatValue,
|
const route = G.toRoute(route0);
|
||||||
"addr": \_,
|
|
||||||
"control": \_,
|
|
||||||
"resolved": \_,
|
|
||||||
}) }) => {
|
|
||||||
const route = Q.drop_lit(routePatValue, G.toRoute);
|
|
||||||
if (!route) return;
|
if (!route) return;
|
||||||
field candidates: IdentitySet<TransportState> = new IdentitySet();
|
field candidates: IdentitySet<TransportState> = new IdentitySet();
|
||||||
route.transports.forEach(t => {
|
route.transports.forEach(addr => {
|
||||||
const addr = T.toWebSocket(t);
|
console.log('tracking', addr);
|
||||||
if (!addr) return;
|
assert Question(G.ConnectTransport(addr));
|
||||||
console.log('tracking', addr.url);
|
during Answer(G.ConnectTransport(addr), resultOk(G.ConnectedTransport({
|
||||||
during G.TransportConnection({
|
|
||||||
"addr": addr,
|
"addr": addr,
|
||||||
"control": $control: Ref,
|
"control": $control: Ref,
|
||||||
"resolved": G.Resolved.accepted($peer: Ref),
|
"responderSession": $peer: Ref,
|
||||||
}) => {
|
}))) => {
|
||||||
const entry = { addr, control, peer };
|
const entry = { addr, control, peer };
|
||||||
candidates.value.add(entry);
|
candidates.value.add(entry);
|
||||||
candidates.changed();
|
candidates.changed();
|
||||||
|
@ -161,39 +149,34 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
}
|
}
|
||||||
rootPeer.value = best.value?.peer ?? null;
|
rootPeer.value = best.value?.peer ?? null;
|
||||||
}
|
}
|
||||||
resolve(() => rootPeer.value, route.pathSteps, (r) => {
|
resolve(() => ({ ref: rootPeer.value, error: false }), route.pathSteps, (r) => {
|
||||||
console.log('leaf', best.value?.addr?.url);
|
console.log('leaf', best.value?.addr);
|
||||||
assert G.ResolvePath<Ref>({
|
assert Answer(G.ResolvePath(route), resultOk(G.ResolvedPath({
|
||||||
"route": route,
|
"addr": best.value!.addr,
|
||||||
"addr": fromJS(best.value!.addr),
|
|
||||||
"control": best.value!.control,
|
"control": best.value!.control,
|
||||||
"resolved": r()!
|
"responderSession": r().ref!,
|
||||||
}) when (r());
|
}))) when (r().ref);
|
||||||
|
assert Answer(G.ResolvePath(route), resultError(r().error)) when (!r().ref);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function resolve(
|
function resolve(
|
||||||
e: () => Ref | null,
|
e: () => { ref: Ref | null, error: AnyValue }, // gross
|
||||||
steps: G.PathStep[],
|
steps: G.PathStep[],
|
||||||
k: (r: () => G.Resolved | null) => void,
|
k: (r: () => { ref: Ref | null, error: AnyValue }) => void,
|
||||||
) {
|
) {
|
||||||
if (steps.length === 0) {
|
if (steps.length === 0) {
|
||||||
k(() => {
|
k(e);
|
||||||
const peer = e();
|
|
||||||
return peer === null ? null : G.Resolved.accepted(peer);
|
|
||||||
});
|
|
||||||
} else {
|
} else {
|
||||||
const [step, ...more] = steps;
|
const [step, ...more] = steps;
|
||||||
at ds {
|
at ds {
|
||||||
during G.ResolvedPathStep({
|
const q = () => G.ResolvePathStep({ origin: (e().ref!), pathStep: step });
|
||||||
"origin": (e()!),
|
assert Question(q()) when (e().ref);
|
||||||
"pathStep": step,
|
during Answer(((q)()) /* omg */, $a: Result) when (e().ref) => {
|
||||||
"resolved": $resolved: G.Resolved,
|
switch (a._variant) {
|
||||||
}) when (e()) => {
|
case "ok":
|
||||||
switch (resolved._variant) {
|
|
||||||
case "accepted":
|
|
||||||
// Include a call to our e() in the e we pass in to the recursive
|
// Include a call to our e() in the e we pass in to the recursive
|
||||||
// call to resolve(). e() returning non-null is a precondition for
|
// call to resolve(). e() returning non-null is a precondition for
|
||||||
// the call; if that precondition ever changes, we want to NOT
|
// the call; if that precondition ever changes, we want to NOT
|
||||||
|
@ -208,10 +191,18 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
// best.value!, which is now null, boom. With the call to e(), we
|
// best.value!, which is now null, boom. With the call to e(), we
|
||||||
// short circuit and so the assertion becomes null at that point.
|
// short circuit and so the assertion becomes null at that point.
|
||||||
//
|
//
|
||||||
resolve(() => e() && resolved.responderSession, more, k);
|
const nextRef = G.toResolvedPathStep(a.value);
|
||||||
|
const nextResult = (nextRef === void 0)
|
||||||
|
? { ref: null, error: 'bad ResolvedPathStep' }
|
||||||
|
: { ref: nextRef, error: false };
|
||||||
|
const nextE = () => {
|
||||||
|
const result = e();
|
||||||
|
return result.ref ? nextResult : result;
|
||||||
|
};
|
||||||
|
resolve(nextE, more, k);
|
||||||
break;
|
break;
|
||||||
case "Rejected":
|
case "error":
|
||||||
k(() => resolved);
|
k(() => ({ ref: null, error: a.error }));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -221,22 +212,13 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
|
|
||||||
spawn named 'noiseStep' {
|
spawn named 'noiseStep' {
|
||||||
at ds {
|
at ds {
|
||||||
during Observe({ "pattern": :pattern G.ResolvedPathStep({
|
during Question($q(G.ResolvePathStep({
|
||||||
"origin": \$originPatValue,
|
origin: $origin: Ref,
|
||||||
"pathStep": G.PathStep({
|
pathStep: G.PathStep({
|
||||||
"stepType": N.$noise,
|
stepType: N.$noise,
|
||||||
"detail": \$detailPatValue,
|
detail: $spec: N.NoisePathStepDetail,
|
||||||
}),
|
}),
|
||||||
"resolved": \_,
|
}))) => {
|
||||||
}) }) => {
|
|
||||||
const origin0 = Q.drop_lit(originPatValue);
|
|
||||||
if (!origin0 || !isEmbedded(origin0)) return;
|
|
||||||
const origin = origin0;
|
|
||||||
|
|
||||||
const spec0 = Q.drop_lit(detailPatValue, N.toNoisePathStepDetail);
|
|
||||||
if (!spec0) return;
|
|
||||||
const spec = spec0;
|
|
||||||
|
|
||||||
const algorithms = SaltyCrypto.Noise_25519_ChaChaPoly_BLAKE2s;
|
const algorithms = SaltyCrypto.Noise_25519_ChaChaPoly_BLAKE2s;
|
||||||
const protocol =
|
const protocol =
|
||||||
spec.protocol._variant === "present" ? spec.protocol.protocol :
|
spec.protocol._variant === "present" ? spec.protocol.protocol :
|
||||||
|
@ -270,14 +252,7 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
case "Rejected":
|
case "Rejected":
|
||||||
stop {
|
stop {
|
||||||
at ds {
|
at ds {
|
||||||
assert G.ResolvedPathStep<Ref>({
|
assert Answer(q, resultError(response.value.detail));
|
||||||
"origin": origin,
|
|
||||||
"pathStep": G.PathStep({
|
|
||||||
"stepType": N.$noise,
|
|
||||||
"detail": fromJS(N.NoisePathStepDetail(spec)),
|
|
||||||
}),
|
|
||||||
"resolved": response,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -332,14 +307,7 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
setup: r => relay = r,
|
setup: r => relay = r,
|
||||||
initialOid: 0,
|
initialOid: 0,
|
||||||
}).peer!;
|
}).peer!;
|
||||||
assert G.ResolvedPathStep<Ref>({
|
assert Answer(q, resultOk(peer));
|
||||||
"origin": origin,
|
|
||||||
"pathStep": G.PathStep({
|
|
||||||
"stepType": N.$noise,
|
|
||||||
"detail": fromJS(spec),
|
|
||||||
}),
|
|
||||||
"resolved": G.Resolved.accepted(peer),
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function handlePacket(body: Assertion) {
|
function handlePacket(body: Assertion) {
|
||||||
|
@ -368,21 +336,13 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
|
|
||||||
spawn named 'sturdyRefStep' {
|
spawn named 'sturdyRefStep' {
|
||||||
at ds {
|
at ds {
|
||||||
during Observe({ "pattern": :pattern G.ResolvedPathStep({
|
during Question($q(G.ResolvePathStep({
|
||||||
"origin": \$originPatValue,
|
origin: $origin: Ref,
|
||||||
"pathStep": G.PathStep({
|
pathStep: G.PathStep({
|
||||||
"stepType": S.$ref,
|
stepType: S.$ref,
|
||||||
"detail": \$detailPatValue,
|
detail: $parameters: S.SturdyPathStepDetail,
|
||||||
}),
|
}),
|
||||||
"resolved": \_,
|
}))) => {
|
||||||
}) }) => {
|
|
||||||
const origin0 = Q.drop_lit(originPatValue);
|
|
||||||
if (!origin0 || !isEmbedded(origin0)) return;
|
|
||||||
const origin = origin0;
|
|
||||||
|
|
||||||
const parameters = Q.drop_lit(detailPatValue, S.toSturdyPathStepDetail);
|
|
||||||
if (!parameters) return;
|
|
||||||
|
|
||||||
at origin {
|
at origin {
|
||||||
assert G.Resolve({
|
assert G.Resolve({
|
||||||
"step": G.Step({
|
"step": G.Step({
|
||||||
|
@ -392,15 +352,13 @@ export function boot(ds = Dataspace.local, debug: boolean = false, WebSocketCons
|
||||||
"observer": create assertionFacetObserver(e => {
|
"observer": create assertionFacetObserver(e => {
|
||||||
const response = G.toResolved(e);
|
const response = G.toResolved(e);
|
||||||
if (!response) return;
|
if (!response) return;
|
||||||
at ds {
|
switch (response._variant) {
|
||||||
assert G.ResolvedPathStep<Ref>({
|
case "accepted":
|
||||||
"origin": origin,
|
assert Answer(q, resultOk(response.responderSession));
|
||||||
"pathStep": G.PathStep({
|
break;
|
||||||
"stepType": S.$ref,
|
case "Rejected":
|
||||||
"detail": fromJS(parameters),
|
assert Answer(q, resultError(response.value.detail));
|
||||||
}),
|
break;
|
||||||
"resolved": response,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}),
|
}),
|
||||||
});
|
});
|
||||||
|
@ -465,7 +423,7 @@ export function decodeStandardRoute(s: string): G.Route | null {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function contactRemote(
|
export function contactRemote(
|
||||||
route: G.Route<Ref> | Record<AnyValue, Array<AnyValue>, Ref>,
|
route: G.Route | Record<AnyValue, Array<AnyValue>, Ref> ,
|
||||||
connectedFacet: (
|
connectedFacet: (
|
||||||
remoteObject: Ref,
|
remoteObject: Ref,
|
||||||
controlObject: Ref,
|
controlObject: Ref,
|
||||||
|
@ -473,14 +431,14 @@ export function contactRemote(
|
||||||
) => void,
|
) => void,
|
||||||
ds = Dataspace.local,
|
ds = Dataspace.local,
|
||||||
) {
|
) {
|
||||||
const routeValue = 'pathSteps' in route ? G.fromRoute(G.Route(route)) : route;
|
const routeValue = 'pathSteps' in route ? route : G.asRoute(route);
|
||||||
at ds {
|
at ds {
|
||||||
during G.ResolvePath({
|
assert Question(G.ResolvePath(routeValue));
|
||||||
"route": routeValue,
|
during Answer(G.ResolvePath(routeValue), resultOk(G.ResolvedPath({
|
||||||
"addr": $addr,
|
"addr": $addr,
|
||||||
"control": $control: Ref,
|
"control": $control: Ref,
|
||||||
"resolved": G.Resolved.accepted($resolved: Ref),
|
"responderSession": $resolved: Ref,
|
||||||
}) => {
|
}))) => {
|
||||||
connectedFacet(resolved, control, addr);
|
connectedFacet(resolved, control, addr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue