@djangocfg/layouts 2.1.457 → 2.1.459
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/README.md +1 -1
- package/package.json +16 -18
- package/src/components/errors/ErrorsTracker/index.ts +1 -1
- package/src/components/errors/ErrorsTracker/providers/ErrorTrackingProvider.tsx +2 -2
- package/src/components/errors/ErrorsTracker/utils/formatters.ts +4 -4
- package/src/components/errors/MonitorBoundary.tsx +5 -5
- package/src/components/errors/README.md +2 -2
- package/src/layouts/AppLayout/BaseApp.tsx +9 -20
- package/src/layouts/types/index.ts +1 -1
- package/src/layouts/types/layout.types.ts +11 -15
- package/src/snippets/index.ts +3 -3
package/README.md
CHANGED
|
@@ -136,7 +136,7 @@ When `routing` is set, `BaseApp` mounts a locale-aware `<Link>` adapter so every
|
|
|
136
136
|
|
|
137
137
|
### `MonitorBoundary`
|
|
138
138
|
|
|
139
|
-
Error boundary that automatically reports caught errors to `@djangocfg/
|
|
139
|
+
Error boundary that automatically reports caught errors to `@djangocfg/devtools`. Use at page/layout level so unexpected render errors land in your backend dashboard.
|
|
140
140
|
|
|
141
141
|
```tsx
|
|
142
142
|
import { MonitorBoundary } from '@djangocfg/layouts';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/layouts",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.459",
|
|
4
4
|
"description": "Simple, straightforward layout components for Next.js - import and use with props",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"layouts",
|
|
@@ -89,12 +89,10 @@
|
|
|
89
89
|
"check": "tsc --noEmit"
|
|
90
90
|
},
|
|
91
91
|
"peerDependencies": {
|
|
92
|
-
"@djangocfg/api": "^2.1.
|
|
93
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
94
|
-
"@djangocfg/
|
|
95
|
-
"@djangocfg/
|
|
96
|
-
"@djangocfg/monitor": "^2.1.457",
|
|
97
|
-
"@djangocfg/ui-core": "^2.1.457",
|
|
92
|
+
"@djangocfg/api": "^2.1.459",
|
|
93
|
+
"@djangocfg/centrifugo": "^2.1.459",
|
|
94
|
+
"@djangocfg/i18n": "^2.1.459",
|
|
95
|
+
"@djangocfg/ui-core": "^2.1.459",
|
|
98
96
|
"@hookform/resolvers": "^5.2.2",
|
|
99
97
|
"consola": "^3.4.2",
|
|
100
98
|
"lucide-react": "^0.545.0",
|
|
@@ -110,10 +108,11 @@
|
|
|
110
108
|
"tailwindcss": "^4.1.18",
|
|
111
109
|
"tailwindcss-animate": "^1.0.7",
|
|
112
110
|
"zod": "^4.3.6",
|
|
113
|
-
"zustand": "^5.0.0"
|
|
111
|
+
"zustand": "^5.0.0",
|
|
112
|
+
"@djangocfg/devtools": "^2.1.459"
|
|
114
113
|
},
|
|
115
114
|
"peerDependenciesMeta": {
|
|
116
|
-
"@djangocfg/
|
|
115
|
+
"@djangocfg/devtools": {
|
|
117
116
|
"optional": true
|
|
118
117
|
}
|
|
119
118
|
},
|
|
@@ -125,21 +124,20 @@
|
|
|
125
124
|
"uuid": "^11.1.0"
|
|
126
125
|
},
|
|
127
126
|
"devDependencies": {
|
|
128
|
-
"@djangocfg/api": "^2.1.
|
|
129
|
-
"@djangocfg/centrifugo": "^2.1.
|
|
130
|
-
"@djangocfg/
|
|
131
|
-
"@djangocfg/
|
|
132
|
-
"@djangocfg/
|
|
133
|
-
"@djangocfg/
|
|
134
|
-
"@djangocfg/ui-core": "^2.1.457",
|
|
135
|
-
"@djangocfg/ui-tools": "^2.1.457",
|
|
127
|
+
"@djangocfg/api": "^2.1.459",
|
|
128
|
+
"@djangocfg/centrifugo": "^2.1.459",
|
|
129
|
+
"@djangocfg/i18n": "^2.1.459",
|
|
130
|
+
"@djangocfg/typescript-config": "^2.1.459",
|
|
131
|
+
"@djangocfg/ui-core": "^2.1.459",
|
|
132
|
+
"@djangocfg/ui-tools": "^2.1.459",
|
|
136
133
|
"@types/node": "^25.2.3",
|
|
137
134
|
"@types/react": "^19.2.15",
|
|
138
135
|
"@types/react-dom": "^19.2.3",
|
|
139
136
|
"eslint": "^9.37.0",
|
|
140
137
|
"next-intl": "^4.9.1",
|
|
141
138
|
"typescript": "^5.9.3",
|
|
142
|
-
"zustand": "^5.0.9"
|
|
139
|
+
"zustand": "^5.0.9",
|
|
140
|
+
"@djangocfg/devtools": "^2.1.459"
|
|
143
141
|
},
|
|
144
142
|
"publishConfig": {
|
|
145
143
|
"access": "public"
|
|
@@ -31,7 +31,7 @@ import React, {
|
|
|
31
31
|
} from 'react';
|
|
32
32
|
|
|
33
33
|
import { toast } from '@djangocfg/ui-core/hooks';
|
|
34
|
-
import { useDebugMode, isProduction } from '@djangocfg/
|
|
34
|
+
import { useDebugMode, isProduction } from '@djangocfg/devtools';
|
|
35
35
|
|
|
36
36
|
import { createErrorToast } from '../components/ErrorToast';
|
|
37
37
|
import { generateShortErrorId, getProductionToast } from '../utils/formatters';
|
|
@@ -171,7 +171,7 @@ export interface ErrorTrackingProviderProps {
|
|
|
171
171
|
centrifugo?: Partial<CentrifugoErrorConfig>;
|
|
172
172
|
runtime?: Partial<RuntimeErrorConfig>;
|
|
173
173
|
onError?: (error: ErrorDetail) => boolean | void;
|
|
174
|
-
/** Called with the raw ErrorDetail for every tracked error. Wire to
|
|
174
|
+
/** Called with the raw ErrorDetail for every tracked error. Wire to devtools.capture() (via errorDetailToDevtoolsEvent) to forward errors to the backend. */
|
|
175
175
|
onMonitorCapture?: (detail: ErrorDetail) => void;
|
|
176
176
|
}
|
|
177
177
|
|
|
@@ -6,8 +6,8 @@
|
|
|
6
6
|
|
|
7
7
|
import type { ZodError } from 'zod';
|
|
8
8
|
import type { ValidationErrorDetail, CORSErrorDetail, NetworkErrorDetail, CentrifugoErrorDetail, RuntimeErrorDetail, ErrorDetail } from '../types';
|
|
9
|
-
import type {
|
|
10
|
-
import { EventType, EventLevel } from '@djangocfg/
|
|
9
|
+
import type { DevtoolsEvent } from '@djangocfg/devtools';
|
|
10
|
+
import { EventType, EventLevel } from '@djangocfg/devtools';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Safely read Zod issues. The error toast must never crash itself, so we
|
|
@@ -148,10 +148,10 @@ export function formatRuntimeErrorForClipboard(detail: RuntimeErrorDetail): stri
|
|
|
148
148
|
}
|
|
149
149
|
|
|
150
150
|
/**
|
|
151
|
-
* Convert ErrorDetail to
|
|
151
|
+
* Convert ErrorDetail to DevtoolsEvent for forwarding to the backend ingest.
|
|
152
152
|
* Use via ErrorTrackingProvider.onMonitorCapture.
|
|
153
153
|
*/
|
|
154
|
-
export function
|
|
154
|
+
export function errorDetailToDevtoolsEvent(detail: ErrorDetail): DevtoolsEvent {
|
|
155
155
|
const url = typeof window !== 'undefined' ? window.location.href : ''
|
|
156
156
|
switch (detail.type) {
|
|
157
157
|
case 'validation':
|
|
@@ -5,12 +5,12 @@ import type {
|
|
|
5
5
|
BoundaryProps,
|
|
6
6
|
BoundaryResetDetails,
|
|
7
7
|
} from '@djangocfg/ui-core/components';
|
|
8
|
-
import { EventLevel, EventType,
|
|
8
|
+
import { EventLevel, EventType, devtools } from '@djangocfg/devtools';
|
|
9
9
|
import { useCallback } from 'react';
|
|
10
10
|
import type { ErrorInfo, ReactNode } from 'react';
|
|
11
11
|
|
|
12
12
|
export interface MonitorBoundaryProps extends Omit<BoundaryProps, 'onError' | 'onReset'> {
|
|
13
|
-
/** Forwarded to
|
|
13
|
+
/** Forwarded to devtools as `extra.source` so you can filter events by boundary. */
|
|
14
14
|
name?: string;
|
|
15
15
|
/** Additional render-error handler called alongside the monitor capture. */
|
|
16
16
|
onError?: (error: Error, info: ErrorInfo) => void;
|
|
@@ -27,7 +27,7 @@ function currentUrl(): string | undefined {
|
|
|
27
27
|
|
|
28
28
|
function reportError(name: string | undefined, error: Error, info: ErrorInfo): void {
|
|
29
29
|
try {
|
|
30
|
-
|
|
30
|
+
devtools.capture({
|
|
31
31
|
event_type: EventType.ERROR,
|
|
32
32
|
level: EventLevel.ERROR,
|
|
33
33
|
message: error.message || 'Unhandled React render error',
|
|
@@ -45,7 +45,7 @@ function reportError(name: string | undefined, error: Error, info: ErrorInfo): v
|
|
|
45
45
|
|
|
46
46
|
function reportReset(name: string | undefined, details: BoundaryResetDetails): void {
|
|
47
47
|
try {
|
|
48
|
-
|
|
48
|
+
devtools.capture({
|
|
49
49
|
event_type: EventType.ERROR,
|
|
50
50
|
level: EventLevel.INFO,
|
|
51
51
|
message: `Boundary recovered (${details.reason})`,
|
|
@@ -61,7 +61,7 @@ function reportReset(name: string | undefined, details: BoundaryResetDetails): v
|
|
|
61
61
|
}
|
|
62
62
|
|
|
63
63
|
/**
|
|
64
|
-
* `Boundary` + automatic reporting to `@djangocfg/
|
|
64
|
+
* `Boundary` + automatic reporting to `@djangocfg/devtools`.
|
|
65
65
|
*
|
|
66
66
|
* Use at page/layout level so unexpected render errors are captured in your backend.
|
|
67
67
|
* For widgets you don't want to report (chat, embeds), use `Boundary` from ui-core directly.
|
|
@@ -12,7 +12,7 @@ All boundaries here build on the single `Boundary` primitive in
|
|
|
12
12
|
| File | What it does |
|
|
13
13
|
|------|--------------|
|
|
14
14
|
| `ErrorBoundary.tsx` | Thin wrapper over ui-core `Boundary` — i18n fallback + support email (for direct use; `BaseApp` no longer wraps it). |
|
|
15
|
-
| `MonitorBoundary.tsx` | ui-core `Boundary` that also reports to `@djangocfg/
|
|
15
|
+
| `MonitorBoundary.tsx` | ui-core `Boundary` that also reports to `@djangocfg/devtools`. |
|
|
16
16
|
| `ErrorLayout.tsx` | Full-page error layout (`getErrorContent` / `ERROR_CODES`). |
|
|
17
17
|
| `ErrorsTracker/` | Global runtime tracker — listens for error CustomEvents and shows toasts. |
|
|
18
18
|
|
|
@@ -63,5 +63,5 @@ internal proof wording (gated by `isDev`).
|
|
|
63
63
|
|
|
64
64
|
- Env/feature flags come from the single source of truth: `isDev` from
|
|
65
65
|
`@djangocfg/ui-core/lib`, `dpopEnabled` from `@djangocfg/api`.
|
|
66
|
-
- Errors also flow to `@djangocfg/
|
|
66
|
+
- Errors also flow to `@djangocfg/devtools` (backend ingest + debug panel) for
|
|
67
67
|
inspection regardless of toast visibility.
|
|
@@ -47,8 +47,8 @@ import { nodeEnv } from "@djangocfg/ui-core/lib";
|
|
|
47
47
|
import NextTopLoader from 'nextjs-toploader';
|
|
48
48
|
import { SWRConfig } from 'swr';
|
|
49
49
|
|
|
50
|
-
import {
|
|
51
|
-
import {
|
|
50
|
+
import { Devtools, devtools } from '@djangocfg/devtools';
|
|
51
|
+
import { errorDetailToDevtoolsEvent } from '../../components/errors/ErrorsTracker';
|
|
52
52
|
import { CfgCentrifugo } from '@djangocfg/api';
|
|
53
53
|
import { AuthProvider } from '@djangocfg/api/auth';
|
|
54
54
|
import { CentrifugoProvider } from '@djangocfg/centrifugo';
|
|
@@ -67,9 +67,6 @@ import type { BaseLayoutProps } from '../types/layout.types';
|
|
|
67
67
|
import { LayoutI18nProvider } from './LayoutI18nProvider';
|
|
68
68
|
|
|
69
69
|
import React from 'react';
|
|
70
|
-
const DebugButton = React.lazy(() =>
|
|
71
|
-
import('@djangocfg/debuger').then((m) => ({ default: m.DebugButton }))
|
|
72
|
-
);
|
|
73
70
|
|
|
74
71
|
// For backwards compatibility, re-export as BaseAppProps
|
|
75
72
|
export type BaseAppProps = BaseLayoutProps;
|
|
@@ -136,8 +133,7 @@ export function BaseApp({
|
|
|
136
133
|
errorTracking,
|
|
137
134
|
errorBoundary,
|
|
138
135
|
swr,
|
|
139
|
-
|
|
140
|
-
debug,
|
|
136
|
+
devtools: devtoolsConfig,
|
|
141
137
|
i18n,
|
|
142
138
|
}: BaseAppProps) {
|
|
143
139
|
// auth=false disables AuthProvider entirely (public apps with no login)
|
|
@@ -151,15 +147,12 @@ export function BaseApp({
|
|
|
151
147
|
const centrifugoUrl = centrifugo?.url || process.env.NEXT_PUBLIC_CENTRIFUGO_URL;
|
|
152
148
|
const centrifugoEnabled = centrifugo?.enabled !== false;
|
|
153
149
|
|
|
154
|
-
//
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
// Monitor — project prop as default, override with monitor config
|
|
159
|
-
const monitorConfig = {
|
|
150
|
+
// Devtools — capture + ingest + debug panel in one component.
|
|
151
|
+
// Project prop is the default; the devtools prop overrides field by field.
|
|
152
|
+
const devtoolsProps = {
|
|
160
153
|
project,
|
|
161
154
|
environment: nodeEnv,
|
|
162
|
-
...
|
|
155
|
+
...devtoolsConfig,
|
|
163
156
|
};
|
|
164
157
|
|
|
165
158
|
const content = (
|
|
@@ -215,9 +208,9 @@ export function BaseApp({
|
|
|
215
208
|
cors={errorTracking?.cors}
|
|
216
209
|
network={errorTracking?.network}
|
|
217
210
|
onError={errorTracking?.onError}
|
|
218
|
-
onMonitorCapture={(d) =>
|
|
211
|
+
onMonitorCapture={(d) => devtools.capture(errorDetailToDevtoolsEvent(d))}
|
|
219
212
|
>
|
|
220
|
-
<
|
|
213
|
+
<Devtools {...devtoolsProps} />
|
|
221
214
|
<LayoutI18nProvider value={i18n}>
|
|
222
215
|
{i18n?.routing ? (
|
|
223
216
|
<NextIntlLinkBridge routing={i18n.routing}>{children}</NextIntlLinkBridge>
|
|
@@ -234,10 +227,6 @@ export function BaseApp({
|
|
|
234
227
|
|
|
235
228
|
{/* Auth Dialog - only when auth is enabled */}
|
|
236
229
|
{authEnabled && <AuthDialog authPath={authConfig?.routes?.auth} />}
|
|
237
|
-
|
|
238
|
-
{/* Debug Panel — auto in dev, ?debug=1 in prod, disable with debug={{ enabled: false }} */}
|
|
239
|
-
{/* eslint-disable-next-line @typescript-eslint/no-explicit-any */}
|
|
240
|
-
<DebugButton enabled={debugEnabled} {...(debugProps as any)} />
|
|
241
230
|
</ErrorTrackingProvider>
|
|
242
231
|
</CentrifugoProvider>
|
|
243
232
|
</AnalyticsProvider>
|
|
@@ -22,7 +22,7 @@ export type NextIntlRouting = object & { __nextIntlRouting?: never };
|
|
|
22
22
|
|
|
23
23
|
// Import local provider configs
|
|
24
24
|
import type { ThemeConfig, SWRConfigOptions, CentrifugoConfig } from './providers.types';
|
|
25
|
-
import type {
|
|
25
|
+
import type { DevtoolsProps } from '@djangocfg/devtools';
|
|
26
26
|
|
|
27
27
|
// ============================================================================
|
|
28
28
|
// Base Layout Props
|
|
@@ -37,7 +37,7 @@ import type { MonitorConfig } from '@djangocfg/monitor';
|
|
|
37
37
|
export interface BaseLayoutProps {
|
|
38
38
|
children: ReactNode;
|
|
39
39
|
|
|
40
|
-
/** Project name — used as default for
|
|
40
|
+
/** Project name — used as default for devtools.project */
|
|
41
41
|
project?: string;
|
|
42
42
|
|
|
43
43
|
/** Theme configuration */
|
|
@@ -61,11 +61,13 @@ export interface BaseLayoutProps {
|
|
|
61
61
|
/** Error boundary configuration (from components/errors, enabled by default) */
|
|
62
62
|
errorBoundary?: ErrorBoundaryConfig;
|
|
63
63
|
|
|
64
|
-
/**
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
64
|
+
/**
|
|
65
|
+
* Devtools configuration (`@djangocfg/devtools`): error/console capture with
|
|
66
|
+
* backend ingest + the floating debug panel. Capture is on by default;
|
|
67
|
+
* `devtools={{ button: false }}` hides the panel button, `ingest: false`
|
|
68
|
+
* keeps events local.
|
|
69
|
+
*/
|
|
70
|
+
devtools?: DevtoolsConfig;
|
|
69
71
|
|
|
70
72
|
/**
|
|
71
73
|
* Locale-switching plumbing. Mounted into a `LayoutI18nProvider` inside
|
|
@@ -75,14 +77,8 @@ export interface BaseLayoutProps {
|
|
|
75
77
|
i18n?: I18nLayoutConfig;
|
|
76
78
|
}
|
|
77
79
|
|
|
78
|
-
/**
|
|
79
|
-
export
|
|
80
|
-
/** Set false to disable, true to force-enable. Default: process.env.NODE_ENV === 'development' */
|
|
81
|
-
enabled?: boolean;
|
|
82
|
-
className?: string;
|
|
83
|
-
/** Props forwarded to DebugPanel */
|
|
84
|
-
panel?: Record<string, unknown>;
|
|
85
|
-
}
|
|
80
|
+
/** Devtools config for BaseApp — the `<Devtools>` props minus children. */
|
|
81
|
+
export type DevtoolsConfig = Omit<DevtoolsProps, 'children'>;
|
|
86
82
|
|
|
87
83
|
/**
|
|
88
84
|
* Brand block surfaced inside the locale-switcher dialog. Shared via
|
package/src/snippets/index.ts
CHANGED
|
@@ -8,6 +8,6 @@ export * from './Breadcrumbs';
|
|
|
8
8
|
export * from './AuthDialog';
|
|
9
9
|
export * from './Analytics';
|
|
10
10
|
|
|
11
|
-
//
|
|
12
|
-
export {
|
|
13
|
-
export type {
|
|
11
|
+
// Devtools lives in @djangocfg/devtools — re-exported here for convenience
|
|
12
|
+
export { Devtools } from '@djangocfg/devtools';
|
|
13
|
+
export type { DevtoolsProps } from '@djangocfg/devtools';
|