@imenam/self-register-proxy 1.0.37 → 1.0.38

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -41,6 +41,18 @@ npm start
41
41
 
42
42
  Le proxy démarre par défaut sur le port `3000`.
43
43
 
44
+ #### Interface HTML minimale (`--minimal-dashboard`)
45
+
46
+ Par défaut, la page d’accueil en HTML affiche l’interface complète (statistiques, barre d’outils, actions sur les services, etc.). Le flag **`--minimal-dashboard`** réduit cette page au **nom du proxy** (`PROXY_NAME`) et, pour chaque service enregistré, au **nom** et au bouton **Ouvrir** uniquement — sans URL détaillée, sans port visible, sans barre d’outils ni modale d’ajout. Il n’existe pas d’équivalent via variable d’environnement ; seul ce flag CLI est pris en charge.
47
+
48
+ Avec **`npx`**, placez **`--`** avant le flag pour qu’il soit transmis au script Node :
49
+
50
+ ```bash
51
+ npx @imenam/self-register-proxy -- --minimal-dashboard
52
+ ```
53
+
54
+ Les réponses **JSON** de `GET /` lorsque le client envoie `Accept: application/json` restent **inchangées** (le mode minimal ne concerne que le HTML).
55
+
44
56
  ### Configuration via fichier .env
45
57
 
46
58
  Créez un fichier `.env` à la racine du projet (voir `.env.example`) :
@@ -91,7 +103,7 @@ http://localhost:3000/myapp/ → votre application sur le port 4000
91
103
 
92
104
  L'URL racine `/` affiche une page listant tous les serveurs enregistrés avec des liens pour y accéder.
93
105
 
94
- Le nom du proxy (configurable via `PROXY_NAME`) est affiché dans le titre et l'en-tête de la page.
106
+ Le nom du proxy (configurable via `PROXY_NAME`) est affiché dans le titre et l'en-tête de la page. Pour une variante HTML épurée (titre + noms + bouton « Ouvrir » uniquement), démarrez le proxy avec `--minimal-dashboard` (voir **Démarrage rapide**).
95
107
 
96
108
  - **Navigateurs** (`Accept: text/html`) → Page HTML avec interface moderne
97
109
  - **Clients API** (`Accept: application/json`) → Réponse JSON
package/config.js CHANGED
@@ -15,6 +15,8 @@ const TERMINAL_CWD = process.env.PROXY_TERMINAL_CWD || process.env.HOME || proce
15
15
  const TERMINAL_COMMAND = process.env.PROXY_TERMINAL_COMMAND || '';
16
16
  const OPENCODE_CLEAN_UP = process.env.PROXY_OPENCODE_CLEAN_UP || '';
17
17
 
