creevey 0.10.0-beta.44 → 0.10.0-beta.45

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.
Files changed (30) hide show
  1. package/dist/server/index.js +2 -2
  2. package/dist/server/index.js.map +1 -1
  3. package/dist/server/master/api.d.ts +5 -10
  4. package/dist/server/master/api.js +19 -18
  5. package/dist/server/master/api.js.map +1 -1
  6. package/dist/server/master/handlers/capture-handler.d.ts +5 -2
  7. package/dist/server/master/handlers/capture-handler.js +6 -16
  8. package/dist/server/master/handlers/capture-handler.js.map +1 -1
  9. package/dist/server/master/handlers/ping-handler.d.ts +2 -2
  10. package/dist/server/master/handlers/ping-handler.js +2 -1
  11. package/dist/server/master/handlers/ping-handler.js.map +1 -1
  12. package/dist/server/master/handlers/static-handler.d.ts +1 -2
  13. package/dist/server/master/handlers/static-handler.js +10 -20
  14. package/dist/server/master/handlers/static-handler.js.map +1 -1
  15. package/dist/server/master/handlers/stories-handler.d.ts +4 -2
  16. package/dist/server/master/handlers/stories-handler.js +13 -27
  17. package/dist/server/master/handlers/stories-handler.js.map +1 -1
  18. package/dist/server/master/server.js +182 -70
  19. package/dist/server/master/server.js.map +1 -1
  20. package/dist/server/playwright/docker-file.js +2 -2
  21. package/dist/server/playwright/docker-file.js.map +1 -1
  22. package/package.json +3 -3
  23. package/src/server/index.ts +2 -2
  24. package/src/server/master/api.ts +24 -27
  25. package/src/server/master/handlers/capture-handler.ts +5 -24
  26. package/src/server/master/handlers/ping-handler.ts +4 -3
  27. package/src/server/master/handlers/static-handler.ts +10 -21
  28. package/src/server/master/handlers/stories-handler.ts +12 -40
  29. package/src/server/master/server.ts +194 -78
  30. package/src/server/playwright/docker-file.ts +2 -2
@@ -4,101 +4,213 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.start = start;
7
+ const fs_1 = __importDefault(require("fs"));
8
+ const url_1 = __importDefault(require("url"));
7
9
  const path_1 = __importDefault(require("path"));
8
- const hyper_express_1 = __importDefault(require("hyper-express"));
9
- const url_1 = require("url");
10
+ const http_1 = require("http");
11
+ const ws_1 = require("ws");
12
+ const url_2 = require("url");
13
+ const utils_js_1 = require("../utils.js");
10
14
  const messages_js_1 = require("../messages.js");
11
15
  const types_js_1 = require("../../types.js");
12
16
  const logger_js_1 = require("../logger.js");
13
17
  const index_js_1 = require("./handlers/index.js");
