summaryrefslogtreecommitdiff
path: root/server/server.js
diff options
context:
space:
mode:
Diffstat (limited to 'server/server.js')
-rw-r--r--server/server.js94
1 files changed, 94 insertions, 0 deletions
diff --git a/server/server.js b/server/server.js
new file mode 100644
index 0000000..cc685d1
--- /dev/null
+++ b/server/server.js
@@ -0,0 +1,94 @@
+const express = require('express');
+const path = require('path');
+const fs = require('fs');
+const { WebSocketServer } = require('ws');
+const chokidar = require('chokidar');
+
+const PORT = process.env.PORT || 3030;
+const SCHEMAS_ROOT = path.resolve(__dirname, '..');
+
+const app = express();
+app.use(express.static(path.join(__dirname, 'public')));
+
+function scanSchemas() {
+ const schemas = [];
+
+ function walk(dir, category) {
+ if (!fs.existsSync(dir)) return;
+ for (const file of fs.readdirSync(dir)) {
+ const fullPath = path.join(dir, file);
+ if (fs.statSync(fullPath).isDirectory()) {
+ walk(fullPath, file);
+ } else if (file.endsWith('.mmd')) {
+ const relativePath = path.relative(SCHEMAS_ROOT, fullPath).replace(/\\/g, '/');
+ schemas.push({
+ name: file.replace('.mmd', ''),
+ category: category || 'root',
+ path: relativePath,
+ fullPath
+ });
+ }
+ }
+ }
+
+ walk(path.join(SCHEMAS_ROOT, 'macro'), 'macro');
+ walk(path.join(SCHEMAS_ROOT, 'micro'), null);
+ return schemas;
+}
+
+app.get('/api/schemas', (req, res) => {
+ const schemas = scanSchemas();
+ const grouped = {};
+ for (const s of schemas) {
+ if (!grouped[s.category]) grouped[s.category] = [];
+ grouped[s.category].push({ name: s.name, path: s.path });
+ }
+ res.json(grouped);
+});
+
+app.get('/api/schema/:encodedPath', (req, res) => {
+ const schemaPath = decodeURIComponent(req.params.encodedPath);
+ const fullPath = path.join(SCHEMAS_ROOT, schemaPath);
+ const resolved = path.resolve(fullPath);
+
+ if (!resolved.startsWith(SCHEMAS_ROOT)) {
+ return res.status(403).json({ error: 'Acces interdit' });
+ }
+ if (!fs.existsSync(resolved)) {
+ return res.status(404).json({ error: 'Schema introuvable' });
+ }
+
+ const content = fs.readFileSync(resolved, 'utf-8');
+ res.json({ path: schemaPath, content });
+});
+
+const server = app.listen(PORT, () => {
+ console.log(`\n Araucaria Schemas Viewer`);
+ console.log(` -> http://localhost:${PORT}\n`);
+ console.log(` Schemas root: ${SCHEMAS_ROOT}`);
+ console.log(` Watching for .mmd changes...\n`);
+});
+
+const wss = new WebSocketServer({ server });
+
+const watcher = chokidar.watch(
+ [path.join(SCHEMAS_ROOT, 'macro'), path.join(SCHEMAS_ROOT, 'micro')],
+ { ignoreInitial: true, persistent: true }
+);
+
+watcher.on('all', (event, filePath) => {
+ if (!filePath.endsWith('.mmd')) return;
+ const relativePath = path.relative(SCHEMAS_ROOT, filePath).replace(/\\/g, '/');
+ console.log(` [${event}] ${relativePath}`);
+
+ const message = JSON.stringify({ type: 'reload', event, path: relativePath });
+ for (const client of wss.clients) {
+ if (client.readyState === 1) client.send(message);
+ }
+});
+
+process.on('SIGINT', () => {
+ watcher.close();
+ server.close();
+ process.exit(0);
+});