restricted-github-mcp 1.1.25 → 1.1.28
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 +27 -2
- package/dist/config-server.d.ts +4 -0
- package/dist/config-server.d.ts.map +1 -1
- package/dist/config-server.js +89 -15
- package/dist/config-server.js.map +1 -1
- package/dist/gui.js +25 -1
- package/dist/gui.js.map +1 -1
- package/package.json +1 -1
- package/public/index.html +15 -4
package/README.md
CHANGED
|
@@ -35,6 +35,8 @@ Le serveur lance automatiquement une interface graphique sur le port **3000** au
|
|
|
35
35
|
|
|
36
36
|
Accès : [http://localhost:3000](http://localhost:3000)
|
|
37
37
|
|
|
38
|
+
> **Proxy dynamique** : La GUI peut s'enregistrer automatiquement auprès d'un reverse proxy pour recevoir un port dynamique. Voir la section [Configuration Proxy](#-configuration-proxy-optionnel).
|
|
39
|
+
|
|
38
40
|
## 📝 Journalisation (Logs)
|
|
39
41
|
|
|
40
42
|
Pour garantir la stabilité et faciliter le débogage, le serveur enregistre ses activités et ses erreurs dans un fichier de log persistant.
|
|
@@ -66,6 +68,22 @@ Le serveur se configure exclusivement via des variables d'environnement. Ces var
|
|
|
66
68
|
| `REPO_PATH` | (Optionnel) Le chemin local du dépôt Git | `/chemin/vers/projet` |
|
|
67
69
|
| `READ_ONLY` | (Optionnel) Désactive les actions d'écriture | `false` (défaut) |
|
|
68
70
|
|
|
71
|
+
### 🌐 Configuration Proxy (Optionnel)
|
|
72
|
+
|
|
73
|
+
Si vous utilisez un reverse proxy dynamique pour centraliser plusieurs applications sur un seul port, vous pouvez configurer les variables suivantes :
|
|
74
|
+
|
|
75
|
+
| Variable | Description | Exemple |
|
|
76
|
+
| :--- | :--- | :--- |
|
|
77
|
+
| `PROXY_URL` | URL du serveur proxy | `http://localhost:3000` |
|
|
78
|
+
| `GUI_PATH` | Chemin d'accès via le proxy | `/github-mcp` (défaut) |
|
|
79
|
+
| `GUI_NAME` | Nom affiché dans le proxy | `GitHub MCP Config` (défaut) |
|
|
80
|
+
|
|
81
|
+
**Comportement :**
|
|
82
|
+
- Si `PROXY_URL` est défini, la GUI tente de s'enregistrer au démarrage
|
|
83
|
+
- En cas de succès, elle utilise le port attribué par le proxy et devient accessible via `http://[PROXY_URL][GUI_PATH]/`
|
|
84
|
+
- En cas d'échec (proxy indisponible, timeout), elle démarre sur le port 3000 par défaut
|
|
85
|
+
- À l'arrêt, elle se désenregistre automatiquement du proxy
|
|
86
|
+
|
|
69
87
|
## 🖥️ Exemple de Configuration MCP
|
|
70
88
|
|
|
71
89
|
Copiez-collez cette configuration dans votre client MCP (ex: `claude_desktop_config.json` ou paramètres Cursor) :
|
|
@@ -85,12 +103,16 @@ Copiez-collez cette configuration dans votre client MCP (ex: `claude_desktop_con
|
|
|
85
103
|
"TARGET_REPO": "propriétaire/nom-du-repo",
|
|
86
104
|
"TARGET_BRANCH": "votre-branche-de-travail",
|
|
87
105
|
"BASE_BRANCH": "main",
|
|
88
|
-
"REPO_PATH": "/chemin/vers/votre/projet/local"
|
|
106
|
+
"REPO_PATH": "/chemin/vers/votre/projet/local",
|
|
107
|
+
"PROXY_URL": "http://localhost:3000",
|
|
108
|
+
"GUI_PATH": "/github-mcp",
|
|
109
|
+
"GUI_NAME": "GitHub MCP Config"
|
|
89
110
|
}
|
|
90
111
|
}
|
|
91
112
|
}
|
|
92
113
|
}
|
|
93
114
|
```
|
|
115
|
+
> **Note** : Les variables `PROXY_URL`, `GUI_PATH` et `GUI_NAME` sont optionnelles. Supprimez-les si vous n'utilisez pas de proxy.
|
|
94
116
|
|
|
95
117
|
### Via installation locale
|
|
96
118
|
Si vous avez cloné le dépôt et exécuté `npm run build` :
|
|
@@ -107,7 +129,10 @@ Si vous avez cloné le dépôt et exécuté `npm run build` :
|
|
|
107
129
|
"TARGET_REPO": "propriétaire/nom-du-repo",
|
|
108
130
|
"TARGET_BRANCH": "votre-branche-de-travail",
|
|
109
131
|
"BASE_BRANCH": "main",
|
|
110
|
-
"REPO_PATH": "/chemin/vers/votre/projet/local"
|
|
132
|
+
"REPO_PATH": "/chemin/vers/votre/projet/local",
|
|
133
|
+
"PROXY_URL": "http://localhost:3000",
|
|
134
|
+
"GUI_PATH": "/github-mcp",
|
|
135
|
+
"GUI_NAME": "GitHub MCP Config"
|
|
111
136
|
}
|
|
112
137
|
}
|
|
113
138
|
}
|
package/dist/config-server.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-server.d.ts","sourceRoot":"","sources":["../src/config-server.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"config-server.d.ts","sourceRoot":"","sources":["../src/config-server.ts"],"names":[],"mappings":"AAyEA;;GAEG;AACH,wBAAsB,mBAAmB,IAAI,OAAO,CAAC,IAAI,CAAC,CAazD;AAED,wBAAsB,iBAAiB,kBAqJtC"}
|
package/dist/config-server.js
CHANGED
|
@@ -3,18 +3,99 @@ import path from "path";
|
|
|
3
3
|
import fs from "fs";
|
|
4
4
|
import { fileURLToPath } from "url";
|
|
5
5
|
import { logToFile } from "./logger.js";
|
|
6
|
+
/**
|
|
7
|
+
* Envoie un message au parent de manière sécurisée.
|
|
8
|
+
*/
|
|
9
|
+
function safeSend(message) {
|
|
10
|
+
if (process.send && process.connected) {
|
|
11
|
+
try {
|
|
12
|
+
return process.send(message);
|
|
13
|
+
}
|
|
14
|
+
catch (err) {
|
|
15
|
+
logToFile(`[IPC] Échec de l'envoi : ${err.message}`);
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
return false;
|
|
20
|
+
}
|
|
6
21
|
const __filename = fileURLToPath(import.meta.url);
|
|
7
22
|
const __dirname = path.dirname(__filename);
|
|
23
|
+
// Proxy configuration
|
|
24
|
+
const DEFAULT_PORT = 3000;
|
|
25
|
+
const PROXY_URL = process.env.PROXY_URL;
|
|
26
|
+
const GUI_PATH = process.env.GUI_PATH || "/github-mcp";
|
|
27
|
+
const GUI_NAME = process.env.GUI_NAME || "GitHub MCP Config";
|
|
28
|
+
// État du proxy pour le désenregistrement
|
|
29
|
+
let registeredPath = null;
|
|
30
|
+
/**
|
|
31
|
+
* Tente de s'enregistrer auprès du proxy dynamique.
|
|
32
|
+
* @returns Le port attribué par le proxy, ou null en cas d'échec.
|
|
33
|
+
*/
|
|
34
|
+
async function tryProxyRegistration() {
|
|
35
|
+
if (!PROXY_URL) {
|
|
36
|
+
logToFile("[GUI] PROXY_URL non défini, utilisation du port par défaut");
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
try {
|
|
40
|
+
const controller = new AbortController();
|
|
41
|
+
const timeoutId = setTimeout(() => controller.abort(), 5000);
|
|
42
|
+
const response = await fetch(`${PROXY_URL}/proxy/register`, {
|
|
43
|
+
method: "POST",
|
|
44
|
+
headers: { "Content-Type": "application/json" },
|
|
45
|
+
body: JSON.stringify({ path: GUI_PATH, name: GUI_NAME }),
|
|
46
|
+
signal: controller.signal,
|
|
47
|
+
});
|
|
48
|
+
clearTimeout(timeoutId);
|
|
49
|
+
if (!response.ok) {
|
|
50
|
+
const errorData = await response.json().catch(() => ({}));
|
|
51
|
+
logToFile(`[GUI] Échec enregistrement proxy: ${errorData.error || response.statusText}. Fallback sur port ${DEFAULT_PORT}`);
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
54
|
+
const data = await response.json();
|
|
55
|
+
registeredPath = GUI_PATH;
|
|
56
|
+
logToFile(`[GUI] Enregistré auprès du proxy (path: ${GUI_PATH}, port: ${data.port})`);
|
|
57
|
+
return data.port;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
const reason = error.name === "AbortError" ? "timeout" : error.message;
|
|
61
|
+
logToFile(`[GUI] Échec enregistrement proxy: ${reason}. Fallback sur port ${DEFAULT_PORT}`);
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Se désenregistre du proxy dynamique (si enregistré).
|
|
67
|
+
*/
|
|
68
|
+
export async function unregisterFromProxy() {
|
|
69
|
+
if (!PROXY_URL || !registeredPath)
|
|
70
|
+
return;
|
|
71
|
+
try {
|
|
72
|
+
await fetch(`${PROXY_URL}/proxy/unregister`, {
|
|
73
|
+
method: "DELETE",
|
|
74
|
+
headers: { "Content-Type": "application/json" },
|
|
75
|
+
body: JSON.stringify({ path: registeredPath }),
|
|
76
|
+
});
|
|
77
|
+
logToFile(`[GUI] Désenregistré du proxy (path: ${registeredPath})`);
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
// Ignorer les erreurs de désenregistrement
|
|
81
|
+
}
|
|
82
|
+
}
|
|
8
83
|
export async function startConfigServer() {
|
|
9
84
|
logToFile("[GUI] Initializing config server...");
|
|
85
|
+
// Tentative d'enregistrement auprès du proxy
|
|
86
|
+
const proxyPort = await tryProxyRegistration();
|
|
87
|
+
const port = proxyPort ?? DEFAULT_PORT;
|
|
10
88
|
const app = express();
|
|
11
|
-
const port = 3000;
|
|
12
89
|
app.use(express.json());
|
|
13
90
|
// Logging middleware for GUI requests
|
|
14
91
|
app.use((req, res, next) => {
|
|
15
92
|
logToFile(`[GUI] Request: ${req.method} ${req.url}`);
|
|
16
93
|
next();
|
|
17
94
|
});
|
|
95
|
+
// Health check route (requise par le proxy)
|
|
96
|
+
app.get("/proxy/health", (req, res) => {
|
|
97
|
+
res.status(200).json({ status: "healthy" });
|
|
98
|
+
});
|
|
18
99
|
// Utilise un chemin relatif au fichier compilé pour trouver public
|
|
19
100
|
const publicPath = path.join(__dirname, "..", "public");
|
|
20
101
|
logToFile(`[GUI] Looking for static files in: ${publicPath}`);
|
|
@@ -59,9 +140,7 @@ export async function startConfigServer() {
|
|
|
59
140
|
Object.assign(process.env, newConfig);
|
|
60
141
|
// Notify master process about the update
|
|
61
142
|
logToFile("[GUI] Sending CONFIG_UPDATED to master process");
|
|
62
|
-
|
|
63
|
-
process.send({ type: "CONFIG_UPDATED", config: newConfig });
|
|
64
|
-
}
|
|
143
|
+
safeSend({ type: "CONFIG_UPDATED", config: newConfig });
|
|
65
144
|
logToFile("[GUI] Configuration updated and master notified");
|
|
66
145
|
res.sendStatus(200);
|
|
67
146
|
}
|
|
@@ -78,11 +157,8 @@ export async function startConfigServer() {
|
|
|
78
157
|
res.json({ message: "Restarting GitHub MCP server..." });
|
|
79
158
|
setTimeout(() => {
|
|
80
159
|
logToFile("[GUI] Sending RESTART signal to master process");
|
|
81
|
-
if (
|
|
82
|
-
process.send
|
|
83
|
-
}
|
|
84
|
-
else {
|
|
85
|
-
logToFile("[GUI] ERROR: process.send is not defined");
|
|
160
|
+
if (!safeSend({ type: "RESTART" })) {
|
|
161
|
+
logToFile("[GUI] ERROR: process.send failed or not connected");
|
|
86
162
|
process.exit(0);
|
|
87
163
|
}
|
|
88
164
|
}, 500);
|
|
@@ -99,11 +175,8 @@ export async function startConfigServer() {
|
|
|
99
175
|
res.json({ message: "Stopping GitHub MCP server..." });
|
|
100
176
|
setTimeout(() => {
|
|
101
177
|
logToFile("[GUI] Sending STOP signal to master process");
|
|
102
|
-
if (
|
|
103
|
-
process.send
|
|
104
|
-
}
|
|
105
|
-
else {
|
|
106
|
-
logToFile("[GUI] ERROR: process.send is not defined");
|
|
178
|
+
if (!safeSend({ type: "STOP" })) {
|
|
179
|
+
logToFile("[GUI] ERROR: process.send failed or not connected");
|
|
107
180
|
process.exit(0);
|
|
108
181
|
}
|
|
109
182
|
}, 500);
|
|
@@ -117,7 +190,8 @@ export async function startConfigServer() {
|
|
|
117
190
|
try {
|
|
118
191
|
logToFile(`[GUI] Attempting to listen on port ${port}...`);
|
|
119
192
|
const serverListener = app.listen(port, () => {
|
|
120
|
-
const
|
|
193
|
+
const mode = proxyPort ? `via proxy (${PROXY_URL}${GUI_PATH})` : "mode standalone";
|
|
194
|
+
const msg = `[GUI] Config GUI disponible sur http://localhost:${port} - ${mode}`;
|
|
121
195
|
console.error(msg);
|
|
122
196
|
logToFile(msg);
|
|
123
197
|
});
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config-server.js","sourceRoot":"","sources":["../src/config-server.ts"],"names":[],"mappings":"AAAA,OAAO,OAAO,MAAM,SAAS,CAAC;AAC9B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C,MAAM,CAAC,KAAK,UAAU,iBAAiB;
|
|
1
|
+
{"version":3,"file":"config-server.js","sourceRoot":"","sources":["../src/config-server.ts"],"names":[],"mappings":"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"}
|
package/dist/gui.js
CHANGED
|
@@ -1,11 +1,35 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import { startConfigServer } from "./config-server.js";
|
|
2
|
+
import { startConfigServer, unregisterFromProxy } from "./config-server.js";
|
|
3
3
|
import * as dotenv from "dotenv";
|
|
4
4
|
import { logToFile } from "./logger.js";
|
|
5
5
|
// On s'assure que même la GUI ne pollue pas stdout au cas où
|
|
6
6
|
console.log = console.error;
|
|
7
7
|
dotenv.config();
|
|
8
8
|
logToFile(`[GUI-PROCESS] Starting standalone GUI process (PID: ${process.pid})`);
|
|
9
|
+
// 1. Intercepter l'événement d'erreur global pour l'IPC
|
|
10
|
+
process.on("error", (err) => {
|
|
11
|
+
if (err.code === "ERR_IPC_CHANNEL_CLOSED") {
|
|
12
|
+
logToFile("[IPC] Canal fermé, message ignoré.");
|
|
13
|
+
return;
|
|
14
|
+
}
|
|
15
|
+
logToFile(`[GUI-PROCESS] Erreur inattendue : ${err.message}`);
|
|
16
|
+
});
|
|
17
|
+
// 2. Gérer la déconnexion du parent (éviter les zombies)
|
|
18
|
+
process.on("disconnect", () => {
|
|
19
|
+
logToFile("[IPC] Parent déconnecté. Arrêt du processus GUI...");
|
|
20
|
+
// On laisse un petit délai pour finir d'éventuels logs
|
|
21
|
+
setTimeout(() => {
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}, 100);
|
|
24
|
+
});
|
|
25
|
+
// Gestion propre de l'arrêt avec désenregistrement du proxy
|
|
26
|
+
async function gracefulShutdown(signal) {
|
|
27
|
+
logToFile(`[GUI-PROCESS] Received ${signal}, shutting down...`);
|
|
28
|
+
await unregisterFromProxy();
|
|
29
|
+
process.exit(0);
|
|
30
|
+
}
|
|
31
|
+
process.on("SIGTERM", () => gracefulShutdown("SIGTERM"));
|
|
32
|
+
process.on("SIGINT", () => gracefulShutdown("SIGINT"));
|
|
9
33
|
startConfigServer().catch(err => {
|
|
10
34
|
const msg = `[GUI-PROCESS] FATAL ERROR: ${err.message}`;
|
|
11
35
|
console.error(msg);
|
package/dist/gui.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gui.js","sourceRoot":"","sources":["../src/gui.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"gui.js","sourceRoot":"","sources":["../src/gui.ts"],"names":[],"mappings":";AACA,OAAO,EAAE,iBAAiB,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AAC5E,OAAO,KAAK,MAAM,MAAM,QAAQ,CAAC;AACjC,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAExC,6DAA6D;AAC7D,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,KAAK,CAAC;AAE5B,MAAM,CAAC,MAAM,EAAE,CAAC;AAEhB,SAAS,CAAC,uDAAuD,OAAO,CAAC,GAAG,GAAG,CAAC,CAAC;AAEjF,wDAAwD;AACxD,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAQ,EAAE,EAAE;IAC/B,IAAI,GAAG,CAAC,IAAI,KAAK,wBAAwB,EAAE,CAAC;QAC1C,SAAS,CAAC,oCAAoC,CAAC,CAAC;QAChD,OAAO;IACT,CAAC;IACD,SAAS,CAAC,qCAAqC,GAAG,CAAC,OAAO,EAAE,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,yDAAyD;AACzD,OAAO,CAAC,EAAE,CAAC,YAAY,EAAE,GAAG,EAAE;IAC5B,SAAS,CAAC,oDAAoD,CAAC,CAAC;IAChE,uDAAuD;IACvD,UAAU,CAAC,GAAG,EAAE;QACd,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IAClB,CAAC,EAAE,GAAG,CAAC,CAAC;AACV,CAAC,CAAC,CAAC;AAEH,4DAA4D;AAC5D,KAAK,UAAU,gBAAgB,CAAC,MAAc;IAC5C,SAAS,CAAC,0BAA0B,MAAM,oBAAoB,CAAC,CAAC;IAChE,MAAM,mBAAmB,EAAE,CAAC;IAC5B,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;AACzD,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,GAAG,EAAE,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAC,CAAC;AAEvD,iBAAiB,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE;IAC9B,MAAM,GAAG,GAAG,8BAA8B,GAAG,CAAC,OAAO,EAAE,CAAC;IACxD,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACnB,SAAS,CAAC,GAAG,CAAC,CAAC;IACf,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC"}
|
package/package.json
CHANGED
package/public/index.html
CHANGED
|
@@ -58,6 +58,17 @@
|
|
|
58
58
|
</div>
|
|
59
59
|
|
|
60
60
|
<script>
|
|
61
|
+
// Détection automatique du base path pour fonctionner via proxy
|
|
62
|
+
const pathname = window.location.pathname;
|
|
63
|
+
const BASE_PATH = pathname.includes('.')
|
|
64
|
+
? pathname.replace(/\/[^/]*$/, '') // /github-mcp/index.html -> /github-mcp
|
|
65
|
+
: pathname.endsWith('/')
|
|
66
|
+
? pathname.slice(0, -1) // /github-mcp/ -> /github-mcp
|
|
67
|
+
: pathname === '/' ? '' : pathname; // /github-mcp -> /github-mcp, / -> ''
|
|
68
|
+
|
|
69
|
+
// Helper pour construire les URLs d'API
|
|
70
|
+
const api = (endpoint) => `${BASE_PATH}/${endpoint}`.replace(/\/+/g, '/');
|
|
71
|
+
|
|
61
72
|
const form = document.getElementById('configForm');
|
|
62
73
|
const status = document.getElementById('status');
|
|
63
74
|
const inputsContainer = document.getElementById('inputs');
|
|
@@ -75,7 +86,7 @@
|
|
|
75
86
|
// Fetch current config
|
|
76
87
|
async function fetchConfig() {
|
|
77
88
|
try {
|
|
78
|
-
const response = await fetch('
|
|
89
|
+
const response = await fetch(api('api/config'));
|
|
79
90
|
if (!response.ok) {
|
|
80
91
|
const data = await response.json().catch(() => ({ error: 'Erreur lors du chargement' }));
|
|
81
92
|
throw new Error(data.error || 'Erreur lors du chargement');
|
|
@@ -119,7 +130,7 @@
|
|
|
119
130
|
});
|
|
120
131
|
|
|
121
132
|
try {
|
|
122
|
-
const response = await fetch('
|
|
133
|
+
const response = await fetch(api('api/config'), {
|
|
123
134
|
method: 'POST',
|
|
124
135
|
headers: { 'Content-Type': 'application/json' },
|
|
125
136
|
body: JSON.stringify(config)
|
|
@@ -145,7 +156,7 @@
|
|
|
145
156
|
restartBtn.disabled = true;
|
|
146
157
|
restartBtn.innerHTML = '<span>Redémarrage en cours...</span>';
|
|
147
158
|
|
|
148
|
-
const response = await fetch('
|
|
159
|
+
const response = await fetch(api('api/restart'), {
|
|
149
160
|
method: 'POST'
|
|
150
161
|
});
|
|
151
162
|
|
|
@@ -179,7 +190,7 @@
|
|
|
179
190
|
stopBtn.disabled = true;
|
|
180
191
|
stopBtn.innerHTML = '<span>Arrêt en cours...</span>';
|
|
181
192
|
|
|
182
|
-
const response = await fetch('
|
|
193
|
+
const response = await fetch(api('api/stop'), {
|
|
183
194
|
method: 'POST'
|
|
184
195
|
});
|
|
185
196
|
|