@protobase/ui 0.12.4 → 0.12.6

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.
package/dist/app/app.js CHANGED
@@ -11,6 +11,7 @@ import { useRecord } from "../data/use-record.js";
11
11
  import { recordTitle } from "../live/model-helpers.js";
12
12
  import { humanize } from "../live/naming.js";
13
13
  import { ToastProvider } from "../toasts/toast-provider.js";
14
+ import { startErrorReporting } from "./error-reporting.js";
14
15
  import { useProjectUi } from "./pages/project-ui.js";
15
16
  import { AssistantButton, AssistantPanel } from "./assistant-shell.js";
16
17
  import { bottomBarFromMeta } from "./bottom-bar-from-meta.js";
@@ -101,6 +102,10 @@ const Routes = ({ workspace, sidebarMode, assistant, runtime }) => {
101
102
  page: params.size > 0 ? `${path}?${params}` : path,
102
103
  onClose: () => setAssistantOpen(false)
103
104
  });
105
+ const errorReporting = meta.errorReporting;
106
+ useEffect(() => {
107
+ if (errorReporting) startErrorReporting(errorReporting);
108
+ }, [errorReporting]);
104
109
  const runtimeUrl = meta.runtime?.url;
105
110
  const runtimeButton = runtimeUrl && /* @__PURE__ */ jsx(RuntimeUpdateButton, {
106
111
  url: runtimeUrl,
@@ -0,0 +1,25 @@
1
+ import { redactSecrets } from "@protobase/schema";
2
+ //#region src/app/error-reporting.ts
3
+ let loading;
4
+ let capture;
5
+ /**
6
+ * Sends the app's uncaught errors to the error tracker `/meta` names, from the first call on; the Sentry SDK loads only
7
+ * then, so an app without a DSN never loads it. Errors only, with no performance tracing and no session tracking,
8
+ * every event without its secrets (see `redactSecrets`).
9
+ */
10
+ const startErrorReporting = ({ dsn, environment }) => {
11
+ loading ??= import("@sentry/browser").then((sentry) => {
12
+ sentry.init({
13
+ dsn,
14
+ ...environment && { environment },
15
+ integrations: (defaults) => defaults.filter((integration) => integration.name !== "BrowserSession"),
16
+ beforeSend: (event) => redactSecrets(event)
17
+ });
18
+ capture = (error, componentStack) => sentry.captureException(error, componentStack ? { contexts: { react: { componentStack } } } : void 0);
19
+ });
20
+ return loading;
21
+ };
22
+ /** Reports an error a boundary caught while drawing, with the components it was drawn in; nothing before error reporting started. */
23
+ const reportRenderError = (error, componentStack) => capture?.(error, componentStack ?? void 0);
24
+ //#endregion
25
+ export { reportRenderError, startErrorReporting };
@@ -1,3 +1,4 @@
1
+ import { reportRenderError } from "../error-reporting.js";
1
2
  import { Problem } from "./problem.js";
2
3
  import { Component } from "react";
3
4
  import { jsxs } from "react/jsx-runtime";
@@ -8,6 +9,9 @@ var CustomBoundary = class extends Component {
8
9
  static getDerivedStateFromError() {
9
10
  return { failed: true };
10
11
  }
12
+ componentDidCatch(error, info) {
13
+ reportRenderError(error, info.componentStack);
14
+ }
11
15
  render() {
12
16
  if (!this.state.failed) return this.props.children;
13
17
  return this.props.fallback === void 0 ? /* @__PURE__ */ jsxs(Problem, { children: [this.props.name, " could not be drawn."] }) : this.props.fallback;
@@ -1,4 +1,5 @@
1
1
  import { ActionCard } from "../action-card/action-card.js";
2
+ import { reportRenderError } from "../app/error-reporting.js";
2
3
  import { useProjectUi } from "../app/pages/project-ui.js";
3
4
  import { Component } from "react";
4
5
  import { jsx } from "react/jsx-runtime";
@@ -20,6 +21,9 @@ var WidgetBoundary = class extends Component {
20
21
  static getDerivedStateFromError() {
21
22
  return { failed: true };
22
23
  }
24
+ componentDidCatch(error, info) {
25
+ reportRenderError(error, info.componentStack);
26
+ }
23
27
  render() {
24
28
  return this.state.failed ? /* @__PURE__ */ jsx(Fallback, {
25
29
  part: this.props.part,
@@ -20,6 +20,11 @@ export type MetaData = {
20
20
  runtime?: {
21
21
  url: string;
22
22
  };
23
+ /** The error tracker the app sends its errors to, when the app reports them (see `startErrorReporting`). */
24
+ errorReporting?: {
25
+ dsn: string;
26
+ environment?: string;
27
+ };
23
28
  /** The plugins the app loads for the user (see `PluginGate`). */
24
29
  plugins?: PluginRef[];
25
30
  /** The other APIs the app draws resources from for the user, and how far their `/meta` has loaded (see `withSources`). */
@@ -34,6 +34,7 @@ const useMeta = () => {
34
34
  ...result.meta.bottomBar && { bottomBar: result.meta.bottomBar },
35
35
  ...result.meta.assistant && { assistant: result.meta.assistant },
36
36
  ...result.meta.runtime && { runtime: result.meta.runtime },
37
+ ...result.meta.errorReporting && { errorReporting: result.meta.errorReporting },
37
38
  ...result.meta.plugins && { plugins: result.meta.plugins },
38
39
  ...result.meta.sources && { sources: result.meta.sources.map((source) => ({
39
40
  source,
package/dist/package.js CHANGED
@@ -1,5 +1,5 @@
1
1
  //#region package.json
2
- var version = "0.12.4";
2
+ var version = "0.12.6";
3
3
  var protobase = { "pluginApi": 1 };
4
4
  //#endregion
5
5
  export { protobase, version };