@sentry/remix
Advanced tools
Comparing version 7.85.0 to 7.86.0
@@ -14,58 +14,27 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
function captureRemixErrorBoundaryError(error) { | ||
let eventId; | ||
const isClientSideRuntimeError = !utils.isNodeEnv() && error instanceof Error; | ||
// We only capture `ErrorResponse`s that are 5xx errors. | ||
const isRemixErrorResponse = response.isRouteErrorResponse(error) && error.status >= 500; | ||
// Server-side errors apart from `ErrorResponse`s also appear here without their stacktraces. | ||
// So, we only capture: | ||
// 1. `ErrorResponse`s | ||
// 2. Client-side runtime errors here, | ||
// And other server-side errors captured in `handleError` function where stacktraces are available. | ||
if (isRemixErrorResponse || isClientSideRuntimeError) { | ||
const eventData = isRemixErrorResponse | ||
? { | ||
function: 'ErrorResponse', | ||
...getErrorData(error), | ||
} | ||
: { | ||
function: 'ReactError', | ||
}; | ||
// Server-side errors also appear here without their stacktraces. | ||
// So, we only capture client-side runtime errors here. | ||
// ErrorResponses that are 5xx errors captured at loader / action level by `captureRemixRouteError` function, | ||
// And other server-side errors captured in `handleError` function where stacktraces are available. | ||
// | ||
// We don't want to capture: | ||
// - Response Errors / Objects [They are originated and handled on the server-side] | ||
// - SSR Errors [They are originated and handled on the server-side] | ||
// - Anything without a stacktrace [Remix trims the stacktrace of the errors that are thrown on the server-side] | ||
if (response.isResponse(error) || utils.isNodeEnv() || !(error instanceof Error)) { | ||
return; | ||
} | ||
const actualError = isRemixErrorResponse ? getExceptionToCapture(error) : error; | ||
eventId = core.captureException(actualError, { | ||
mechanism: { | ||
type: 'instrument', | ||
handled: false, | ||
data: eventData, | ||
return core.captureException(error, { | ||
mechanism: { | ||
type: 'instrument', | ||
handled: false, | ||
data: { | ||
function: 'ReactError', | ||
}, | ||
}); | ||
} | ||
return eventId; | ||
}, | ||
}); | ||
} | ||
function getErrorData(error) { | ||
if (utils.isString(error.data)) { | ||
return { | ||
error: error.data, | ||
}; | ||
} | ||
return error.data; | ||
} | ||
function getExceptionToCapture(error) { | ||
if (utils.isString(error.data)) { | ||
return error.data; | ||
} | ||
if (error.statusText) { | ||
return error.statusText; | ||
} | ||
return error; | ||
} | ||
exports.captureRemixErrorBoundaryError = captureRemixErrorBoundaryError; | ||
//# sourceMappingURL=errors.js.map |
@@ -80,2 +80,3 @@ Object.defineProperty(exports, '__esModule', { value: true }); | ||
exports.captureRemixServerException = instrumentServer.captureRemixServerException; | ||
exports.wrapRemixHandleError = instrumentServer.wrapRemixHandleError; | ||
exports.ErrorBoundary = react.ErrorBoundary; | ||
@@ -82,0 +83,0 @@ exports.withErrorBoundary = react.withErrorBoundary; |
@@ -47,2 +47,24 @@ var { | ||
/** | ||
* Sentry utility to be used in place of `handleError` function of Remix v2 | ||
* Remix Docs: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror | ||
* | ||
* Should be used in `entry.server` like: | ||
* | ||
* export const handleError = Sentry.wrapRemixHandleError | ||
*/ | ||
function wrapRemixHandleError(err, { request }) { | ||
// We are skipping thrown responses here as they are handled by | ||
// `captureRemixServerException` at loader / action level | ||
// We don't want to capture them twice. | ||
// This function if only for capturing unhandled server-side exceptions. | ||
// https://remix.run/docs/en/main/file-conventions/entry.server#thrown-responses | ||
// https://remix.run/docs/en/v1/api/conventions#throwing-responses-in-loaders | ||
if (response.isResponse(err) || response.isRouteErrorResponse(err)) { | ||
return; | ||
} | ||
void captureRemixServerException(err, 'remix.server.handleError', request); | ||
} | ||
/** | ||
* Captures an exception happened in the Remix server. | ||
@@ -84,3 +106,5 @@ * | ||
node.captureException(response.isResponse(err) ? await extractResponseError(err) : err, scope => { | ||
const objectifiedErr = utils.objectify(err); | ||
node.captureException(response.isResponse(objectifiedErr) ? await extractResponseError(objectifiedErr) : objectifiedErr, scope => { | ||
const activeTransactionName = _optionalChain([core.getActiveTransaction, 'call', _ => _(), 'optionalAccess', _2 => _2.name]); | ||
@@ -127,3 +151,2 @@ | ||
let res; | ||
const activeTransaction = core.getActiveTransaction(); | ||
@@ -153,3 +176,8 @@ | ||
} catch (err) { | ||
if (!_optionalChain([FUTURE_FLAGS, 'optionalAccess', _7 => _7.v2_errorBoundary]) && remixVersion !== 2) { | ||
const isRemixV1 = !_optionalChain([FUTURE_FLAGS, 'optionalAccess', _7 => _7.v2_errorBoundary]) && remixVersion !== 2; | ||
// This exists to capture the server-side rendering errors on Remix v1 | ||
// On Remix v2, we capture SSR errors at `handleError` | ||
// We also skip primitives here, as we can't dedupe them, and also we don't expect any primitive SSR errors. | ||
if (isRemixV1 && !utils.isPrimitive(err)) { | ||
await captureRemixServerException(err, 'documentRequest', request); | ||
@@ -197,3 +225,8 @@ } | ||
} catch (err) { | ||
if (!_optionalChain([FUTURE_FLAGS, 'optionalAccess', _12 => _12.v2_errorBoundary]) && remixVersion !== 2) { | ||
const isRemixV2 = _optionalChain([FUTURE_FLAGS, 'optionalAccess', _12 => _12.v2_errorBoundary]) || remixVersion === 2; | ||
// On Remix v2, we capture all unexpected errors (except the `Route Error Response`s / Thrown Responses) in `handleError` function. | ||
// This is both for consistency and also avoid duplicates such as primitives like `string` or `number` being captured twice. | ||
// Remix v1 does not have a `handleError` function, so we capture all errors here. | ||
if (isRemixV2 ? response.isResponse(err) : true) { | ||
await captureRemixServerException(err, name, args.request); | ||
@@ -221,3 +254,5 @@ } | ||
function getTraceAndBaggage() { | ||
function getTraceAndBaggage() | ||
{ | ||
const transaction = core.getActiveTransaction(); | ||
@@ -269,3 +304,7 @@ const currentScope = node.getCurrentHub().getScope(); | ||
{ ...data, ...traceAndBaggage, remixVersion }, | ||
{ headers: res.headers, statusText: res.statusText, status: res.status }, | ||
{ | ||
headers: res.headers, | ||
statusText: res.statusText, | ||
status: res.status, | ||
}, | ||
); | ||
@@ -477,4 +516,6 @@ } else { | ||
function instrumentServer() { | ||
const pkg = utils.loadModule('@remix-run/server-runtime'); | ||
const pkg = utils.loadModule | ||
('@remix-run/server-runtime'); | ||
if (!pkg) { | ||
@@ -495,2 +536,3 @@ debugBuild.DEBUG_BUILD && utils.logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); | ||
exports.startRequestHandlerTransaction = startRequestHandlerTransaction; | ||
exports.wrapRemixHandleError = wrapRemixHandleError; | ||
//# sourceMappingURL=instrumentServer.js.map |
import { captureException } from '@sentry/core'; | ||
import { isNodeEnv, isString } from '@sentry/utils'; | ||
import { isRouteErrorResponse } from '../utils/vendor/response.js'; | ||
import { isNodeEnv } from '@sentry/utils'; | ||
import { isResponse } from '../utils/vendor/response.js'; | ||
@@ -12,58 +12,27 @@ /** | ||
function captureRemixErrorBoundaryError(error) { | ||
let eventId; | ||
const isClientSideRuntimeError = !isNodeEnv() && error instanceof Error; | ||
// We only capture `ErrorResponse`s that are 5xx errors. | ||
const isRemixErrorResponse = isRouteErrorResponse(error) && error.status >= 500; | ||
// Server-side errors apart from `ErrorResponse`s also appear here without their stacktraces. | ||
// So, we only capture: | ||
// 1. `ErrorResponse`s | ||
// 2. Client-side runtime errors here, | ||
// And other server-side errors captured in `handleError` function where stacktraces are available. | ||
if (isRemixErrorResponse || isClientSideRuntimeError) { | ||
const eventData = isRemixErrorResponse | ||
? { | ||
function: 'ErrorResponse', | ||
...getErrorData(error), | ||
} | ||
: { | ||
function: 'ReactError', | ||
}; | ||
// Server-side errors also appear here without their stacktraces. | ||
// So, we only capture client-side runtime errors here. | ||
// ErrorResponses that are 5xx errors captured at loader / action level by `captureRemixRouteError` function, | ||
// And other server-side errors captured in `handleError` function where stacktraces are available. | ||
// | ||
// We don't want to capture: | ||
// - Response Errors / Objects [They are originated and handled on the server-side] | ||
// - SSR Errors [They are originated and handled on the server-side] | ||
// - Anything without a stacktrace [Remix trims the stacktrace of the errors that are thrown on the server-side] | ||
if (isResponse(error) || isNodeEnv() || !(error instanceof Error)) { | ||
return; | ||
} | ||
const actualError = isRemixErrorResponse ? getExceptionToCapture(error) : error; | ||
eventId = captureException(actualError, { | ||
mechanism: { | ||
type: 'instrument', | ||
handled: false, | ||
data: eventData, | ||
return captureException(error, { | ||
mechanism: { | ||
type: 'instrument', | ||
handled: false, | ||
data: { | ||
function: 'ReactError', | ||
}, | ||
}); | ||
} | ||
return eventId; | ||
}, | ||
}); | ||
} | ||
function getErrorData(error) { | ||
if (isString(error.data)) { | ||
return { | ||
error: error.data, | ||
}; | ||
} | ||
return error.data; | ||
} | ||
function getExceptionToCapture(error) { | ||
if (isString(error.data)) { | ||
return error.data; | ||
} | ||
if (error.statusText) { | ||
return error.statusText; | ||
} | ||
return error; | ||
} | ||
export { captureRemixErrorBoundaryError }; | ||
//# sourceMappingURL=errors.js.map |
@@ -7,3 +7,3 @@ import { init as init$1, configureScope, getCurrentHub } from '@sentry/node'; | ||
import { instrumentServer } from './utils/instrumentServer.js'; | ||
export { captureRemixServerException } from './utils/instrumentServer.js'; | ||
export { captureRemixServerException, wrapRemixHandleError } from './utils/instrumentServer.js'; | ||
import { buildMetadata } from './utils/metadata.js'; | ||
@@ -10,0 +10,0 @@ export { ErrorBoundary, withErrorBoundary } from '@sentry/react'; |
import { _optionalChain } from '@sentry/utils'; | ||
import { getActiveTransaction, hasTracingEnabled, runWithAsyncContext } from '@sentry/core'; | ||
import { captureException, getCurrentHub } from '@sentry/node'; | ||
import { logger, addExceptionMechanism, fill, loadModule, tracingContextFromHeaders, isNodeEnv, dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils'; | ||
import { logger, objectify, addExceptionMechanism, fill, loadModule, isPrimitive, tracingContextFromHeaders, isNodeEnv, dynamicSamplingContextToSentryBaggageHeader } from '@sentry/utils'; | ||
import { DEBUG_BUILD } from './debug-build.js'; | ||
import { getFutureFlagsServer, getRemixVersionFromBuild } from './futureFlags.js'; | ||
import { isResponse, extractData, isRouteErrorResponse, isDeferredData, json, matchServerRoutes, getRequestMatch } from './vendor/response.js'; | ||
import { isResponse, isRouteErrorResponse, extractData, isDeferredData, json, matchServerRoutes, getRequestMatch } from './vendor/response.js'; | ||
import { normalizeRemixRequest } from './web-fetch.js'; | ||
@@ -42,2 +42,24 @@ | ||
/** | ||
* Sentry utility to be used in place of `handleError` function of Remix v2 | ||
* Remix Docs: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror | ||
* | ||
* Should be used in `entry.server` like: | ||
* | ||
* export const handleError = Sentry.wrapRemixHandleError | ||
*/ | ||
function wrapRemixHandleError(err, { request }) { | ||
// We are skipping thrown responses here as they are handled by | ||
// `captureRemixServerException` at loader / action level | ||
// We don't want to capture them twice. | ||
// This function if only for capturing unhandled server-side exceptions. | ||
// https://remix.run/docs/en/main/file-conventions/entry.server#thrown-responses | ||
// https://remix.run/docs/en/v1/api/conventions#throwing-responses-in-loaders | ||
if (isResponse(err) || isRouteErrorResponse(err)) { | ||
return; | ||
} | ||
void captureRemixServerException(err, 'remix.server.handleError', request); | ||
} | ||
/** | ||
* Captures an exception happened in the Remix server. | ||
@@ -79,3 +101,5 @@ * | ||
captureException(isResponse(err) ? await extractResponseError(err) : err, scope => { | ||
const objectifiedErr = objectify(err); | ||
captureException(isResponse(objectifiedErr) ? await extractResponseError(objectifiedErr) : objectifiedErr, scope => { | ||
const activeTransactionName = _optionalChain([getActiveTransaction, 'call', _ => _(), 'optionalAccess', _2 => _2.name]); | ||
@@ -122,3 +146,2 @@ | ||
let res; | ||
const activeTransaction = getActiveTransaction(); | ||
@@ -148,3 +171,8 @@ | ||
} catch (err) { | ||
if (!_optionalChain([FUTURE_FLAGS, 'optionalAccess', _7 => _7.v2_errorBoundary]) && remixVersion !== 2) { | ||
const isRemixV1 = !_optionalChain([FUTURE_FLAGS, 'optionalAccess', _7 => _7.v2_errorBoundary]) && remixVersion !== 2; | ||
// This exists to capture the server-side rendering errors on Remix v1 | ||
// On Remix v2, we capture SSR errors at `handleError` | ||
// We also skip primitives here, as we can't dedupe them, and also we don't expect any primitive SSR errors. | ||
if (isRemixV1 && !isPrimitive(err)) { | ||
await captureRemixServerException(err, 'documentRequest', request); | ||
@@ -192,3 +220,8 @@ } | ||
} catch (err) { | ||
if (!_optionalChain([FUTURE_FLAGS, 'optionalAccess', _12 => _12.v2_errorBoundary]) && remixVersion !== 2) { | ||
const isRemixV2 = _optionalChain([FUTURE_FLAGS, 'optionalAccess', _12 => _12.v2_errorBoundary]) || remixVersion === 2; | ||
// On Remix v2, we capture all unexpected errors (except the `Route Error Response`s / Thrown Responses) in `handleError` function. | ||
// This is both for consistency and also avoid duplicates such as primitives like `string` or `number` being captured twice. | ||
// Remix v1 does not have a `handleError` function, so we capture all errors here. | ||
if (isRemixV2 ? isResponse(err) : true) { | ||
await captureRemixServerException(err, name, args.request); | ||
@@ -216,3 +249,5 @@ } | ||
function getTraceAndBaggage() { | ||
function getTraceAndBaggage() | ||
{ | ||
const transaction = getActiveTransaction(); | ||
@@ -264,3 +299,7 @@ const currentScope = getCurrentHub().getScope(); | ||
{ ...data, ...traceAndBaggage, remixVersion }, | ||
{ headers: res.headers, statusText: res.statusText, status: res.status }, | ||
{ | ||
headers: res.headers, | ||
statusText: res.statusText, | ||
status: res.status, | ||
}, | ||
); | ||
@@ -472,4 +511,6 @@ } else { | ||
function instrumentServer() { | ||
const pkg = loadModule('@remix-run/server-runtime'); | ||
const pkg = loadModule | ||
('@remix-run/server-runtime'); | ||
if (!pkg) { | ||
@@ -484,3 +525,3 @@ DEBUG_BUILD && logger.warn('Remix SDK was unable to require `@remix-run/server-runtime` package.'); | ||
export { captureRemixServerException, createRoutes, getTransactionName, instrumentBuild, instrumentServer, isRequestHandlerWrapped, startRequestHandlerTransaction }; | ||
export { captureRemixServerException, createRoutes, getTransactionName, instrumentBuild, instrumentServer, isRequestHandlerWrapped, startRequestHandlerTransaction, wrapRemixHandleError }; | ||
//# sourceMappingURL=instrumentServer.js.map |
{ | ||
"name": "@sentry/remix", | ||
"version": "7.85.0", | ||
"version": "7.86.0", | ||
"description": "Official Sentry SDK for Remix", | ||
@@ -30,8 +30,8 @@ "repository": "git://github.com/getsentry/sentry-javascript.git", | ||
"dependencies": { | ||
"@sentry/cli": "^2.21.2", | ||
"@sentry/core": "7.85.0", | ||
"@sentry/node": "7.85.0", | ||
"@sentry/react": "7.85.0", | ||
"@sentry/types": "7.85.0", | ||
"@sentry/utils": "7.85.0", | ||
"@sentry/cli": "^2.22.3", | ||
"@sentry/core": "7.86.0", | ||
"@sentry/node": "7.86.0", | ||
"@sentry/react": "7.86.0", | ||
"@sentry/types": "7.86.0", | ||
"@sentry/utils": "7.86.0", | ||
"glob": "^10.3.4", | ||
@@ -38,0 +38,0 @@ "yargs": "^17.6.0" |
import { RemixOptions } from './utils/remixOptions'; | ||
export { addGlobalEventProcessor, addEventProcessor, addBreadcrumb, captureCheckIn, withMonitor, captureException, captureEvent, captureMessage, configureScope, createTransport, extractTraceparentData, getActiveTransaction, getHubFromCarrier, getCurrentHub, Hub, makeMain, Scope, startTransaction, SDK_VERSION, setContext, setExtra, setExtras, setTag, setTags, setUser, spanStatusfromHttpCode, trace, withScope, autoDiscoverNodePerformanceMonitoringIntegrations, makeNodeTransport, defaultIntegrations, defaultStackParser, lastEventId, flush, close, getSentryRelease, addRequestDataToEvent, DEFAULT_USER_INCLUDES, extractRequestData, deepReadDirSync, Integrations, Handlers, } from '@sentry/node'; | ||
export * from '@sentry/node'; | ||
export { captureRemixServerException } from './utils/instrumentServer'; | ||
export { captureRemixServerException, wrapRemixHandleError } from './utils/instrumentServer'; | ||
export { ErrorBoundary, withErrorBoundary } from '@sentry/react'; | ||
@@ -6,0 +6,0 @@ export { remixRouterInstrumentation, withSentry } from './client/performance'; |
import { Hub } from '@sentry/node'; | ||
import { Transaction, TransactionSource } from '@sentry/types'; | ||
import { ReactRouterDomPkg, ServerBuild, ServerRoute, ServerRouteManifest } from './vendor/types'; | ||
import { DataFunctionArgs, ReactRouterDomPkg, ServerBuild, ServerRoute, ServerRouteManifest } from './vendor/types'; | ||
export declare let isRequestHandlerWrapped: boolean; | ||
/** | ||
* Sentry utility to be used in place of `handleError` function of Remix v2 | ||
* Remix Docs: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror | ||
* | ||
* Should be used in `entry.server` like: | ||
* | ||
* export const handleError = Sentry.wrapRemixHandleError | ||
*/ | ||
export declare function wrapRemixHandleError(err: unknown, { request }: DataFunctionArgs): void; | ||
/** | ||
* Captures an exception happened in the Remix server. | ||
@@ -7,0 +16,0 @@ * |
import type { RemixOptions } from './utils/remixOptions'; | ||
export { addGlobalEventProcessor, addEventProcessor, addBreadcrumb, captureCheckIn, withMonitor, captureException, captureEvent, captureMessage, configureScope, createTransport, extractTraceparentData, getActiveTransaction, getHubFromCarrier, getCurrentHub, Hub, makeMain, Scope, startTransaction, SDK_VERSION, setContext, setExtra, setExtras, setTag, setTags, setUser, spanStatusfromHttpCode, trace, withScope, autoDiscoverNodePerformanceMonitoringIntegrations, makeNodeTransport, defaultIntegrations, defaultStackParser, lastEventId, flush, close, getSentryRelease, addRequestDataToEvent, DEFAULT_USER_INCLUDES, extractRequestData, deepReadDirSync, Integrations, Handlers, } from '@sentry/node'; | ||
export * from '@sentry/node'; | ||
export { captureRemixServerException } from './utils/instrumentServer'; | ||
export { captureRemixServerException, wrapRemixHandleError } from './utils/instrumentServer'; | ||
export { ErrorBoundary, withErrorBoundary } from '@sentry/react'; | ||
@@ -6,0 +6,0 @@ export { remixRouterInstrumentation, withSentry } from './client/performance'; |
import type { Hub } from '@sentry/node'; | ||
import type { Transaction, TransactionSource } from '@sentry/types'; | ||
import type { ReactRouterDomPkg, ServerBuild, ServerRoute, ServerRouteManifest } from './vendor/types'; | ||
import type { DataFunctionArgs, ReactRouterDomPkg, ServerBuild, ServerRoute, ServerRouteManifest } from './vendor/types'; | ||
export declare let isRequestHandlerWrapped: boolean; | ||
/** | ||
* Sentry utility to be used in place of `handleError` function of Remix v2 | ||
* Remix Docs: https://remix.run/docs/en/main/file-conventions/entry.server#handleerror | ||
* | ||
* Should be used in `entry.server` like: | ||
* | ||
* export const handleError = Sentry.wrapRemixHandleError | ||
*/ | ||
export declare function wrapRemixHandleError(err: unknown, { request }: DataFunctionArgs): void; | ||
/** | ||
* Captures an exception happened in the Remix server. | ||
@@ -7,0 +16,0 @@ * |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
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
482967
3570
+ Added@sentry-internal/feedback@7.86.0(transitive)
+ Added@sentry-internal/tracing@7.86.0(transitive)
+ Added@sentry/browser@7.86.0(transitive)
+ Added@sentry/core@7.86.0(transitive)
+ Added@sentry/node@7.86.0(transitive)
+ Added@sentry/react@7.86.0(transitive)
+ Added@sentry/replay@7.86.0(transitive)
+ Added@sentry/types@7.86.0(transitive)
+ Added@sentry/utils@7.86.0(transitive)
- Removed@sentry-internal/feedback@7.85.0(transitive)
- Removed@sentry-internal/tracing@7.85.0(transitive)
- Removed@sentry/browser@7.85.0(transitive)
- Removed@sentry/core@7.85.0(transitive)
- Removed@sentry/node@7.85.0(transitive)
- Removed@sentry/react@7.85.0(transitive)
- Removed@sentry/replay@7.85.0(transitive)
- Removed@sentry/types@7.85.0(transitive)
- Removed@sentry/utils@7.85.0(transitive)
Updated@sentry/cli@^2.22.3
Updated@sentry/core@7.86.0
Updated@sentry/node@7.86.0
Updated@sentry/react@7.86.0
Updated@sentry/types@7.86.0
Updated@sentry/utils@7.86.0