feat(web-tanstack): Sentry instrumentation via @sentry/node + @sentry/react + R38 PII test
Adds initSentryServerNode + initSentryClientReact to core-shared (Vite/non-Next variants of the existing init helpers — same R31/R32/R33 posture, R34/R35/R37 replay defaults). Extends no-sentry.ts to mock @sentry/node + @sentry/react. Wires the web-tanstack server/client instrumentation entry hooks and adds the R38 PII test. Spec deviation: web-tanstack has no vite.config.ts yet (placeholder app per its package.json). The @sentry/vite-plugin dep is added but unused until the TanStack Start build is wired in a later plan. A minimal src/vite-env.d.ts shims ImportMetaEnv for the client entry until the full Vite types land. @sentry/node and @sentry/react are added to core-shared as optional peerDependencies so feature packages don't transitively pull them in; they're also devDependencies of core-shared for typecheck/test runs. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -14,10 +14,13 @@
|
||||
"dependencies": {
|
||||
"@repo/blog": "workspace:*",
|
||||
"@repo/core-api": "workspace:*",
|
||||
"@repo/core-shared": "workspace:*",
|
||||
"@repo/core-trpc": "workspace:*",
|
||||
"@repo/core-ui": "workspace:*",
|
||||
"@repo/marketing-pages": "workspace:*",
|
||||
"@repo/navigation": "workspace:*",
|
||||
"@sentry/node": "^10.52.0",
|
||||
"@sentry/react": "^10.52.0",
|
||||
"@tanstack/react-query": "^5.66.0",
|
||||
"@tanstack/react-router": "^1.120.0",
|
||||
"react": "^19.0.0",
|
||||
@@ -28,6 +31,7 @@
|
||||
"@repo/core-eslint": "workspace:*",
|
||||
"@repo/core-testing": "workspace:*",
|
||||
"@repo/core-typescript": "workspace:*",
|
||||
"@sentry/vite-plugin": "^5.2.1",
|
||||
"@testing-library/jest-dom": "^6.5.0",
|
||||
"@testing-library/react": "^16.0.0",
|
||||
"@testing-library/user-event": "^14.5.0",
|
||||
|
||||
56
apps/web-tanstack/src/__tests__/sentry-pii-scrubber.test.ts
Normal file
56
apps/web-tanstack/src/__tests__/sentry-pii-scrubber.test.ts
Normal file
@@ -0,0 +1,56 @@
|
||||
import { describe, it, expect } from "vitest";
|
||||
import {
|
||||
beforeSend,
|
||||
beforeSendTransaction,
|
||||
} from "@repo/core-shared/instrumentation/sentry/scrub";
|
||||
|
||||
describe("R38 — apps/web-tanstack PII scrubber", () => {
|
||||
it("strips email/password/cookie/auth/IP from event payload", () => {
|
||||
const event = {
|
||||
extra: {
|
||||
userEmail: "alice@example.com",
|
||||
password: "p4$$w0rd",
|
||||
ipAddress: "192.168.1.10",
|
||||
note: "request from 10.0.0.1",
|
||||
},
|
||||
request: {
|
||||
headers: {
|
||||
Authorization: "Bearer secret",
|
||||
"Set-Cookie": "session=abc",
|
||||
"User-Agent": "Mozilla",
|
||||
},
|
||||
},
|
||||
} as Parameters<typeof beforeSend>[0];
|
||||
const result = beforeSend(event, {}) as {
|
||||
extra: Record<string, string>;
|
||||
request: { headers: Record<string, string> };
|
||||
};
|
||||
expect(result.extra["userEmail"]).toBe("[redacted]");
|
||||
expect(result.extra["password"]).toBe("[redacted]");
|
||||
expect(result.extra["ipAddress"]).toBe("[redacted]");
|
||||
expect(result.extra["note"]).toContain("[redacted-ip]");
|
||||
expect(result.request.headers["Authorization"]).toBe("[redacted]");
|
||||
expect(result.request.headers["Set-Cookie"]).toBe("[redacted]");
|
||||
expect(result.request.headers["User-Agent"]).toBe("Mozilla");
|
||||
});
|
||||
|
||||
it("strips ?token / ?email / ?password / ?secret / ?signature from URLs", () => {
|
||||
const event = {
|
||||
request: {
|
||||
url: "https://app/api/x?token=abc&email=a@b.c&password=p&secret=z&signature=s&safe=1",
|
||||
},
|
||||
transaction: "/foo?accessToken=t",
|
||||
} as Parameters<typeof beforeSendTransaction>[0];
|
||||
const result = beforeSendTransaction(event, {}) as {
|
||||
request: { url: string };
|
||||
transaction: string;
|
||||
};
|
||||
const url = decodeURIComponent(result.request.url);
|
||||
const txn = decodeURIComponent(result.transaction);
|
||||
for (const key of ["token", "email", "password", "secret", "signature"]) {
|
||||
expect(url).toContain(`${key}=[redacted]`);
|
||||
}
|
||||
expect(url).toContain("safe=1");
|
||||
expect(txn).toContain("accessToken=[redacted]");
|
||||
});
|
||||
});
|
||||
9
apps/web-tanstack/src/instrumentation-client.ts
Normal file
9
apps/web-tanstack/src/instrumentation-client.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// apps/web-tanstack/src/instrumentation-client.ts
|
||||
// Browser-entry hook. Imported at the top of the client entry file.
|
||||
import { initSentryClientReact } from "@repo/core-shared/instrumentation/sentry/init-client-react";
|
||||
|
||||
initSentryClientReact({
|
||||
dsn: import.meta.env["VITE_WEB_TANSTACK_SENTRY_DSN"],
|
||||
app: "web-tanstack",
|
||||
release: import.meta.env["VITE_GIT_COMMIT_SHA"],
|
||||
});
|
||||
9
apps/web-tanstack/src/instrumentation.ts
Normal file
9
apps/web-tanstack/src/instrumentation.ts
Normal file
@@ -0,0 +1,9 @@
|
||||
// apps/web-tanstack/src/instrumentation.ts
|
||||
// Server-entry hook. Imported at the top of the server entry file.
|
||||
import { initSentryServerNode } from "@repo/core-shared/instrumentation/sentry/init-server-node";
|
||||
|
||||
initSentryServerNode({
|
||||
dsn: process.env["WEB_TANSTACK_SENTRY_DSN"],
|
||||
app: "web-tanstack",
|
||||
release: process.env["VITE_GIT_COMMIT_SHA"],
|
||||
});
|
||||
11
apps/web-tanstack/src/vite-env.d.ts
vendored
Normal file
11
apps/web-tanstack/src/vite-env.d.ts
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
// Minimal Vite-style env typing for the instrumentation-client entry.
|
||||
// When the full TanStack Start / Vite build is wired in a later plan,
|
||||
// replace this with `/// <reference types="vite/client" />`.
|
||||
interface ImportMetaEnv {
|
||||
readonly VITE_WEB_TANSTACK_SENTRY_DSN?: string;
|
||||
readonly VITE_GIT_COMMIT_SHA?: string;
|
||||
}
|
||||
|
||||
interface ImportMeta {
|
||||
readonly env: ImportMetaEnv;
|
||||
}
|
||||
@@ -12,6 +12,8 @@
|
||||
"./instrumentation": "./src/instrumentation/index.ts",
|
||||
"./instrumentation/sentry/init-server": "./src/instrumentation/sentry/init-server.ts",
|
||||
"./instrumentation/sentry/init-client": "./src/instrumentation/sentry/init-client.ts",
|
||||
"./instrumentation/sentry/init-server-node": "./src/instrumentation/sentry/init-server-node.ts",
|
||||
"./instrumentation/sentry/init-client-react": "./src/instrumentation/sentry/init-client-react.ts",
|
||||
"./instrumentation/sentry/scrub": "./src/instrumentation/sentry/scrub.ts"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -27,10 +29,20 @@
|
||||
"superjson": "^2.2.1",
|
||||
"zod": "^3.24.0"
|
||||
},
|
||||
"peerDependencies": {
|
||||
"@sentry/node": "^10.51.0",
|
||||
"@sentry/react": "^10.51.0"
|
||||
},
|
||||
"peerDependenciesMeta": {
|
||||
"@sentry/node": { "optional": true },
|
||||
"@sentry/react": { "optional": true }
|
||||
},
|
||||
"devDependencies": {
|
||||
"@repo/core-eslint": "workspace:*",
|
||||
"@repo/core-testing": "workspace:*",
|
||||
"@repo/core-typescript": "workspace:*",
|
||||
"@sentry/node": "^10.51.0",
|
||||
"@sentry/react": "^10.51.0",
|
||||
"@types/node": "^22.0.0",
|
||||
"inversify": "^6.2.0",
|
||||
"reflect-metadata": "^0.2.2",
|
||||
|
||||
@@ -18,3 +18,5 @@ export {
|
||||
bindSentryInstrumentation,
|
||||
type BindSentryOpts,
|
||||
} from "./di/bind-sentry-instrumentation";
|
||||
export { initSentryServerNode } from "./sentry/init-server-node";
|
||||
export { initSentryClientReact } from "./sentry/init-client-react";
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
// packages/core-shared/src/instrumentation/sentry/init-client-react.test.ts
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
const { replayIntegration } = vi.hoisted(() => {
|
||||
const replayIntegration = vi.fn((opts: unknown) => ({ name: "Replay", _opts: opts }));
|
||||
return { replayIntegration };
|
||||
});
|
||||
|
||||
vi.mock("@sentry/react", () => ({
|
||||
init: vi.fn(),
|
||||
replayIntegration,
|
||||
}));
|
||||
|
||||
import * as SentryReact from "@sentry/react";
|
||||
import { initSentryClientReact } from "@/instrumentation/sentry/init-client-react";
|
||||
|
||||
describe("initSentryClientReact", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("calls SentryReact.init with sendDefaultPii: false (R31)", () => {
|
||||
initSentryClientReact({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryReact.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(call["sendDefaultPii"]).toBe(false);
|
||||
});
|
||||
|
||||
it("attaches replay integration with mask flags (R34, R35)", () => {
|
||||
initSentryClientReact({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
expect(replayIntegration).toHaveBeenCalledTimes(1);
|
||||
const replayOpts = (replayIntegration as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(replayOpts["maskAllText"]).toBe(true);
|
||||
expect(replayOpts["maskAllInputs"]).toBe(true);
|
||||
expect(replayOpts["blockAllMedia"]).toBe(true);
|
||||
});
|
||||
|
||||
it("defaults replay sample rates per R37", () => {
|
||||
initSentryClientReact({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryReact.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(call["replaysSessionSampleRate"]).toBe(0.0);
|
||||
expect(call["replaysOnErrorSampleRate"]).toBe(1.0);
|
||||
});
|
||||
|
||||
it("attaches beforeSend + beforeSendTransaction scrubbers", () => {
|
||||
initSentryClientReact({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryReact.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(typeof call["beforeSend"]).toBe("function");
|
||||
expect(typeof call["beforeSendTransaction"]).toBe("function");
|
||||
});
|
||||
|
||||
it("is a no-op when dsn is missing", () => {
|
||||
initSentryClientReact({ dsn: "", app: "web-tanstack" });
|
||||
expect(SentryReact.init).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,48 @@
|
||||
// packages/core-shared/src/instrumentation/sentry/init-client-react.ts
|
||||
import * as SentryReact from "@sentry/react";
|
||||
import { beforeSend, beforeSendTransaction } from "./scrub";
|
||||
import type { InitClientOpts } from "./init-client";
|
||||
|
||||
/**
|
||||
* Client-side init for non-Next.js (Vite/React) runtimes (TanStack Start).
|
||||
* Mirrors init-client.ts but uses @sentry/react directly. R31, R32, R33,
|
||||
* R34, R35, R37 still apply.
|
||||
*/
|
||||
export function initSentryClientReact(opts: InitClientOpts): void {
|
||||
if (!opts.dsn) return;
|
||||
|
||||
const isProd = process.env["NODE_ENV"] === "production";
|
||||
const tracesSampleRate =
|
||||
process.env["SENTRY_TRACES_SAMPLE_RATE"] !== undefined
|
||||
? Number(process.env["SENTRY_TRACES_SAMPLE_RATE"])
|
||||
: isProd
|
||||
? 0.1
|
||||
: 1.0;
|
||||
|
||||
const environment =
|
||||
process.env["SENTRY_ENVIRONMENT"] ?? process.env["NODE_ENV"] ?? "development";
|
||||
const release = opts.release ?? "unknown";
|
||||
|
||||
type InitOpts = Parameters<typeof SentryReact.init>[0];
|
||||
SentryReact.init({
|
||||
dsn: opts.dsn,
|
||||
environment,
|
||||
release,
|
||||
tracesSampleRate,
|
||||
sendDefaultPii: false, // R31
|
||||
beforeSend: beforeSend as unknown as NonNullable<InitOpts>["beforeSend"], // R32
|
||||
beforeSendTransaction:
|
||||
beforeSendTransaction as unknown as NonNullable<InitOpts>["beforeSendTransaction"], // R33
|
||||
replaysSessionSampleRate: 0.0, // R37
|
||||
replaysOnErrorSampleRate: 1.0, // R37
|
||||
integrations: [
|
||||
// R34, R35 — mandatory mask flags; allowlist starts empty
|
||||
SentryReact.replayIntegration({
|
||||
maskAllText: true,
|
||||
maskAllInputs: true,
|
||||
blockAllMedia: true,
|
||||
}),
|
||||
],
|
||||
initialScope: { tags: { app: opts.app } },
|
||||
});
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
// packages/core-shared/src/instrumentation/sentry/init-server-node.test.ts
|
||||
import { describe, it, expect, vi, beforeEach } from "vitest";
|
||||
|
||||
vi.mock("@sentry/node", () => ({
|
||||
init: vi.fn(),
|
||||
}));
|
||||
|
||||
import * as SentryNode from "@sentry/node";
|
||||
import { initSentryServerNode } from "@/instrumentation/sentry/init-server-node";
|
||||
|
||||
describe("initSentryServerNode", () => {
|
||||
beforeEach(() => {
|
||||
vi.clearAllMocks();
|
||||
});
|
||||
|
||||
it("calls SentryNode.init with sendDefaultPii: false (R31)", () => {
|
||||
initSentryServerNode({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryNode.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(call["sendDefaultPii"]).toBe(false);
|
||||
});
|
||||
|
||||
it("attaches beforeSend + beforeSendTransaction scrubbers", () => {
|
||||
initSentryServerNode({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryNode.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
expect(typeof call["beforeSend"]).toBe("function");
|
||||
expect(typeof call["beforeSendTransaction"]).toBe("function");
|
||||
});
|
||||
|
||||
it("tags events with the app name", () => {
|
||||
initSentryServerNode({ dsn: "https://x@y/1", app: "web-tanstack" });
|
||||
const call = (SentryNode.init as ReturnType<typeof vi.fn>).mock.calls[0]![0] as Record<
|
||||
string,
|
||||
unknown
|
||||
>;
|
||||
const initialScope = call["initialScope"] as { tags?: Record<string, string> };
|
||||
expect(initialScope?.tags?.["app"]).toBe("web-tanstack");
|
||||
});
|
||||
|
||||
it("is a no-op when dsn is missing", () => {
|
||||
initSentryServerNode({ dsn: "", app: "web-tanstack" });
|
||||
expect(SentryNode.init).not.toHaveBeenCalled();
|
||||
initSentryServerNode({ dsn: undefined as unknown as string, app: "web-tanstack" });
|
||||
expect(SentryNode.init).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,40 @@
|
||||
// packages/core-shared/src/instrumentation/sentry/init-server-node.ts
|
||||
import * as SentryNode from "@sentry/node";
|
||||
import { beforeSend, beforeSendTransaction } from "./scrub";
|
||||
import type { InitServerOpts } from "./init-server";
|
||||
|
||||
/**
|
||||
* Server-side init for non-Next.js runtimes (TanStack Start). Mirrors
|
||||
* init-server.ts but uses @sentry/node directly. R31, R32, R33 still apply.
|
||||
*/
|
||||
export function initSentryServerNode(opts: InitServerOpts): void {
|
||||
if (!opts.dsn) return;
|
||||
|
||||
const isProd = process.env["NODE_ENV"] === "production";
|
||||
const tracesSampleRate =
|
||||
process.env["SENTRY_TRACES_SAMPLE_RATE"] !== undefined
|
||||
? Number(process.env["SENTRY_TRACES_SAMPLE_RATE"])
|
||||
: isProd
|
||||
? 0.1
|
||||
: 1.0;
|
||||
|
||||
const environment =
|
||||
process.env["SENTRY_ENVIRONMENT"] ??
|
||||
process.env["VERCEL_ENV"] ??
|
||||
process.env["NODE_ENV"] ??
|
||||
"development";
|
||||
const release = opts.release ?? process.env["VITE_GIT_COMMIT_SHA"] ?? "unknown";
|
||||
|
||||
type InitOpts = Parameters<typeof SentryNode.init>[0];
|
||||
SentryNode.init({
|
||||
dsn: opts.dsn,
|
||||
environment,
|
||||
release,
|
||||
tracesSampleRate,
|
||||
sendDefaultPii: false, // R31
|
||||
beforeSend: beforeSend as unknown as NonNullable<InitOpts>["beforeSend"], // R32
|
||||
beforeSendTransaction:
|
||||
beforeSendTransaction as unknown as NonNullable<InitOpts>["beforeSendTransaction"], // R33
|
||||
initialScope: { tags: { app: opts.app } },
|
||||
});
|
||||
}
|
||||
@@ -27,3 +27,36 @@ vi.mock("@sentry/nextjs", () => ({
|
||||
getActiveSpan: vi.fn(() => undefined),
|
||||
getCurrentHub: vi.fn(() => ({ getClient: () => undefined })),
|
||||
}));
|
||||
|
||||
vi.mock("@sentry/node", () => ({
|
||||
init: vi.fn(),
|
||||
startSpan: vi.fn((_opts: unknown, fn: (span: unknown) => unknown) =>
|
||||
fn({ setAttribute: vi.fn(), setStatus: vi.fn() }),
|
||||
),
|
||||
captureException: vi.fn(),
|
||||
captureMessage: vi.fn(),
|
||||
addBreadcrumb: vi.fn(),
|
||||
setUser: vi.fn(),
|
||||
setContext: vi.fn(),
|
||||
setTag: vi.fn(),
|
||||
setExtra: vi.fn(),
|
||||
withScope: vi.fn((fn: (scope: unknown) => unknown) =>
|
||||
fn({ setTag: vi.fn(), setExtra: vi.fn() }),
|
||||
),
|
||||
getActiveSpan: vi.fn(() => undefined),
|
||||
}));
|
||||
|
||||
vi.mock("@sentry/react", () => ({
|
||||
init: vi.fn(),
|
||||
captureException: vi.fn(),
|
||||
captureMessage: vi.fn(),
|
||||
addBreadcrumb: vi.fn(),
|
||||
setUser: vi.fn(),
|
||||
setContext: vi.fn(),
|
||||
setTag: vi.fn(),
|
||||
setExtra: vi.fn(),
|
||||
withScope: vi.fn((fn: (scope: unknown) => unknown) =>
|
||||
fn({ setTag: vi.fn(), setExtra: vi.fn() }),
|
||||
),
|
||||
replayIntegration: vi.fn(() => ({ name: "Replay" })),
|
||||
}));
|
||||
|
||||
206
pnpm-lock.yaml
generated
206
pnpm-lock.yaml
generated
@@ -242,6 +242,9 @@ importers:
|
||||
'@repo/core-api':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core-api
|
||||
'@repo/core-shared':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core-shared
|
||||
'@repo/core-trpc':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core-trpc
|
||||
@@ -254,6 +257,12 @@ importers:
|
||||
'@repo/navigation':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/navigation
|
||||
'@sentry/node':
|
||||
specifier: ^10.52.0
|
||||
version: 10.52.0
|
||||
'@sentry/react':
|
||||
specifier: ^10.52.0
|
||||
version: 10.52.0(react@19.2.4)
|
||||
'@tanstack/react-query':
|
||||
specifier: ^5.66.0
|
||||
version: 5.96.2(react@19.2.4)
|
||||
@@ -279,6 +288,9 @@ importers:
|
||||
'@repo/core-typescript':
|
||||
specifier: workspace:*
|
||||
version: link:../../packages/core-typescript
|
||||
'@sentry/vite-plugin':
|
||||
specifier: ^5.2.1
|
||||
version: 5.2.1(rollup@4.60.1)
|
||||
'@testing-library/jest-dom':
|
||||
specifier: ^6.5.0
|
||||
version: 6.9.1
|
||||
@@ -521,6 +533,12 @@ importers:
|
||||
'@repo/core-typescript':
|
||||
specifier: workspace:*
|
||||
version: link:../core-typescript
|
||||
'@sentry/node':
|
||||
specifier: ^10.51.0
|
||||
version: 10.52.0
|
||||
'@sentry/react':
|
||||
specifier: ^10.51.0
|
||||
version: 10.52.0(react@19.2.4)
|
||||
'@types/node':
|
||||
specifier: ^22.0.0
|
||||
version: 22.19.17
|
||||
@@ -2749,18 +2767,34 @@ packages:
|
||||
resolution: {integrity: sha512-lNKBS4P7RUvf1niojXQWe9bU3gnBUCbST4Dj0pSiyat1N96cXVyHkeE+uGxowD0RrVWhs+kGHiVX3FcmRWF6sA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/browser-utils@10.52.0':
|
||||
resolution: {integrity: sha512-x/yEPZdpH6NGQeoeQnV9tj8reAH8twNttiltGZl2o8Rk7sQeUfe7E8yuYP2XbJ2RqyZK5qRS3COrNyMPzf6KFA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/feedback@10.51.0':
|
||||
resolution: {integrity: sha512-bCM95bcpphx28e6aU0bwRLxOgwosYsdNzezM1sM0pVOkb0TB3hDFRamramVDK+/Hp1o8qmRxS4c5w/A7YBZGkA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/feedback@10.52.0':
|
||||
resolution: {integrity: sha512-5kAn1W8ZvCuHtEHXpq6iRkUMdNCilwww+YxaN2yofVrCivAbB3Ha5JJUMqmWOPW0pC27zGYmoJMIDvG+PczUxA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay-canvas@10.51.0':
|
||||
resolution: {integrity: sha512-8PW1Pp+Yl3lPwYqhBCr5SgkuhDanu9ZLzUqD2bPKL/ElqbM2eDVIWxq4z4ZzePrmZa6IcCjTv6sVQJ7Z4dLyLA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay-canvas@10.52.0':
|
||||
resolution: {integrity: sha512-BI5ie4dxPuUJ344CXVSnAxY1xZCbghglPSCIlTOYODpR9so9yo5IZh+Mwspt0oWsUMaxWJiQSNYlbPWi7WDavg==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay@10.51.0':
|
||||
resolution: {integrity: sha512-jCpI5HXSwK6ZT2HX70+mDRciAocHzSiDk4DTgvzV69Wvd+Ei5WLgE+d39eaEPsm8lUC0Ydntb5sJIB6uG9D4bw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry-internal/replay@10.52.0':
|
||||
resolution: {integrity: sha512-diywyuc/H7VTUR+W5ryVmLF+0X4UP1OskMqb6V8RSAvJHcj2JmIm7uP+Fc6ACTno+b6AUShwT/L4xVXzO6X9Cw==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/babel-plugin-component-annotate@5.2.1':
|
||||
resolution: {integrity: sha512-QQ9AL5EXIbSK26ObLVtiU6l3tCUdpGSJ/6VwDkPhC3qvtoksSlcoU9Yzm7XC0NBcvu1N2abL5R7gckKGZ4JewQ==}
|
||||
engines: {node: '>= 18'}
|
||||
@@ -2769,6 +2803,10 @@ packages:
|
||||
resolution: {integrity: sha512-Zdc0sKfenxUtW/OGhtJ7xHFN44bXR7YqxJ1zBDzlZfW0nTbeTTUZBq9z5NUw6qdS0Vs/i3V4qzAKTbRKWfqSEA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/browser@10.52.0':
|
||||
resolution: {integrity: sha512-ijL9jN86oXwXQWbwhPlEb70ODJSEmjxQEQdnZkC4gDWbjswcwvRsVJPYk+1xl2ir2iZixRIHipVxDcLwian35g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/bundler-plugin-core@5.2.1':
|
||||
resolution: {integrity: sha512-uXb+TOZKXxm2STsP3iR70Jh/yYHwlHOvql7w/bUVYgDyiB/1Mv0D6oNGS0kelsgBsBwCq3ngyJYlyNy3oM1pPw==}
|
||||
engines: {node: '>= 18'}
|
||||
@@ -2829,6 +2867,10 @@ packages:
|
||||
resolution: {integrity: sha512-Y45V/YXvVLEXmOdkbD1oG1gkRWFi9guCEGg3PlIlIpRjAbZUrvLGgjRJIc1E7XpSzmOnWbs5BbUxMv4PDaPj2w==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/core@10.52.0':
|
||||
resolution: {integrity: sha512-VA/kAqLhkMnRWY2RXdBLyTemR9D4m7MVRy/gyapoq9yvllVPx9WXbvKgnMP2LQp7mFgT/oLFvw58aQKaYTGn3A==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/nextjs@10.51.0':
|
||||
resolution: {integrity: sha512-Bh3DeieTnbOOfhFEWbT57vgxlCdoTU7+x5or8QLa8VGCmZEekIdt0rGd8exbG1msI4g6SusCiJzbF/8bucmY/A==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2859,10 +2901,38 @@ packages:
|
||||
'@opentelemetry/semantic-conventions':
|
||||
optional: true
|
||||
|
||||
'@sentry/node-core@10.52.0':
|
||||
resolution: {integrity: sha512-IG7MBtLRPQ2LuU+kbD14AFZroZgAeUmJQTP1FI/F8n56O31+p+9R703LuBTpvZr6sm+eRYDMWcGYYkfLHRVjwg==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.9.0
|
||||
'@opentelemetry/core': ^1.30.1 || ^2.1.0
|
||||
'@opentelemetry/exporter-trace-otlp-http': '>=0.57.0 <1'
|
||||
'@opentelemetry/instrumentation': '>=0.57.1 <1'
|
||||
'@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
|
||||
'@opentelemetry/semantic-conventions': ^1.39.0
|
||||
peerDependenciesMeta:
|
||||
'@opentelemetry/api':
|
||||
optional: true
|
||||
'@opentelemetry/core':
|
||||
optional: true
|
||||
'@opentelemetry/exporter-trace-otlp-http':
|
||||
optional: true
|
||||
'@opentelemetry/instrumentation':
|
||||
optional: true
|
||||
'@opentelemetry/sdk-trace-base':
|
||||
optional: true
|
||||
'@opentelemetry/semantic-conventions':
|
||||
optional: true
|
||||
|
||||
'@sentry/node@10.51.0':
|
||||
resolution: {integrity: sha512-2yZLRZwS1dKG8/4eOTpGSo/gO/EgmT9aPj6lAzUkRa7bZCTTdW4BraaHU0leX5T94909Qfhbr3W5AVTfDOCKiQ==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/node@10.52.0':
|
||||
resolution: {integrity: sha512-9+p3KJUk3rHO1HOEZuSknP2RgKCJZONDm4HWgkVDtVBtocb66KLtVlMjc59d2/bWP7tM3wc877tpG30quFfU9g==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/opentelemetry@10.51.0':
|
||||
resolution: {integrity: sha512-Qc7AlCE4uhB+SvHLqah4RgR1WdY7wmmr/hx9g/prDP9R1ocshmUEMrZK9qjuwaklW7/fmkFCXI8ETxo5L1bHIA==}
|
||||
engines: {node: '>=18'}
|
||||
@@ -2872,16 +2942,44 @@ packages:
|
||||
'@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
|
||||
'@opentelemetry/semantic-conventions': ^1.39.0
|
||||
|
||||
'@sentry/opentelemetry@10.52.0':
|
||||
resolution: {integrity: sha512-Sc7StsvC0bwhMcgDfTRWUIexO5cNzzKUurvUwtpgQUnxO7AzexU3lkY3yHYDsCbWYAEQMXAgQYQtbcqoh+Ie7g==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
'@opentelemetry/api': ^1.9.0
|
||||
'@opentelemetry/core': ^1.30.1 || ^2.1.0
|
||||
'@opentelemetry/sdk-trace-base': ^1.30.1 || ^2.1.0
|
||||
'@opentelemetry/semantic-conventions': ^1.39.0
|
||||
|
||||
'@sentry/react@10.51.0':
|
||||
resolution: {integrity: sha512-RRHHqjNvjji6ebIqdlAr453AkST8Vm4cxdu1vWm772IgbzTO7Jx46Cj6Bt2/GjMyH0YLE5euDaAOQhFMmpvAOw==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
react: ^16.14.0 || 17.x || 18.x || 19.x
|
||||
|
||||
'@sentry/react@10.52.0':
|
||||
resolution: {integrity: sha512-2m72QCsja2cJJHD0ALxRnVt0qMEC2FV4LSi6AAiEdEG4lTb6mgcxavx5pJrW90jE+6dMGPbUz4q8c9vi4jh1qQ==}
|
||||
engines: {node: '>=18'}
|
||||
peerDependencies:
|
||||
react: ^16.14.0 || 17.x || 18.x || 19.x
|
||||
|
||||
'@sentry/rollup-plugin@5.2.1':
|
||||
resolution: {integrity: sha512-LKJyL4fzcHnHExipVN0/QinhBNoGZt+UXg8xJaqc6MwOolOhxHW0ii2hu1OZsiOhX0+r9MK7T+a7Sx0F0bzdMQ==}
|
||||
engines: {node: '>= 18'}
|
||||
peerDependencies:
|
||||
rollup: '>=3.2.0'
|
||||
peerDependenciesMeta:
|
||||
rollup:
|
||||
optional: true
|
||||
|
||||
'@sentry/vercel-edge@10.51.0':
|
||||
resolution: {integrity: sha512-tADUhv+S3gtAj/hSAih6FcYTRZQma+brI4dY6bue2RwgWQvaQoP5CF/PsTb4RhK82etPhqphsdJivY09/L7vWA==}
|
||||
engines: {node: '>=18'}
|
||||
|
||||
'@sentry/vite-plugin@5.2.1':
|
||||
resolution: {integrity: sha512-sSQzOhN8xvo/R70vqgyonnC/fwXpJ1kbkJ0g81Xy/OR+N89+v5tPN4VlKTAq3T2c5yAPE39XCbdgeEnI4kbWGg==}
|
||||
engines: {node: '>= 18'}
|
||||
|
||||
'@sentry/webpack-plugin@5.2.1':
|
||||
resolution: {integrity: sha512-ZGxwCkszFHdk9N11XIbAyTTsJsGUKHMYEXMRLUwPLi+iKi+b+YuXLBg7rlxe6Nd3M0i7xWy3gz6jcW7jeqEfIw==}
|
||||
engines: {node: '>= 18'}
|
||||
@@ -9364,20 +9462,38 @@ snapshots:
|
||||
dependencies:
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry-internal/browser-utils@10.52.0':
|
||||
dependencies:
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry-internal/feedback@10.51.0':
|
||||
dependencies:
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry-internal/feedback@10.52.0':
|
||||
dependencies:
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry-internal/replay-canvas@10.51.0':
|
||||
dependencies:
|
||||
'@sentry-internal/replay': 10.51.0
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry-internal/replay-canvas@10.52.0':
|
||||
dependencies:
|
||||
'@sentry-internal/replay': 10.52.0
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry-internal/replay@10.51.0':
|
||||
dependencies:
|
||||
'@sentry-internal/browser-utils': 10.51.0
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry-internal/replay@10.52.0':
|
||||
dependencies:
|
||||
'@sentry-internal/browser-utils': 10.52.0
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry/babel-plugin-component-annotate@5.2.1': {}
|
||||
|
||||
'@sentry/browser@10.51.0':
|
||||
@@ -9388,6 +9504,14 @@ snapshots:
|
||||
'@sentry-internal/replay-canvas': 10.51.0
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry/browser@10.52.0':
|
||||
dependencies:
|
||||
'@sentry-internal/browser-utils': 10.52.0
|
||||
'@sentry-internal/feedback': 10.52.0
|
||||
'@sentry-internal/replay': 10.52.0
|
||||
'@sentry-internal/replay-canvas': 10.52.0
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry/bundler-plugin-core@5.2.1':
|
||||
dependencies:
|
||||
'@babel/core': 7.29.0
|
||||
@@ -9447,6 +9571,8 @@ snapshots:
|
||||
|
||||
'@sentry/core@10.51.0': {}
|
||||
|
||||
'@sentry/core@10.52.0': {}
|
||||
|
||||
'@sentry/nextjs@10.51.0(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(next@15.5.14(@opentelemetry/api@1.9.1)(@playwright/test@1.59.1)(react-dom@19.2.4(react@19.2.4))(react@19.2.4)(sass@1.99.0))(react@19.2.4)(webpack@5.106.2)':
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
@@ -9509,6 +9635,18 @@ snapshots:
|
||||
'@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
|
||||
'@sentry/node-core@10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)':
|
||||
dependencies:
|
||||
'@sentry/core': 10.52.0
|
||||
'@sentry/opentelemetry': 10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)
|
||||
import-in-the-middle: 3.0.1
|
||||
optionalDependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
|
||||
'@sentry/node@10.51.0':
|
||||
dependencies:
|
||||
'@fastify/otel': 0.18.0(@opentelemetry/api@1.9.1)
|
||||
@@ -9546,6 +9684,41 @@ snapshots:
|
||||
- '@opentelemetry/exporter-trace-otlp-http'
|
||||
- supports-color
|
||||
|
||||
'@sentry/node@10.52.0':
|
||||
dependencies:
|
||||
'@fastify/otel': 0.18.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation': 0.214.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-amqplib': 0.61.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-connect': 0.57.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-dataloader': 0.31.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-fs': 0.33.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-generic-pool': 0.57.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-graphql': 0.62.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-hapi': 0.60.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-http': 0.214.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-kafkajs': 0.23.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-knex': 0.58.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-koa': 0.62.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-lru-memoizer': 0.58.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-mongodb': 0.67.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-mongoose': 0.60.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-mysql': 0.60.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-mysql2': 0.60.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-pg': 0.66.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/instrumentation-tedious': 0.33.0(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
'@prisma/instrumentation': 7.6.0(@opentelemetry/api@1.9.1)
|
||||
'@sentry/core': 10.52.0
|
||||
'@sentry/node-core': 10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/instrumentation@0.214.0(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)
|
||||
'@sentry/opentelemetry': 10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)
|
||||
import-in-the-middle: 3.0.1
|
||||
transitivePeerDependencies:
|
||||
- '@opentelemetry/exporter-trace-otlp-http'
|
||||
- supports-color
|
||||
|
||||
'@sentry/opentelemetry@10.51.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)':
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
@@ -9554,18 +9727,51 @@ snapshots:
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry/opentelemetry@10.52.0(@opentelemetry/api@1.9.1)(@opentelemetry/core@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/sdk-trace-base@2.7.1(@opentelemetry/api@1.9.1))(@opentelemetry/semantic-conventions@1.40.0)':
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@opentelemetry/core': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/sdk-trace-base': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@opentelemetry/semantic-conventions': 1.40.0
|
||||
'@sentry/core': 10.52.0
|
||||
|
||||
'@sentry/react@10.51.0(react@19.2.4)':
|
||||
dependencies:
|
||||
'@sentry/browser': 10.51.0
|
||||
'@sentry/core': 10.51.0
|
||||
react: 19.2.4
|
||||
|
||||
'@sentry/react@10.52.0(react@19.2.4)':
|
||||
dependencies:
|
||||
'@sentry/browser': 10.52.0
|
||||
'@sentry/core': 10.52.0
|
||||
react: 19.2.4
|
||||
|
||||
'@sentry/rollup-plugin@5.2.1(rollup@4.60.1)':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 5.2.1
|
||||
magic-string: 0.30.21
|
||||
optionalDependencies:
|
||||
rollup: 4.60.1
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- supports-color
|
||||
|
||||
'@sentry/vercel-edge@10.51.0':
|
||||
dependencies:
|
||||
'@opentelemetry/api': 1.9.1
|
||||
'@opentelemetry/resources': 2.7.1(@opentelemetry/api@1.9.1)
|
||||
'@sentry/core': 10.51.0
|
||||
|
||||
'@sentry/vite-plugin@5.2.1(rollup@4.60.1)':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 5.2.1
|
||||
'@sentry/rollup-plugin': 5.2.1(rollup@4.60.1)
|
||||
transitivePeerDependencies:
|
||||
- encoding
|
||||
- rollup
|
||||
- supports-color
|
||||
|
||||
'@sentry/webpack-plugin@5.2.1(webpack@5.106.2)':
|
||||
dependencies:
|
||||
'@sentry/bundler-plugin-core': 5.2.1
|
||||
|
||||
Reference in New Issue
Block a user