diff options
| author | ertopogo <erwin.t.pombett@gmail.com> | 2026-02-20 19:36:00 +0100 |
|---|---|---|
| committer | ertopogo <erwin.t.pombett@gmail.com> | 2026-02-20 19:36:00 +0100 |
| commit | b713be161431729305701f80b3b6f53d2f07f62a (patch) | |
| tree | 820d055331f38e6edda2c1ee160a6611560fbf7c /server/server.js | |
Initial commit: schemas infrastructure Arauco avec serveur web
Diffstat (limited to 'server/server.js')
| -rw-r--r-- | server/server.js | 94 |
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);
+});
|
