creevey
Version:
Cross-browser screenshot testing tool for Storybook with fancy UI Runner
114 lines • 4.88 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.start = start;
const path_1 = __importDefault(require("path"));
const http_1 = __importDefault(require("http"));
const cluster_1 = __importDefault(require("cluster"));
const koa_1 = __importDefault(require("koa"));
const cors_1 = __importDefault(require("@koa/cors"));
const koa_static_1 = __importDefault(require("koa-static"));
const koa_mount_1 = __importDefault(require("koa-mount"));
const koa_bodyparser_1 = __importDefault(require("koa-bodyparser"));
const ws_1 = __importDefault(require("ws"));
const url_1 = require("url");
const messages_js_1 = require("../messages.js");
const types_js_1 = require("../../types.js");
const logger_js_1 = require("../logger.js");
const index_js_1 = require("../../shared/index.js");
const importMetaUrl = (0, url_1.pathToFileURL)(__filename).href;
function start(reportDir, port, ui, host) {
let resolveApi = types_js_1.noop;
let setStoriesCounter = 0;
const creeveyApi = new Promise((resolve) => (resolveApi = resolve));
const app = new koa_1.default();
const server = http_1.default.createServer(app.callback());
const wss = new ws_1.default.Server({ server });
app.use((0, cors_1.default)());
app.use((0, koa_bodyparser_1.default)());
app.use(async (ctx, next) => {
if (ctx.method == 'GET' && ctx.path == '/ping') {
ctx.body = 'pong';
return;
}
await next();
});
if (ui) {
app.use(async (_, next) => {
await creeveyApi;
await next();
});
}
app.use(async (ctx, next) => {
if (ctx.method == 'POST' && ctx.path == '/stories') {
const { setStoriesCounter: counter, stories } = ctx.request.body;
if (setStoriesCounter >= counter)
return;
const deserializedStories = stories.map(([file, stories]) => [
file,
stories.map(index_js_1.deserializeStory),
]);
setStoriesCounter = counter;
(0, messages_js_1.emitStoriesMessage)({ type: 'update', payload: deserializedStories });
Object.values(cluster_1.default.workers ?? {})
.filter(types_js_1.isDefined)
.filter((worker) => worker.isConnected())
.forEach((worker) => {
(0, messages_js_1.sendStoriesMessage)(worker, { type: 'update', payload: deserializedStories });
});
return;
}
await next();
});
app.use(async (ctx, next) => {
if (ctx.method == 'POST' && ctx.path == '/capture') {
const { workerId, options } = ctx.request.body;
const worker = Object.values(cluster_1.default.workers ?? {})
.filter(types_js_1.isDefined)
.find((worker) => worker.process.pid == workerId);
// NOTE: Hypothetical case when someone send to us capture req and we don't have a worker with browser session for it
if (!worker)
return;
await new Promise((resolve) => {
const unsubscribe = (0, messages_js_1.subscribeOnWorker)(worker, 'stories', (message) => {
if (message.type != 'capture')
return;
unsubscribe();
resolve();
});
(0, messages_js_1.sendStoriesMessage)(worker, { type: 'capture', payload: options });
});
// TODO Pass screenshot result to show it in inspector
ctx.body = 'Ok';
return;
}
await next();
});
app.use((0, koa_static_1.default)(path_1.default.join(path_1.default.dirname((0, url_1.fileURLToPath)(importMetaUrl)), '../../client/web')));
app.use((0, koa_mount_1.default)('/report', (0, koa_static_1.default)(reportDir)));
wss.on('error', (error) => {
(0, logger_js_1.logger)().error(error);
});
server.listen(port, host);
(0, messages_js_1.subscribeOn)('shutdown', () => {
server.close();
wss.close();
wss.clients.forEach((ws) => {
ws.close();
});
});
void creeveyApi.then((api) => {
api.subscribe(wss);
wss.on('connection', (ws) => {
ws.on('message', (message, isBinary) => {
// NOTE Text messages are passed as Buffer https://github.com/websockets/ws/releases/tag/8.0.0
// eslint-disable-next-line @typescript-eslint/no-base-to-string
api.handleMessage(ws, isBinary ? message : message.toString('utf-8'));
});
});
});
return resolveApi;
}
//# sourceMappingURL=server.js.map