14
- const importMetaUrl = (0, url_1.pathToFileURL)(__filename).href;
18
+ function json(handler, defaultValue) {
19
+ return (request, response) => {
20
+ const chunks = [];
21
+ request.on('data', (chunk) => {
22
+ chunks.push(chunk);
23
+ });
24
+ request.on('end', () => {
25
+ try {
26
+ const body = Buffer.concat(chunks);
27
+ const value = body.length === 0 ? defaultValue : JSON.parse(body.toString('utf-8'));
28
+ handler(value);
29
+ response.end();
30
+ }
31
+ catch (error) {
32
+ (0, logger_js_1.logger)().error('Failed to parse JSON', error);
33
+ const errorMessage = error instanceof Error ? error.message : String(error);
34
+ response.statusCode = 500;
35
+ response.setHeader('Content-Type', 'text/plain');
36
+ response.end(`Failed to parse JSON: ${errorMessage}`);
37
+ }
38
+ });
39
+ request.on('error', (error) => {
40
+ (0, logger_js_1.logger)().error('Failed to parse JSON', error);
41
+ const errorMessage = error instanceof Error ? error.message : String(error);
42
+ response.statusCode = 500;
43
+ response.setHeader('Content-Type', 'text/plain');
44
+ response.end(`Failed to parse JSON: ${errorMessage}`);
45
+ });
46
+ };
47
+ }
48
+ function file(handler) {
49
+ return (request, response) => {
50
+ const parsedUrl = url_1.default.parse(request.url ?? '/', true);
51
+ const requestedPath = parsedUrl.pathname ?? '/';
52
+ try {
53
+ const filePath = handler(requestedPath);
54
+ if (filePath) {
55
+ const stat = fs_1.default.statSync(filePath);
56
+ // Set appropriate MIME type
57
+ const ext = path_1.default.extname(filePath).toLowerCase();
58
+ const mimeTypes = {
59
+ '.html': 'text/html',
60
+ '.js': 'application/javascript',
61
+ '.css': 'text/css',
62
+ '.json': 'application/json',
63
+ '.png': 'image/png',
64
+ '.jpg': 'image/jpeg',
65
+ '.jpeg': 'image/jpeg',
66
+ '.gif': 'image/gif',
67
+ '.svg': 'image/svg+xml',
68
+ '.ico': 'image/x-icon',
69
+ };
70
+ const contentType = mimeTypes[ext] || 'application/octet-stream';
71
+ response.statusCode = 200;
72
+ response.setHeader('Content-Type', contentType);
73
+ response.setHeader('Content-Length', stat.size);
74
+ // Stream the file
75
+ const stream = fs_1.default.createReadStream(filePath);
76
+ stream.pipe(response);
77
+ stream.on('error', (error) => {
78
+ (0, logger_js_1.logger)().error('Error streaming file', error);
79
+ if (!response.headersSent) {
80
+ const errorMessage = error instanceof Error ? error.message : String(error);
81
+ response.statusCode = 500;
82
+ response.setHeader('Content-Type', 'text/plain');
83
+ response.end(`Internal server error: ${errorMessage}`);
84
+ }
85
+ });
86
+ }
87
+ else {
88
+ (0, logger_js_1.logger)().error('File not found', requestedPath);
89
+ response.statusCode = 404;
90
+ response.setHeader('Content-Type', 'text/plain');
91
+ response.end('File not found');
92
+ }
93
+ }
94
+ catch (error) {
95
+ (0, logger_js_1.logger)().error('Failed to serve file', error);
96
+ const errorMessage = error instanceof Error ? error.message : String(error);
97
+ response.statusCode = 500;
98
+ response.setHeader('Content-Type', 'text/plain');
99
+ response.end(`Failed to serve file: ${errorMessage}`);
100
+ }
101
+ };
102
+ }
103
+ const importMetaUrl = (0, url_2.pathToFileURL)(__filename).href;
15
104
  function start(reportDir, port, ui) {
105
+ let wss = null;
106
+ let creeveyApi = null;
16
107
  let resolveApi = types_js_1.noop;
17
- const creeveyApi = new Promise((resolve) => (resolveApi = resolve));
18
- // Create HyperExpress server instance
19
- const server = new hyper_express_1.default.Server();
20
- // Store active WebSocket connections
21
- const activeConnections = new Set();
22
- // Enable CORS for all routes
23
- server.use((request, response, next) => {
24
- response.header('Access-Control-Allow-Origin', '*');
25
- response.header('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
26
- response.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
108
+ const webDir = path_1.default.join(path_1.default.dirname((0, url_2.fileURLToPath)(importMetaUrl)), '../../client/web');
109
+ const server = (0, http_1.createServer)();
110
+ const routes = [
111
+ {
112
+ path: '/ping',
113
+ method: 'GET',
114
+ handler: index_js_1.pingHandler,
115
+ },
116
+ {
117
+ path: '/stories',
118
+ method: 'POST',
119
+ handler: json(index_js_1.storiesHandler, { stories: [] }),
120
+ },
121
+ {
122
+ path: '/capture',
123
+ method: 'POST',
124
+ handler: json(index_js_1.captureHandler, { workerId: 0, options: undefined }),
125
+ },
126
+ {
127
+ path: '/report/',
128
+ method: 'GET',
129
+ handler: file((0, index_js_1.staticHandler)(reportDir, '/report/')),
130
+ },
131
+ {
132
+ path: '/',
133
+ method: 'GET',
134
+ handler: file((0, index_js_1.staticHandler)(webDir)),
135
+ },
136
+ ];
137
+ const router = (request, response) => {
138
+ const parsedUrl = url_1.default.parse(request.url ?? '/', true);
139
+ const path = parsedUrl.pathname ?? '/';
140
+ const method = request.method ?? 'GET';
141
+ try {
142
+ const route = routes.find((route) => path.startsWith(route.path) && route.method === method);
143
+ if (route) {
144
+ route.handler(request, response);
145
+ }
146
+ else {
147
+ response.statusCode = 404;
148
+ response.setHeader('Content-Type', 'text/plain');
149
+ response.end('Not Found');
150
+ }
151
+ }
152
+ catch (error) {
153
+ (0, logger_js_1.logger)().error('Request handling error', error);
154
+ response.statusCode = 500;
155
+ response.setHeader('Content-Type', 'text/plain');
156
+ response.end('Internal Server Error');
157
+ }
158
+ };
159
+ server.on('request', (request, response) => {
160
+ response.setHeader('Access-Control-Allow-Origin', '*');
161
+ response.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
162
+ response.setHeader('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
27
163
  if (request.method === 'OPTIONS') {
28
- return response.status(200).send();
164
+ response.statusCode = 200;
165
+ response.end();
166
+ return;
29
167
  }
30
- next();
168
+ router(request, response);
31
169
  });
32
- // Health check endpoint
33
- server.get('/ping', index_js_1.pingHandler);
34
- // Stories endpoint
35
- server.post('/stories', (0, index_js_1.createStoriesHandler)());
36
- // Capture endpoint
37
- server.post('/capture', index_js_1.captureHandler);
38
- // Serve report files
39
- server.get('/report/*', (0, index_js_1.createStaticFileHandler)(reportDir, '/report/'));
40
- // Serve static files
41
- const webDir = path_1.default.join(path_1.default.dirname((0, url_1.fileURLToPath)(importMetaUrl)), '../../client/web');
42
- server.get('/*', (0, index_js_1.createStaticFileHandler)(webDir));
43
- // If UI mode, wait for CreeveyApi to be resolved
44
170
  if (ui) {
45
- // Create a custom broadcast function that works with our connections
46
- const broadcast = (message) => {
47
- for (const connection of activeConnections) {
48
- connection.send(message);
49
- }
50
- };
51
- // Create a custom WebSocket server that simulates the standard behavior
52
- const customWsServer = {
53
- clients: activeConnections,
54
- publish: broadcast,
55
- };
56
- let api = null;
57
- server.use(async (request, _response, next) => {
58
- if (!api && request.path === '/') {
59
- api = await creeveyApi;
60
- api.subscribe(customWsServer);
61
- }
62
- next();
63
- });
64
- // Create WebSocket listener
65
- server.ws('/', (ws) => {
66
- // Add connection to the set of active connections
67
- activeConnections.add(ws);
68
- // Handle message events
69
- ws.on('message', (message) => {
70
- api?.handleMessage(ws, message);
171
+ wss = new ws_1.WebSocketServer({ server });
172
+ wss.on('connection', (ws) => {
173
+ ws.on('message', (message, isBinary) => {
174
+ if (creeveyApi) {
175
+ // NOTE Text messages are passed as Buffer https://github.com/websockets/ws/releases/tag/8.0.0
176
+ // eslint-disable-next-line @typescript-eslint/no-base-to-string
177
+ creeveyApi.handleMessage(ws, isBinary ? message : message.toString('utf-8'));
178
+ return;
179
+ }
71
180
  });
72
- // Handle close events to clean up connections
73
- ws.on('close', () => {
74
- activeConnections.delete(ws);
181
+ ws.on('error', (error) => {
182
+ (0, logger_js_1.logger)().error('WebSocket error', error);
75
183
  });
76
184
  });
185
+ wss.on('error', (error) => {
186
+ (0, logger_js_1.logger)().error('WebSocket error', error);
187
+ });
77
188
  }
78
- // Shutdown handling
79
189
  (0, messages_js_1.subscribeOn)('shutdown', () => {
80
- // Close all WebSocket connections
81
- for (const connection of activeConnections) {
82
- try {
83
- connection.close();
84
- }
85
- catch (error) {
86
- (0, logger_js_1.logger)().error('Error closing WebSocket connection', error);
87
- }
190
+ if (wss) {
191
+ wss.clients.forEach((ws) => {
192
+ ws.close();
193
+ });
194
+ wss.close();
88
195
  }
89
- // Close the server
90
196
  server.close();
91
197
  });
92
- // Start server
93
198
  server
94
- .listen(port)
95
- .then(() => {
199
+ .listen(port, () => {
96
200
  (0, logger_js_1.logger)().info(`Server starting on port ${port}`);
97
201
  })
98
- .catch((error) => {
202
+ .on('error', (error) => {
99
203
  (0, logger_js_1.logger)().error('Failed to start server', error);
100
204
  process.exit(1);
101
205
  });
206
+ void new Promise((resolve) => (resolveApi = resolve))
207
+ .then((api) => {
208
+ creeveyApi = api;
209
+ if (wss) {
210
+ creeveyApi.subscribe(wss);
211
+ }
212
+ })
213
+ .catch(utils_js_1.shutdownOnException);
102
214
  // Return the function to resolve the API
103
215
  return resolveApi;
104
216
  }
@@ -1 +1 @@
1
- {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/master/server.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../../../src/server/master/server.ts"],"names":[],"mappings":"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"}
@@ -7,14 +7,14 @@ exports.playwrightDockerFile = playwrightDockerFile;
7
7
  const promises_1 = require("fs/promises");
8
8
  const url_1 = require("url");
9
9
  const semver_1 = __importDefault(require("semver"));
10
- const shelljs_1 = require("shelljs");
10
+ const shelljs_1 = __importDefault(require("shelljs"));
11
11
  const importMetaUrl = (0, url_1.pathToFileURL)(__filename).href;
12
12
  // TODO Support custom docker images
13
13
  async function playwrightDockerFile(browser, version) {
14
14
  const sv = semver_1.default.coerce(version);
15
15
  let npmRegistry;
16
16
  try {
17
- npmRegistry = (0, shelljs_1.exec)('npm config get registry', { silent: true }).stdout.trim();
17
+ npmRegistry = shelljs_1.default.exec('npm config get registry', { silent: true }).stdout.trim();
18
18
  }
19
19
  catch {
20
20
  /* noop */
@@ -1 +1 @@
1
- {"version":3,"file":"docker-file.js","sourceRoot":"","sources":["../../../src/server/playwright/docker-file.ts"],"names":[],"mappings":";;;;;AAQA,oDAqCC;AA7CD,0CAAuC;AACvC,6BAAoC;AACpC,oDAA4B;AAC5B,qCAA+B;AAE/B,MAAM,aAAa,GAAG,IAAA,mBAAa,EAAC,UAAU,CAAC,CAAC,IAAI,CAAC;AAErD,oCAAoC;AAC7B,KAAK,UAAU,oBAAoB,CAAC,OAAe,EAAE,OAAe;IACzE,MAAM,EAAE,GAAG,gBAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElC,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,IAAA,cAAI,EAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IAChF,CAAC;IAAC,MAAM,CAAC;QACP,UAAU;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;IAEtF,MAAM,UAAU,GAAG;;;;;;EAMnB,OAAO;SACN,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,qBAAqB,CAAC;SAC1E,IAAI,CAAC,IAAI,CAAC;MAEP,WAAW;QACT,CAAC,CAAC;qBACW,WAAW,kBAAkB;QAC1C,CAAC,CAAC,EACN;2BACuB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;uBAC/B,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,wBAAwB,OAAO;;;;;CAKhF,CAAC;IAEA,OAAO,UAAU,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
1
+ {"version":3,"file":"docker-file.js","sourceRoot":"","sources":["../../../src/server/playwright/docker-file.ts"],"names":[],"mappings":";;;;;AAQA,oDAqCC;AA7CD,0CAAuC;AACvC,6BAAoC;AACpC,oDAA4B;AAC5B,sDAAyB;AAEzB,MAAM,aAAa,GAAG,IAAA,mBAAa,EAAC,UAAU,CAAC,CAAC,IAAI,CAAC;AAErD,oCAAoC;AAC7B,KAAK,UAAU,oBAAoB,CAAC,OAAe,EAAE,OAAe;IACzE,MAAM,EAAE,GAAG,gBAAM,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAElC,IAAI,WAAW,CAAC;IAChB,IAAI,CAAC;QACH,WAAW,GAAG,iBAAE,CAAC,IAAI,CAAC,yBAAyB,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC;IACnF,CAAC;IAAC,MAAM,CAAC;QACP,UAAU;IACZ,CAAC;IAED,MAAM,OAAO,GAAG,MAAM,IAAA,mBAAQ,EAAC,IAAI,GAAG,CAAC,oBAAoB,EAAE,aAAa,CAAC,EAAE,OAAO,CAAC,CAAC;IAEtF,MAAM,UAAU,GAAG;;;;;;EAMnB,OAAO;SACN,KAAK,CAAC,IAAI,CAAC;SACX,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,aAAa,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,KAAK,CAAC,qBAAqB,CAAC;SAC1E,IAAI,CAAC,IAAI,CAAC;MAEP,WAAW;QACT,CAAC,CAAC;qBACW,WAAW,kBAAkB;QAC1C,CAAC,CAAC,EACN;2BACuB,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE;uBAC/B,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,wBAAwB,OAAO;;;;;CAKhF,CAAC;IAEA,OAAO,UAAU,CAAC,OAAO,CAAC,eAAe,EAAE,MAAM,CAAC,CAAC;AACrD,CAAC"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "creevey",
3
3
  "description": "Cross-browser screenshot testing tool for Storybook with fancy UI Runner",
4
- "version": "0.10.0-beta.44",
4
+ "version": "0.10.0-beta.45",
5
5
  "type": "commonjs",
6
6
  "bin": "dist/cli.js",
7
7
  "main": "./dist/index.js",
@@ -52,7 +52,8 @@
52
52
  "lint:tsc": "tsc --noEmit",
53
53
  "lint:eslint": "eslint",
54
54
  "lint:prettier": "prettier --check .",
55
- "test": "vitest",
55
+ "test": "vitest run",
56
+ "test:watch": "vitest",
56
57
  "start": "concurrently \"yarn start:client\" \"yarn start:storybook\" \"yarn start:creevey\"",
57
58
  "start:client": "vite",
58
59
  "start:storybook": "storybook dev --ci -p 6006",
@@ -111,7 +112,6 @@
111
112
  "dockerode": "^4.0.5",
112
113
  "find-cache-dir": "^5.0.0",
113
114
  "get-port": "^7.1.0",
114
- "hyper-express": "^6.17.3",
115
115
  "lodash": "^4.17.21",
116
116
  "loglevel": "^1.9.2",
117
117
  "loglevel-plugin-prefix": "^0.8.4",
@@ -1,6 +1,6 @@
1
1
  import cluster from 'cluster';
2
2
  import path from 'path';
3
- import { exec } from 'shelljs';
3
+ import sh from 'shelljs';
4
4
  import { getUserAgent } from 'package-manager-detector/detect';
5
5
  import { resolveCommand } from 'package-manager-detector/commands';
6
6
  import { readConfig, defaultBrowser } from './config.js';
@@ -121,7 +121,7 @@ export default async function (options: Options): Promise<void> {
121
121
  if (remoteUrl && localUrl != remoteUrl) logger().info(`On your network - ${remoteUrl}`);
122
122
  logger().info('Waiting Storybook...');
123
123
 
124
- const storybook = exec(storybookCommand, { async: true });
124
+ const storybook = sh.exec(storybookCommand, { async: true });
125
125
  subscribeOn('shutdown', () => {
126
126
  if (storybook.pid) void killTree(storybook.pid);
127
127
  });
@@ -1,25 +1,28 @@
1
- import Runner from './runner.js';
2
- import { Request, Response, CreeveyUpdate } from '../../types.js';
1
+ import { Data, WebSocket, WebSocketServer } from 'ws';
2
+ import type { Request, Response, CreeveyUpdate } from '../../types.js';
3
+ import type { TestsManager } from './testsManager.js';
4
+ import type Runner from './runner.js';
3
5
  import { logger } from '../logger.js';
4
- import { TestsManager } from './testsManager.js';
5
- import HyperExpress from 'hyper-express';
6
6
 
7
- interface CustomWSServer {
8
- clients: Set<HyperExpress.Websocket>;
9
- publish: (message: string) => void;
7
+ function broadcast(wss: WebSocketServer, message: Response): void {
8
+ wss.clients.forEach((ws) => {
9
+ if (ws.readyState === WebSocket.OPEN) {
10
+ ws.send(JSON.stringify(message));
11
+ }
12
+ });
10
13
  }
11
14
 
12
- // Helper function for HyperExpress WebSocket broadcasting
13
- function broadcastHyperExpress(wss: CustomWSServer, message: Response): void {
14
- const serializedMessage = JSON.stringify(message);
15
- wss.publish(serializedMessage);
15
+ function send(ws: WebSocket, message: Response): void {
16
+ if (ws.readyState === WebSocket.OPEN) {
17
+ ws.send(JSON.stringify(message));
18
+ }
16
19
  }
17
20
 
18
- // The class-based implementation of CreeveyApi
21
+ // The class-based implementation of CreeveyApi for native WebSockets
19
22
  export class CreeveyApi {
20
23
  private runner: Runner | null = null;
21
24
  private testsManager: TestsManager;
22
- private wss: CustomWSServer | null = null;
25
+ private wss: WebSocketServer | null = null;
23
26
 
24
27
  constructor(testsManager: TestsManager, runner?: Runner) {
25
28
  this.testsManager = testsManager;
@@ -30,7 +33,7 @@ export class CreeveyApi {
30
33
  }
31
34
  }
32
35
 
33
- subscribe(wss: CustomWSServer): void {
36
+ subscribe(wss: WebSocketServer): void {
34
37
  this.wss = wss;
35
38
 
36
39
  // If we have a runner, subscribe to its updates
@@ -46,26 +49,20 @@ export class CreeveyApi {
46
49
  }
47
50
  }
48
51
 
49
- handleMessage(ws: HyperExpress.Websocket, message: string | Buffer): void {
52
+ handleMessage(ws: WebSocket, message: Data): void {
50
53
  if (typeof message != 'string') {
51
- if (Buffer.isBuffer(message)) {
52
- message = message.toString('utf-8');
53
- } else {
54
- logger().info('unhandled message', message);
55
- return;
56
- }
54
+ logger().info('unhandled message', message);
55
+ return;
57
56
  }
58
57
 
59
58
  const command = JSON.parse(message) as Request;
60
- const sendResponse = (response: Response) => {
61
- ws.send(JSON.stringify(response));
62
- };
63
59
 
64
60
  if (this.runner) {
65
61
  // Normal mode handling with runner
66
62
  switch (command.type) {
67
63
  case 'status': {
68
- sendResponse({ type: 'status', payload: this.runner.status });
64
+ const status = this.runner.status;
65
+ send(ws, { type: 'status', payload: status });
69
66
  return;
70
67
  }
71
68
  case 'start': {
@@ -98,7 +95,7 @@ export class CreeveyApi {
98
95
  }
99
96
  case 'status': {
100
97
  // In update mode, respond with static status including tests data
101
- sendResponse({
98
+ send(ws, {
102
99
  type: 'status',
103
100
  payload: {
104
101
  isRunning: false,
@@ -123,6 +120,6 @@ export class CreeveyApi {
123
120
 
124
121
  const message: Response = { type: 'update', payload };
125
122
 
126
- broadcastHyperExpress(this.wss, message);
123
+ broadcast(this.wss, message);
127
124
  }
128
125
  }
@@ -1,39 +1,20 @@
1
- import { Request, Response } from 'hyper-express';
2
1
  import cluster from 'cluster';
3
2
  import { subscribeOnWorker, sendStoriesMessage } from '../../messages.js';
4
3
  import { CaptureOptions, isDefined } from '../../../types.js';
5
4
 
6
- export async function captureHandler(request: Request, response: Response): Promise<void> {
7
- const { workerId, options } = await request.json<
8
- { workerId: number; options?: CaptureOptions },
9
- {
10
- workerId: number;
11
- options?: CaptureOptions;
12
- }
13
- >({
14
- workerId: 0,
15
- options: undefined,
16
- });
17
-
5
+ export function captureHandler({ workerId, options }: { workerId: number; options?: CaptureOptions }): void {
18
6
  const worker = Object.values(cluster.workers ?? {})
19
7
  .filter(isDefined)
20
8
  .find((worker) => worker.process.pid == workerId);
21
9
 
22
10
  // NOTE: Hypothetical case when someone send to us capture req and we don't have a worker with browser session for it
23
11
  if (!worker) {
24
- response.send();
25
12
  return;
26
13
  }
27
14
 
28
- await new Promise<void>((resolve) => {
29
- const unsubscribe = subscribeOnWorker(worker, 'stories', (message) => {
30
- if (message.type != 'capture') return;
31
- unsubscribe();
32
- resolve();
33
- });
34
- sendStoriesMessage(worker, { type: 'capture', payload: options });
15
+ const unsubscribe = subscribeOnWorker(worker, 'stories', (message) => {
16
+ if (message.type != 'capture') return;
17
+ unsubscribe();
35
18
  });
36
-
37
- // TODO Pass screenshot result to show it in inspector
38
- response.send('Ok');
19
+ sendStoriesMessage(worker, { type: 'capture', payload: options });
39
20
  }
@@ -1,5 +1,6 @@
1
- import { Request, Response } from 'hyper-express';
1
+ import { IncomingMessage, ServerResponse } from 'http';
2
2
 
3
- export function pingHandler(_request: Request, response: Response): void {
4
- response.send('pong');
3
+ export function pingHandler(_request: IncomingMessage, response: ServerResponse): void {
4
+ response.setHeader('Content-Type', 'text/plain');
5
+ response.end('pong');
5
6
  }
@@ -1,29 +1,18 @@
1
- import { Request, Response } from 'hyper-express';
2
1
  import path from 'path';
3
2
  import fs from 'fs';
4
- import { logger } from '../../logger.js';
5
3
 
6
- export function createStaticFileHandler(baseDir: string, pathPrefix?: string) {
7
- return (request: Request, response: Response): void => {
8
- try {
9
- const decodedPath = decodeURIComponent(request.path);
10
- const relativePath = pathPrefix ? decodedPath.replace(pathPrefix, '') : decodedPath;
11
- let filePath = path.join(baseDir, relativePath || 'index.html');
4
+ export function staticHandler(baseDir: string, pathPrefix?: string) {
5
+ return (requestedPath: string): string | undefined => {
6
+ const relativePath = pathPrefix ? requestedPath.replace(pathPrefix, '') : requestedPath;
7
+ let filePath = path.join(baseDir, relativePath || 'index.html');
12
8
 
13
- // If the path points to a directory, append index.html
14
- if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
15
- filePath = path.join(filePath, 'index.html');
16
- }
17
-
18
- if (!fs.existsSync(filePath)) {
19
- response.status(404).send('File not found');
20
- return;
21
- }
9
+ // If the path points to a directory, append index.html
10
+ if (fs.existsSync(filePath) && fs.statSync(filePath).isDirectory()) {
11
+ filePath = path.join(filePath, 'index.html');
12
+ }
22
13
 
23
- response.sendFile(filePath);
24
- } catch (error) {
25
- logger().error('Error serving file', error);
26
- response.status(500).send('Internal server error');
14
+ if (!fs.existsSync(filePath)) {
15
+ return undefined;
27
16
  }
28
17
  };
29
18
  }