Fix up secure-chat using facets!; and factor out readline
This commit is contained in:
parent
ff1feff82b
commit
8b460a2f1c
|
@ -0,0 +1,19 @@
|
|||
import { Turn, Entity, Facet } from './actor.js';
|
||||
import readline from 'readline';
|
||||
|
||||
export function attachReadline(t: Turn, entity: Partial<Entity>): Facet {
|
||||
const ref = t.ref(entity);
|
||||
return t.facet(t => {
|
||||
let rl: readline.Interface | null =
|
||||
readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
function shutdown(_t: Turn) {
|
||||
rl?.close();
|
||||
rl = null;
|
||||
}
|
||||
t.assert(ref, true);
|
||||
t.activeFacet.actor.atExit(shutdown);
|
||||
t.activeFacet.onStop(shutdown);
|
||||
rl.on('line', (line: string) => t.freshen(t => t.message(ref, line)));
|
||||
rl.on('close', () => t.freshen(t => t.stop()));
|
||||
});
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
import { $joinedUser, $says, $user, asJoin, asSays, asUserInfo, fromNickClaim, fromSays, NickClaim, Says, UserId } from "./gen/secure-chat-protocol.js";
|
||||
import { during, observe } from "./dataspace.js";
|
||||
import { Assertion, Ref, Turn } from "./actor.js";
|
||||
import readline from 'readline';
|
||||
import { attachReadline } from './readline.js';
|
||||
|
||||
export default function (t: Turn, ds: Ref) {
|
||||
observe(t, ds, $joinedUser, {
|
||||
|
@ -52,15 +52,14 @@ function runSession(t: Turn, uid: UserId, session: Ref) {
|
|||
},
|
||||
});
|
||||
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
|
||||
rl.on('line', (line: string) => t.freshen(t => {
|
||||
if (line.toLowerCase().startsWith('/nick ')) {
|
||||
updateUsername(t, line.slice(5).trimLeft());
|
||||
} else {
|
||||
t.message(session, fromSays(Says({ who: uid, what: line })));
|
||||
}
|
||||
}));
|
||||
|
||||
rl.on('close', () => t.freshen(t => t.stopActor()));
|
||||
attachReadline(t, {
|
||||
retract(t) { t.stop(); },
|
||||
message(t, line: string) {
|
||||
if (line.toLowerCase().startsWith('/nick ')) {
|
||||
updateUsername(t, line.slice(5).trimLeft());
|
||||
} else {
|
||||
t.message(session, fromSays(Says({ who: uid, what: line })));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
|
@ -6,37 +6,33 @@ export default function (t: Turn, ds: Ref) {
|
|||
let nextUserId: UserId = 0;
|
||||
|
||||
const nicks = new Map<string, UserId>();
|
||||
const users = new Map<UserId, { infoHandle: Handle | undefined, nick: string | undefined }>();
|
||||
|
||||
observe(t, ds, $claimNick, {
|
||||
assert(t: Turn, c0: Assertion): void {
|
||||
const c = asNickClaim(c0);
|
||||
if (nicks.has(c.name)) {
|
||||
t.message(c.k, fromNickConflict(NickConflict()));
|
||||
} else {
|
||||
t.message(c.k, true);
|
||||
let u = users.get(c.uid);
|
||||
if (!u) {
|
||||
u = { infoHandle: void 0, nick: void 0 };
|
||||
users.set(c.uid, u);
|
||||
}
|
||||
if (u.nick !== void 0) nicks.delete(u.nick);
|
||||
u.infoHandle = t.replace(ds, u.infoHandle, fromUserInfo(UserInfo(c)));
|
||||
u.nick = c.name;
|
||||
nicks.set(c.name, c.uid);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
observe(t, ds, $Observe, during((t, o0) => {
|
||||
const o = asObserve(o0);
|
||||
if (o.label !== $joinedUser) return null;
|
||||
|
||||
const uid: UserId = nextUserId++;
|
||||
const h = t.assert(o.observer, fromJoin(Join({
|
||||
uid,
|
||||
handle: ds,
|
||||
})));
|
||||
return t => t.retract(h);
|
||||
const f = t.facet(t => {
|
||||
t.assert(o.observer, fromJoin(Join({ uid, handle: ds })));
|
||||
let infoHandle: Handle | undefined;
|
||||
let nick: string | undefined;
|
||||
observe(t, ds, $claimNick, {
|
||||
assert(t: Turn, c0: Assertion): void {
|
||||
const c = asNickClaim(c0);
|
||||
if (c.uid !== uid) return;
|
||||
if (nicks.has(c.name)) {
|
||||
t.message(c.k, fromNickConflict(NickConflict()));
|
||||
} else {
|
||||
t.message(c.k, true);
|
||||
if (nick !== void 0) nicks.delete(nick);
|
||||
infoHandle = t.replace(ds, infoHandle, fromUserInfo(UserInfo(c)));
|
||||
nick = c.name;
|
||||
nicks.set(nick, uid);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
return t => t.stop(f);
|
||||
}));
|
||||
}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { $Present, $Says, asPresent, asSays, fromPresent, fromSays, Present, Says } from "./gen/simple-chat-protocol.js";
|
||||
import { during, observe } from "./dataspace.js";
|
||||
import { Assertion, Handle, Ref, Turn } from "./actor.js";
|
||||
import readline from 'readline';
|
||||
import { attachReadline } from './readline.js';
|
||||
|
||||
export default function (t: Turn, ds: Ref) {
|
||||
let username = '';
|
||||
|
@ -26,16 +26,14 @@ export default function (t: Turn, ds: Ref) {
|
|||
},
|
||||
});
|
||||
|
||||
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
||||
t.activeFacet.actor.atExit(_t => rl.close());
|
||||
|
||||
rl.on('line', (line: string) => t.freshen(t => {
|
||||
if (line.toLowerCase().startsWith('/nick ')) {
|
||||
updateUsername(t, line.slice(5).trimLeft());
|
||||
} else {
|
||||
t.message(ds, fromSays(Says({ who: username, what: line })));
|
||||
}
|
||||
}));
|
||||
|
||||
rl.on('close', () => t.freshen(t => t.stopActor()));
|
||||
attachReadline(t, {
|
||||
retract(t) { t.stop(); },
|
||||
message(t, line: string) {
|
||||
if (line.toLowerCase().startsWith('/nick ')) {
|
||||
updateUsername(t, line.slice(5).trimLeft());
|
||||
} else {
|
||||
t.message(ds, fromSays(Says({ who: username, what: line })));
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue