Socket
Socket
Sign inDemoInstall

@percy/core

Package Overview
Dependencies
Maintainers
6
Versions
238
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@percy/core - npm Package Compare versions

Comparing version 1.0.0-beta.75 to 1.0.0-beta.76

dist/api.js

13

dist/percy.js

@@ -20,3 +20,3 @@ "use strict";

var _server = _interopRequireDefault(require("./server"));
var _api = require("./api");

@@ -143,3 +143,3 @@ var _snapshot = require("./snapshot");

yield (_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(this.port); // mark instance as started
yield (_this$server = this.server) === null || _this$server === void 0 ? void 0 : _this$server.listen(); // mark instance as started

@@ -280,4 +280,3 @@ this.log.info('Percy has started!');

if (server) {
this.server = (0, _server.default)(this);
this.port = port;
this.server = (0, _api.createPercyServer)(this, port);
}

@@ -293,3 +292,5 @@ } // Shortcut for controlling the global logger's log level.

address() {
return `http://localhost:${this.port}`;
var _this$server4;
return (_this$server4 = this.server) === null || _this$server4 === void 0 ? void 0 : _this$server4.address();
} // Set client & environment info, and override loaded config options

@@ -410,3 +411,3 @@

let failed = ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.status) === 422 && error.response.body.errors.find(e => {
let failed = ((_error$response = error.response) === null || _error$response === void 0 ? void 0 : _error$response.statusCode) === 422 && error.response.body.errors.find(e => {
var _e$source;

@@ -413,0 +414,0 @@

@@ -6,191 +6,467 @@ "use strict";

});
exports.createPercyServer = createPercyServer;
exports.createServer = createServer;
exports.default = void 0;
exports.default = exports.ServerResponse = exports.ServerError = exports.Server = exports.IncomingMessage = void 0;
var _fs = _interopRequireDefault(require("fs"));
var _path = _interopRequireDefault(require("path"));
var _http = _interopRequireDefault(require("http"));
var _ws = require("ws");
var _ws = _interopRequireDefault(require("ws"));
var _logger = _interopRequireDefault(require("@percy/logger"));
var _mimeTypes = _interopRequireDefault(require("mime-types"));
var _package = _interopRequireDefault(require("../package.json"));
var _contentDisposition = _interopRequireDefault(require("content-disposition"));
var _pathToRegexp = require("path-to-regexp");
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
async function getReply({
version,
routes
}, request, response) {
var _headers$ContentType, _body$length, _body;
function _classPrivateMethodInitSpec(obj, privateSet) { _checkPrivateRedeclaration(obj, privateSet); privateSet.add(obj); }
let [url] = request.url.split('?');
let route = routes[url] || routes.default;
let reply; // cors preflight
function _classPrivateFieldInitSpec(obj, privateMap, value) { _checkPrivateRedeclaration(obj, privateMap); privateMap.set(obj, value); }
if (request.method === 'OPTIONS') {
reply = [204, {}];
reply[1]['Access-Control-Allow-Methods'] = 'GET,POST,OPTIONS';
reply[1]['Access-Control-Request-Headers'] = 'Vary';
let allowed = request.headers['access-control-request-headers'];
if (allowed !== null && allowed !== void 0 && allowed.length) reply[1]['Access-Control-Allow-Headers'] = allowed;
} else {
reply = await Promise.resolve().then(() => {
var _routes$middleware;
function _checkPrivateRedeclaration(obj, privateCollection) { if (privateCollection.has(obj)) { throw new TypeError("Cannot initialize the same private elements twice on an object"); } }
return (_routes$middleware = routes.middleware) === null || _routes$middleware === void 0 ? void 0 : _routes$middleware.call(routes, request, response);
}).then(() => route === null || route === void 0 ? void 0 : route(request, response)).catch(routes.catch);
} // response was handled
function _classPrivateFieldGet(receiver, privateMap) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "get"); return _classApplyDescriptorGet(receiver, descriptor); }
function _classApplyDescriptorGet(receiver, descriptor) { if (descriptor.get) { return descriptor.get.call(receiver); } return descriptor.value; }
if (response.headersSent) return []; // default 404 when reply is not an array
function _classPrivateMethodGet(receiver, privateSet, fn) { if (!privateSet.has(receiver)) { throw new TypeError("attempted to get private field on non-instance"); } return fn; }
let [status, headers, body] = Array.isArray(reply) ? reply : [404, {}]; // support content-type header shortcut
function _classPrivateFieldSet(receiver, privateMap, value) { var descriptor = _classExtractFieldDescriptor(receiver, privateMap, "set"); _classApplyDescriptorSet(receiver, descriptor, value); return value; }
if (typeof headers === 'string') headers = {
'Content-Type': headers
}; // auto stringify json
function _classExtractFieldDescriptor(receiver, privateMap, action) { if (!privateMap.has(receiver)) { throw new TypeError("attempted to " + action + " private field on non-instance"); } return privateMap.get(receiver); }
if ((_headers$ContentType = headers['Content-Type']) !== null && _headers$ContentType !== void 0 && _headers$ContentType.includes('json')) body = JSON.stringify(body); // add additional headers
function _classApplyDescriptorSet(receiver, descriptor, value) { if (descriptor.set) { descriptor.set.call(receiver, value); } else { if (!descriptor.writable) { throw new TypeError("attempted to set read only private field"); } descriptor.value = value; } }
headers['Content-Length'] = (_body$length = (_body = body) === null || _body === void 0 ? void 0 : _body.length) !== null && _body$length !== void 0 ? _body$length : 0; // cors headers
// custom incoming message adds a `url` and `body` properties containing the parsed URL and message
// buffer respectively; both available after the 'end' event is emitted
class IncomingMessage extends _http.default.IncomingMessage {
constructor(socket) {
let buffer = [];
super(socket).on('data', d => buffer.push(d)).on('end', () => {
var _this$headers$content;
headers['Access-Control-Expose-Headers'] = 'X-Percy-Core-Version';
headers['Access-Control-Allow-Origin'] = '*'; // version header
this.url = new URL(this.url, `http://${this.headers.host}`);
if (buffer.length) this.body = Buffer.concat(buffer);
headers['X-Percy-Core-Version'] = version;
return [status, headers, body];
}
if (this.body && (_this$headers$content = this.headers['content-type']) !== null && _this$headers$content !== void 0 && _this$headers$content.includes('json')) {
try {
this.body = JSON.parse(this.body);
} catch {}
}
});
}
function createServer(routes) {
let context = {
version: _package.default.version,
} // custom server response adds additional convenience methods
get listening() {
return context.server.listening;
exports.IncomingMessage = IncomingMessage;
class ServerResponse extends _http.default.ServerResponse {
// responds with a status, headers, and body; the second argument can be an content-type string,
// or a headers object, with content-length being automatically set when a `body` is provided
send(status, headers, body) {
if (typeof headers === 'string') {
this.setHeader('Content-Type', headers);
headers = null;
}
}; // create a simple server to route request responses
if (body != null && !this.hasHeader('Content-Length')) {
this.setHeader('Content-Length', Buffer.byteLength(body));
}
context.routes = routes;
context.server = _http.default.createServer((request, response) => {
request.params = new URLSearchParams(request.url.split('?')[1]);
request.on('data', chunk => {
request.body = (request.body || '') + chunk;
return this.writeHead(status, headers).end(body);
} // responds with a status and content with a plain/text content-type
text(status, content) {
if (arguments.length < 2) [status, content] = [200, status];
return this.send(status, 'text/plain', content.toString());
} // responds with a status and stringified `data` with a json content-type
json(status, data) {
if (arguments.length < 2) [status, data] = [200, status];
return this.send(status, 'application/json', JSON.stringify(data));
} // responds with a status and streams a file with appropriate headers
file(status, filepath) {
if (arguments.length < 2) [status, filepath] = [200, status];
filepath = _path.default.resolve(filepath);
let {
size
} = _fs.default.lstatSync(filepath);
let range = parseByteRange(this.req.headers.range, size); // support simple range requests
if (this.req.headers.range) {
let byteRange = range ? `${range.start}-${range.end}` : '*';
this.setHeader('Content-Range', `bytes ${byteRange}/${size}`);
if (!range) return this.send(416);
}
this.writeHead(range ? 206 : status, {
'Accept-Ranges': 'bytes',
'Content-Type': _mimeTypes.default.contentType(_path.default.extname(filepath)),
'Content-Length': range ? range.end - range.start + 1 : size,
'Content-Disposition': (0, _contentDisposition.default)(filepath, {
type: 'inline'
})
});
request.on('end', async () => {
_fs.default.createReadStream(filepath, range).pipe(this);
return this;
}
} // custom server error with a status and default reason
exports.ServerResponse = ServerResponse;
class ServerError extends Error {
static throw(status, reason) {
throw new this(status, reason);
}
constructor(status = 500, reason) {
super(reason || _http.default.STATUS_CODES[status]);
this.status = status;
}
} // custom server class handles routing requests and provides alternate methods and properties
exports.ServerError = ServerError;
var _sockets = /*#__PURE__*/new WeakMap();
var _defaultPort = /*#__PURE__*/new WeakMap();
var _up = /*#__PURE__*/new WeakMap();
var _handleUpgrade = /*#__PURE__*/new WeakSet();
var _routes = /*#__PURE__*/new WeakMap();
var _route = /*#__PURE__*/new WeakSet();
var _handleRequest = /*#__PURE__*/new WeakSet();
class Server extends _http.default.Server {
constructor({
port
} = {}) {
super({
IncomingMessage,
ServerResponse
});
_classPrivateMethodInitSpec(this, _handleRequest);
_classPrivateMethodInitSpec(this, _route);
_classPrivateMethodInitSpec(this, _handleUpgrade);
_classPrivateFieldInitSpec(this, _sockets, {
writable: true,
value: new Set()
});
_classPrivateFieldInitSpec(this, _defaultPort, {
writable: true,
value: void 0
});
_classPrivateFieldInitSpec(this, _up, {
writable: true,
value: []
});
_classPrivateFieldInitSpec(this, _routes, {
writable: true,
value: [{
priority: -1,
handle: (req, res, next) => {
res.setHeader('Access-Control-Allow-Origin', '*');
if (req.method === 'OPTIONS') {
let allowHeaders = req.headers['access-control-request-headers'] || '*';
let allowMethods = [...new Set(_classPrivateFieldGet(this, _routes).flatMap(route => (!route.match || route.match(req.url.pathname)) && route.methods || []))].join(', ');
res.setHeader('Access-Control-Allow-Headers', allowHeaders);
res.setHeader('Access-Control-Allow-Methods', allowMethods);
res.writeHead(204).end();
} else {
res.setHeader('Access-Control-Expose-Headers', '*');
return next();
}
}
}, {
priority: 3,
handle: req => ServerError.throw(404)
}]
});
_classPrivateFieldSet(this, _defaultPort, port); // handle requests on end
this.on('request', (req, res) => {
req.on('end', () => _classPrivateMethodGet(this, _handleRequest, _handleRequest2).call(this, req, res));
}); // handle websocket upgrades
this.on('upgrade', (req, sock, head) => {
_classPrivateMethodGet(this, _handleUpgrade, _handleUpgrade2).call(this, req, sock, head);
}); // track open connections to terminate when the server closes
this.on('connection', socket => {
let handleClose = () => _classPrivateFieldGet(this, _sockets).delete(socket);
_classPrivateFieldGet(this, _sockets).add(socket.on('close', handleClose));
});
} // return the listening port or any default port
get port() {
var _super$address$port, _super$address;
return (_super$address$port = (_super$address = super.address()) === null || _super$address === void 0 ? void 0 : _super$address.port) !== null && _super$address$port !== void 0 ? _super$address$port : _classPrivateFieldGet(this, _defaultPort);
} // return a string representation of the server address
address() {
let port = this.port;
let host = 'http://localhost';
return port ? `${host}:${port}` : host;
} // return a promise that resolves when the server is listening
listen(port = _classPrivateFieldGet(this, _defaultPort)) {
return new Promise((resolve, reject) => {
let handle = err => off() && err ? reject(err) : resolve(this);
let off = () => this.off('error', handle).off('listening', handle);
super.listen(port, handle).once('error', handle);
});
} // return a promise that resolves when the server closes
close() {
return new Promise(resolve => {
_classPrivateFieldGet(this, _sockets).forEach(socket => socket.destroy());
super.close(resolve);
});
} // handle websocket upgrades
websocket(pathname, handle) {
if (!handle) [pathname, handle] = [null, pathname];
_classPrivateFieldGet(this, _up).push({
match: pathname && (0, _pathToRegexp.match)(pathname),
handle: (req, sock, head) => new Promise(resolve => {
let wss = new _ws.default.Server({
noServer: true,
clientTracking: false
});
wss.handleUpgrade(req, sock, head, resolve);
}).then(ws => handle(ws, req))
});
if (pathname) {
_classPrivateFieldGet(this, _up).sort((a, b) => (a.match ? -1 : 1) - (b.match ? -1 : 1));
}
return this;
}
// set request routing and handling for pathnames and methods
route(method, pathname, handle) {
if (arguments.length === 1) [handle, method] = [method];
if (arguments.length === 2) [handle, pathname] = [pathname];
if (arguments.length === 2 && !Array.isArray(method) && method[0] === '/') [pathname, method] = [method];
return _classPrivateMethodGet(this, _route, _route2).call(this, {
priority: !pathname ? 0 : !method ? 1 : 2,
methods: method && [].concat(method).map(m => m.toUpperCase()),
match: pathname && (0, _pathToRegexp.match)(pathname),
handle
});
} // install a route that serves requested files from the provided directory
serve(pathname, directory, options) {
var _options;
if (typeof directory !== 'string') [options, directory] = [directory];
if (!directory) [pathname, directory] = ['/', pathname];
let root = _path.default.resolve(directory);
let mountPattern = (0, _pathToRegexp.pathToRegexp)(pathname, null, {
end: false
});
let rewritePath = createRewriter((_options = options) === null || _options === void 0 ? void 0 : _options.rewrites, (pathname, rewrite) => {
try {
request.body = JSON.parse(request.body);
} catch (e) {}
let filepath = decodeURIComponent(pathname.replace(mountPattern, ''));
if (!isPathInside(root, filepath)) ServerError.throw();
return rewrite(filepath);
} catch {
throw new ServerError(400);
}
});
return _classPrivateMethodGet(this, _route, _route2).call(this, {
priority: 2,
methods: ['GET'],
match: pathname => mountPattern.test(pathname),
handle: async (req, res, next) => {
try {
var _options2;
let [status, headers, body] = await getReply(context, request, response);
if (!response.headersSent) response.writeHead(status, headers).end(body);
let pathname = rewritePath(req.url.pathname);
let file = await getFile(root, pathname, (_options2 = options) === null || _options2 === void 0 ? void 0 : _options2.cleanUrls);
if (!(file !== null && file !== void 0 && file.stats.isFile())) return await next();
return res.file(file.path);
} catch (err) {
let statusPage = _path.default.join(root, `${err.status}.html`);
if (!_fs.default.existsSync(statusPage)) throw err;
return res.file(err.status, statusPage);
}
}
});
}); // track connections
} // route and respond to requests; handling errors if necessary
context.sockets = new Set();
context.server.on('connection', s => {
context.sockets.add(s.on('close', () => context.sockets.delete(s)));
}); // immediately kill connections on close
context.close = () => new Promise(resolve => {
context.sockets.forEach(s => s.destroy());
context.server.close(resolve);
}); // starts the server
} // create a url rewriter from provided rewrite rules
context.listen = port => new Promise((resolve, reject) => {
context.server.on('listening', () => resolve(context));
context.server.on('error', reject);
context.server.listen(port);
}); // add routes programatically
exports.Server = Server;
function _handleUpgrade2(req, sock, head) {
let up = _classPrivateFieldGet(this, _up).find(u => !u.match || u.match(req.url));
context.reply = (url, handler) => {
routes[url] = handler;
return context;
};
if (up) return up.handle(req, sock, head);
sock.write(`HTTP/1.1 400 ${_http.default.STATUS_CODES[400]}\r\n` + 'Connection: close\r\n\r\n');
sock.destroy();
}
return context;
function _route2(route) {
let i = _classPrivateFieldGet(this, _routes).findIndex(r => r.priority >= route.priority);
_classPrivateFieldGet(this, _routes).splice(i, 0, route);
return this;
}
function createPercyServer(percy) {
let log = (0, _logger.default)('core:server');
let context = createServer({
// healthcheck returns meta info on success
'/percy/healthcheck': () => [200, 'application/json', {
success: true,
config: percy.config,
loglevel: percy.loglevel(),
build: percy.build
}],
// remotely get and set percy config options
'/percy/config': ({
body
}) => [200, 'application/json', {
config: body ? percy.setConfig(body) : percy.config,
success: true
}],
// responds when idle
'/percy/idle': () => percy.idle().then(() => [200, 'application/json', {
success: true
}]),
// 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]),
// serves the new DOM library, wrapped for compatability to `@percy/agent`
'/percy-agent.js': () => _fs.default.promises.readFile(require.resolve('@percy/dom'), 'utf-8').then(content => {
let wrapper = '(window.PercyAgent = class PercyAgent { snapshot(n, o) { return PercyDOM.serialize(o); } });';
log.deprecated('It looks like you’re using @percy/cli with an older SDK. Please upgrade to the latest version' + ' to fix this warning. See these docs for more info: https://docs.percy.io/docs/migrating-to-percy-cli');
return [200, 'applicaton/javascript', content.concat(wrapper)];
}),
// forward snapshot requests
'/percy/snapshot': async ({
body,
params
}) => {
let snapshot = percy.snapshot(body);
if (!params.has('async')) await snapshot;
return [200, 'application/json', {
success: true
}];
},
// stops the instance async at the end of the event loop
'/percy/stop': () => {
setImmediate(async () => await percy.stop());
return [200, 'application/json', {
success: true
}];
},
// other routes 404
default: () => [404, 'application/json', {
error: 'Not found',
success: false
}],
// generic error handler
catch: ({
message
}) => [500, 'application/json', {
error: message,
success: false
}]
}); // start a websocket server
async function _handleRequest2(req, res) {
var _res$req;
context.wss = new _ws.Server({
noServer: true
}); // manually handle upgrades to avoid wss handling all events
// support node < 15.7.0
(_res$req = res.req) !== null && _res$req !== void 0 ? _res$req : res.req = req;
context.server.on('upgrade', (req, sock, head) => {
context.wss.handleUpgrade(req, sock, head, socket => {
// allow remote logging connections
let disconnect = _logger.default.connect(socket);
try {
// invoke routes like middleware
await async function cont(routes, i = 0) {
let next = () => cont(routes, i + 1);
socket.once('close', () => disconnect());
});
});
return context;
let {
methods,
match,
handle
} = routes[i];
let result = !methods || methods.includes(req.method);
result && (result = !match || match(req.url.pathname));
if (result) req.params = result.params;
return result ? handle(req, res, next) : next();
}(_classPrivateFieldGet(this, _routes));
} catch (error) {
var _req$headers$accept, _req$headers$content;
let {
status = 500,
message
} = error; // fallback error handling
if ((_req$headers$accept = req.headers.accept) !== null && _req$headers$accept !== void 0 && _req$headers$accept.includes('json') || (_req$headers$content = req.headers['content-type']) !== null && _req$headers$content !== void 0 && _req$headers$content.includes('json')) {
res.json(status, {
error: message
});
} else {
res.text(status, message);
}
}
}
var _default = createPercyServer;
function createRewriter(rewrites = [], cb) {
let normalize = p => _path.default.posix.normalize(_path.default.posix.join('/', p));
if (!Array.isArray(rewrites)) rewrites = Object.entries(rewrites);
let rewrite = [{
// resolve and normalize the path before rewriting
apply: p => _path.default.posix.resolve(normalize(p))
}].concat(rewrites.map(([src, dest]) => {
// compile rewrite rules into functions
let match = (0, _pathToRegexp.match)(normalize(src));
let toPath = (0, _pathToRegexp.compile)(normalize(dest));
return {
match,
apply: r => toPath(r.params)
};
})).reduceRight((next, rule) => pathname => {
var _rule$match, _rule$match2;
// compose all rewrites into a single function
let result = (_rule$match = (_rule$match2 = rule.match) === null || _rule$match2 === void 0 ? void 0 : _rule$match2.call(rule, pathname)) !== null && _rule$match !== void 0 ? _rule$match : pathname;
if (result) pathname = rule.apply(result);
return next(pathname);
}, p => p); // allow additional pathname processing around the rewriter
return p => cb(p, rewrite);
} // returns true if the pathname is inside the root pathname
function isPathInside(root, pathname) {
let abs = _path.default.resolve(_path.default.join(root, pathname));
return !abs.lastIndexOf(root, 0) && (abs[root.length] === _path.default.sep || !abs[root.length]);
} // get the absolute path and stats of a possible file
async function getFile(root, pathname, cleanUrls) {
for (let filename of [pathname].concat(cleanUrls ? _path.default.join(pathname, 'index.html') : [], cleanUrls && pathname.length > 2 ? pathname.replace(/\/?$/, '.html') : [])) {
let filepath = _path.default.resolve(_path.default.join(root, filename));
let stats = await _fs.default.promises.lstat(filepath).catch(() => {});
if (stats !== null && stats !== void 0 && stats.isFile()) return {
path: filepath,
stats
};
}
} // returns the start and end of a byte range or undefined if unable to parse
const RANGE_REGEXP = /^bytes=(\d*)?-(\d*)?(?:\b|$)/;
function parseByteRange(range, size) {
var _range$match;
let [, start, end = size] = (_range$match = range === null || range === void 0 ? void 0 : range.match(RANGE_REGEXP)) !== null && _range$match !== void 0 ? _range$match : [0, 0, 0];
start = Math.max(parseInt(start, 10), 0);
end = Math.min(parseInt(end, 10), size - 1);
if (isNaN(start)) [start, end] = [size - end, size - 1];
if (start >= 0 && start < end) return {
start,
end
};
} // include ServerError and createRewriter as static properties
Server.Error = ServerError;
Server.createRewriter = createRewriter;
var _default = Server;
exports.default = _default;
{
"name": "@percy/core",
"version": "1.0.0-beta.75",
"version": "1.0.0-beta.76",
"license": "MIT",

@@ -33,12 +33,15 @@ "repository": {

"dependencies": {
"@percy/client": "1.0.0-beta.75",
"@percy/config": "1.0.0-beta.75",
"@percy/dom": "1.0.0-beta.75",
"@percy/logger": "1.0.0-beta.75",
"@percy/client": "1.0.0-beta.76",
"@percy/config": "1.0.0-beta.76",
"@percy/dom": "1.0.0-beta.76",
"@percy/logger": "1.0.0-beta.76",
"content-disposition": "^0.5.4",
"cross-spawn": "^7.0.3",
"extract-zip": "^2.0.1",
"mime-types": "^2.1.34",
"path-to-regexp": "^6.2.0",
"rimraf": "^3.0.2",
"ws": "^8.0.0"
},
"gitHead": "3b778a9c0b72dcbf113910227f1a073a2714042a"
"gitHead": "445af68d8e270e2a35fc74e26422ed5d3c91d2ae"
}
// aliased to src for coverage during tests without needing to compile this file
const { createServer } = require('@percy/core/dist/server');
const { default: Server } = require('@percy/core/dist/server');
function createTestServer(routes, port = 8000) {
let context = createServer(routes);
function createTestServer({ default: defaultReply, ...replies }, port = 8000) {
let server = new Server();
// handle route errors
context.routes.catch = ({ message }) => [500, 'text/plain', message];
// track requests
context.requests = [];
context.routes.middleware = ({ url, body }) => {
context.requests.push(body ? [url, body] : [url]);
// alternate route handling
let handleReply = reply => async (req, res) => {
let [status, headers, body] = typeof reply === 'function' ? await reply(req) : reply;
if (!Buffer.isBuffer(body) && typeof body !== 'string') body = JSON.stringify(body);
return res.send(status, headers, body);
};
// map replies to alternate route handlers
server.reply = (p, reply) => (replies[p] = handleReply(reply));
for (let [p, reply] of Object.entries(replies)) server.reply(p, reply);
if (defaultReply) defaultReply = handleReply(defaultReply);
// track requests and route replies
server.requests = [];
server.route(async (req, res, next) => {
let pathname = req.url.pathname;
if (req.url.search) pathname += req.url.search;
server.requests.push(req.body ? [pathname, req.body] : [pathname]);
let reply = replies[req.url.pathname] || defaultReply;
return reply ? await reply(req, res) : next();
});
// automatically listen
return context.listen(port);
return server.listen(port);
};

@@ -19,0 +32,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc