Setup client + server framework
This commit is contained in:
parent
28e3a1f1e5
commit
7480da4b69
11 changed files with 189 additions and 18 deletions
2
.env.example
Normal file
2
.env.example
Normal file
|
@ -0,0 +1,2 @@
|
|||
OAUTH_CLIENT_ID=
|
||||
OAUTH_CLIENT_SECRET=
|
8
.gitignore
vendored
8
.gitignore
vendored
|
@ -39,4 +39,10 @@ yarn-error.log*
|
|||
**/*.tgz
|
||||
**/*.log
|
||||
package-lock.json
|
||||
**/*.bun
|
||||
**/*.bun
|
||||
|
||||
.vscode
|
||||
|
||||
.env
|
||||
|
||||
db.sqlite
|
||||
|
|
3
.gitmodules
vendored
Normal file
3
.gitmodules
vendored
Normal file
|
@ -0,0 +1,3 @@
|
|||
[submodule "client"]
|
||||
path = client
|
||||
url = git@code.incremental.social:thepaperpilot/chromatic-lattice.git
|
17
Dockerfile
Normal file
17
Dockerfile
Normal file
|
@ -0,0 +1,17 @@
|
|||
FROM oven/bun
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY package.json .
|
||||
COPY bun.lockb .
|
||||
|
||||
RUN bun install --production
|
||||
|
||||
COPY src src
|
||||
COPY tsconfig.json .
|
||||
# COPY public public
|
||||
|
||||
ENV NODE_ENV production
|
||||
CMD ["bun", "src/index.ts"]
|
||||
|
||||
EXPOSE 3000
|
BIN
bun.lockb
Normal file
BIN
bun.lockb
Normal file
Binary file not shown.
1
client
Submodule
1
client
Submodule
|
@ -0,0 +1 @@
|
|||
Subproject commit 337d394fd33496d9aff23ef847ce56b1464deee6
|
22
common/events.ts
Normal file
22
common/events.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { t } from "elysia";
|
||||
|
||||
interface ServerToClientEvents {
|
||||
"server version": (semver: string) => void;
|
||||
info: (message: string) => void;
|
||||
"set cursor position": (user: string, pos: { x: number; y: number }) => void;
|
||||
chat: (user: string, message: string) => void;
|
||||
}
|
||||
|
||||
export const clientToServerEvents = t.Object({
|
||||
message: t.Union([
|
||||
t.Object({
|
||||
type: t.Literal("set cursor position"),
|
||||
x: t.Number(),
|
||||
y: t.Number()
|
||||
}),
|
||||
t.Object({
|
||||
type: t.Literal("chat"),
|
||||
messageq: t.String()
|
||||
})
|
||||
])
|
||||
});
|
26
package.json
26
package.json
|
@ -1,18 +1,24 @@
|
|||
{
|
||||
"name": "@bun-examples/elysia",
|
||||
"version": "1.0.50",
|
||||
"name": "chromatic-lattice",
|
||||
"version": "1.0.0",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"dev": "bun run --watch src/index.ts"
|
||||
"start": "bun run server/index.ts",
|
||||
"dev": "conc npm:dev:server npm:dev:client",
|
||||
"dev:server": "bun run --watch server/index.ts",
|
||||
"dev:client": "bunx --bun vite client",
|
||||
"build": "bunx --bun vite build client",
|
||||
"test": "vitest run -r client",
|
||||
"testw": "vitest -r client"
|
||||
},
|
||||
"dependencies": {
|
||||
"elysia": "latest"
|
||||
"@bogeychan/elysia-oauth2": "^0.0.19",
|
||||
"elysia": "latest",
|
||||
"profectus": "file:./client"
|
||||
},
|
||||
"devDependencies": {
|
||||
"bun-types": "latest"
|
||||
"bun-types": "latest",
|
||||
"concurrently": "^8.2.2"
|
||||
},
|
||||
"module": "src/index.js",
|
||||
"bun-create": {
|
||||
"start": "bun run src/index.ts"
|
||||
}
|
||||
"module": "server/index.js"
|
||||
}
|
||||
|
|
109
server/index.ts
Normal file
109
server/index.ts
Normal file
|
@ -0,0 +1,109 @@
|
|||
import { Elysia, t } from "elysia";
|
||||
import oauth2 from "@bogeychan/elysia-oauth2";
|
||||
import { Database } from "bun:sqlite";
|
||||
import { randomBytes } from "crypto";
|
||||
|
||||
|
||||
import { migrateDatabase } from "./migrations";
|
||||
import { clientToServerEvents } from "../common/events";
|
||||
|
||||
const db = new Database("db.sqlite", { create: true });
|
||||
migrateDatabase(db);
|
||||
|
||||
const states = new Set();
|
||||
|
||||
const auth = oauth2({
|
||||
profiles: {
|
||||
incsoc: {
|
||||
provider: {
|
||||
clientId: Bun.env.OAUTH_CLIENT_ID!,
|
||||
clientSecret: Bun.env.OAUTH_CLIENT_SECRET!,
|
||||
|
||||
auth: {
|
||||
url: 'https://auth.incremental.social/auth/v1',
|
||||
params: {}
|
||||
},
|
||||
|
||||
token: {
|
||||
url: 'https://auth.incremental.social/oauth/v2/token',
|
||||
params: {}
|
||||
}
|
||||
},
|
||||
scope: ['email', 'profile']
|
||||
}
|
||||
},
|
||||
state: {
|
||||
check(ctx, id, state) {
|
||||
if (states.has(state)) {
|
||||
states.delete(state);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
},
|
||||
generate(ctx, id) {
|
||||
const state = randomBytes(8).toString('hex');
|
||||
states.add(state);
|
||||
return state;
|
||||
}
|
||||
},
|
||||
storage: {
|
||||
get(ctx, id) {
|
||||
console.log(`get token: ${id}`);
|
||||
|
||||
// const token = (
|
||||
// db
|
||||
// .query('SELECT token FROM storage WHERE uuid = ? AND id = ?')
|
||||
// .get(uuid, id) as { token: string }
|
||||
// )?.token;
|
||||
|
||||
// if (!token) {
|
||||
// return;
|
||||
// }
|
||||
|
||||
// return JSON.parse(token);
|
||||
return undefined;
|
||||
},
|
||||
set(ctx, id, token) {
|
||||
console.log(`new token: ${id}`);
|
||||
|
||||
// db.run(
|
||||
// 'INSERT OR REPLACE INTO storage (id, token) VALUES (?, ?)',
|
||||
// [id, JSON.stringify(token)]
|
||||
// );
|
||||
},
|
||||
delete(ctx, id) {
|
||||
// db.run('DELETE FROM storage WHERE id = ?', [id]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
const app = new Elysia()
|
||||
.use(auth)
|
||||
.ws('/ws', {
|
||||
body: t.Object({
|
||||
message: clientToServerEvents
|
||||
}),
|
||||
message(ws, { message }) {
|
||||
console.log(message);
|
||||
},
|
||||
beforeHandle: async function({ set, authorized, tokenHeaders }) {
|
||||
// Check auth
|
||||
if (!(await authorized("incsoc"))) {
|
||||
return (set.status = 'Unauthorized');
|
||||
}
|
||||
|
||||
const user = await fetch('https://auth.incremental.social/oidc/v1/userinfo', {
|
||||
headers: await tokenHeaders("incsoc")
|
||||
});
|
||||
|
||||
console.log(JSON.stringify(user));
|
||||
|
||||
// Update avatar and display name from mbin, fallback to userinfo
|
||||
}
|
||||
})
|
||||
.listen(3000);
|
||||
|
||||
console.log(
|
||||
`🦊 Chromatic Lattice server is running at ${app.server?.url.href}`
|
||||
);
|
12
server/migrations.ts
Normal file
12
server/migrations.ts
Normal file
|
@ -0,0 +1,12 @@
|
|||
import { Database } from "bun:sqlite";
|
||||
|
||||
export function migrateDatabase(db: Database) {
|
||||
const version = (db.query("PRAGMA user_version").get() as { user_version: number }).user_version;
|
||||
|
||||
if (version < 1) {
|
||||
console.log("Applying migration 0 -> 1")
|
||||
db.run("CREATE TABLE tokens (id TEXT, token TEXT, PRIMARY KEY(id))")
|
||||
}
|
||||
|
||||
db.run("PRAGMA user_version = 1;");
|
||||
}
|
|
@ -1,7 +0,0 @@
|
|||
import { Elysia } from "elysia";
|
||||
|
||||
const app = new Elysia().get("/", () => "Hello Elysia").listen(3000);
|
||||
|
||||
console.log(
|
||||
`🦊 Elysia is running at ${app.server?.hostname}:${app.server?.port}`
|
||||
);
|
Loading…
Add table
Reference in a new issue