summaryrefslogtreecommitdiff
path: root/server/server.js
blob: cc685d1bb230634f331c31e55cf3ae5c928ebdba (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
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);
});