@percy/core
Advanced tools
Comparing version 1.0.0-beta.13 to 1.0.0-beta.14
@@ -20,3 +20,3 @@ "use strict"; | ||
var _server = require("./server"); | ||
var _server = _interopRequireDefault(require("./server")); | ||
@@ -104,3 +104,3 @@ var _queue = _interopRequireDefault(require("./queue")); | ||
this.port = port; | ||
this.app = (0, _server.createServerApp)(this); | ||
this.server = (0, _server.default)(this); | ||
} | ||
@@ -146,7 +146,6 @@ | ||
try { | ||
// if there is an exress app, a server should be started | ||
if (this.app) { | ||
this.server = await (0, _server.startServer)(this.app, this.port); | ||
} // launch the discoverer browser and create a percy build | ||
var _this$server; | ||
// if there is a server, start listening | ||
await ((_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(this.port)); // launch the discoverer browser and create a percy build | ||
@@ -170,7 +169,7 @@ await this.discoverer.launch(); | ||
} catch (error) { | ||
var _this$server; | ||
var _this$server2; | ||
// on error, close any running browser or server | ||
await this.discoverer.close(); | ||
(_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.close(); // throw an easier-to understand error when the port is taken | ||
(_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close(); // throw an easier-to understand error when the port is taken | ||
@@ -190,3 +189,3 @@ if (error.code === 'EADDRINUSE') { | ||
if (this.isRunning() && !_classPrivateFieldGet(this, _stopping)) { | ||
var _this$server2; | ||
var _this$server3; | ||
@@ -214,3 +213,3 @@ _classPrivateFieldSet(this, _stopping, true); | ||
(_this$server2 = this.server) === null || _this$server2 === void 0 ? void 0 : _this$server2.close(); | ||
(_this$server3 = this.server) === null || _this$server3 === void 0 ? void 0 : _this$server3.close(); | ||
await this.discoverer.close(); | ||
@@ -217,0 +216,0 @@ |
@@ -6,27 +6,84 @@ "use strict"; | ||
}); | ||
exports.createServerApp = createServerApp; | ||
exports.startServer = startServer; | ||
exports.createServer = createServer; | ||
exports.default = createPercyServer; | ||
// Handles async routes with a middleware pattern to catch and forward errors | ||
function asyncRoute(handler) { | ||
return (req, res, next) => handler(req, res, next).catch(next); | ||
} // Lazily creates and returns an express app for communicating with the Percy | ||
// instance using a local API | ||
var _http = _interopRequireDefault(require("http")); | ||
var _fs = _interopRequireDefault(require("fs")); | ||
function createServerApp(percy) { | ||
// lazily required to speed up imports when the server is not needed | ||
let express = require('express'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
let cors = require('cors'); | ||
async function getReply(routes, request) { | ||
var _headers$ContentType, _body$length, _body; | ||
let bodyParser = require('body-parser'); | ||
let route = routes[request.url] || routes.default; | ||
let reply; // cors preflight | ||
return express().use(cors()).use(bodyParser.urlencoded({ | ||
extended: true | ||
})).use(bodyParser.json({ | ||
limit: '50mb' | ||
})) // healthcheck returns meta info as well | ||
.get('/percy/healthcheck', (_, res) => { | ||
res.json({ | ||
if (request.method === 'OPTIONS') { | ||
reply = [204, { | ||
'Access-Control-Allow-Methods': 'GET,POST' | ||
}]; | ||
} else { | ||
reply = await Promise.resolve().then(() => { | ||
var _routes$middleware; | ||
return (_routes$middleware = routes.middleware) === null || _routes$middleware === void 0 ? void 0 : _routes$middleware.call(routes, request); | ||
}).then(() => route === null || route === void 0 ? void 0 : route(request)).catch(routes.catch); | ||
} // default 404 when reply is not an array | ||
let [status, headers, body] = Array.isArray(reply) ? reply : [404, {}]; // support content-type header shortcut | ||
if (typeof headers === 'string') headers = { | ||
'Content-Type': headers | ||
}; // auto stringify json | ||
if ((_headers$ContentType = headers['Content-Type']) === null || _headers$ContentType === void 0 ? void 0 : _headers$ContentType.includes('json')) body = JSON.stringify(body); // add content length and cors headers | ||
headers['Content-Length'] = (_body$length = (_body = body) === null || _body === void 0 ? void 0 : _body.length) !== null && _body$length !== void 0 ? _body$length : 0; | ||
headers['Access-Control-Allow-Origin'] = '*'; | ||
return [status, headers, body]; | ||
} | ||
function createServer(routes) { | ||
let context = { | ||
get listening() { | ||
return context.server.listening; | ||
} | ||
}; | ||
context.server = _http.default.createServer((request, response) => { | ||
request.on('data', chunk => { | ||
request.body = (request.body || '') + chunk; | ||
}); | ||
request.on('end', async () => { | ||
try { | ||
request.body = JSON.parse(request.body); | ||
} catch {} | ||
let [status, headers, body] = await getReply(routes, request); | ||
response.writeHead(status, headers).end(body); | ||
}); | ||
}); | ||
context.close = () => context.server.close(); | ||
context.listen = port => new Promise((resolve, reject) => { | ||
context.server.on('listening', () => resolve(context)); | ||
context.server.on('error', reject); | ||
context.server.listen(port); | ||
}); | ||
context.reply = (url, handler) => { | ||
routes[url] = handler; | ||
return context; | ||
}; | ||
return context; | ||
} | ||
function createPercyServer(percy) { | ||
return createServer({ | ||
// healthcheck returns meta info on success | ||
'/percy/healthcheck': () => [200, 'application/json', { | ||
success: true, | ||
@@ -36,49 +93,32 @@ config: percy.config, | ||
build: percy.client.build | ||
}); | ||
}) // responds when idle | ||
.get('/percy/idle', asyncRoute(async (_, res) => { | ||
await percy.idle(); | ||
res.json({ | ||
}], | ||
// responds when idle | ||
'/percy/idle': () => percy.idle().then(() => [200, 'application/json', { | ||
success: true | ||
}); | ||
})) // serves @percy/dom as a convenience | ||
.get('/percy/dom.js', (_, res) => { | ||
res.sendFile(require.resolve('@percy/dom')); | ||
}) // forward snapshot requests | ||
.post('/percy/snapshot', asyncRoute(async (req, res) => { | ||
await percy.snapshot(req.body); | ||
res.json({ | ||
}]), | ||
// serves @percy/dom as a convenience | ||
'/percy/dom.js': () => _fs.default.promises.readFile(require.resolve('@percy/dom'), 'utf-8').then(content => [200, 'applicaton/javascript', content]), | ||
// forward snapshot requests | ||
'/percy/snapshot': ({ | ||
body | ||
}) => percy.snapshot(body).then(() => [200, 'application/json', { | ||
success: true | ||
}); | ||
})) // stops the instance | ||
.post('/percy/stop', asyncRoute(async (_, res) => { | ||
await percy.stop(); | ||
res.json({ | ||
}]), | ||
// stops the instance | ||
'/percy/stop': () => percy.stop().then(() => [200, 'application/json', { | ||
success: true | ||
}); | ||
})) // other routes 404 | ||
.use('*', (_, res) => { | ||
res.status(404).json({ | ||
success: false, | ||
error: 'Not found' | ||
}); | ||
}) // generic error handler | ||
.use(({ | ||
message | ||
}, req, res, next) => { | ||
res.status(500).json({ | ||
success: false, | ||
error: message | ||
}); | ||
}]), | ||
// other routes 404 | ||
default: () => [404, 'application/json', { | ||
error: 'Not found', | ||
success: false | ||
}], | ||
// generic error handler | ||
catch: ({ | ||
message | ||
}) => [500, 'application/json', { | ||
error: message, | ||
success: false | ||
}] | ||
}); | ||
} // Promised based helper for starting an app at the specified port. Resolves | ||
// when the server is listening, rejects if there are any errors when starting. | ||
function startServer(app, port) { | ||
return new Promise((resolve, reject) => { | ||
let server = app.listen(port); | ||
server.once('listening', () => resolve(server)); | ||
server.once('error', reject); | ||
}); | ||
} |
{ | ||
"name": "@percy/core", | ||
"version": "1.0.0-beta.13", | ||
"version": "1.0.0-beta.14", | ||
"license": "MIT", | ||
@@ -9,3 +9,4 @@ "main": "dist/index.js", | ||
"dist", | ||
"types/index.d.ts" | ||
"types/index.d.ts", | ||
"test/helpers/server.js" | ||
], | ||
@@ -28,8 +29,5 @@ "scripts": { | ||
"dependencies": { | ||
"@percy/client": "^1.0.0-beta.13", | ||
"@percy/dom": "^1.0.0-beta.13", | ||
"@percy/logger": "^1.0.0-beta.13", | ||
"body-parser": "^1.19.0", | ||
"cors": "^2.8.5", | ||
"express": "^4.17.1", | ||
"@percy/client": "^1.0.0-beta.14", | ||
"@percy/dom": "^1.0.0-beta.14", | ||
"@percy/logger": "^1.0.0-beta.14", | ||
"node-fetch": "^2.6.1", | ||
@@ -43,3 +41,3 @@ "progress": "^2.0.3", | ||
}, | ||
"gitHead": "9e694cfb410f5736467e5dafd96e6a8e9834c77b" | ||
"gitHead": "be425adadd5ad0f8862e9449ec8d9380961b313d" | ||
} |
@@ -48,4 +48,3 @@ # @percy/core | ||
Starting a `Percy` instance will start a local API server unless `server` is `false`. The server can | ||
be found at `http://localhost:5338/` or at the provided `port` number. All POST requests accept a | ||
JSON body with the `application/json` content-type. | ||
be found at `http://localhost:5338/` or at the provided `port` number. | ||
@@ -52,0 +51,0 @@ - GET `/percy/healthcheck` – Responds with information about the running instance |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Network access
Supply chain riskThis module accesses the network.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
56117
6
18
1190
120
6
1
- Removedbody-parser@^1.19.0
- Removedcors@^2.8.5
- Removedexpress@^4.17.1
- Removedaccepts@1.3.8(transitive)
- Removedarray-flatten@1.1.1(transitive)
- Removedbody-parser@1.20.3(transitive)
- Removedbytes@3.1.2(transitive)
- Removedcall-bind@1.0.7(transitive)
- Removedcontent-disposition@0.5.4(transitive)
- Removedcontent-type@1.0.5(transitive)
- Removedcookie@0.6.0(transitive)
- Removedcookie-signature@1.0.6(transitive)
- Removedcors@2.8.5(transitive)
- Removeddebug@2.6.9(transitive)
- Removeddefine-data-property@1.1.4(transitive)
- Removeddepd@2.0.0(transitive)
- Removeddestroy@1.2.0(transitive)
- Removedee-first@1.1.1(transitive)
- Removedencodeurl@1.0.22.0.0(transitive)
- Removedes-define-property@1.0.0(transitive)
- Removedes-errors@1.3.0(transitive)
- Removedescape-html@1.0.3(transitive)
- Removedetag@1.8.1(transitive)
- Removedexpress@4.21.0(transitive)
- Removedfinalhandler@1.3.1(transitive)
- Removedforwarded@0.2.0(transitive)
- Removedfresh@0.5.2(transitive)
- Removedfunction-bind@1.1.2(transitive)
- Removedget-intrinsic@1.2.4(transitive)
- Removedgopd@1.0.1(transitive)
- Removedhas-property-descriptors@1.0.2(transitive)
- Removedhas-proto@1.0.3(transitive)
- Removedhas-symbols@1.0.3(transitive)
- Removedhasown@2.0.2(transitive)
- Removedhttp-errors@2.0.0(transitive)
- Removediconv-lite@0.4.24(transitive)
- Removedipaddr.js@1.9.1(transitive)
- Removedmedia-typer@0.3.0(transitive)
- Removedmerge-descriptors@1.0.3(transitive)
- Removedmethods@1.1.2(transitive)
- Removedmime@1.6.0(transitive)
- Removedmime-db@1.52.0(transitive)
- Removedmime-types@2.1.35(transitive)
- Removedms@2.0.0(transitive)
- Removednegotiator@0.6.3(transitive)
- Removedobject-assign@4.1.1(transitive)
- Removedobject-inspect@1.13.2(transitive)
- Removedon-finished@2.4.1(transitive)
- Removedparseurl@1.3.3(transitive)
- Removedpath-to-regexp@0.1.10(transitive)
- Removedproxy-addr@2.0.7(transitive)
- Removedqs@6.13.0(transitive)
- Removedrange-parser@1.2.1(transitive)
- Removedraw-body@2.5.2(transitive)
- Removedsafer-buffer@2.1.2(transitive)
- Removedsend@0.19.0(transitive)
- Removedserve-static@1.16.2(transitive)
- Removedset-function-length@1.2.2(transitive)
- Removedsetprototypeof@1.2.0(transitive)
- Removedside-channel@1.0.6(transitive)
- Removedstatuses@2.0.1(transitive)
- Removedtoidentifier@1.0.1(transitive)
- Removedtype-is@1.6.18(transitive)
- Removedunpipe@1.0.0(transitive)
- Removedutils-merge@1.0.1(transitive)
- Removedvary@1.1.2(transitive)
Updated@percy/client@^1.0.0-beta.14
Updated@percy/dom@^1.0.0-beta.14
Updated@percy/logger@^1.0.0-beta.14