Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
sagemathinc
GitHub Repository: sagemathinc/cocalc
Path: blob/master/src/packages/project/conat/browser-websocket-api.ts
1447 views
1
/*
2
Implement the same protocol as browser-websocket was built on using primus,
3
but instead using NATS.
4
5
How to do development (so in a dev project doing cc-in-cc dev):
6
7
0. From the browser, send a terminate-handler message, so the handler running in the project stops:
8
9
await cc.client.conat_client.projectWebsocketApi({project_id:cc.current().project_id, mesg:{cmd:"terminate"}})
10
11
1. Open a terminal in the project itself, which sets up the required environment variables. See api/index.ts for details!!
12
13
2. cd to your dev packages/project source code, e.g., ../cocalc/src/packages/project
14
15
3. Do this:
16
17
echo 'require("@cocalc/project/client").init(); require("@cocalc/project/conat/browser-websocket-api").init()' | DEBUG=cocalc:* DEBUG_CONSOLE=yes node
18
19
Or just run node then paste in
20
21
require("@cocalc/project/client").init(); require("@cocalc/project/conat/browser-websocket-api").init()
22
23
A nice thing about doing that is if you write this deep in some code:
24
25
global.x = { t: this };
26
27
then after that code runs you can access x from the node console!
28
29
4. Use the browser to see the project is on conat and works:
30
31
await cc.client.conat_client.projectWebsocketApi({project_id:'56eb622f-d398-489a-83ef-c09f1a1e8094', mesg:{cmd:"listing"}})
32
33
5. In a terminal you can always tap into the message stream for a particular project:
34
35
cd packages/backend
36
pnpm conat-watch project.56eb622f-d398-489a-83ef-c09f1a1e8094.browser-api --match-replies
37
38
*/
39
40
import { getLogger } from "@cocalc/project/logger";
41
import { connectToConat } from "./connection";
42
import { handleApiCall } from "@cocalc/project/browser-websocket/api";
43
import { getSubject } from "./names";
44
45
const logger = getLogger("project:conat:browser-websocket-api");
46
47
export async function init() {
48
const client = connectToConat();
49
const subject = getSubject({
50
service: "browser-api",
51
});
52
logger.debug(`initAPI -- project subject '${subject}'`);
53
const sub = await client.subscribe(subject);
54
logger.debug(`browser primus subject: ${getSubject({ service: "primus" })}`);
55
const primus = client.socket.listen(getSubject({ service: "primus" }));
56
primus.on("connection", (spark) => {
57
logger.debug("got a spark");
58
spark.on("data", (data) => {
59
spark.write(`${data}`.repeat(3));
60
});
61
});
62
for await (const mesg of sub) {
63
const data = mesg.data ?? ({} as any);
64
if (data.cmd == "terminate") {
65
logger.debug(
66
"received terminate-handler, so will not handle any further messages",
67
);
68
mesg.respond({ exiting: true });
69
return;
70
}
71
handleRequest({ data, mesg, primus });
72
}
73
}
74
75
async function handleRequest({ data, mesg, primus }) {
76
let resp;
77
logger.debug("received cmd:", data?.cmd);
78
try {
79
resp = await handleApiCall({ data, spark: {} as any, primus });
80
} catch (err) {
81
resp = { error: `${err}` };
82
}
83
//logger.debug("responded", resp);
84
mesg.respond(resp ?? null);
85
}
86
87