mirror of
https://github.com/Nystik-gh/ignis.git
synced 2026-06-17 04:35:53 +00:00
some styling cleanup
This commit is contained in:
@@ -3,7 +3,7 @@ const fs = require("fs");
|
||||
|
||||
// VAULT_ROOT: a directory that contains vault folders.
|
||||
// Each subdirectory is a vault. New vaults are created as new subdirs.
|
||||
// Falls back to parent of VAULT_PATH (single-vault compat) or ./vaults.
|
||||
// Falls back to parent of VAULT_PATH (single-vault compatibility) or ./vaults.
|
||||
const vaultRoot =
|
||||
process.env.VAULT_ROOT ||
|
||||
(process.env.VAULT_PATH
|
||||
@@ -19,8 +19,10 @@ try {
|
||||
|
||||
function discoverVaults() {
|
||||
const vaults = {};
|
||||
|
||||
try {
|
||||
const entries = fs.readdirSync(vaultRoot, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory() && !entry.name.startsWith(".")) {
|
||||
vaults[entry.name] = path.join(vaultRoot, entry.name);
|
||||
@@ -29,12 +31,15 @@ function discoverVaults() {
|
||||
} catch (e) {
|
||||
console.error("[config] Failed to read VAULT_ROOT:", vaultRoot, e.message);
|
||||
}
|
||||
|
||||
// Create a default vault if none exist
|
||||
if (Object.keys(vaults).length === 0) {
|
||||
const defaultPath = path.join(vaultRoot, "My Vault");
|
||||
|
||||
try {
|
||||
fs.mkdirSync(path.join(defaultPath, ".obsidian"), { recursive: true });
|
||||
vaults["My Vault"] = defaultPath;
|
||||
|
||||
console.log("[config] Created default vault: My Vault");
|
||||
} catch (e) {
|
||||
console.error("[config] Failed to create default vault:", e.message);
|
||||
|
||||
@@ -3,28 +3,39 @@ const path = require("path");
|
||||
const config = require("./config");
|
||||
const { setupWebSocket } = require("./ws");
|
||||
|
||||
const ANSI_RED = "\x1b[31m";
|
||||
const ANSI_YELLOW = "\x1b[33m";
|
||||
const ANSI_GREEN = "\x1b[32m";
|
||||
const ANSI_RESET = "\x1b[0m";
|
||||
|
||||
const app = express();
|
||||
|
||||
app.use(express.json({ limit: "50mb" }));
|
||||
|
||||
// logger middleware
|
||||
app.use((req, res, next) => {
|
||||
const start = Date.now();
|
||||
const origEnd = res.end;
|
||||
|
||||
res.end = function (...args) {
|
||||
const duration = Date.now() - start;
|
||||
const status = res.statusCode;
|
||||
|
||||
const color =
|
||||
status >= 500 ? "\x1b[31m" : status >= 400 ? "\x1b[33m" : "\x1b[32m";
|
||||
const reset = "\x1b[0m";
|
||||
status >= 500 ? ANSI_RED : status >= 400 ? ANSI_YELLOW : ANSI_GREEN;
|
||||
|
||||
const path =
|
||||
req.originalUrl.length > 80
|
||||
? req.originalUrl.slice(0, 80) + "..."
|
||||
: req.originalUrl;
|
||||
|
||||
console.log(
|
||||
`${color}${req.method} ${status}${reset} ${path} (${duration}ms)`,
|
||||
`${color}${req.method} ${status}${ANSI_RESET} ${path} (${duration}ms)`,
|
||||
);
|
||||
|
||||
origEnd.apply(this, args);
|
||||
};
|
||||
|
||||
next();
|
||||
});
|
||||
|
||||
@@ -41,11 +52,18 @@ app.use("/api/proxy", proxyRoutes);
|
||||
app.use("/vault-files", (req, res, next) => {
|
||||
// Extract vault ID from the first path segment
|
||||
const parts = req.path.split("/").filter(Boolean);
|
||||
if (parts.length === 0)
|
||||
|
||||
if (parts.length === 0) {
|
||||
return res.status(400).json({ error: "Missing vault ID" });
|
||||
}
|
||||
|
||||
const vaultId = decodeURIComponent(parts[0]);
|
||||
const vaultPath = config.getVaultPath(vaultId);
|
||||
if (!vaultPath) return res.status(404).json({ error: "Vault not found" });
|
||||
|
||||
if (!vaultPath) {
|
||||
return res.status(404).json({ error: "Vault not found" });
|
||||
}
|
||||
|
||||
// Rewrite req.url to strip the vault ID prefix, then serve statically
|
||||
req.url = "/" + parts.slice(1).join("/");
|
||||
express.static(vaultPath)(req, res, next);
|
||||
|
||||
@@ -9,6 +9,7 @@ const router = express.Router();
|
||||
function getVaultRoot(req, res) {
|
||||
const vaultId = req.query.vault || req.body?.vault || config.defaultVaultId;
|
||||
const vaultPath = config.getVaultPath(vaultId);
|
||||
|
||||
if (!vaultPath) {
|
||||
res.status(404).json({ error: "Vault not found", id: vaultId });
|
||||
return null;
|
||||
@@ -21,39 +22,35 @@ function getVaultRoot(req, res) {
|
||||
function resolveVaultPath(vaultRoot, relativePath) {
|
||||
const cleaned = (relativePath || "").replace(/^\/+/, "");
|
||||
const resolved = path.resolve(vaultRoot, cleaned);
|
||||
|
||||
if (!resolved.startsWith(path.resolve(vaultRoot))) {
|
||||
return null;
|
||||
}
|
||||
return resolved;
|
||||
}
|
||||
|
||||
function guardPath(req, res) {
|
||||
function guardPath(req, res, source = "query") {
|
||||
const vaultRoot = getVaultRoot(req, res);
|
||||
if (!vaultRoot) return null;
|
||||
const p = req.query.path ?? req.body?.path;
|
||||
|
||||
if (!vaultRoot) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const p = source === "body" ? req.body?.path : req.query.path;
|
||||
|
||||
if (p === undefined || p === null) {
|
||||
res.status(400).json({ error: "Missing path parameter" });
|
||||
return null;
|
||||
}
|
||||
|
||||
// Empty string = vault root, which is valid
|
||||
const resolved = resolveVaultPath(vaultRoot, p);
|
||||
|
||||
if (!resolved) {
|
||||
res.status(403).json({ error: "Path traversal rejected" });
|
||||
return null;
|
||||
}
|
||||
req._vaultRoot = vaultRoot;
|
||||
return resolved;
|
||||
}
|
||||
|
||||
// Same as guardPath but reads path from req.body (POST routes)
|
||||
function guardBodyPath(req, res) {
|
||||
const vaultRoot = getVaultRoot(req, res);
|
||||
if (!vaultRoot) return null;
|
||||
const resolved = resolveVaultPath(vaultRoot, req.body?.path);
|
||||
if (!resolved) {
|
||||
res.status(403).json({ error: "Invalid path" });
|
||||
return null;
|
||||
}
|
||||
req._vaultRoot = vaultRoot;
|
||||
return resolved;
|
||||
}
|
||||
@@ -61,9 +58,14 @@ function guardBodyPath(req, res) {
|
||||
// GET /api/fs/stat?path=...
|
||||
router.get("/stat", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const stat = await fs.promises.stat(resolved);
|
||||
|
||||
res.json({
|
||||
type: stat.isDirectory() ? "directory" : "file",
|
||||
size: stat.size,
|
||||
@@ -80,18 +82,25 @@ router.get("/stat", async (req, res) => {
|
||||
// GET /api/fs/readdir?path=...
|
||||
router.get("/readdir", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if path is a file. return ENOTDIR instead of crashing
|
||||
const stat = await fs.promises.stat(resolved);
|
||||
|
||||
if (!stat.isDirectory()) {
|
||||
return res
|
||||
.status(400)
|
||||
.json({ error: "ENOTDIR: not a directory", code: "ENOTDIR" });
|
||||
}
|
||||
|
||||
const entries = await fs.promises.readdir(resolved, {
|
||||
withFileTypes: true,
|
||||
});
|
||||
|
||||
res.json(
|
||||
entries.map((e) => ({
|
||||
name: e.name,
|
||||
@@ -108,22 +117,30 @@ router.get("/readdir", async (req, res) => {
|
||||
// GET /api/fs/readFile?path=...&encoding=...
|
||||
router.get("/readFile", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Check if path is a directory
|
||||
const stat = await fs.promises.stat(resolved);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
return res.status(400).json({
|
||||
error: "EISDIR: illegal operation on a directory",
|
||||
code: "EISDIR",
|
||||
});
|
||||
}
|
||||
|
||||
const encoding = req.query.encoding;
|
||||
|
||||
if (encoding === "utf8" || encoding === "utf-8") {
|
||||
const data = await fs.promises.readFile(resolved, "utf-8");
|
||||
|
||||
res.type("text/plain").send(data);
|
||||
} else {
|
||||
const data = await fs.promises.readFile(resolved);
|
||||
|
||||
res.type("application/octet-stream").send(data);
|
||||
}
|
||||
} catch (e) {
|
||||
@@ -135,8 +152,12 @@ router.get("/readFile", async (req, res) => {
|
||||
|
||||
// POST /api/fs/writeFile { path, content, encoding?, vault? }
|
||||
router.post("/writeFile", async (req, res) => {
|
||||
const resolved = guardBodyPath(req, res);
|
||||
if (!resolved) return;
|
||||
const resolved = guardPath(req, res, "body");
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Ensure parent directory exists
|
||||
const dir = path.dirname(resolved);
|
||||
@@ -144,15 +165,19 @@ router.post("/writeFile", async (req, res) => {
|
||||
|
||||
const encoding = req.body.encoding || "utf-8";
|
||||
let data = req.body.content;
|
||||
|
||||
if (req.body.base64) {
|
||||
data = Buffer.from(req.body.content, "base64");
|
||||
}
|
||||
|
||||
await fs.promises.writeFile(
|
||||
resolved,
|
||||
data,
|
||||
encoding === "binary" ? undefined : encoding,
|
||||
);
|
||||
|
||||
const stat = await fs.promises.stat(resolved);
|
||||
|
||||
res.json({ ok: true, mtime: stat.mtimeMs, size: stat.size });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -161,10 +186,15 @@ router.post("/writeFile", async (req, res) => {
|
||||
|
||||
// POST /api/fs/appendFile { path, content, vault? }
|
||||
router.post("/appendFile", async (req, res) => {
|
||||
const resolved = guardBodyPath(req, res);
|
||||
if (!resolved) return;
|
||||
const resolved = guardPath(req, res, "body");
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.appendFile(resolved, req.body.content, "utf-8");
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -173,10 +203,15 @@ router.post("/appendFile", async (req, res) => {
|
||||
|
||||
// POST /api/fs/mkdir { path, recursive?, vault? }
|
||||
router.post("/mkdir", async (req, res) => {
|
||||
const resolved = guardBodyPath(req, res);
|
||||
if (!resolved) return;
|
||||
const resolved = guardPath(req, res, "body");
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.mkdir(resolved, { recursive: !!req.body.recursive });
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -186,13 +221,21 @@ router.post("/mkdir", async (req, res) => {
|
||||
// POST /api/fs/rename { oldPath, newPath, vault? }
|
||||
router.post("/rename", async (req, res) => {
|
||||
const vaultRoot = getVaultRoot(req, res);
|
||||
if (!vaultRoot) return;
|
||||
|
||||
if (!vaultRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const oldResolved = resolveVaultPath(vaultRoot, req.body?.oldPath);
|
||||
const newResolved = resolveVaultPath(vaultRoot, req.body?.newPath);
|
||||
if (!oldResolved || !newResolved)
|
||||
|
||||
if (!oldResolved || !newResolved) {
|
||||
return res.status(403).json({ error: "Invalid path" });
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.rename(oldResolved, newResolved);
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -202,13 +245,21 @@ router.post("/rename", async (req, res) => {
|
||||
// POST /api/fs/copyFile { src, dest, vault? }
|
||||
router.post("/copyFile", async (req, res) => {
|
||||
const vaultRoot = getVaultRoot(req, res);
|
||||
if (!vaultRoot) return;
|
||||
|
||||
if (!vaultRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const srcResolved = resolveVaultPath(vaultRoot, req.body?.src);
|
||||
const destResolved = resolveVaultPath(vaultRoot, req.body?.dest);
|
||||
if (!srcResolved || !destResolved)
|
||||
|
||||
if (!srcResolved || !destResolved) {
|
||||
return res.status(403).json({ error: "Invalid path" });
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.copyFile(srcResolved, destResolved);
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -218,12 +269,18 @@ router.post("/copyFile", async (req, res) => {
|
||||
// DELETE /api/fs/unlink?path=...
|
||||
router.delete("/unlink", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.unlink(resolved);
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
const status = e.code === "ENOENT" ? 404 : 500;
|
||||
|
||||
res.status(status).json({ error: e.message, code: e.code });
|
||||
}
|
||||
});
|
||||
@@ -231,9 +288,14 @@ router.delete("/unlink", async (req, res) => {
|
||||
// DELETE /api/fs/rmdir?path=...
|
||||
router.delete("/rmdir", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.rmdir(resolved);
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -243,7 +305,11 @@ router.delete("/rmdir", async (req, res) => {
|
||||
// DELETE /api/fs/rm?path=...&recursive=true
|
||||
router.delete("/rm", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.rm(resolved, {
|
||||
recursive: req.query.recursive === "true",
|
||||
@@ -254,12 +320,16 @@ router.delete("/rm", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/fs/access?path=...
|
||||
router.get("/access", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.access(resolved);
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res
|
||||
@@ -268,13 +338,16 @@ router.get("/access", async (req, res) => {
|
||||
}
|
||||
});
|
||||
|
||||
// GET /api/fs/realpath?path=...
|
||||
router.get("/realpath", async (req, res) => {
|
||||
const resolved = guardPath(req, res);
|
||||
if (!resolved) return;
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
const real = await fs.promises.realpath(resolved);
|
||||
// Return path relative to vault root
|
||||
|
||||
res.json({ path: path.relative(req._vaultRoot, real) });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
@@ -283,8 +356,12 @@ router.get("/realpath", async (req, res) => {
|
||||
|
||||
// POST /api/fs/utimes { path, atime, mtime, vault? }
|
||||
router.post("/utimes", async (req, res) => {
|
||||
const resolved = guardBodyPath(req, res);
|
||||
if (!resolved) return;
|
||||
const resolved = guardPath(req, res, "body");
|
||||
|
||||
if (!resolved) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.utimes(
|
||||
resolved,
|
||||
@@ -300,23 +377,36 @@ router.post("/utimes", async (req, res) => {
|
||||
// GET /api/fs/tree?path=...&vault=... returns full recursive file tree with metadata
|
||||
router.get("/tree", async (req, res) => {
|
||||
const vaultRoot = getVaultRoot(req, res);
|
||||
if (!vaultRoot) return;
|
||||
|
||||
if (!vaultRoot) {
|
||||
return;
|
||||
}
|
||||
|
||||
const rootPath = req.query.path
|
||||
? resolveVaultPath(vaultRoot, req.query.path)
|
||||
: vaultRoot;
|
||||
if (!rootPath) return res.status(403).json({ error: "Invalid path" });
|
||||
|
||||
if (!rootPath) {
|
||||
return res.status(403).json({ error: "Invalid path" });
|
||||
}
|
||||
|
||||
try {
|
||||
const tree = {};
|
||||
|
||||
async function walk(dir, prefix) {
|
||||
const entries = await fs.promises.readdir(dir, { withFileTypes: true });
|
||||
|
||||
for (const entry of entries) {
|
||||
const rel = prefix ? prefix + "/" + entry.name : entry.name;
|
||||
const full = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
tree[rel] = { type: "directory" };
|
||||
|
||||
await walk(full, rel);
|
||||
} else {
|
||||
const stat = await fs.promises.stat(full);
|
||||
|
||||
tree[rel] = {
|
||||
type: "file",
|
||||
size: stat.size,
|
||||
@@ -326,7 +416,9 @@ router.get("/tree", async (req, res) => {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await walk(rootPath, "");
|
||||
|
||||
res.json(tree);
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
|
||||
@@ -2,10 +2,11 @@ const express = require("express");
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// POST /api/proxy - forward a request to an external URL (bypasses browser CORS)
|
||||
// Used by the requestUrl shim for plugin installation, update checks, etc.
|
||||
// POST /api/proxy - forward a request to an external URL to bypass CORS
|
||||
// Used by the requestUrl shim for plugin installation, etc.
|
||||
router.post("/", async (req, res) => {
|
||||
const { url, method, headers, body, binary } = req.body;
|
||||
|
||||
if (!url) {
|
||||
return res.status(400).json({ error: "Missing url" });
|
||||
}
|
||||
@@ -15,6 +16,7 @@ router.post("/", async (req, res) => {
|
||||
method: method || "GET",
|
||||
headers: headers || {},
|
||||
};
|
||||
|
||||
if (body && method !== "GET" && method !== "HEAD") {
|
||||
if (binary && typeof body === "string") {
|
||||
fetchOpts.body = Buffer.from(body, "base64");
|
||||
|
||||
@@ -8,11 +8,13 @@ const router = express.Router();
|
||||
// GET /api/vault/list - returns all discovered vaults (re-scans on each call)
|
||||
router.get("/list", (req, res) => {
|
||||
config.refreshVaults();
|
||||
|
||||
const list = Object.entries(config.vaults).map(([id, vaultPath]) => ({
|
||||
id,
|
||||
name: id,
|
||||
path: vaultPath,
|
||||
}));
|
||||
|
||||
res.json(list);
|
||||
});
|
||||
|
||||
@@ -20,9 +22,11 @@ router.get("/list", (req, res) => {
|
||||
router.get("/info", (req, res) => {
|
||||
const vaultId = req.query.vault || config.defaultVaultId;
|
||||
const vaultPath = config.getVaultPath(vaultId);
|
||||
|
||||
if (!vaultPath) {
|
||||
return res.status(404).json({ error: "Vault not found", id: vaultId });
|
||||
}
|
||||
|
||||
res.json({
|
||||
id: vaultId,
|
||||
name: vaultId,
|
||||
@@ -35,21 +39,27 @@ router.get("/info", (req, res) => {
|
||||
// POST /api/vault/create { name } - create a new vault in VAULT_ROOT
|
||||
router.post("/create", async (req, res) => {
|
||||
const name = req.body?.name;
|
||||
|
||||
if (!name || /[\/\\:*?"<>|]/.test(name)) {
|
||||
return res.status(400).json({ error: "Invalid vault name" });
|
||||
}
|
||||
|
||||
const vaultPath = path.join(config.vaultRoot, name);
|
||||
|
||||
try {
|
||||
await fs.promises.mkdir(vaultPath, { recursive: false });
|
||||
await fs.promises.mkdir(path.join(vaultPath, ".obsidian"), {
|
||||
recursive: false,
|
||||
});
|
||||
|
||||
config.refreshVaults();
|
||||
|
||||
res.json({ ok: true, id: name, path: vaultPath });
|
||||
} catch (e) {
|
||||
if (e.code === "EEXIST") {
|
||||
return res.status(409).json({ error: "Vault already exists" });
|
||||
}
|
||||
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
}
|
||||
});
|
||||
@@ -58,12 +68,16 @@ router.post("/create", async (req, res) => {
|
||||
router.delete("/remove", async (req, res) => {
|
||||
const vaultId = req.query.vault;
|
||||
const vaultPath = config.getVaultPath(vaultId);
|
||||
|
||||
if (!vaultPath) {
|
||||
return res.status(404).json({ error: "Vault not found" });
|
||||
}
|
||||
|
||||
try {
|
||||
await fs.promises.rm(vaultPath, { recursive: true });
|
||||
|
||||
config.refreshVaults();
|
||||
|
||||
res.json({ ok: true });
|
||||
} catch (e) {
|
||||
res.status(500).json({ error: e.message, code: e.code });
|
||||
|
||||
20
server/ws.js
20
server/ws.js
@@ -1,24 +1,24 @@
|
||||
const { WebSocketServer } = require('ws');
|
||||
const { WebSocketServer } = require("ws");
|
||||
|
||||
//currently unused
|
||||
function setupWebSocket(server) {
|
||||
const wss = new WebSocketServer({ server, path: '/ws' });
|
||||
const wss = new WebSocketServer({ server, path: "/ws" });
|
||||
|
||||
wss.on('connection', (ws) => {
|
||||
console.log('[ws] Client connected');
|
||||
wss.on("connection", (ws) => {
|
||||
console.log("[ws] Client connected");
|
||||
|
||||
ws.on('message', (data) => {
|
||||
ws.on("message", (data) => {
|
||||
// TODO: handle watch/unwatch subscriptions from client
|
||||
const msg = JSON.parse(data);
|
||||
console.log('[ws] Received:', msg);
|
||||
console.log("[ws] Received:", msg);
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
console.log('[ws] Client disconnected');
|
||||
ws.on("close", () => {
|
||||
console.log("[ws] Client disconnected");
|
||||
});
|
||||
});
|
||||
|
||||
// TODO: integrate chokidar file watching and broadcast changes
|
||||
// This will be implemented once the sync strategy is finalized.
|
||||
// TODO: maybe integrate chokidar file watching and broadcast changes
|
||||
|
||||
return wss;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user