New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@spotlightjs/sidecar

Package Overview
Dependencies
Maintainers
1
Versions
40
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@spotlightjs/sidecar - npm Package Compare versions

Comparing version 1.9.2 to 1.9.3

dist/constants.js

2

dist/main.d.ts

@@ -33,3 +33,3 @@ import { type SidecarLogger } from './logger.js';

export declare function clearBuffer(): void;
export declare function shutdown(): void;
export declare const shutdown: () => void;
export {};

@@ -1,475 +0,365 @@

var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import launchEditor from "launch-editor";
import { readFileSync, createWriteStream } from "node:fs";
import { createServer, get } from "node:http";
import * as path from "node:path";
import { join, resolve, extname } from "node:path";
import { createGunzip, createInflate } from "node:zlib";
import * as os from "node:os";
import * as SourceMap from "source-map";
const DEFAULT_PORT = 8969;
const SERVER_IDENTIFIER = "spotlight-by-sentry";
const CONTEXT_LINES_ENDPOINT = "/contextlines";
async function getGeneratedCodeFromServer(filename) {
var B = Object.defineProperty;
var z = (e, t, n) => t in e ? B(e, t, { enumerable: !0, configurable: !0, writable: !0, value: n }) : e[t] = n;
var h = (e, t, n) => z(e, typeof t != "symbol" ? t + "" : t, n);
import { startSpan as _, getTraceData as V, captureException as J } from "@sentry/node";
import W from "launch-editor";
import { readFileSync as $, createWriteStream as X } from "node:fs";
import { createServer as K, get as Y } from "node:http";
import * as E from "node:path";
import { join as L, resolve as Q, extname as Z } from "node:path";
import { createGunzip as q, createInflate as ee } from "node:zlib";
import { CONTEXT_LINES_ENDPOINT as te, DEFAULT_PORT as ne, SERVER_IDENTIFIER as oe } from "./constants.js";
import * as ie from "node:os";
import * as O from "source-map";
async function re(e) {
try {
const generatedCodeResponse = await fetch(filename);
return generatedCodeResponse.text();
return (await fetch(e)).text();
} catch {
return void 0;
return;
}
}
function parseStackTrace(requestBody) {
function se(e) {
try {
return JSON.parse(requestBody);
return JSON.parse(e);
} catch {
return void 0;
return;
}
}
async function applySourceContextToFrame(sourceMapContent, frame) {
const consumer = await new SourceMap.SourceMapConsumer(sourceMapContent);
const originalPosition = consumer.originalPositionFor({
line: frame.lineno,
column: frame.colno,
bias: SourceMap.SourceMapConsumer.LEAST_UPPER_BOUND
async function ae(e, t) {
const n = await new O.SourceMapConsumer(e), o = n.originalPositionFor({
line: t.lineno,
column: t.colno,
bias: O.SourceMapConsumer.LEAST_UPPER_BOUND
});
if (originalPosition.source && originalPosition.line && originalPosition.column) {
frame.lineno = originalPosition.line;
frame.colno = originalPosition.column;
const filePath = new URL(frame.filename).pathname.slice(1);
frame.filename = path.resolve(path.join(path.dirname(filePath), originalPosition.source));
const content = consumer.sourceContentFor(originalPosition.source);
const lines = (content == null ? void 0 : content.split(os.EOL)) ?? [];
addContextLinesToFrame(lines, frame);
if (o.source && o.line && o.column) {
t.lineno = o.line, t.colno = o.column;
const i = new URL(t.filename).pathname.slice(1);
t.filename = E.resolve(E.join(E.dirname(i), o.source));
const r = n.sourceContentFor(o.source), s = (r == null ? void 0 : r.split(ie.EOL)) ?? [];
A(s, t);
}
return originalPosition;
return o;
}
function addContextLinesToFrame(lines, frame, linesOfContext = 5) {
const maxLines = lines.length;
const sourceLine = Math.max(Math.min(maxLines - 1, frame.lineno - 1), 0);
frame.pre_context = lines.slice(Math.max(0, sourceLine - linesOfContext), sourceLine).map((line) => snipLine(line, 0));
frame.context_line = snipLine(lines[Math.min(maxLines - 1, sourceLine)], frame.colno || 0);
frame.post_context = lines.slice(Math.min(sourceLine + 1, maxLines), sourceLine + 1 + linesOfContext).map((line) => snipLine(line, 0));
function A(e, t, n = 5) {
const o = e.length, i = Math.max(Math.min(o - 1, t.lineno - 1), 0);
t.pre_context = e.slice(Math.max(0, i - n), i).map((r) => v(r, 0)), t.context_line = v(e[Math.min(o - 1, i)], t.colno || 0), t.post_context = e.slice(Math.min(i + 1, o), i + 1 + n).map((r) => v(r, 0));
}
function snipLine(line, colno) {
let newLine = line;
const lineLength = newLine.length;
if (lineLength <= 150) {
return newLine;
}
if (colno > lineLength) {
colno = lineLength;
}
let start = Math.max(colno - 60, 0);
if (start < 5) {
start = 0;
}
let end = Math.min(start + 140, lineLength);
if (end > lineLength - 5) {
end = lineLength;
}
if (end === lineLength) {
start = Math.max(end - 140, 0);
}
newLine = newLine.slice(start, end);
if (start > 0) {
newLine = `'{snip} ${newLine}`;
}
if (end < lineLength) {
newLine += " {snip}";
}
return newLine;
function v(e, t) {
let n = e;
const o = n.length;
if (o <= 150)
return n;
t > o && (t = o);
let i = Math.max(t - 60, 0);
i < 5 && (i = 0);
let r = Math.min(i + 140, o);
return r > o - 5 && (r = o), r === o && (i = Math.max(r - 140, 0)), n = n.slice(i, r), i > 0 && (n = `'{snip} ${n}`), r < o && (n += " {snip}"), n;
}
function isValidSentryStackFrame(frame) {
return !!frame.filename && !!frame.lineno && !!frame.colno;
function ce(e) {
return !!e.filename && !!e.lineno && !!e.colno;
}
function contextLinesHandler(req, res) {
if (req.method !== "PUT") {
res.writeHead(405);
res.end();
function le(e, t) {
if (e.method !== "PUT") {
t.writeHead(405), t.end();
return;
}
let requestBody = "";
req.on("data", (chunk) => {
requestBody += chunk;
});
req.on("end", async () => {
const stacktrace = parseStackTrace(requestBody);
if (!stacktrace) {
res.writeHead(500);
res.end();
let n = "";
e.on("data", (o) => {
n += o;
}), e.on("end", async () => {
const o = se(n);
if (!o) {
t.writeHead(500), t.end();
return;
}
for (const frame of stacktrace.frames ?? []) {
if (!isValidSentryStackFrame(frame) || // let's ignore dependencies for now with this naive check
frame.filename.includes("/node_modules/")) {
for (const r of o.frames ?? []) {
if (!ce(r) || // let's ignore dependencies for now with this naive check
r.filename.includes("/node_modules/"))
continue;
}
const { filename } = frame;
if (filename.includes("://")) {
const generatedCode = await getGeneratedCodeFromServer(frame.filename);
if (!generatedCode) {
const { filename: s } = r;
if (s.includes("://")) {
const a = await re(r.filename);
if (!a)
continue;
const u = a.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.*)/);
if (u && u[1]) {
const c = u[1], l = Buffer.from(c, "base64").toString("utf-8");
await ae(l, r);
}
const inlineSourceMapMatch = generatedCode.match(/\/\/# sourceMappingURL=data:application\/json;base64,(.*)/);
if (inlineSourceMapMatch && inlineSourceMapMatch[1]) {
const sourceMapBase64 = inlineSourceMapMatch[1];
const sourceMapContent = Buffer.from(sourceMapBase64, "base64").toString("utf-8");
await applySourceContextToFrame(sourceMapContent, frame);
}
} else if (!filename.includes(":")) {
} else if (!s.includes(":"))
try {
const lines = readFileSync(filename, { encoding: "utf-8" }).split(/\r?\n/);
addContextLinesToFrame(lines, frame);
} catch (err) {
if (err.code !== "ENOENT") {
throw err;
}
const a = $(s, { encoding: "utf-8" }).split(/\r?\n/);
A(a, r);
} catch (a) {
if (a.code !== "ENOENT")
throw a;
}
}
}
const responseJson = JSON.stringify(stacktrace);
res.writeHead(200, { "Content-Type": "application/json" });
res.end(responseJson);
const i = JSON.stringify(o);
t.writeHead(200, { "Content-Type": "application/json" }), t.end(i);
});
}
const defaultLogger = {
info: (message) => console.log("🔎 [Spotlight]", message),
warn: (message) => console.warn("🔎 [Spotlight]", message),
error: (message) => console.error("🔎 [Spotlight]", message),
debug: (message) => debugEnabled && console.debug("🔎 [Spotlight]", message)
const T = {
info: (e) => console.log("🔎 [Spotlight]", e),
warn: (e) => console.warn("🔎 [Spotlight]", e),
error: (e) => console.error("🔎 [Spotlight]", e),
debug: (e) => N && console.debug("🔎 [Spotlight]", e)
};
let injectedLogger = void 0;
let debugEnabled = false;
function activateLogger(logger2) {
injectedLogger = logger2;
let S, N = !1;
function de(e) {
S = e;
}
function enableDebugLogging(debug) {
debugEnabled = debug;
function ue(e) {
N = e;
}
const logger = {
info: (message) => (injectedLogger || defaultLogger).info(message),
warn: (message) => (injectedLogger || defaultLogger).warn(message),
error: (message) => (injectedLogger || defaultLogger).error(message),
debug: (message) => (injectedLogger || defaultLogger).debug(message)
const d = {
info: (e) => (S || T).info(e),
warn: (e) => (S || T).warn(e),
error: (e) => (S || T).error(e),
debug: (e) => (S || T).debug(e)
};
class MessageBuffer {
constructor(size = 100) {
__publicField(this, "size");
__publicField(this, "items");
__publicField(this, "writePos", 0);
__publicField(this, "head", 0);
__publicField(this, "timeout", 10);
__publicField(this, "readers", /* @__PURE__ */ new Map());
this.size = size;
this.items = new Array(size);
class he {
constructor(t = 100) {
h(this, "size");
h(this, "items");
h(this, "writePos", 0);
h(this, "head", 0);
h(this, "timeout", 10);
h(this, "readers", /* @__PURE__ */ new Map());
this.size = t, this.items = new Array(t);
}
put(item) {
const curTime = (/* @__PURE__ */ new Date()).getTime();
this.items[this.writePos % this.size] = [curTime, item];
this.writePos += 1;
if (this.head === this.writePos) {
put(t) {
const n = (/* @__PURE__ */ new Date()).getTime();
this.items[this.writePos % this.size] = [n, t], this.writePos += 1, this.head === this.writePos && (this.head += 1);
const o = n - this.timeout * 1e3;
let i;
for (; this.head < this.writePos && (i = this.items[this.head % this.size], !(i === void 0 || i[0] > o)); )
this.head += 1;
}
const minTime = curTime - this.timeout * 1e3;
let atItem;
while (this.head < this.writePos) {
atItem = this.items[this.head % this.size];
if (atItem === void 0) break;
if (atItem[0] > minTime) break;
this.head += 1;
}
}
subscribe(callback) {
const readerId = generateUuidv4();
this.readers.set(readerId, callback);
setTimeout(() => this.stream(readerId));
return readerId;
subscribe(t) {
const n = pe();
return this.readers.set(n, t), setTimeout(() => this.stream(n)), n;
}
unsubscribe(readerId) {
this.readers.delete(readerId);
unsubscribe(t) {
this.readers.delete(t);
}
stream(readerId, readPos = this.head) {
const cb = this.readers.get(readerId);
if (!cb) return;
let atReadPos = readPos;
let item;
while (true) {
item = this.items[atReadPos % this.size];
if (typeof item === "undefined" || atReadPos >= this.writePos) {
break;
}
cb(item[1]);
atReadPos += 1;
}
setTimeout(() => this.stream(readerId, atReadPos), 500);
stream(t, n = this.head) {
const o = this.readers.get(t);
if (!o) return;
let i = n, r;
for (; r = this.items[i % this.size], !(typeof r > "u" || i >= this.writePos); )
o(r[1]), i += 1;
setTimeout(() => this.stream(t, i), 500);
}
clear() {
this.items = new Array(this.size);
this.writePos = 0;
this.head = 0;
this.readers = /* @__PURE__ */ new Map();
this.items = new Array(this.size), this.writePos = 0, this.head = 0, this.readers = /* @__PURE__ */ new Map();
}
}
function generateUuidv4() {
let dt = (/* @__PURE__ */ new Date()).getTime();
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(c) {
let rnd = Math.random() * 16;
rnd = (dt + rnd) % 16 | 0;
dt = Math.floor(dt / 16);
return (c === "x" ? rnd : rnd & 3 | 8).toString(16);
function pe() {
let e = (/* @__PURE__ */ new Date()).getTime();
return "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function(t) {
let n = Math.random() * 16;
return n = (e + n) % 16 | 0, e = Math.floor(e / 16), (t === "x" ? n : n & 3 | 8).toString(16);
});
}
function getCorsHeader() {
return {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "GET,POST,PUT,OPTIONS,DELETE,PATCH"
};
}
function enableCORS(handler) {
return function corsMiddleware(req, res, pathname, searchParams) {
const headers = {
...getCorsHeader(),
...getSpotlightHeader()
const b = (e, t = {}) => (...n) => _({ name: e.name, ...t }, () => e(...n)), I = {
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Credentials": "true",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Methods": "GET,POST,PUT,OPTIONS,DELETE,PATCH"
}, D = {
"X-Powered-by": oe
}, x = (e) => b(
(t, n, o, i) => {
const r = {
...I,
...D
};
for (const [header, value] of Object.entries(headers)) {
res.setHeader(header, value);
}
if (req.method === "OPTIONS") {
res.writeHead(204, {
for (const [s, a] of Object.entries(r))
n.setHeader(s, a);
if (t.method === "OPTIONS") {
n.writeHead(204, {
"Cache-Control": "no-cache"
});
res.end();
}), n.end();
return;
}
return handler(req, res, pathname, searchParams);
};
}
function getSpotlightHeader() {
return {
"X-Powered-by": SERVER_IDENTIFIER
};
}
function streamRequestHandler(buffer2, incomingPayload) {
return function handleStreamRequest(req, res, pathname, searchParams) {
if (req.method === "GET" && req.headers.accept && req.headers.accept === "text/event-stream" && pathname === "/stream") {
res.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
});
res.flushHeaders();
res.write("\n");
const sub = buffer2.subscribe(([payloadType, data]) => {
logger.debug("🕊️ sending to Spotlight");
res.write(`event:${payloadType}
return e(t, n, o, i);
},
{ name: "enableCORS", op: "sidecar.http.middleware.cors" }
), fe = (e, t) => function(o, i, r, s) {
if (o.method === "GET" && o.headers.accept && o.headers.accept === "text/event-stream" && r === "/stream") {
i.writeHead(200, {
"Content-Type": "text/event-stream",
"Cache-Control": "no-cache",
Connection: "keep-alive"
}), i.flushHeaders(), i.write(`
`);
for (const line of data.split("\n")) {
res.write(`data:${line}
const a = e.subscribe(([u, c]) => {
d.debug("🕊️ sending to Spotlight"), i.write(`event:${u}
`);
}
res.write("\n");
});
req.on("close", () => {
buffer2.unsubscribe(sub);
res.end();
});
} else if (req.method === "POST") {
logger.debug(`📩 Received event`);
let body = "";
let stream = req;
const encoding = req.headers["content-encoding"];
if (encoding === "gzip") {
stream = req.pipe(createGunzip());
} else if (encoding === "deflate") {
stream = req.pipe(createInflate());
for (const l of c.split(`
`))
i.write(`data:${l}
`);
i.write(`
`);
});
o.on("close", () => {
e.unsubscribe(a), i.end();
});
} else if (o.method === "POST") {
d.debug("📩 Received event");
let a = "", u = o;
const c = o.headers["content-encoding"];
c === "gzip" ? u = o.pipe(q()) : c === "deflate" && (u = o.pipe(ee())), u.on("readable", () => {
let l;
for (; (l = u.read()) !== null; )
a += l;
}), u.on("end", () => {
var p, m;
let l = (p = o.headers["content-type"]) == null ? void 0 : p.split(";")[0].toLocaleLowerCase();
if ((m = s == null ? void 0 : s.get("sentry_client")) != null && m.startsWith("sentry.javascript.browser") && o.headers.origin && (l = "application/x-sentry-envelope"), l ? e.put([l, a]) : d.warn("No content type, skipping payload..."), process.env.SPOTLIGHT_CAPTURE || t) {
const g = (/* @__PURE__ */ new Date()).getTime(), w = `${(l == null ? void 0 : l.replace(/[^a-z0-9]/gi, "_")) || "no_content_type"}-${g}.txt`;
t ? t(a) : (X(w).write(a), d.info(`🗃️ Saved data to ${w}`));
}
stream.on("readable", () => {
let chunk;
while ((chunk = stream.read()) !== null) {
body += chunk;
}
});
stream.on("end", () => {
var _a, _b;
let contentType = (_a = req.headers["content-type"]) == null ? void 0 : _a.split(";")[0].toLocaleLowerCase();
if (((_b = searchParams == null ? void 0 : searchParams.get("sentry_client")) == null ? void 0 : _b.startsWith("sentry.javascript.browser")) && req.headers.origin) {
contentType = "application/x-sentry-envelope";
}
if (!contentType) {
logger.warn("No content type, skipping payload...");
} else {
buffer2.put([contentType, body]);
}
if (process.env.SPOTLIGHT_CAPTURE || incomingPayload) {
const timestamp = (/* @__PURE__ */ new Date()).getTime();
const filename = `${(contentType == null ? void 0 : contentType.replace(/[^a-z0-9]/gi, "_")) || "no_content_type"}-${timestamp}.txt`;
if (incomingPayload) {
incomingPayload(body);
} else {
createWriteStream(filename).write(body);
logger.info(`🗃️ Saved data to ${filename}`);
}
}
res.writeHead(200, {
"Cache-Control": "no-cache",
Connection: "keep-alive"
});
res.end();
});
} else {
error405(req, res);
return;
}
};
}
function fileServer(filesToServe) {
return function serveFile(req, res, pathname) {
let filePath = `${pathname || req.url}`;
if (filePath === "/") {
filePath = "/src/index.html";
}
filePath = filePath.slice(1);
const extName = extname(filePath);
let contentType = "text/html";
switch (extName) {
case ".js":
contentType = "text/javascript";
break;
case ".css":
contentType = "text/css";
break;
case ".json":
contentType = "application/json";
break;
}
if (!Object.prototype.hasOwnProperty.call(filesToServe, filePath)) {
error404(req, res);
} else {
res.writeHead(200, { "Content-Type": contentType });
res.end(filesToServe[filePath]);
}
};
}
function handleHealthRequest(_req, res) {
res.writeHead(200, {
"Content-Type": "text/plain",
...getCorsHeader(),
...getSpotlightHeader()
});
res.end("OK");
}
function handleClearRequest(req, res) {
if (req.method === "DELETE") {
res.writeHead(200, {
"Content-Type": "text/plain"
i.writeHead(200, {
"Cache-Control": "no-cache",
Connection: "keep-alive"
}), i.end();
});
clearBuffer();
res.end("Cleared");
} else {
error405(req, res);
j(o, i);
return;
}
}, me = (e) => function(n, o, i) {
let r = `${i || n.url}`;
r === "/" && (r = "/src/index.html"), r = r.slice(1);
const s = Z(r);
let a = "text/html";
switch (s) {
case ".js":
a = "text/javascript";
break;
case ".css":
a = "text/css";
break;
case ".json":
a = "application/json";
break;
}
Object.hasOwn(e, r) ? (o.writeHead(200, { "Content-Type": a }), o.end(e[r])) : y(n, o);
};
function ge(e, t) {
t.writeHead(200, {
"Content-Type": "text/plain",
...I,
...D
}), t.end("OK");
}
function openRequestHandler(basePath = process.cwd()) {
return (req, res) => {
if (req.method !== "POST") {
res.writeHead(405);
res.end();
function we(e, t) {
e.method === "DELETE" ? (t.writeHead(200, {
"Content-Type": "text/plain"
}), be(), t.end("Cleared")) : j(e, t);
}
function xe(e = process.cwd()) {
return (t, n) => {
if (t.method !== "POST") {
n.writeHead(405), n.end();
return;
}
let requestBody = "";
req.on("data", (chunk) => {
requestBody += chunk;
});
req.on("end", () => {
const targetPath = resolve(basePath, requestBody);
logger.debug(`Launching editor for ${targetPath}`);
launchEditor(
let o = "";
t.on("data", (i) => {
o += i;
}), t.on("end", () => {
const i = Q(e, o);
d.debug(`Launching editor for ${i}`), W(
// filename:line:column
// both line and column are optional
targetPath,
i,
// callback if failed to launch (optional)
(fileName, errorMsg) => {
logger.error(`Failed to launch editor for ${fileName}: ${errorMsg}`);
(r, s) => {
d.error(`Failed to launch editor for ${r}: ${s}`);
}
);
res.writeHead(204);
res.end();
), n.writeHead(204), n.end();
});
};
}
function errorResponse(code) {
return (_req, res) => {
res.writeHead(code);
res.end();
};
function k(e) {
return b(
(t, n) => {
n.writeHead(e), n.end();
},
{ name: `HTTP ${e}`, op: `sidecar.http.error.${e}`, attributes: { "http.response.status_code": e } }
);
}
const error404 = errorResponse(404);
const error405 = errorResponse(405);
function startServer(buffer2, port, basePath, filesToServe, incomingPayload) {
if (basePath && !filesToServe) {
filesToServe = {
"/src/index.html": readFileSync(join(basePath, "src/index.html")),
"/assets/main.js": readFileSync(join(basePath, "assets/main.js"))
};
}
const ROUTES = [
[/^\/health$/, handleHealthRequest],
[/^\/clear$/, enableCORS(handleClearRequest)],
[/^\/stream$|^\/api\/\d+\/envelope\/?$/, enableCORS(streamRequestHandler(buffer2, incomingPayload))],
[/^\/open$/, enableCORS(openRequestHandler(basePath))],
[RegExp(`^${CONTEXT_LINES_ENDPOINT}$`), enableCORS(contextLinesHandler)],
[/^.+$/, filesToServe != null ? enableCORS(fileServer(filesToServe)) : error404]
];
const server = createServer((req, res) => {
const url = req.url;
if (!url) {
return error404(req, res);
}
const { pathname, searchParams } = new URL(url, `http://${req.headers.host || "localhost"}`);
const route = ROUTES.find((route2) => route2[0].test(pathname));
if (!route) {
return error404(req, res);
}
return route[1](req, res, pathname, searchParams);
const y = k(404), j = k(405);
function Se(e, t, n, o, i) {
n && !o && (o = {
"/src/index.html": $(L(n, "src/index.html")),
"/assets/main.js": $(L(n, "assets/main.js"))
});
server.on("error", handleServerError);
server.listen(port, () => {
handleServerListen(port, basePath);
const r = [
[/^\/health$/, ge],
[/^\/clear$/, x(we)],
[/^\/stream$|^\/api\/\d+\/envelope\/?$/, x(fe(e, i))],
[/^\/open$/, x(xe(n))],
[RegExp(`^${te}$`), x(le)],
[/^.+$/, o != null ? x(me(o)) : y]
], s = K((c, l) => {
var R;
const p = c.url;
if (!p)
return y(c, l);
const m = c.headers.host || "localhost", { pathname: g, searchParams: w } = new URL(p, `http://${m}`), P = r.find((C) => C[0].test(g));
return P ? _(
{
name: `HTTP ${c.method} ${g}`,
op: `sidecar.http.${(R = c.method) == null ? void 0 : R.toLowerCase()}`,
forceTransaction: !0,
attributes: {
"http.request.method": c.method,
"http.request.url": p,
"http.request.query": w.toString(),
"server.address": m,
"server.port": c.socket.localPort
}
},
(C) => {
const H = V();
l.appendHeader(
"server-timing",
`sentryTrace;desc="${H["sentry-trace"]}", baggage;desc="${H.baggage}"`
);
const G = P[1](c, l, g, w);
return C.setAttribute("http.response.status_code", l.statusCode), G;
}
) : y(c, l);
});
return server;
function handleServerError(e) {
if ("code" in e && e.code === "EADDRINUSE") {
logger.info(`Port ${port} in use, retrying...`);
setTimeout(() => {
server.close();
server.listen(port);
logger.info(`Port ${port} in use, retrying...`);
}, 5e3);
}
return s.on("error", a), s.listen(t, () => {
u(t, n);
}), s;
function a(c) {
"code" in c && c.code === "EADDRINUSE" ? (d.info(`Port ${t} in use, retrying...`), setTimeout(() => {
s.close(), s.listen(t), d.info(`Port ${t} in use, retrying...`);
}, 5e3)) : J(c);
}
function handleServerListen(port2, basePath2) {
logger.info(`Sidecar listening on ${port2}`);
if (basePath2) {
logger.info(`You can open: http://localhost:${port2} to see the Spotlight overlay directly`);
}
function u(c, l) {
d.info(`Sidecar listening on ${c}`), l && d.info(`You can open: http://localhost:${c} to see the Spotlight overlay directly`);
}
}
let serverInstance;
const buffer = new MessageBuffer();
const isValidPort = (value) => {
if (typeof value === "string") {
const portNumber = Number(value);
return /^\d+$/.test(value) && portNumber > 0 && portNumber <= 65535;
}
return value > 0 && value <= 65535;
};
function isSidecarRunning(port) {
return new Promise((resolve2) => {
const options = {
let f;
const U = new he(), Te = b(
(e) => {
if (typeof e == "string") {
const t = Number(e);
return /^\d+$/.test(e) && t > 0 && t <= 65535;
}
return e > 0 && e <= 65535;
},
{ name: "isValidPort", op: "sidecar.server.portCheck" }
), ye = b(
(e) => new Promise((t) => {
const o = Y({
hostname: "localhost",
port,
port: e,
path: "/health",

@@ -479,71 +369,39 @@ method: "GET",

headers: { Connection: "close" }
};
const healthReq = get(options, (res) => {
const serverIdentifier = res.headers["x-powered-by"];
if (serverIdentifier === "spotlight-by-sentry") {
resolve2(true);
} else {
resolve2(false);
}
}, (i) => {
const r = i.headers["x-powered-by"];
t(r === "spotlight-by-sentry");
});
healthReq.on("error", () => {
resolve2(false);
});
healthReq.end();
});
}
function setupSidecar({
port,
logger: customLogger,
basePath,
filesToServe,
debug,
incomingPayload
o.on("error", () => {
t(!1);
}), o.end();
}),
{ name: "isSidecarRunning", op: "sidecar.server.collideCheck" }
);
function Oe({
port: e,
logger: t,
basePath: n,
filesToServe: o,
debug: i,
incomingPayload: r
} = {}) {
let sidecarPort = DEFAULT_PORT;
if (customLogger) {
activateLogger(customLogger);
}
if (debug || process.env.SPOTLIGHT_DEBUG) {
enableDebugLogging(true);
}
if (port && !isValidPort(port)) {
logger.info("Please provide a valid port.");
process.exit(1);
} else if (port) {
sidecarPort = typeof port === "string" ? Number(port) : port;
}
isSidecarRunning(sidecarPort).then((isRunning) => {
if (isRunning) {
logger.info(`Sidecar is already running on port ${sidecarPort}`);
} else {
if (!serverInstance) {
serverInstance = startServer(buffer, sidecarPort, basePath, filesToServe, incomingPayload);
}
}
let s = ne;
t && de(t), (i || process.env.SPOTLIGHT_DEBUG) && ue(!0), e && !Te(e) ? (d.info("Please provide a valid port."), process.exit(1)) : e && (s = typeof e == "string" ? Number(e) : e), ye(s).then((a) => {
a ? d.info(`Sidecar is already running on port ${s}`) : f || (f = Se(U, s, n, o, r));
});
}
function clearBuffer() {
buffer.clear();
function be() {
U.clear();
}
let forceShutdown = false;
function shutdown() {
if (forceShutdown || !serverInstance) {
logger.info("Bye.");
process.exit(0);
}
if (serverInstance) {
forceShutdown = true;
logger.info("Shutting down server gracefully...");
serverInstance.close();
serverInstance.closeAllConnections();
}
}
process.on("SIGINT", shutdown);
process.on("SIGTERM", shutdown);
let M = !1;
const F = () => {
(M || !f) && (d.info("Bye."), process.exit(0)), f && (M = !0, d.info("Shutting down server gracefully..."), f.close(), f.closeAllConnections());
};
process.on("SIGINT", F);
process.on("SIGTERM", F);
export {
clearBuffer,
setupSidecar,
shutdown
be as clearBuffer,
Oe as setupSidecar,
F as shutdown
};
//# sourceMappingURL=main.js.map
{
"name": "@spotlightjs/sidecar",
"description": "A small proxy server to capture and forward data from backend services to Spotlight.",
"version": "1.9.2",
"version": "1.9.3",
"license": "Apache-2.0",
"type": "module",
"files": [
"dist",
"src"
"dist"
],
"bin": {
"spotlight-sidecar": "./server.js"
"spotlight-sidecar": "dist/server.js"
},

@@ -23,3 +22,4 @@ "main": "dist/main.js",

"./vite-plugin": {
"import": "./src/vite-plugin.js"
"import": "./dist/vite-plugin.js",
"types": "./dist/vite-plugin.d.ts"
},

@@ -29,8 +29,6 @@ "./constants": {

"types": "./dist/constants.d.ts"
},
"./run": {
"import": "./src/run.js"
}
},
"dependencies": {
"@sentry/node": "^8.42.0",
"kleur": "^4.1.5",

@@ -37,0 +35,0 @@ "launch-editor": "^2.9.1",

Sorry, the diff of this file is not supported yet

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