18
+ const MINIMAL_DASHBOARD = process.argv.includes('--minimal-dashboard');
19
+
18
20
  module.exports = {
19
21
  PROXY_PORT,
20
22
  PROXY_NAME,
@@ -28,4 +30,5 @@ module.exports = {
28
30
  TERMINAL_CWD,
29
31
  TERMINAL_COMMAND,
30
32
  OPENCODE_CLEAN_UP,
33
+ MINIMAL_DASHBOARD,
31
34
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imenam/self-register-proxy",
3
- "version": "1.0.37",
3
+ "version": "1.0.38",
4
4
  "description": "Dynamic reverse proxy with self-registration API - applications can register themselves and receive an automatically assigned port",
5
5
  "main": "proxy-client.js",
6
6
  "bin": {
@@ -5,7 +5,7 @@ const { safeEqual, createSession, setSessionCookie, destroySession, clearSession
5
5
  const { registry } = require('../services/registry');
6
6
  const { renderLogin } = require('../views/login');
7
7
  const { renderDashboard } = require('../views/dashboard');
8
- const { PROXY_NAME, PROXY_PORT, ADMIN_PASSWORD, INTERNAL_PORT_START, INTERNAL_PORT_END, OPENCODE_CLEAN_UP, TERMINAL_CWD } = require('../config');
8
+ const { PROXY_NAME, PROXY_PORT, ADMIN_PASSWORD, INTERNAL_PORT_START, INTERNAL_PORT_END, OPENCODE_CLEAN_UP, TERMINAL_CWD, MINIMAL_DASHBOARD } = require('../config');
9
9
 
10
10
  const router = Router();
11
11
 
@@ -100,7 +100,7 @@ router.get('/', requireAuth, (req, res) => {
100
100
  }
101
101
 
102
102
  const availablePorts = (INTERNAL_PORT_END - INTERNAL_PORT_START) - registry.usedPorts.size;
103
- const html = renderDashboard(routes, availablePorts, PROXY_NAME, !!ADMIN_PASSWORD, OPENCODE_CLEAN_UP);
103
+ const html = renderDashboard(routes, availablePorts, PROXY_NAME, !!ADMIN_PASSWORD, OPENCODE_CLEAN_UP, MINIMAL_DASHBOARD);
104
104
  res.type('html').send(html);
105
105
  });
106
106
 
@@ -7,8 +7,117 @@ const { escapeHtml } = require('../services/proxyRouter');
7
7
  * @param {string} proxyName
8
8
  * @param {boolean} hasAuth - true si l'authentification est activée
9
9
  * @param {string|undefined} cleanUpCommand - si défini, affiche le bouton de nettoyage
10
+ * @param {boolean} [minimalDashboard] - interface HTML réduite (nom + Ouvrir uniquement)
10
11
  */
11
- function renderDashboard(routes, availablePorts, proxyName, hasAuth, cleanUpCommand) {
12
+ function renderDashboard(routes, availablePorts, proxyName, hasAuth, cleanUpCommand, minimalDashboard) {
13
+ if (minimalDashboard) {
14
+ const servicesHtml = routes.length > 0
15
+ ? `<div class="services-list">
16
+ ${routes.map(route => `
17
+ <div class="service-card">
18
+ <div class="service-info">
19
+ <span class="service-name">${escapeHtml(route.name)}</span>
20
+ </div>
21
+ <div class="service-actions">
22
+ <a href="${escapeHtml(route.path)}" class="action-btn primary" title="Acc&eacute;der">Ouvrir</a>
23
+ </div>
24
+ </div>
25
+ `).join('')}
26
+ </div>`
27
+ : `<div class="empty-state minimal-empty">
28
+ <p>Aucun service</p>
29
+ </div>`;
30
+
31
+ return `<!DOCTYPE html>
32
+ <html lang="fr">
33
+ <head>
34
+ <meta charset="UTF-8">
35
+ <meta name="viewport" content="width=device-width, initial-scale=1.0">
36
+ <title>${escapeHtml(proxyName)}</title>
37
+ <style>
38
+ * { margin: 0; padding: 0; box-sizing: border-box; }
39
+ body.minimal-dashboard {
40
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
41
+ background: linear-gradient(135deg, #1a1a2e 0%, #16213e 100%);
42
+ min-height: 100vh;
43
+ color: #e4e4e7;
44
+ padding: 1rem;
45
+ }
46
+ .minimal-dashboard .container { max-width: 560px; margin: 0 auto; }
47
+ .minimal-dashboard header { text-align: center; margin-bottom: 1rem; }
48
+ .minimal-dashboard h1 {
49
+ font-size: 1.75rem;
50
+ background: linear-gradient(90deg, #6366f1, #8b5cf6);
51
+ -webkit-background-clip: text;
52
+ -webkit-text-fill-color: transparent;
53
+ background-clip: text;
54
+ }
55
+ .services-list { display: flex; flex-direction: column; gap: 0.5rem; }
56
+ .service-card {
57
+ background: rgba(255, 255, 255, 0.05);
58
+ border: 1px solid rgba(255, 255, 255, 0.1);
59
+ border-radius: 8px;
60
+ padding: 0.6rem 0.9rem;
61
+ display: flex;
62
+ align-items: center;
63
+ justify-content: space-between;
64
+ gap: 0.75rem;
65
+ transition: all 0.15s ease;
66
+ }
67
+ .service-card:hover {
68
+ background: rgba(255, 255, 255, 0.08);
69
+ border-color: rgba(139, 92, 246, 0.4);
70
+ }
71
+ .service-info { display: flex; align-items: center; min-width: 0; flex: 1; }
72
+ .service-name {
73
+ font-size: 0.95rem;
74
+ font-weight: 600;
75
+ color: #f4f4f5;
76
+ white-space: nowrap;
77
+ overflow: hidden;
78
+ text-overflow: ellipsis;
79
+ }
80
+ .service-actions { display: flex; flex-shrink: 0; align-items: center; }
81
+ .action-btn {
82
+ background: rgba(255, 255, 255, 0.1);
83
+ color: #e4e4e7;
84
+ border: 1px solid rgba(255, 255, 255, 0.15);
85
+ padding: 0.35rem 0.6rem;
86
+ border-radius: 5px;
87
+ cursor: pointer;
88
+ font-size: 0.75rem;
89
+ font-weight: 500;
90
+ text-decoration: none;
91
+ display: inline-flex;
92
+ align-items: center;
93
+ }
94
+ .action-btn.primary {
95
+ background: linear-gradient(90deg, #6366f1, #8b5cf6);
96
+ border: none;
97
+ color: white;
98
+ }
99
+ .action-btn.primary:hover { opacity: 0.9; }
100
+ .empty-state.minimal-empty {
101
+ text-align: center;
102
+ padding: 2rem 1rem;
103
+ background: rgba(255, 255, 255, 0.03);
104
+ border-radius: 10px;
105
+ border: 1px dashed rgba(255, 255, 255, 0.1);
106
+ }
107
+ .empty-state.minimal-empty p { color: #a1a1aa; font-size: 0.95rem; }
108
+ </style>
109
+ </head>
110
+ <body class="minimal-dashboard">
111
+ <div class="container">
112
+ <header>
113
+ <h1>${escapeHtml(proxyName)}</h1>
114
+ </header>
115
+ ${servicesHtml}
116
+ </div>
117
+ </body>
118
+ </html>`;
119
+ }
120
+
12
121
  const servicesHtml = routes.length > 0
13
122
  ? `<div class="services-list">
14
123
  ${routes.map(route => `