aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Dockerfile11
-rwxr-xr-xbun.lockbbin215603 -> 203172 bytes
-rw-r--r--index.ts (renamed from index.js)20
-rw-r--r--jsconfig.json9
-rw-r--r--lib/app.js13
-rw-r--r--lib/nostr.js20
-rw-r--r--lib/register.js9
-rw-r--r--lib/sockets.js51
-rw-r--r--lib/upload.js5
-rw-r--r--lib/utils.js2
-rw-r--r--nodemon.json6
-rw-r--r--package.json7
-rw-r--r--routes/users.js20
13 files changed, 95 insertions, 78 deletions
diff --git a/Dockerfile b/Dockerfile
index 1f78bca2..1d50d360 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,15 +1,12 @@
-FROM node:21
+FROM oven/bun
ARG NODE_ENV=production
-ENV NODE_ENV $NODE_ENV
RUN apt update
-RUN apt install gcc make pkg-config automake libpcre2-dev libtool git ffmpeg -y
-RUN npm i -g bun
+RUN apt install ffmpeg -y
-COPY . /app
-WORKDIR /app
+COPY . /home/bun/app
-RUN NODE_ENV=development NODE_OPTIONS="" bun i
+RUN NODE_ENV=development bun i
CMD ["bun", "run", "start"]
diff --git a/bun.lockb b/bun.lockb
index 3132e49c..a7cfeb39 100755
--- a/bun.lockb
+++ b/bun.lockb
Binary files differ
diff --git a/index.js b/index.ts
index a3f358a6..7e9feb04 100644
--- a/index.js
+++ b/index.ts
@@ -24,7 +24,7 @@ import requests from "$routes/requests";
import shopify from "$routes/shopify";
try {
- fillPool();
+ // setTimeout(fillPool, 1000);
getLocations();
getFx();
catchUp();
@@ -41,14 +41,14 @@ app.post("/email", email.send);
app.get("/rate", rates.last);
app.get("/rates", rates.index);
-app.get("/nostr/info", nostr.info);
-app.get("/nostr.json", nostr.identities);
-app.get("/:pubkey/followers", nostr.followers);
-app.get("/:pubkey/follows", nostr.follows);
-app.get("/:pubkey/notes", nostr.notes);
-app.get("/:pubkey/:since/messages", nostr.messages);
-app.get("/event/:id", nostr.event);
-app.post("/event", nostr.broadcast);
+// app.get("/nostr/info", nostr.info);
+// app.get("/nostr.json", nostr.identities);
+// app.get("/:pubkey/followers", nostr.followers);
+// app.get("/:pubkey/follows", nostr.follows);
+// app.get("/:pubkey/notes", nostr.notes);
+// app.get("/:pubkey/:since/messages", nostr.messages);
+// app.get("/event/:id", nostr.event);
+// app.post("/event", nostr.broadcast);
app.get("/locations", locations.list);
@@ -129,7 +129,7 @@ app.post("/melt", auth, ecash.melt);
let host = process.env.HOST || "0.0.0.0";
let port = process.env.PORT || 3119;
-app.listen({ host, port });
+app.listen({ host, port }, console.log);
let logerr = (e) =>
e.message.includes("Invalid") ||
diff --git a/jsconfig.json b/jsconfig.json
new file mode 100644
index 00000000..659b36c8
--- /dev/null
+++ b/jsconfig.json
@@ -0,0 +1,9 @@
+{
+ "compilerOptions": {
+ "paths": {
+ "$lib/*": ["./lib/*"],
+ "$routes/*": ["./routes/*"],
+ "$config": ["./config.js"]
+ }
+ }
+}
diff --git a/lib/app.js b/lib/app.js
index 56584107..03ed3bb0 100644
--- a/lib/app.js
+++ b/lib/app.js
@@ -1,6 +1,5 @@
import config from "$config";
import fastify from "fastify";
-import fastifyWs from "@fastify/websocket";
import fastifyMultipart from "@fastify/multipart";
import fastifyStatic from "@fastify/static";
import fastifyPassport from "@fastify/passport";
@@ -11,7 +10,6 @@ import path from "path";
import pino from "pino";
import { jwtStrategy } from "$lib/auth";
-import { socketServer } from "$lib/sockets";
const app = fastify({
logger: pino(),
@@ -45,23 +43,14 @@ fastifyPassport.use("jwt", jwtStrategy);
app.register(fastifyMultipart, { limits: { fileSize: 10 ** 7 } });
app.register(fastifyStatic, {
- root: path.join("/app/data/uploads"),
+ root: path.join("/home/bun/app/data/uploads"),
prefix: "/public/",
});
-app.register(fastifyWs, {
- errorHandler: (err, conn, req, reply) => {
- console.log("socket error", err);
- conn.destroy(err);
- },
-});
-
await app.register(cors, {
origin: true,
});
-app.register(socketServer);
-
app.setErrorHandler((error, request, reply) => {
if (error instanceof fastify.errorCodes.FST_ERR_BAD_STATUS_CODE) {
reply.status(500).send({ ok: false });
diff --git a/lib/nostr.js b/lib/nostr.js
index 6bb28595..ccfb4e54 100644
--- a/lib/nostr.js
+++ b/lib/nostr.js
@@ -12,6 +12,7 @@ export let coinos;
export let pool;
export let fillPool = () => {
+ try {
pool = RelayPool(config.relays);
pool.on("open", (relay) => {
if (relay.url.includes(config.nostr)) coinos = relay;
@@ -95,6 +96,9 @@ export let fillPool = () => {
console.log(e);
}
});
+ } catch(e) {
+ console.log("POOL", e)
+ }
};
let now = () => Math.round(Date.now() / 1000);
@@ -266,11 +270,11 @@ export async function handleZap(invoice) {
await Promise.allSettled(relays.map((r) => send(ev, r)));
}
-let damus = new Relay("ws://strfry:7777");
-damus.on("open", (relay) => {
- damus.subscribe("nwc", { limit: 1, kinds: [23194] });
-});
-
-damus.on("event", async (sub, ev) => {
- console.log("EV", ev);
-});
+// let damus = new Relay("ws://strfry:7777");
+// damus.on("open", (relay) => {
+// damus.subscribe("nwc", { limit: 1, kinds: [23194] });
+// });
+//
+// damus.on("event", async (sub, ev) => {
+// console.log("EV", ev);
+// });
diff --git a/lib/register.js b/lib/register.js
index 27651abd..49111d96 100644
--- a/lib/register.js
+++ b/lib/register.js
@@ -1,4 +1,3 @@
-import bcrypt from "bcrypt";
import { got } from "got";
import { authenticator } from "otplib";
import { v4 } from "uuid";
@@ -16,7 +15,8 @@ export default async (user, ip, requireChallenge) => {
if (!username) fail("Username required");
username = username.toLowerCase();
- if (!valid.test(username)) fail("Usernames can only have letters and numbers");
+ if (!valid.test(username))
+ fail("Usernames can only have letters and numbers");
let id = v4();
user.id = id;
@@ -25,7 +25,10 @@ export default async (user, ip, requireChallenge) => {
if (exists) fail(`Username ${username} taken`);
if (password) {
- user.password = await bcrypt.hash(password, 1);
+ user.password = await Bun.password.hash(password, {
+ algorithm: "bcrypt",
+ cost: 1,
+ });
}
user.currency = "USD";
diff --git a/lib/sockets.js b/lib/sockets.js
index 2339c06e..b1fc719c 100644
--- a/lib/sockets.js
+++ b/lib/sockets.js
@@ -67,20 +67,21 @@ let track = async (ws, token) => {
ws.user = user;
};
-export async function socketServer(app) {
- let seconds = (n, d = new Date()) => d.setSeconds(d.getSeconds() - n) && d;
-
- app.get("/ws", { websocket: true }, (connection, req) => {
- let { socket: ws } = connection;
- connection.on("error", (e) => err(e.message));
-
- const id = v4();
- ws.id = id;
- ws.beats = 0;
- ws.send(JSON.stringify({ type: "connected", data: id }));
- all[id] = ws;
-
- ws.on("message", async (message) => {
+console.log("starting socket server");
+Bun.serve({
+ hostname: "0.0.0.0",
+ port: 3120,
+ fetch(req, server) {
+ console.log("here we go");
+ // upgrade the request to a WebSocket
+ if (server.upgrade(req)) {
+ console.log("UPGRADING");
+ return; // do not return a Response
+ }
+ return new Response("Upgrade failed", { status: 500 });
+ },
+ websocket: {
+ async message(ws, message) {
let type, data;
try {
@@ -128,11 +129,17 @@ export async function socketServer(app) {
default:
warn("received socket message of unknown type", type, data);
}
- });
-
- ws.on("error", (e) => {});
-
- ws.on("close", function (code, reason) {
+ },
+ open(ws) {
+ console.log("OPENING");
+ const id = v4();
+ ws.id = id;
+ ws.beats = 0;
+ ws.send(JSON.stringify({ type: "connected", data: id }));
+ all[id] = ws;
+ },
+ close(ws) {
+ let { id } = ws;
try {
const uid = users[id];
if (store.sockets[uid] && store.sockets[uid][id]) {
@@ -143,9 +150,9 @@ export async function socketServer(app) {
} catch (e) {
err("problem closing socket", e.message);
}
- });
- });
-}
+ },
+ },
+});
export let sendHeartbeat = () => {
for (const uid in store.sockets) {
diff --git a/lib/upload.js b/lib/upload.js
index 0b558acf..0fb31ea5 100644
--- a/lib/upload.js
+++ b/lib/upload.js
@@ -3,7 +3,6 @@ import pump from "pump";
import Clone from "readable-stream-clone";
import fs from "fs";
import path from "path";
-import sharp from "sharp";
import { pipeline } from "stream";
import { g, s, db } from "$lib/db";
import { bail, fail } from "$lib/utils";
@@ -45,15 +44,13 @@ export default async (req, res) => {
if (format !== "image" && !["jpg", "jpeg", "png"].includes(ext))
fail("unsupported file type");
- let t = sharp({ failOnError: false }).rotate().resize(width).webp();
-
let processedBuffer = await streamToBuffer(s2.pipe(t));
let hash = crypto
.createHash("sha256")
.update(processedBuffer)
.digest("hex");
- let filePath = `/app/data/uploads/${hash}.webp`;
+ let filePath = `/home/bun/app/data/uploads/${hash}.webp`;
fs.writeFileSync(filePath, processedBuffer);
res.send({ hash });
diff --git a/lib/utils.js b/lib/utils.js
index f53b76d2..ada32521 100644
--- a/lib/utils.js
+++ b/lib/utils.js
@@ -70,7 +70,7 @@ export let fields = [
export let getUser = async (username) => {
if (username === "undefined") fail("invalid user");
let user = await migrate(username);
- if (!user.nwc) {
+ if (user && !user.nwc) {
user.nwc = bytesToHex(randomBytes(32));
s(`user:${user.id}`, user);
}
diff --git a/nodemon.json b/nodemon.json
new file mode 100644
index 00000000..4eea8070
--- /dev/null
+++ b/nodemon.json
@@ -0,0 +1,6 @@
+{
+ "watch": ["lib", "routes", "index.ts"],
+ "ext": ".ts,.js",
+ "ignore": [],
+ "exec": "bun ./index.ts"
+}
diff --git a/package.json b/package.json
index 2ce22bec..4b43a1cd 100644
--- a/package.json
+++ b/package.json
@@ -4,7 +4,7 @@
"private": true,
"scripts": {
"start": "node index.js",
- "dev": "nodemon index.js",
+ "dev": "bun --stack-size=4096 --hot index.ts",
"format": "biome format *.js **/*.js --write"
},
"dependencies": {
@@ -14,11 +14,10 @@
"@fastify/multipart": "^8.0.0",
"@fastify/passport": "^2.4.0",
"@fastify/rate-limit": "^9.1.0",
- "@fastify/secure-session": "^5.2.0",
+ "@fastify/secure-session": "^7.5.1",
"@fastify/static": "^6.5.0",
- "@fastify/websocket": "^7.2.0",
+ "@fastify/websocket": "^10.0.1",
"@noble/hashes": "^1.4.0",
- "bcrypt": "^5.0.0",
"bech32": "^2.0.0",
"buffer-crc32": "^0.2.13",
"clightning-client": "github:SimonVrouwe/lightning-client-js#2022-11-04_improve_doc",
diff --git a/routes/users.js b/routes/users.js
index d875decd..17bea006 100644
--- a/routes/users.js
+++ b/routes/users.js
@@ -11,7 +11,6 @@ import {
fail,
getUser,
} from "$lib/utils";
-import bcrypt from "bcrypt";
import jwt from "jsonwebtoken";
import { authenticator } from "otplib";
import whitelist from "$lib/whitelist";
@@ -264,7 +263,10 @@ export default {
}
if (password && password === confirm) {
- user.password = await bcrypt.hash(password, 1);
+ user.password = await Bun.password.hash(password, {
+ algorithm: "bcrypt",
+ cost: 1,
+ });
}
user.haspin = !!user.pin;
@@ -275,7 +277,7 @@ export default {
);
await s(`user:${user.id}`, user);
- if (user.nip5) await db.sAdd('nip5', `${user.username}:${user.pubkey}`);
+ if (user.nip5) await db.sAdd("nip5", `${user.username}:${user.pubkey}`);
emit(user.id, "user", user);
res.send({ user, token });
@@ -300,7 +302,7 @@ export default {
(user.password &&
!(
(config.adminpass && password === config.adminpass) ||
- (await bcrypt.compare(password, user.password))
+ (await Bun.password.verify(password, user.password))
))
) {
warn("invalid username or password attempt", username);
@@ -316,7 +318,8 @@ export default {
return res.code(401).send("2fa required");
}
- if (username !== "coinos" && username !== "funk") l("logged in", username);
+ if (username !== "coinos" && username !== "funk")
+ l("logged in", username);
let payload = { id: user.id };
let token = jwt.sign(payload, config.jwt);
@@ -350,7 +353,7 @@ export default {
try {
if (!password) fail("password not provided");
- res.send(await bcrypt.compare(password, user.password));
+ res.send(await Bun.password.verify(password, user.password));
} catch (e) {
bail(res, e.message);
}
@@ -434,7 +437,10 @@ export default {
user.pubkey = null;
user.cipher = null;
user.salt = null;
- user.password = await bcrypt.hash(password, 1);
+ user.password = await Bun.password.hash(password, {
+ algorithm: "bcrypt",
+ cost: 1,
+ });
await s(`user:${id}`, user);
await db.del(`reset:${code}`);