Monorepo for Aesthetic.Computer
aesthetic.computer
1// Session
2// Produces a valid URL for a given session backend.
3
4/* #region todo 📓
5+ Done
6- [x] Fix simultaneous joins in this implementation and also
7 implement jamsocket's locks function.
8- [x] Add a "local" redis database also, once it's actually necessary...
9 (It should work, just gotta make sure Redis is runnin')
10 - https://redis.io/docs/getting-started
11 - https://github.com/redis/node-redis follow these and setup a local server
12- [x] Add a SAAS cache to replace "backends" maybe redis?
13 - [x] How to set a grouping / hashmap for "backends" so that they contain an
14 association between the jamsocket URLs and a slug?
15 - [x] How to view all keys in redis database / connect via terminal?
16- [x] Produce a local URL when in development.
17#endregion */
18
19// import { createClient } from "redis";
20
21const dev = process.env.NETLIFY_DEV;
22// const redisConnectionString = process.env.REDIS_CONNECTION_STRING;
23
24const udpUrl = `https://udp.aesthetic.computer`;
25
26async function fun(event, context) {
27 let out,
28 status = 200,
29 forceProd = parseInt(event.queryStringParameters.forceProduction) === 1;
30
31 if (dev && !forceProd) {
32 let host = event.headers.host.split(":")[0];
33
34 // Check if we're in GitHub Codespaces
35 if (host.includes('github.dev') || host.includes('app.github.dev')) {
36 // Extract the codespace name and construct the port-forwarded URL
37 const codespaceUrlParts = host.split('.');
38 const codespaceBase = codespaceUrlParts[0]; // e.g., "cautious-waffle-ppwqx5vgv5hgwj-8888"
39 // Remove the port from the base and add 8889
40 const baseWithoutPort = codespaceBase.replace(/-\d+$/, ''); // Remove trailing port
41 const sessionUrl = `https://${baseWithoutPort}-8889.${codespaceUrlParts.slice(1).join('.')}`;
42 out = { url: sessionUrl, udp: sessionUrl };
43 } else if (host === "local.aesthetic.computer") {
44 out = { url: `https://session.${host}`, udp: `https://session.${host}` };
45 } else {
46 // Dev session server uses HTTPS (with local SSL certs)
47 out = { url: `https://${host}:8889`, udp: `https://${host}:8889` };
48 }
49
50 } else if (event.queryStringParameters.service === "monolith") {
51 out = {
52 url: `https://session-server.aesthetic.computer`,
53 udp: udpUrl,
54 state: "Ready",
55 };
56 } else {
57 const { got } = await import("got");
58 const slug = event.path.replace("/session/", ""); // Take everything after the path.
59 const jamSocketToken = process.env.JAMSOCKET_ACCESS_TOKEN;
60 out = {};
61
62 // rep.header("Access-Control-Allow-Origin", corsOrigin);
63
64 // 1. Check to see if we actually should make a backend.
65 if (slug.length === 1) {
66 status = 500;
67 out = { msg: "😇 Sorry. No backend could be spawned!" };
68 }
69
70 // Check to see if an "existing" backend for this slug is still alive.
71
72 // Connect to redis...
73 // const client = !dev
74 // ? createClient({ url: redisConnectionString })
75 // : createClient();
76 // client.on("error", (err) => console.log("🔴 Redis client error!", err));
77 // await client.connect();
78
79 // Check to see if a backend is already available...
80 // const currentBackend = await client.HGET("backends", slug);
81
82 // console.log("🫂 Current backend:", currentBackend);
83
84 // if (currentBackend) {
85 // try {
86 // out = await got(
87 // `https://api.jamsocket.com/backend/${currentBackend}/status`,
88 // ).json();
89 // out.url = `https://${currentBackend}.jamsocket.run`; // Add URL for client.
90 // out.udp = udpUrl;
91 // // console.log("Out:", out);
92 // } catch (err) {
93 // console.error("🔴 Error:", err);
94 // status = 500;
95 // out = err;
96 // }
97 // }
98
99 // if (out?.state !== "Ready") {
100 // Make a new session backend if one doesn't already exist.
101 try {
102 console.log("🟡 Spawning a new session for:", slug);
103 const session = await got
104 .post({
105 url: "https://api.jamsocket.com/user/jas/service/session-server/spawn",
106 json: { grace_period_seconds: 60, lock: slug }, // jamsocket api settings
107 headers: { Authorization: `Bearer ${jamSocketToken}` },
108 })
109 .json(); // Note: A failure will yield a 500 code here to the client.
110
111 // console.log("🫂 Session:", session);
112 // await client.HSET("backends", slug, session.name); // Store the session name in redis using the 'slug' key.
113
114 console.log("Session:", session);
115 out = session;
116 out.udp = udpUrl;
117 } catch (err) {
118 // console.error("🔴 Error:", err);
119 status = 500;
120 out = err;
121 }
122 // }
123
124 // await client.quit(); // Disconnect from redis client.
125 }
126
127 return {
128 statusCode: status,
129 body: JSON.stringify(out),
130 headers: {
131 "Access-Control-Allow-Origin": "*",
132 "Cache-Control": "no-cache, no-store, must-revalidate",
133 "Pragma": "no-cache",
134 "Expires": "0"
135 },
136 };
137}
138
139export const handler = fun;