@imenam/simple-scraper 1.0.8 → 1.0.9

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/dist/gui.js CHANGED
@@ -3,7 +3,16 @@ import bodyParser from 'body-parser';
3
3
  import path from 'path';
4
4
  import fs from 'fs';
5
5
  import { fileURLToPath } from 'url';
6
- import { setupLogging, ProxyClient } from '@imenam/mcp-gui-interface';
6
+ import { setupLogging, ProxyClient, IpcHub } from '@imenam/mcp-gui-interface';
7
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
8
+ const ipc = new IpcHub(process);
9
+ async function callMaster(type, data, timeoutMs = 5000) {
10
+ const resp = await ipc.request({ type, data }, timeoutMs);
11
+ if (resp.error)
12
+ throw new Error(resp.error);
13
+ return resp.data;
14
+ }
15
+ const SESSION_ID_RE = /^sess_[a-z0-9]{6}$/;
7
16
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
8
17
  const rootDir = path.resolve(__dirname, '..');
9
18
  setupLogging({ processLabel: 'GUI', logDir: process.env.MCP_LOG_DIR });
@@ -59,6 +68,23 @@ app.post('/api/cookies', (req, res) => {
59
68
  res.status(500).json({ success: false, error: message });
60
69
  }
61
70
  });
71
+ // ─── GET /api/cookies/:filename — lit le contenu d'un fichier ────────────────
72
+ app.get('/api/cookies/:filename', (req, res) => {
73
+ const cookiesDir = getCookiesDir();
74
+ if (!cookiesDir) {
75
+ res.status(400).json({ success: false, error: 'COOKIES_DIR not configured' });
76
+ return;
77
+ }
78
+ const safeName = path.basename(req.params.filename);
79
+ try {
80
+ const content = fs.readFileSync(path.join(cookiesDir, safeName), 'utf-8');
81
+ res.json({ success: true, content });
82
+ }
83
+ catch (error) {
84
+ const message = error instanceof Error ? error.message : String(error);
85
+ res.status(500).json({ success: false, error: message });
86
+ }
87
+ });
62
88
  // ─── DELETE /api/cookies/:filename — supprime un fichier ──────────────────────
63
89
  app.delete('/api/cookies/:filename', (req, res) => {
64
90
  const cookiesDir = getCookiesDir();
@@ -76,6 +102,33 @@ app.delete('/api/cookies/:filename', (req, res) => {
76
102
  res.status(500).json({ success: false, error: message });
77
103
  }
78
104
  });
105
+ // ─── GET /api/sessions — liste les sessions actives ──────────────────────────
106
+ app.get('/api/sessions', async (_req, res) => {
107
+ try {
108
+ const sessions = await callMaster('SESSION_LIST');
109
+ res.json({ success: true, sessions });
110
+ }
111
+ catch (error) {
112
+ const message = error instanceof Error ? error.message : String(error);
113
+ res.status(500).json({ success: false, error: message });
114
+ }
115
+ });
116
+ // ─── GET /api/sessions/:id/screenshot — capture JPEG de la session ───────────
117
+ app.get('/api/sessions/:id/screenshot', async (req, res) => {
118
+ const { id } = req.params;
119
+ if (!SESSION_ID_RE.test(id)) {
120
+ res.status(400).json({ success: false, error: 'Invalid session ID' });
121
+ return;
122
+ }
123
+ try {
124
+ const data = await callMaster('SESSION_SCREENSHOT', { sessionId: id });
125
+ res.type('image/jpeg').send(Buffer.from(data.base64, 'base64'));
126
+ }
127
+ catch (error) {
128
+ const message = error instanceof Error ? error.message : String(error);
129
+ res.status(500).json({ success: false, error: message });
130
+ }
131
+ });
79
132
  async function startServer() {
80
133
  const proxyClient = new ProxyClient(process.env.PROXY_URL);
81
134
  const result = await proxyClient.register({
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ import { getBrowser, closeBrowser, getDefaultTimeout } from './browser.js';
11
11
  import { loadAllCookies } from './cookies.js';
12
12
  import { GuiLauncher } from '@imenam/mcp-gui-interface';
13
13
  import { createSession, getSession, closeSession, closeAllSessions, listSessions, getSessionLogs, clearSessionLogs } from './sessions.js';
14
+ import { registerSessionRpc } from './session-rpc.js';
14
15
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
15
16
  const rootDir = path.resolve(__dirname, '..');
16
17
  const envPath = path.join(rootDir, '.env');
@@ -614,6 +615,7 @@ async function main() {
614
615
  }
615
616
  else {
616
617
  launcher.start();
618
+ registerSessionRpc(launcher);
617
619
  }
618
620
  const transport = new StdioServerTransport();
619
621
  await server.connect(transport);
@@ -0,0 +1,26 @@
1
+ import { getSession, listSessions } from './sessions.js';
2
+ export function registerSessionRpc(launcher) {
3
+ launcher.getIpcHub().onMessage(async (msg) => {
4
+ const reply = (data, error) => launcher.getIpcHub().send({
5
+ type: `${msg.type}_RESPONSE`,
6
+ correlationId: msg.correlationId,
7
+ data,
8
+ error,
9
+ timestamp: new Date().toISOString(),
10
+ });
11
+ try {
12
+ if (msg.type === 'SESSION_LIST') {
13
+ reply(listSessions());
14
+ }
15
+ else if (msg.type === 'SESSION_SCREENSHOT') {
16
+ const { sessionId } = msg.data;
17
+ const page = getSession(sessionId);
18
+ const buffer = await page.screenshot({ type: 'jpeg', quality: 60 });
19
+ reply({ base64: Buffer.from(buffer).toString('base64') });
20
+ }
21
+ }
22
+ catch (err) {
23
+ reply(undefined, err instanceof Error ? err.message : String(err));
24
+ }
25
+ });
26
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@imenam/simple-scraper",
3
- "version": "1.0.8",
3
+ "version": "1.0.9",
4
4
  "description": "MCP server for web scraping and JavaScript execution using Puppeteer",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -41,6 +41,7 @@
41
41
  "dotenv": "^17.3.1",
42
42
  "express": "^5.2.1",
43
43
  "puppeteer": "^24.40.0",
44
+ "react-router-dom": "^7.15.1",
44
45
  "zod": "^4.3.6"
45
46
  },
46
47
  "devDependencies": {