better-ship 0.33.0 → 0.34.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -11,6 +11,27 @@ export type SentryClientOptions = Sentry.BrowserOptions & {
11
11
  export declare function createSentryClientOptions(options: SentryClientOptions): Sentry.BrowserOptions;
12
12
  /** Forward logged browser errors once, excluding TanStack navigation control flow. */
13
13
  export declare function createSentryLoggerErrorHook(): LoggerErrorHook;
14
+ /** The error value as Sentry's React handler receives it. */
15
+ type ReactRootError = Parameters<ReturnType<typeof Sentry.reactErrorHandler>>[0];
16
+ /** The details React passes to a root error option; React may omit the component stack. */
17
+ export type ReactRootErrorInfo = {
18
+ readonly componentStack?: string | undefined;
19
+ };
20
+ /** A `hydrateRoot` error option in React's own shape. */
21
+ type ReactRootErrorHandler = (error: ReactRootError, errorInfo: ReactRootErrorInfo) => void;
22
+ /** The `hydrateRoot` error options; each one replaces React's console default. */
23
+ export type SentryReactRootOptions = {
24
+ readonly onCaughtError: ReactRootErrorHandler;
25
+ readonly onUncaughtError: ReactRootErrorHandler;
26
+ readonly onRecoverableError: ReactRootErrorHandler;
27
+ };
28
+ /**
29
+ * Report React errors to Sentry from `hydrateRoot`, as Sentry's React 19 setup does.
30
+ * Covers errors that a boundary catches, errors that no boundary catches, and hydration
31
+ * errors that React recovers from. TanStack redirects and not-found control flow are not
32
+ * reported. Each error still goes to the console, as with React's defaults.
33
+ */
34
+ export declare function createSentryReactRootOptions(): SentryReactRootOptions;
14
35
  /** Initialize once in the browser entrypoint before hydration; server imports have no side effects. */
15
36
  export declare function initializeSentry(options: SentryClientOptions): ReturnType<typeof Sentry.init>;
16
37
  /** Attach tracing once after creating the browser router, as Porte does in getRouter. */
@@ -1 +1 @@
1
- {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/infrastructure/sentry/client.ts"],"mappings":";;;;YAMY,sBAAsB,OAAO;WAC9B;WACA;WACA;;;wBAIK,0BAA0B,SAAS,sBAAsB,OAAO;;wBAWhE,+BAA+B;;wBAY/B,iBAAiB,SAAS,sBAAsB,kBAAkB,OAAO;;wBAOzE,uBACd,QAAQ,kBAAkB,OAAO;;qBAOtB,sBAAsB,OAAO"}
1
+ {"version":3,"file":"client.d.ts","names":[],"sources":["../../src/infrastructure/sentry/client.ts"],"mappings":";;;;YAMY,sBAAsB,OAAO;WAC9B;WACA;WACA;;;wBAIK,0BAA0B,SAAS,sBAAsB,OAAO;;wBAWhE,+BAA+B;;KAY1C,iBAAiB,WAAW,kBAAkB,OAAO;;YAG9C;WAAgC;;;KAGvC,yBAAyB,OAAO,gBAAgB,WAAW;;YAGpD;WACD,eAAe;WACf,iBAAiB;WACjB,oBAAoB;;;;;;;;wBASf,gCAAgC;;wBAoBhC,iBAAiB,SAAS,sBAAsB,kBAAkB,OAAO;;wBAOzE,uBACd,QAAQ,kBAAkB,OAAO;;qBAOtB,sBAAsB,OAAO"}
@@ -24,6 +24,28 @@ function createSentryLoggerErrorHook() {
24
24
  Sentry.captureException(error, { extra: attributes });
25
25
  };
26
26
  }
27
+ /**
28
+ * Report React errors to Sentry from `hydrateRoot`, as Sentry's React 19 setup does.
29
+ * Covers errors that a boundary catches, errors that no boundary catches, and hydration
30
+ * errors that React recovers from. TanStack redirects and not-found control flow are not
31
+ * reported. Each error still goes to the console, as with React's defaults.
32
+ */
33
+ function createSentryReactRootOptions() {
34
+ const handler = Sentry.reactErrorHandler((error, errorInfo) => {
35
+ console.error(error, errorInfo.componentStack);
36
+ });
37
+ const report = (error, { componentStack }) => {
38
+ handler(error, { componentStack: componentStack ?? null });
39
+ };
40
+ return {
41
+ onCaughtError: (error, errorInfo) => {
42
+ if (isNotFound(error) || isRedirect(error)) return;
43
+ report(error, errorInfo);
44
+ },
45
+ onUncaughtError: report,
46
+ onRecoverableError: report
47
+ };
48
+ }
27
49
  /** Initialize once in the browser entrypoint before hydration; server imports have no side effects. */
28
50
  function initializeSentry(options) {
29
51
  const client = Sentry.init(createSentryClientOptions(options));
@@ -39,5 +61,5 @@ function instrumentSentryRouter(router) {
39
61
  const ErrorBoundary = Sentry.ErrorBoundary;
40
62
 
41
63
  //#endregion
42
- export { ErrorBoundary, Sentry, createSentryClientOptions, createSentryLoggerErrorHook, initializeSentry, instrumentSentryRouter };
64
+ export { ErrorBoundary, Sentry, createSentryClientOptions, createSentryLoggerErrorHook, createSentryReactRootOptions, initializeSentry, instrumentSentryRouter };
43
65
  //# sourceMappingURL=client.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"client.js","names":[],"sources":["../../src/infrastructure/sentry/client.ts"],"sourcesContent":["import * as Sentry from '@sentry/tanstackstart-react'\nimport { isNotFound, isRedirect } from '@tanstack/react-router'\n\nimport { setLoggerErrorHook, type LoggerErrorHook } from '@/core'\n\n/** Application settings use Sentry's names; enablement and environment belong to the application. */\nexport type SentryClientOptions = Sentry.BrowserOptions & {\n readonly dsn: string\n readonly environment: string\n readonly enabled: boolean\n}\n\n/** Filter known DOM errors and use SDK collection defaults; application options take precedence. */\nexport function createSentryClientOptions(options: SentryClientOptions): Sentry.BrowserOptions {\n return {\n ignoreErrors: [\n /^NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node\\.$/,\n /^NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node\\.$/,\n ],\n ...options,\n }\n}\n\n/** Forward logged browser errors once, excluding TanStack navigation control flow. */\nexport function createSentryLoggerErrorHook(): LoggerErrorHook {\n return ({ error, userId, attributes }) => {\n if (isNotFound(error) || isRedirect(error)) return\n if (userId !== undefined) {\n Sentry.captureException(error, { extra: attributes, user: { id: userId } })\n return\n }\n Sentry.captureException(error, { extra: attributes })\n }\n}\n\n/** Initialize once in the browser entrypoint before hydration; server imports have no side effects. */\nexport function initializeSentry(options: SentryClientOptions): ReturnType<typeof Sentry.init> {\n const client = Sentry.init(createSentryClientOptions(options))\n setLoggerErrorHook(createSentryLoggerErrorHook())\n return client\n}\n\n/** Attach tracing once after creating the browser router, as Porte does in getRouter. */\nexport function instrumentSentryRouter(\n router: Parameters<typeof Sentry.tanstackRouterBrowserTracingIntegration>[0],\n): void {\n if (router.isServer) return\n Sentry.addIntegration(Sentry.tanstackRouterBrowserTracingIntegration(router))\n}\n\n/** The SDK error boundary; the application supplies its fallback component. */\nexport const ErrorBoundary: typeof Sentry.ErrorBoundary = Sentry.ErrorBoundary\n\nexport { Sentry }\n"],"mappings":";;;;;;AAaA,SAAgB,0BAA0B,SAAqD;CAC7F,OAAO;EACL,cAAc,CACZ,oHACA,iJACF;EACA,GAAG;CACL;AACF;;AAGA,SAAgB,8BAA+C;CAC7D,QAAQ,EAAE,OAAO,QAAQ,iBAAiB;EACxC,IAAI,WAAW,KAAK,KAAK,WAAW,KAAK,GAAG;EAC5C,IAAI,WAAW,QAAW;GACxB,OAAO,iBAAiB,OAAO;IAAE,OAAO;IAAY,MAAM,EAAE,IAAI,OAAO;GAAE,CAAC;GAC1E;EACF;EACA,OAAO,iBAAiB,OAAO,EAAE,OAAO,WAAW,CAAC;CACtD;AACF;;AAGA,SAAgB,iBAAiB,SAA8D;CAC7F,MAAM,SAAS,OAAO,KAAK,0BAA0B,OAAO,CAAC;CAC7D,mBAAmB,4BAA4B,CAAC;CAChD,OAAO;AACT;;AAGA,SAAgB,uBACd,QACM;CACN,IAAI,OAAO,UAAU;CACrB,OAAO,eAAe,OAAO,wCAAwC,MAAM,CAAC;AAC9E;;AAGA,MAAa,gBAA6C,OAAO"}
1
+ {"version":3,"file":"client.js","names":[],"sources":["../../src/infrastructure/sentry/client.ts"],"sourcesContent":["import * as Sentry from '@sentry/tanstackstart-react'\nimport { isNotFound, isRedirect } from '@tanstack/react-router'\n\nimport { setLoggerErrorHook, type LoggerErrorHook } from '@/core'\n\n/** Application settings use Sentry's names; enablement and environment belong to the application. */\nexport type SentryClientOptions = Sentry.BrowserOptions & {\n readonly dsn: string\n readonly environment: string\n readonly enabled: boolean\n}\n\n/** Filter known DOM errors and use SDK collection defaults; application options take precedence. */\nexport function createSentryClientOptions(options: SentryClientOptions): Sentry.BrowserOptions {\n return {\n ignoreErrors: [\n /^NotFoundError: Failed to execute 'removeChild' on 'Node': The node to be removed is not a child of this node\\.$/,\n /^NotFoundError: Failed to execute 'insertBefore' on 'Node': The node before which the new node is to be inserted is not a child of this node\\.$/,\n ],\n ...options,\n }\n}\n\n/** Forward logged browser errors once, excluding TanStack navigation control flow. */\nexport function createSentryLoggerErrorHook(): LoggerErrorHook {\n return ({ error, userId, attributes }) => {\n if (isNotFound(error) || isRedirect(error)) return\n if (userId !== undefined) {\n Sentry.captureException(error, { extra: attributes, user: { id: userId } })\n return\n }\n Sentry.captureException(error, { extra: attributes })\n }\n}\n\n/** The error value as Sentry's React handler receives it. */\ntype ReactRootError = Parameters<ReturnType<typeof Sentry.reactErrorHandler>>[0]\n\n/** The details React passes to a root error option; React may omit the component stack. */\nexport type ReactRootErrorInfo = { readonly componentStack?: string | undefined }\n\n/** A `hydrateRoot` error option in React's own shape. */\ntype ReactRootErrorHandler = (error: ReactRootError, errorInfo: ReactRootErrorInfo) => void\n\n/** The `hydrateRoot` error options; each one replaces React's console default. */\nexport type SentryReactRootOptions = {\n readonly onCaughtError: ReactRootErrorHandler\n readonly onUncaughtError: ReactRootErrorHandler\n readonly onRecoverableError: ReactRootErrorHandler\n}\n\n/**\n * Report React errors to Sentry from `hydrateRoot`, as Sentry's React 19 setup does.\n * Covers errors that a boundary catches, errors that no boundary catches, and hydration\n * errors that React recovers from. TanStack redirects and not-found control flow are not\n * reported. Each error still goes to the console, as with React's defaults.\n */\nexport function createSentryReactRootOptions(): SentryReactRootOptions {\n const handler = Sentry.reactErrorHandler((error, errorInfo) => {\n console.error(error, errorInfo.componentStack)\n })\n // Sentry's handler takes `null` for a missing component stack.\n const report: ReactRootErrorHandler = (error, { componentStack }) => {\n handler(error, { componentStack: componentStack ?? null })\n }\n return {\n // TanStack Router renders not-found through a React error boundary, so each 404 arrives here.\n onCaughtError: (error, errorInfo) => {\n if (isNotFound(error) || isRedirect(error)) return\n report(error, errorInfo)\n },\n onUncaughtError: report,\n onRecoverableError: report,\n }\n}\n\n/** Initialize once in the browser entrypoint before hydration; server imports have no side effects. */\nexport function initializeSentry(options: SentryClientOptions): ReturnType<typeof Sentry.init> {\n const client = Sentry.init(createSentryClientOptions(options))\n setLoggerErrorHook(createSentryLoggerErrorHook())\n return client\n}\n\n/** Attach tracing once after creating the browser router, as Porte does in getRouter. */\nexport function instrumentSentryRouter(\n router: Parameters<typeof Sentry.tanstackRouterBrowserTracingIntegration>[0],\n): void {\n if (router.isServer) return\n Sentry.addIntegration(Sentry.tanstackRouterBrowserTracingIntegration(router))\n}\n\n/** The SDK error boundary; the application supplies its fallback component. */\nexport const ErrorBoundary: typeof Sentry.ErrorBoundary = Sentry.ErrorBoundary\n\nexport { Sentry }\n"],"mappings":";;;;;;AAaA,SAAgB,0BAA0B,SAAqD;CAC7F,OAAO;EACL,cAAc,CACZ,oHACA,iJACF;EACA,GAAG;CACL;AACF;;AAGA,SAAgB,8BAA+C;CAC7D,QAAQ,EAAE,OAAO,QAAQ,iBAAiB;EACxC,IAAI,WAAW,KAAK,KAAK,WAAW,KAAK,GAAG;EAC5C,IAAI,WAAW,QAAW;GACxB,OAAO,iBAAiB,OAAO;IAAE,OAAO;IAAY,MAAM,EAAE,IAAI,OAAO;GAAE,CAAC;GAC1E;EACF;EACA,OAAO,iBAAiB,OAAO,EAAE,OAAO,WAAW,CAAC;CACtD;AACF;;;;;;;AAwBA,SAAgB,+BAAuD;CACrE,MAAM,UAAU,OAAO,mBAAmB,OAAO,cAAc;EAC7D,QAAQ,MAAM,OAAO,UAAU,cAAc;CAC/C,CAAC;CAED,MAAM,UAAiC,OAAO,EAAE,qBAAqB;EACnE,QAAQ,OAAO,EAAE,gBAAgB,kBAAkB,KAAK,CAAC;CAC3D;CACA,OAAO;EAEL,gBAAgB,OAAO,cAAc;GACnC,IAAI,WAAW,KAAK,KAAK,WAAW,KAAK,GAAG;GAC5C,OAAO,OAAO,SAAS;EACzB;EACA,iBAAiB;EACjB,oBAAoB;CACtB;AACF;;AAGA,SAAgB,iBAAiB,SAA8D;CAC7F,MAAM,SAAS,OAAO,KAAK,0BAA0B,OAAO,CAAC;CAC7D,mBAAmB,4BAA4B,CAAC;CAChD,OAAO;AACT;;AAGA,SAAgB,uBACd,QACM;CACN,IAAI,OAAO,UAAU;CACrB,OAAO,eAAe,OAAO,wCAAwC,MAAM,CAAC;AAC9E;;AAGA,MAAa,gBAA6C,OAAO"}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://www.schemastore.org/package.json",
3
3
  "name": "better-ship",
4
- "version": "0.33.0",
4
+ "version": "0.34.0",
5
5
  "description": "Foundation for applications on Cloudflare Workers: logger, errors, message bus, infrastructure adapters, and UI primitives",
6
6
  "license": "Apache-2.0",
7
7
  "repository": {
@@ -33,6 +33,47 @@ export function createSentryLoggerErrorHook(): LoggerErrorHook {
33
33
  }
34
34
  }
35
35
 
36
+ /** The error value as Sentry's React handler receives it. */
37
+ type ReactRootError = Parameters<ReturnType<typeof Sentry.reactErrorHandler>>[0]
38
+
39
+ /** The details React passes to a root error option; React may omit the component stack. */
40
+ export type ReactRootErrorInfo = { readonly componentStack?: string | undefined }
41
+
42
+ /** A `hydrateRoot` error option in React's own shape. */
43
+ type ReactRootErrorHandler = (error: ReactRootError, errorInfo: ReactRootErrorInfo) => void
44
+
45
+ /** The `hydrateRoot` error options; each one replaces React's console default. */
46
+ export type SentryReactRootOptions = {
47
+ readonly onCaughtError: ReactRootErrorHandler
48
+ readonly onUncaughtError: ReactRootErrorHandler
49
+ readonly onRecoverableError: ReactRootErrorHandler
50
+ }
51
+
52
+ /**
53
+ * Report React errors to Sentry from `hydrateRoot`, as Sentry's React 19 setup does.
54
+ * Covers errors that a boundary catches, errors that no boundary catches, and hydration
55
+ * errors that React recovers from. TanStack redirects and not-found control flow are not
56
+ * reported. Each error still goes to the console, as with React's defaults.
57
+ */
58
+ export function createSentryReactRootOptions(): SentryReactRootOptions {
59
+ const handler = Sentry.reactErrorHandler((error, errorInfo) => {
60
+ console.error(error, errorInfo.componentStack)
61
+ })
62
+ // Sentry's handler takes `null` for a missing component stack.
63
+ const report: ReactRootErrorHandler = (error, { componentStack }) => {
64
+ handler(error, { componentStack: componentStack ?? null })
65
+ }
66
+ return {
67
+ // TanStack Router renders not-found through a React error boundary, so each 404 arrives here.
68
+ onCaughtError: (error, errorInfo) => {
69
+ if (isNotFound(error) || isRedirect(error)) return
70
+ report(error, errorInfo)
71
+ },
72
+ onUncaughtError: report,
73
+ onRecoverableError: report,
74
+ }
75
+ }
76
+
36
77
  /** Initialize once in the browser entrypoint before hydration; server imports have no side effects. */
37
78
  export function initializeSentry(options: SentryClientOptions): ReturnType<typeof Sentry.init> {
38
79
  const client = Sentry.init(createSentryClientOptions(options))