@djangocfg/centrifugo 1.0.1

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.
@@ -0,0 +1,253 @@
1
+ # Centrifugo Client Generator
2
+
3
+ Documentation for generating Centrifugo WebSocket RPC clients from gRPC services and Django configuration.
4
+
5
+ ## Overview
6
+
7
+ The Centrifugo client generator creates typed WebSocket RPC clients from:
8
+ - **gRPC Services**: Protocol buffer definitions and service implementations
9
+ - **Django Config**: Configuration schema from `config.py`
10
+
11
+ This enables full-stack type safety and auto-completion for WebSocket RPC communication.
12
+
13
+ ## Paths Reference
14
+
15
+ ```
16
+ $PACKAGES = ../packages (monorepo packages root)
17
+ $ADMIN = ../apps/admin (admin app root)
18
+ $DJANGO = ../../../../solution/projects/django (django project root)
19
+ $DJANGO_CFG = ../../../../solution/projects/django_cfg (django_cfg package)
20
+ ```
21
+
22
+ ## Quick Start
23
+
24
+ ```bash
25
+ # From admin app root
26
+ cd $ADMIN && make centrifugo
27
+ ```
28
+
29
+ This will:
30
+ 1. Generate clients (TypeScript, Python, Go) in `$DJANGO/openapi/centrifugo/`
31
+ 2. Copy TypeScript client to `$ADMIN/src/centrifugo/generated/`
32
+
33
+ ## Generator Architecture
34
+
35
+ ### 1. Management Command
36
+
37
+ **Location**: `$DJANGO/core/management/commands/generate_centrifugo.py`
38
+
39
+ This is the main entry point that orchestrates the generation process.
40
+
41
+ ```python
42
+ # Usage
43
+ python manage.py generate_centrifugo
44
+ ```
45
+
46
+ ### 2. Codegen Logic
47
+
48
+ **Location**: `$DJANGO_CFG/apps/integrations/centrifugo/codegen/`
49
+
50
+ The generator has modular architecture:
51
+
52
+ ```
53
+ codegen/
54
+ ├── management/commands/
55
+ │ └── generate_centrifugo_clients.py # Core generator command
56
+ ├── generators/
57
+ │ ├── typescript_thin/ # TypeScript client generator
58
+ │ │ ├── generator.py
59
+ │ │ └── templates/ # Jinja2 templates
60
+ │ ├── python/ # Python client generator
61
+ │ └── go/ # Go client generator
62
+ └── utils/ # Shared utilities
63
+ ```
64
+
65
+ ### 3. Templates
66
+
67
+ Client generation uses Jinja2 templates located in:
68
+ - `$DJANGO_CFG/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/`
69
+
70
+ Key templates:
71
+ - `client.ts.j2` - RPC method wrappers
72
+ - `rpc-client.ts.j2` - Base Centrifugo client with connection logic
73
+ - `types.ts.j2` - TypeScript type definitions
74
+
75
+ ## Source Data
76
+
77
+ ### gRPC Services
78
+
79
+ **Location**: `$DJANGO/apps/*/grpc_services`
80
+
81
+ The generator scans all Django apps for gRPC service definitions:
82
+ - `.proto` files
83
+ - Service implementations
84
+ - Method signatures
85
+
86
+ ### Django Config
87
+
88
+ **Location**: `$DJANGO/api/config.py`
89
+
90
+ Configuration schema is extracted from:
91
+ ```python
92
+ class ConfigView(APIView):
93
+ @action(detail=False, methods=['get'])
94
+ def config(self, request):
95
+ return Response({
96
+ 'centrifugo': {
97
+ 'enabled': settings.CENTRIFUGO_ENABLED,
98
+ 'url': settings.CENTRIFUGO_URL,
99
+ # ...
100
+ }
101
+ })
102
+ ```
103
+
104
+ ## Generated Outputs
105
+
106
+ ### TypeScript Client
107
+
108
+ **Output**: `$DJANGO/openapi/centrifugo/typescript/`
109
+
110
+ Generated files:
111
+ - `client.ts` - High-level RPC method wrappers
112
+ - `rpc-client.ts` - Low-level Centrifugo client
113
+ - `types.ts` - TypeScript interfaces
114
+
115
+ **Copied to**: `$ADMIN/src/centrifugo/generated/`
116
+
117
+ ### Python Client
118
+
119
+ **Output**: `$DJANGO/openapi/centrifugo/python/`
120
+
121
+ ### Go Client
122
+
123
+ **Output**: `$DJANGO/openapi/centrifugo/go/`
124
+
125
+ ## Modifying the Generator
126
+
127
+ The codegen logic is in `$DJANGO_CFG` which is auto-linked to Django. Changes are immediately available:
128
+
129
+ 1. Edit generator code or templates in `$DJANGO_CFG/apps/integrations/centrifugo/codegen/`
130
+ 2. Re-run generation: `cd $ADMIN && make centrifugo`
131
+ 3. Verify generated output
132
+
133
+ ### Example: Modify TypeScript Template
134
+
135
+ ```bash
136
+ # Edit base client template
137
+ vim $DJANGO_CFG/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/rpc-client.ts.j2
138
+
139
+ # Regenerate
140
+ cd $ADMIN && make centrifugo
141
+
142
+ # Check output
143
+ cat $ADMIN/src/centrifugo/generated/rpc-client.ts
144
+ ```
145
+
146
+ ## Integration with Admin App
147
+
148
+ The admin app wraps the generated client with app-specific providers:
149
+
150
+ ```
151
+ $ADMIN/src/centrifugo/
152
+ ├── generated/ # Auto-generated (DO NOT EDIT)
153
+ │ ├── client.ts
154
+ │ ├── rpc-client.ts
155
+ │ └── types.ts
156
+ ├── AppCentrifugoProvider.tsx # App-specific wrapper
157
+ └── index.ts # Re-exports from @djangocfg/centrifugo
158
+ ```
159
+
160
+ Universal components (context, hooks, debug) are in `@djangocfg/centrifugo` package:
161
+
162
+ ```
163
+ $PACKAGES/centrifugo/src/
164
+ ├── context/ # React context provider
165
+ ├── hooks/ # Custom hooks
166
+ ├── components/ # Debug panel, etc.
167
+ ├── config.ts # Environment config
168
+ └── types.ts # Shared types
169
+ ```
170
+
171
+ ## Development Workflow
172
+
173
+ ### 1. Add New gRPC Service
174
+
175
+ ```bash
176
+ # 1. Define .proto file
177
+ vim $DJANGO/apps/myapp/grpc_services/myservice.proto
178
+
179
+ # 2. Implement service
180
+ vim $DJANGO/apps/myapp/grpc_services/myservice.py
181
+
182
+ # 3. Regenerate client
183
+ cd $ADMIN && make centrifugo
184
+ ```
185
+
186
+ ### 2. Use in Frontend
187
+
188
+ ```tsx
189
+ import { useCentrifugo } from '@/centrifugo';
190
+
191
+ function MyComponent() {
192
+ const { client, isConnected } = useCentrifugo();
193
+
194
+ const handleCall = async () => {
195
+ // Auto-generated typed method
196
+ const result = await client?.myMethod({ param: 'value' });
197
+ };
198
+ }
199
+ ```
200
+
201
+ ## Troubleshooting
202
+
203
+ ### Client Generation Fails
204
+
205
+ 1. Check Django apps are properly configured
206
+ 2. Verify gRPC services are valid
207
+ 3. Check template syntax in `$DJANGO_CFG/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/`
208
+
209
+ ### TypeScript Errors After Generation
210
+
211
+ 1. Check generated types in `src/centrifugo/generated/types.ts`
212
+ 2. Verify imports match package structure
213
+ 3. Run type check: `pnpm tsc --noEmit`
214
+
215
+ ### Connection Issues
216
+
217
+ Use the debug panel (FAB button in bottom-left corner) to inspect:
218
+ - Connection state
219
+ - Authentication status
220
+ - WebSocket URL
221
+ - Channel subscriptions
222
+ - Error messages
223
+
224
+ ## Advanced Configuration
225
+
226
+ ### Custom Templates
227
+
228
+ You can customize the generated output by modifying templates:
229
+
230
+ ```bash
231
+ # Location
232
+ $DJANGO_CFG/apps/integrations/centrifugo/codegen/generators/typescript_thin/templates/
233
+
234
+ # Files
235
+ client.ts.j2 # Method wrappers
236
+ rpc-client.ts.j2 # Base client
237
+ types.ts.j2 # Type definitions
238
+ ```
239
+
240
+ ### Generator Options
241
+
242
+ The `generate_centrifugo_clients` command supports options:
243
+
244
+ ```bash
245
+ python manage.py generate_centrifugo_clients --help
246
+ ```
247
+
248
+ ## References
249
+
250
+ - **Centrifugo Docs**: https://centrifugal.dev/
251
+ - **Centrifuge-JS**: https://github.com/centrifugal/centrifuge-js
252
+ - **gRPC**: https://grpc.io/
253
+ - **Jinja2**: https://jinja.palletsprojects.com/
package/README.md ADDED
@@ -0,0 +1,84 @@
1
+ # @djangocfg/centrifugo
2
+
3
+ WebSocket client package for Django-CFG + Centrifugo integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @djangocfg/centrifugo
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### 1. Wrap your app with CentrifugoProvider
14
+
15
+ ```tsx
16
+ import { CentrifugoProvider } from '@djangocfg/centrifugo';
17
+
18
+ function App() {
19
+ return (
20
+ <CentrifugoProvider auth={authContext} config={centrifugoConfig}>
21
+ <YourApp />
22
+ </CentrifugoProvider>
23
+ );
24
+ }
25
+ ```
26
+
27
+ ### 2. Use hooks to interact with Centrifugo
28
+
29
+ ```tsx
30
+ import { useCentrifugo, useSubscription } from '@djangocfg/centrifugo';
31
+
32
+ function MyComponent() {
33
+ const { isConnected, baseClient } = useCentrifugo();
34
+
35
+ const { data, isLoading, error } = useSubscription({
36
+ channel: 'notifications',
37
+ onPublication: (data) => console.log('New message:', data),
38
+ });
39
+
40
+ return <div>Connected: {isConnected ? 'Yes' : 'No'}</div>;
41
+ }
42
+ ```
43
+
44
+ ### 3. Debug connection (development only)
45
+
46
+ ```tsx
47
+ import { CentrifugoDebug } from '@djangocfg/centrifugo/components';
48
+
49
+ function DevTools() {
50
+ return <CentrifugoDebug auth={authContext} config={centrifugoConfig} />;
51
+ }
52
+ ```
53
+
54
+ ## Exports
55
+
56
+ ### Context & Provider
57
+ - `CentrifugoProvider` - WebSocket connection provider
58
+ - `useCentrifugo` - Access connection state and client
59
+
60
+ ### Hooks
61
+ - `useCentrifugoLogger` - Consola logger for debugging
62
+ - `useSubscription` - Subscribe to Centrifugo channels
63
+
64
+ ### Components
65
+ - `CentrifugoDebug` - Development debug panel
66
+
67
+ ### Types
68
+ - `CentrifugoConfig` - Configuration interface
69
+ - `CentrifugoToken` - JWT token structure
70
+ - `User` - User type with Centrifugo data
71
+ - `AuthContext` - Authentication context interface
72
+ - `CentrifugoProviderProps` - Provider props
73
+ - `CentrifugoContextValue` - Context value type
74
+
75
+ ## Architecture
76
+
77
+ This package provides universal WebSocket logic that can be used across multiple Django-CFG admin applications. The generated RPC client is imported separately from your app's generated code.
78
+
79
+ ## Requirements
80
+
81
+ - React 19+
82
+ - `@djangocfg/ui` - UI components
83
+ - `@djangocfg/layouts` - Layout components
84
+ - `centrifuge` - WebSocket client library
package/package.json ADDED
@@ -0,0 +1,35 @@
1
+ {
2
+ "name": "@djangocfg/centrifugo",
3
+ "version": "1.0.1",
4
+ "description": "WebSocket RPC client for Django-CFG + Centrifugo integration",
5
+ "main": "./src/index.ts",
6
+ "types": "./src/index.ts",
7
+ "exports": {
8
+ ".": "./src/index.ts",
9
+ "./components": "./src/components/index.ts",
10
+ "./hooks": "./src/hooks/index.ts",
11
+ "./context": "./src/context/index.ts",
12
+ "./types": "./src/types/index.ts"
13
+ },
14
+ "scripts": {
15
+ "check": "tsc --noEmit",
16
+ "lint": "eslint . --max-warnings 0"
17
+ },
18
+ "dependencies": {
19
+ "centrifuge": "^5.2.2"
20
+ },
21
+ "peerDependencies": {
22
+ "@djangocfg/ui": "^1.2.26",
23
+ "@djangocfg/layouts": "^1.2.26",
24
+ "consola": "^3.4.2",
25
+ "lucide-react": "^0.468.0",
26
+ "react": "^19.0.0",
27
+ "react-dom": "^19.0.0"
28
+ },
29
+ "devDependencies": {
30
+ "@djangocfg/typescript-config": "^1.2.26",
31
+ "@types/react": "^19.0.6",
32
+ "@types/react-dom": "^19.0.2",
33
+ "typescript": "^5.7.3"
34
+ }
35
+ }
@@ -0,0 +1,182 @@
1
+ /**
2
+ * Centrifugo Debug Component
3
+ *
4
+ * Displays detailed Centrifugo connection status and diagnostics
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import React from 'react';
10
+ import { useCentrifugo } from '../context';
11
+ import { useAuth } from '@djangocfg/layouts';
12
+ import { Card, CardHeader, CardTitle, CardContent, Badge, Separator, Button, useCopy } from '@djangocfg/ui';
13
+ import { PrettyCode } from '@djangocfg/ui/tools';
14
+ import { Wifi, WifiOff, Radio, X, Copy, RefreshCw } from 'lucide-react';
15
+ import { centrifugoConfig } from '../config';
16
+
17
+ export function CentrifugoDebug() {
18
+ const { isConnected, isConnecting, error, connectionState, baseClient, enabled, reconnect } = useCentrifugo();
19
+ const { isAuthenticated, isLoading: authLoading, user } = useAuth();
20
+ const [isVisible, setIsVisible] = React.useState(true);
21
+ const [isReconnecting, setIsReconnecting] = React.useState(false);
22
+ const { copyToClipboard } = useCopy();
23
+
24
+ const centrifugoToken = user?.centrifugo;
25
+ const hasCentrifugoToken = !!centrifugoToken?.token;
26
+
27
+ const shouldConnect = isAuthenticated && !authLoading && enabled && hasCentrifugoToken;
28
+
29
+ const debugInfo = React.useMemo(() => ({
30
+ connection: {
31
+ status: connectionState,
32
+ isConnected,
33
+ isConnecting,
34
+ error: error?.message || null,
35
+ },
36
+ auth: {
37
+ isAuthenticated,
38
+ authLoading,
39
+ userId: user?.id,
40
+ },
41
+ config: {
42
+ centrifugoEnabled: enabled,
43
+ hasCentrifugoToken,
44
+ },
45
+ websocket: {
46
+ url: centrifugoToken?.centrifugo_url || null,
47
+ channels: centrifugoToken?.channels || [],
48
+ activeSubscriptions: baseClient?.getAllSubscriptions?.() || [],
49
+ },
50
+ autoConnect: {
51
+ shouldConnect,
52
+ reasons: {
53
+ authenticated: isAuthenticated,
54
+ authLoading: !authLoading,
55
+ centrifugoEnabled: enabled,
56
+ hasToken: hasCentrifugoToken,
57
+ },
58
+ },
59
+ }), [connectionState, isConnected, isConnecting, error, isAuthenticated, authLoading, user?.id, enabled, hasCentrifugoToken, centrifugoToken, baseClient, shouldConnect]);
60
+
61
+ const copyDebugInfo = () => {
62
+ copyToClipboard(JSON.stringify(debugInfo, null, 2), 'Debug info copied to clipboard');
63
+ };
64
+
65
+ const handleReconnect = async () => {
66
+ setIsReconnecting(true);
67
+ try {
68
+ await reconnect();
69
+ } finally {
70
+ setTimeout(() => setIsReconnecting(false), 1000);
71
+ }
72
+ };
73
+
74
+ // Only show in development mode and not in static builds
75
+ if (!centrifugoConfig.showDebugPanel) {
76
+ return null;
77
+ }
78
+
79
+ return (
80
+ <>
81
+ {/* FAB Button (always visible) */}
82
+ <button
83
+ onClick={() => setIsVisible(!isVisible)}
84
+ className="rounded-full bg-primary text-primary-foreground shadow-lg hover:shadow-xl transition-all duration-200 flex items-center justify-center"
85
+ style={{ position: 'fixed', bottom: '1rem', left: '1rem', width: '56px', height: '56px', zIndex: 9999 }}
86
+ title="Toggle Centrifugo Debug Panel"
87
+ >
88
+ {isConnected ? (
89
+ <Wifi style={{ width: '24px', height: '24px' }} />
90
+ ) : (
91
+ <WifiOff style={{ width: '24px', height: '24px' }} />
92
+ )}
93
+ </button>
94
+
95
+ {/* Debug Panel */}
96
+ {isVisible && (
97
+ <div style={{ position: 'fixed', bottom: '5rem', left: '1rem', width: '420px', zIndex: 9999 }}>
98
+ <Card className="shadow-lg">
99
+ <CardHeader className="pb-3">
100
+ <div className="flex items-center justify-between">
101
+ <div className="flex items-center gap-2">
102
+ {isConnected ? (
103
+ <Wifi className="text-green-600 dark:text-green-500" style={{ width: '16px', height: '16px' }} />
104
+ ) : (
105
+ <WifiOff className="text-red-600 dark:text-red-500" style={{ width: '16px', height: '16px' }} />
106
+ )}
107
+ <CardTitle className="text-base">Centrifugo Debug</CardTitle>
108
+ </div>
109
+ <div className="flex items-center gap-1">
110
+ <Button
111
+ variant="ghost"
112
+ size="sm"
113
+ onClick={handleReconnect}
114
+ disabled={isReconnecting || isConnecting}
115
+ className="px-2 py-1"
116
+ title="Reconnect"
117
+ >
118
+ <RefreshCw
119
+ style={{ width: '14px', height: '14px' }}
120
+ className={isReconnecting ? 'animate-spin' : ''}
121
+ />
122
+ </Button>
123
+ <Button
124
+ variant="ghost"
125
+ size="sm"
126
+ onClick={copyDebugInfo}
127
+ className="px-2 py-1"
128
+ title="Copy debug info"
129
+ >
130
+ <Copy style={{ width: '14px', height: '14px' }} />
131
+ </Button>
132
+ <Button
133
+ variant="ghost"
134
+ size="sm"
135
+ onClick={() => setIsVisible(false)}
136
+ className="px-2 py-1"
137
+ >
138
+ <X style={{ width: '14px', height: '14px' }} />
139
+ </Button>
140
+ </div>
141
+ </div>
142
+ </CardHeader>
143
+
144
+ <CardContent className="space-y-3">
145
+ {/* Connection Status Badge */}
146
+ <div className="flex items-center justify-between">
147
+ <span className="text-sm font-medium">Status:</span>
148
+ <Badge variant={isConnected ? 'default' : isConnecting ? 'secondary' : 'destructive'}>
149
+ {connectionState.toUpperCase()}
150
+ </Badge>
151
+ </div>
152
+
153
+ {/* Auto-Connect Decision */}
154
+ <div className="flex items-center justify-between">
155
+ <span className="text-sm font-medium">Should Connect:</span>
156
+ <Badge variant={shouldConnect ? 'default' : 'outline'}>
157
+ {shouldConnect ? 'YES' : 'NO'}
158
+ </Badge>
159
+ </div>
160
+
161
+ <Separator />
162
+
163
+ {/* JSON Debug Output */}
164
+ <div className="space-y-2">
165
+ <div className="flex items-center gap-2">
166
+ <Radio className="text-muted-foreground" style={{ width: '14px', height: '14px' }} />
167
+ <span className="text-sm font-medium">Debug State:</span>
168
+ </div>
169
+ <div className="max-h-[300px] overflow-y-auto">
170
+ <PrettyCode data={debugInfo} language="json" />
171
+ </div>
172
+ </div>
173
+ </CardContent>
174
+ </Card>
175
+ </div>
176
+ )}
177
+ </>
178
+ );
179
+ }
180
+
181
+ // Alias for backward compatibility
182
+ export const WSRPCDebug = CentrifugoDebug;
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Centrifugo Components
3
+ */
4
+
5
+ export { CentrifugoDebug, WSRPCDebug } from './CentrifugoDebug';
package/src/config.ts ADDED
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Centrifugo Package Configuration
3
+ */
4
+
5
+ export const isDevelopment = process.env.NODE_ENV === 'development';
6
+ export const isProduction = !isDevelopment;
7
+ export const isStaticBuild = process.env.NEXT_PUBLIC_STATIC_BUILD === 'true';
8
+
9
+ const showDebugPanel = isDevelopment && !isStaticBuild;
10
+
11
+ export const centrifugoConfig = {
12
+ // Show debug panel only in development and not in static builds
13
+ showDebugPanel,
14
+ } as const;
15
+
16
+ export type CentrifugoConfig = typeof centrifugoConfig;
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Base Centrifugo Provider
3
+ *
4
+ * Generic WebSocket RPC provider that can be used in any app.
5
+ * Automatically accesses auth context from @djangocfg/layouts.
6
+ */
7
+
8
+ 'use client';
9
+
10
+ import { createContext, useContext, useState, useEffect, useCallback, useRef, useMemo } from 'react';
11
+ import { useAuth } from '@djangocfg/layouts';
12
+ import type { CentrifugoProviderProps, CentrifugoContextValue } from '../types';
13
+ import { useCentrifugoLogger } from '../hooks';
14
+ import { CentrifugoDebug } from '../components';
15
+
16
+ const CentrifugoContext = createContext<CentrifugoContextValue | undefined>(undefined);
17
+
18
+ export function CentrifugoProvider({
19
+ children,
20
+ enabled = false,
21
+ RPCClientClass,
22
+ APIClientClass,
23
+ url,
24
+ autoConnect: autoConnectProp = true,
25
+ }: CentrifugoProviderProps) {
26
+ const { isAuthenticated, isLoading, user } = useAuth();
27
+
28
+ const [client, setClient] = useState<any>(null);
29
+ const [baseClient, setBaseClient] = useState<any>(null);
30
+ const [isConnected, setIsConnected] = useState(false);
31
+ const [isConnecting, setIsConnecting] = useState(false);
32
+ const [error, setError] = useState<Error | null>(null);
33
+
34
+ const logger = useCentrifugoLogger();
35
+
36
+ const reconnectTimeoutRef = useRef<NodeJS.Timeout | null>(null);
37
+ const hasConnectedRef = useRef(false);
38
+ const isConnectingRef = useRef(false);
39
+ const isMountedRef = useRef(true);
40
+
41
+ const centrifugoToken = user?.centrifugo;
42
+ const hasCentrifugoToken = !!centrifugoToken?.token;
43
+
44
+ const wsUrl = useMemo(() => {
45
+ if (url) return url;
46
+ if (centrifugoToken?.centrifugo_url) return centrifugoToken.centrifugo_url;
47
+ return '';
48
+ }, [url, centrifugoToken?.centrifugo_url]);
49
+
50
+ const autoConnect = autoConnectProp &&
51
+ (isAuthenticated && !isLoading) &&
52
+ enabled &&
53
+ hasCentrifugoToken;
54
+
55
+ useEffect(() => {
56
+ if (!isLoading) {
57
+ logger.info(`[RPC] Auto-connect decision: ${autoConnect ? 'YES' : 'NO'}`);
58
+ logger.info(`[RPC] - Authenticated: ${isAuthenticated}`);
59
+ logger.info(`[RPC] - Auth loading: ${isLoading}`);
60
+ logger.info(`[RPC] - Centrifugo enabled: ${enabled}`);
61
+ logger.info(`[RPC] - Centrifugo token from profile: ${hasCentrifugoToken}`);
62
+ logger.info(`[RPC] - WebSocket URL: ${wsUrl}`);
63
+
64
+ if (hasCentrifugoToken && centrifugoToken) {
65
+ logger.info(`[RPC] - Channels: ${centrifugoToken.channels?.join(', ')}`);
66
+ }
67
+ }
68
+ }, [autoConnect, isAuthenticated, isLoading, enabled, hasCentrifugoToken, centrifugoToken, logger, wsUrl]);
69
+
70
+ const connect = useCallback(async () => {
71
+ if (hasConnectedRef.current || isConnectingRef.current) return;
72
+ if (isConnecting || isConnected) return;
73
+
74
+ isConnectingRef.current = true;
75
+ setIsConnecting(true);
76
+ setError(null);
77
+
78
+ try {
79
+ logger.info('Connecting to WebSocket RPC server...');
80
+
81
+ if (!centrifugoToken?.token) {
82
+ throw new Error('No Centrifugo token available in user profile. Please refresh the page.');
83
+ }
84
+
85
+ const token = centrifugoToken.token;
86
+ let userId = user?.id?.toString() || '1';
87
+
88
+ if (!user?.id) {
89
+ try {
90
+ const tokenPayload = JSON.parse(atob(token.split('.')[1]));
91
+ userId = tokenPayload.user_id?.toString() || tokenPayload.sub?.toString() || '1';
92
+ } catch (err) {
93
+ // Silently fallback
94
+ }
95
+ }
96
+
97
+ const baseRPC = new RPCClientClass(wsUrl, token, userId);
98
+ await baseRPC.connect();
99
+
100
+ if (!isMountedRef.current) {
101
+ baseRPC.disconnect();
102
+ isConnectingRef.current = false;
103
+ return;
104
+ }
105
+
106
+ const rpcClient = new APIClientClass(baseRPC);
107
+
108
+ hasConnectedRef.current = true;
109
+ isConnectingRef.current = false;
110
+
111
+ setBaseClient(baseRPC);
112
+ setClient(rpcClient);
113
+ setIsConnected(true);
114
+ setError(null);
115
+
116
+ logger.success('WebSocket RPC connected successfully');
117
+ } catch (err) {
118
+ const error = err instanceof Error ? err : new Error('Connection failed');
119
+ setError(error);
120
+ setBaseClient(null);
121
+ setClient(null);
122
+ setIsConnected(false);
123
+ hasConnectedRef.current = false;
124
+ isConnectingRef.current = false;
125
+
126
+ const isAuthError = error.message.includes('token') ||
127
+ error.message.includes('auth') ||
128
+ error.message.includes('expired');
129
+
130
+ if (isAuthError) {
131
+ logger.error('WebSocket RPC authentication failed', error);
132
+ } else {
133
+ logger.error('WebSocket RPC connection failed', error);
134
+ reconnectTimeoutRef.current = setTimeout(() => {
135
+ logger.info('Attempting to reconnect...');
136
+ connect();
137
+ }, 5000);
138
+ }
139
+ } finally {
140
+ setIsConnecting(false);
141
+ }
142
+ }, [wsUrl, centrifugoToken, user, logger, RPCClientClass, APIClientClass, isConnecting, isConnected]);
143
+
144
+ const disconnect = useCallback(() => {
145
+ if (isConnectingRef.current) return;
146
+
147
+ if (reconnectTimeoutRef.current) {
148
+ clearTimeout(reconnectTimeoutRef.current);
149
+ reconnectTimeoutRef.current = null;
150
+ }
151
+
152
+ if (baseClient) {
153
+ logger.info('Disconnecting from WebSocket RPC server...');
154
+ baseClient.disconnect();
155
+ setBaseClient(null);
156
+ setClient(null);
157
+ setIsConnected(false);
158
+ setError(null);
159
+ }
160
+
161
+ hasConnectedRef.current = false;
162
+ isConnectingRef.current = false;
163
+ }, [baseClient, logger]);
164
+
165
+ const reconnect = useCallback(async () => {
166
+ disconnect();
167
+ await connect();
168
+ }, [connect, disconnect]);
169
+
170
+ useEffect(() => {
171
+ isMountedRef.current = true;
172
+
173
+ if (autoConnect && !hasConnectedRef.current) {
174
+ connect();
175
+ }
176
+
177
+ return () => {
178
+ if (isConnectingRef.current && !hasConnectedRef.current) {
179
+ return;
180
+ }
181
+
182
+ if (!hasConnectedRef.current) {
183
+ return;
184
+ }
185
+
186
+ isMountedRef.current = false;
187
+ disconnect();
188
+ };
189
+ }, [autoConnect, connect, disconnect]);
190
+
191
+ const connectionState = isConnected
192
+ ? 'connected'
193
+ : isConnecting
194
+ ? 'connecting'
195
+ : error
196
+ ? 'error'
197
+ : 'disconnected';
198
+
199
+ const value: CentrifugoContextValue = {
200
+ client,
201
+ baseClient,
202
+ isConnected,
203
+ isConnecting,
204
+ error,
205
+ connectionState,
206
+ enabled,
207
+ connect,
208
+ disconnect,
209
+ reconnect,
210
+ };
211
+
212
+ return (
213
+ <CentrifugoContext.Provider value={value}>
214
+ {children}
215
+ <CentrifugoDebug />
216
+ </CentrifugoContext.Provider>
217
+ );
218
+ }
219
+
220
+ export function useCentrifugo(): CentrifugoContextValue {
221
+ const context = useContext(CentrifugoContext);
222
+
223
+ if (context === undefined) {
224
+ throw new Error('useCentrifugo must be used within a CentrifugoProvider');
225
+ }
226
+
227
+ return context;
228
+ }
@@ -0,0 +1,5 @@
1
+ /**
2
+ * Centrifugo Providers
3
+ */
4
+
5
+ export { CentrifugoProvider, useCentrifugo } from './CentrifugoProvider';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Centrifugo Hooks
3
+ */
4
+
5
+ export { useCentrifugoLogger, useRPCLogger } from './useLogger';
6
+ export type { CentrifugoLogger, RPCLogger } from './useLogger';
7
+
8
+ export { useSubscription } from './useSubscription';
9
+ export type { useSubscriptionOptions } from './useSubscription';
@@ -0,0 +1,69 @@
1
+ /**
2
+ * Centrifugo Logger Hook
3
+ *
4
+ * React hook for Centrifugo logging using consola library.
5
+ */
6
+
7
+ 'use client';
8
+
9
+ import { useMemo } from 'react';
10
+ import { createConsola, type ConsolaInstance } from 'consola';
11
+
12
+ export interface CentrifugoLogger {
13
+ info: (message: string) => void;
14
+ debug: (message: string) => void;
15
+ warning: (message: string) => void;
16
+ error: (message: string, error?: Error) => void;
17
+ success: (message: string) => void;
18
+ }
19
+
20
+ /**
21
+ * React hook for Centrifugo logger with consola
22
+ *
23
+ * @param isDevelopment - Enable debug logging (optional)
24
+ * @returns Centrifugo logger instance
25
+ *
26
+ * @example
27
+ * ```tsx
28
+ * function MyComponent() {
29
+ * const logger = useCentrifugoLogger();
30
+ * logger.info('Connected to Centrifugo server');
31
+ * }
32
+ * ```
33
+ */
34
+ export function useCentrifugoLogger(isDevelopment = process.env.NODE_ENV === 'development'): CentrifugoLogger {
35
+ const logger = useMemo(() => {
36
+ const consola = createConsola({
37
+ level: isDevelopment ? 4 : 3, // debug in dev, info in prod
38
+ formatOptions: {
39
+ colors: true,
40
+ date: false,
41
+ compact: !isDevelopment,
42
+ },
43
+ }).withTag('Centrifugo');
44
+
45
+ return {
46
+ info: (message: string) => {
47
+ if (isDevelopment) consola.info(message);
48
+ },
49
+ debug: (message: string) => {
50
+ if (isDevelopment) consola.debug(message);
51
+ },
52
+ warning: (message: string) => {
53
+ if (isDevelopment) consola.warn(message);
54
+ },
55
+ error: (message: string, error?: Error) => {
56
+ consola.error(message, error || '');
57
+ },
58
+ success: (message: string) => {
59
+ if (isDevelopment) consola.success(message);
60
+ },
61
+ };
62
+ }, [isDevelopment]);
63
+
64
+ return logger;
65
+ }
66
+
67
+ // Alias for backward compatibility
68
+ export const useRPCLogger = useCentrifugoLogger;
69
+ export type RPCLogger = CentrifugoLogger;
@@ -0,0 +1,86 @@
1
+ /**
2
+ * React hook for subscribing to Centrifugo channels.
3
+ *
4
+ * Automatically handles subscription lifecycle (mount/unmount).
5
+ *
6
+ * @example
7
+ * // Subscribe to bot heartbeat
8
+ * useSubscription('bot#bot-123#heartbeat', (data) => {
9
+ * console.log('Heartbeat:', data);
10
+ * updateMetrics(data);
11
+ * });
12
+ *
13
+ * @example
14
+ * // Conditional subscription
15
+ * useSubscription(
16
+ * 'bot#bot-123#status',
17
+ * (data) => console.log('Status:', data),
18
+ * { enabled: isMonitoring }
19
+ * );
20
+ */
21
+
22
+ import { useEffect, useRef } from 'react';
23
+ import { useCentrifugo } from '../context';
24
+
25
+ export interface useSubscriptionOptions {
26
+ /**
27
+ * Enable/disable subscription.
28
+ * Defaults to true.
29
+ */
30
+ enabled?: boolean;
31
+ }
32
+
33
+ /**
34
+ * Hook for subscribing to a Centrifugo channel.
35
+ *
36
+ * @param channel - Channel name (e.g., 'bot#bot-123#heartbeat'). Set to null to disable.
37
+ * @param callback - Callback function for received messages
38
+ * @param options - Subscription options
39
+ *
40
+ * @example
41
+ * ```tsx
42
+ * function BotMonitor({ botId }: { botId: string }) {
43
+ * const [heartbeat, setHeartbeat] = useState(null);
44
+ *
45
+ * useSubscription(`bot#${botId}#heartbeat`, (data) => {
46
+ * setHeartbeat(data);
47
+ * });
48
+ *
49
+ * return <div>CPU: {heartbeat?.cpu_usage}%</div>;
50
+ * }
51
+ * ```
52
+ */
53
+ export function useSubscription<T = any>(
54
+ channel: string | null,
55
+ callback: (data: T) => void,
56
+ options: useSubscriptionOptions = {}
57
+ ) {
58
+ const { baseClient, isConnected } = useCentrifugo();
59
+ const callbackRef = useRef(callback);
60
+ const { enabled = true } = options;
61
+
62
+ // Keep callback ref updated (avoid stale closures)
63
+ useEffect(() => {
64
+ callbackRef.current = callback;
65
+ }, [callback]);
66
+
67
+ useEffect(() => {
68
+ // Don't subscribe if disabled, not connected, or no channel
69
+ if (!enabled || !isConnected || !baseClient || !channel) {
70
+ return;
71
+ }
72
+
73
+ console.log(`🎣 useSubscription: Subscribing to ${channel}`);
74
+
75
+ // Subscribe with stable callback wrapper
76
+ const unsubscribe = baseClient.subscribe(channel, (data) => {
77
+ callbackRef.current(data);
78
+ });
79
+
80
+ // Cleanup on unmount or channel change
81
+ return () => {
82
+ console.log(`🎣 useSubscription: Unsubscribing from ${channel}`);
83
+ unsubscribe();
84
+ };
85
+ }, [channel, enabled, isConnected, baseClient]);
86
+ }
package/src/index.ts ADDED
@@ -0,0 +1,27 @@
1
+ /**
2
+ * @djangocfg/centrifugo
3
+ *
4
+ * WebSocket client for Django-CFG + Centrifugo integration
5
+ */
6
+
7
+ // Context & Provider
8
+ export { CentrifugoProvider, useCentrifugo } from './context';
9
+
10
+ // Hooks
11
+ export { useCentrifugoLogger, useRPCLogger, useSubscription } from './hooks';
12
+ export type { CentrifugoLogger, RPCLogger } from './hooks';
13
+ export type { useSubscriptionOptions } from './hooks';
14
+
15
+ // Components
16
+ export { CentrifugoDebug, WSRPCDebug } from './components';
17
+
18
+ // Types
19
+ export type {
20
+ CentrifugoToken,
21
+ User,
22
+ CentrifugoProviderProps,
23
+ CentrifugoContextValue,
24
+ } from './types';
25
+
26
+ // Config
27
+ export { isDevelopment, isProduction, isStaticBuild, centrifugoConfig } from './config';
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Centrifugo Package Types
3
+ */
4
+
5
+ export interface CentrifugoToken {
6
+ token: string;
7
+ centrifugo_url: string;
8
+ channels: string[];
9
+ expires_at: string;
10
+ }
11
+
12
+ export interface User {
13
+ id: number;
14
+ centrifugo?: CentrifugoToken;
15
+ }
16
+
17
+ export interface CentrifugoProviderProps {
18
+ children: React.ReactNode;
19
+ /** Is Centrifugo enabled */
20
+ enabled?: boolean;
21
+ /** Base RPC client class */
22
+ RPCClientClass: any;
23
+ /** API client wrapper class */
24
+ APIClientClass: any;
25
+ /** Custom WebSocket URL (defaults to user profile URL) */
26
+ url?: string;
27
+ /** Auto-connect on mount (default: true) */
28
+ autoConnect?: boolean;
29
+ }
30
+
31
+ export interface CentrifugoContextValue {
32
+ // Connection State
33
+ client: any;
34
+ baseClient: any;
35
+ isConnected: boolean;
36
+ isConnecting: boolean;
37
+ error: Error | null;
38
+ connectionState: string;
39
+ enabled: boolean;
40
+
41
+ // Connection Methods
42
+ connect: () => Promise<void>;
43
+ disconnect: () => void;
44
+ reconnect: () => Promise<void>;
45
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,8 @@
1
+ {
2
+ "extends": "@djangocfg/typescript-config/react-library.json",
3
+ "compilerOptions": {
4
+ "skipLibCheck": true
5
+ },
6
+ "include": ["src"],
7
+ "exclude": ["node_modules", "dist"]
8
+ }
@@ -0,0 +1 @@
1
+ {"fileNames":["../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.es5.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.dom.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.webworker.importscripts.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.scripthost.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.d.ts","../../node_modules/.pnpm/typescript@5.9.3/node_modules/typescript/lib/lib.decorators.legacy.d.ts","./src/context/index.ts","../../node_modules/.pnpm/@types+react@19.2.2/node_modules/@types/react/global.d.ts","../../node_modules/.pnpm/csstype@3.1.3/node_modules/csstype/index.d.ts","../../node_modules/.pnpm/@types+react@19.2.2/node_modules/@types/react/index.d.ts","./src/hooks/uselogger.ts","./src/hooks/usesubscription.ts","./src/hooks/index.ts","./src/components/index.ts","./src/types/index.ts","./src/index.ts","../ui/src/components/index.ts","../../node_modules/.pnpm/moment@2.30.1/node_modules/moment/ts3.1-typings/moment.d.ts","../ui/src/hooks/usecountdown.ts","../ui/src/hooks/usedebouncedcallback.ts","../ui/src/hooks/usedebugtools.ts","../ui/src/hooks/useeventsbus.ts","../ui/src/hooks/uselocalstorage.ts","../ui/src/hooks/usesessionstorage.ts","../ui/src/hooks/usetoast.ts","../ui/src/hooks/usecopy.ts","../ui/src/hooks/usetheme.ts","../ui/src/hooks/useimageloader.ts","../ui/src/hooks/index.ts","../ui/src/blocks/index.ts","../ui/src/animations/index.ts","../../node_modules/.pnpm/clsx@2.1.1/node_modules/clsx/clsx.d.ts","../../node_modules/.pnpm/tailwind-merge@3.3.1/node_modules/tailwind-merge/dist/types.d.ts","../ui/src/lib/utils.ts","../ui/src/lib/index.ts","../ui/src/tools/index.ts","../ui/src/theme/index.ts","../ui/src/index.ts","../../node_modules/.pnpm/lucide-react@0.468.0_react@19.1.0/node_modules/lucide-react/dist/lucide-react.d.ts","./src/components/centrifugodebug.tsx","./src/context/centrifugoprovider.tsx","../../node_modules/.pnpm/@types+react-dom@19.2.1_@types+react@19.2.2/node_modules/@types/react-dom/index.d.ts","../../node_modules/.pnpm/@types+estree@1.0.8/node_modules/@types/estree/index.d.ts","../../node_modules/.pnpm/@types+json-schema@7.0.15/node_modules/@types/json-schema/index.d.ts","../../node_modules/.pnpm/@types+eslint@9.6.1/node_modules/@types/eslint/use-at-your-own-risk.d.ts","../../node_modules/.pnpm/@types+eslint@9.6.1/node_modules/@types/eslint/index.d.ts","../../node_modules/.pnpm/@types+eslint-scope@3.7.7/node_modules/@types/eslint-scope/index.d.ts"],"fileIdsList":[[44,47],[44,45,46],[47],[11],[9,10],[8,11,16,39,40],[41],[11,14,16],[42],[12,13],[8,14,15,16],[20,21,22,23,24,25,26,27,28,29],[11,26],[11,19],[18,30,31,32,36,37,38],[35],[33,34]],"fileInfos":[{"version":"a7297ff837fcdf174a9524925966429eb8e5feecc2cc55cc06574e6b092c1eaa","impliedFormat":1},{"version":"c430d44666289dae81f30fa7b2edebf186ecc91a2d4c71266ea6ae76388792e1","affectsGlobalScope":true,"impliedFormat":1},{"version":"080941d9f9ff9307f7e27a83bcd888b7c8270716c39af943532438932ec1d0b9","affectsGlobalScope":true,"impliedFormat":1},{"version":"80e18897e5884b6723488d4f5652167e7bb5024f946743134ecc4aa4ee731f89","affectsGlobalScope":true,"impliedFormat":1},{"version":"cd034f499c6cdca722b60c04b5b1b78e058487a7085a8e0d6fb50809947ee573","affectsGlobalScope":true,"impliedFormat":1},{"version":"8e7f8264d0fb4c5339605a15daadb037bf238c10b654bb3eee14208f860a32ea","affectsGlobalScope":true,"impliedFormat":1},{"version":"782dec38049b92d4e85c1585fbea5474a219c6984a35b004963b00beb1aab538","affectsGlobalScope":true,"impliedFormat":1},"4757b95eb7c31ff9e4acbc3cdc2e9c9077c0904e85c6d8c7b7033b056c6945c7",{"version":"170d4db14678c68178ee8a3d5a990d5afb759ecb6ec44dbd885c50f6da6204f6","affectsGlobalScope":true,"impliedFormat":1},{"version":"8a8eb4ebffd85e589a1cc7c178e291626c359543403d58c9cd22b81fab5b1fb9","impliedFormat":1},{"version":"0ff1b165090b491f5e1407ae680b9a0bc3806dc56827ec85f93c57390491e732","impliedFormat":1},"066a67181338eaae17358afd59a454beecb0dae8e767a25bb37994de2a014f43","af7ede2ef236aaa2083b492eb0b57b833bf813249ee91c94be63bd8880478ee3","f8a94383d6f72b5d288fa4fa09260fcd679a54403aa1527cb67b71e88fa0400b","d165064e8883f2570d35d0a780d80a394b2efa03445c99737b1d09bffcaa354d","8d14cf166c8f6f0a8563f7ea58bb88dfa507bc1374690d72e07b2414e7f0ec72","60794174640b02141441fbbba83cec65397fa462f2dc86fb512f1f3cfbd6e8af","086cceb0b6b332a1e74131104e911ea622aeb4cfb388c295c87d229ecb4a2e6c",{"version":"4051f6311deb0ce6052329eeb1cd4b1b104378fe52f882f483130bea75f92197","impliedFormat":1},"160eb2c958e4f6d73677c19a6f401d301698c392f0e76838f59955579b3a3e06","3745ae4cd217bdb6f775bfe6a8e92582a8b8316d691847df0aaccac491341e61","f9463828bb8ace2ca6d8267c2d7fe1d82fefd619123692d89a0ce6ecad012d37","f5c7c443338e2764761a9e402f98d3f3754b929ccd112e4cf0df58d13e44960f","a79e5251a9910e79d2eee01a3967ee550292fc5dd63e3f7a8eaca4270739c4cd","7b8583231528ebae505db574f6b2310f50bb3e62cf1ba59c7deaa0e33ed040d4","11422f1a01a0d5247d278dce4ca54c1bfb4964922a24fca846a3526e1a9338e6","2bf5d00c4a73796533c3cf504c8dcef8e910a7c57d4ff8a24b858e24e488de8f","cfd9d21f2d2c7d9b124518c8ea653b956aea17f6271315845b28151422b5ceb3","17a15fb9bbc36593d6e1a98270ed1825229020dea4377073273481211e50c242","1421ff768aeba1e18ae6b562cec87de9e00860d1c1df7ccf179ca441f01609a2","8fedb76b4ba3d059c073da3aa2cd4585c694c7f4c96292f604a58b16a1564062","eaf0b63207c6771cbce157645473b11faf74809a722dbad297edf979a06a4e65",{"version":"ef73bcfef9907c8b772a30e5a64a6bd86a5669cba3d210fcdcc6b625e3312459","impliedFormat":1},{"version":"8b15d05f236e8537d3ecbe4422ce46bf0de4e4cd40b2f909c91c5818af4ff17a","impliedFormat":1},"977654e3a808b6e4be8a7bb8965d36ef88fb4e9a7b69aa0aed36c44cf733477b","4af8c78ed17e46cde04b067d8c72a511b0af5d195f6adb2708a82c1f89287336","07dc4a80bdcf4c0b192e155a9b42b249d5ea02f3d50c93dda2f9d7e0c7f80a2d","dfdbbbc3eb8f4ec5d0e5dd0b7da41d71e672fe7a31b51095452ae4801b5f360f","35f22d21ca29d0d2789ccb04a77f8e922b396a06660121882df0ab5127661d72",{"version":"40eb4eb274d7def754b3352c23328af96a69261fe5e99d20df41f1d5de8d0f5e","impliedFormat":1},"c055c6dfdfe0bc857811e0969dabab2ba3f2fee469ba1ed4da93e1d9702176a3","227ce148b7c12185acd0ad544a580e467ae84253a01139e7aa0672f4990a1126",{"version":"be1cc4d94ea60cbe567bc29ed479d42587bf1e6cba490f123d329976b0fe4ee5","impliedFormat":1},{"version":"151ff381ef9ff8da2da9b9663ebf657eac35c4c9a19183420c05728f31a6761d","impliedFormat":1},{"version":"f3d8c757e148ad968f0d98697987db363070abada5f503da3c06aefd9d4248c1","impliedFormat":1},{"version":"a4a39b5714adfcadd3bbea6698ca2e942606d833bde62ad5fb6ec55f5e438ff8","impliedFormat":1},{"version":"bbc1d029093135d7d9bfa4b38cbf8761db505026cc458b5e9c8b74f4000e5e75","impliedFormat":1},{"version":"1f68ab0e055994eb337b67aa87d2a15e0200951e9664959b3866ee6f6b11a0fe","impliedFormat":1}],"root":[8,[12,17],41,42],"options":{"composite":true,"declarationMap":true,"outDir":"./dist","rootDir":"./src"},"referencedMap":[[48,1],[47,2],[46,3],[43,4],[11,5],[40,4],[41,6],[15,7],[42,8],[8,9],[14,10],[12,4],[13,4],[17,11],[30,12],[27,13],[20,14],[21,4],[22,4],[23,4],[29,4],[24,4],[25,4],[28,4],[26,4],[39,15],[36,16],[35,17]],"semanticDiagnosticsPerFile":[[8,[{"start":83,"length":22,"messageText":"Module './CentrifugoProvider' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/centrifugo/src/context/CentrifugoProvider.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[11,[{"start":1482,"length":8,"messageText":"Cannot find name 'Iterable'.","category":1,"code":2304},{"start":14019,"length":9,"messageText":"Type alias 'ReactNode' circularly references itself.","category":1,"code":2456},{"start":14115,"length":8,"messageText":"Cannot find name 'Iterable'.","category":1,"code":2304}]],[12,[{"start":198,"length":9,"messageText":"Cannot find module 'consola' or its corresponding type declarations.","category":1,"code":2307},{"start":816,"length":7,"messageText":"Cannot find name 'process'. Do you need to install type definitions for node? Try `npm i --save-dev @types/node`.","category":1,"code":2580}]],[13,[{"start":549,"length":11,"messageText":"Cannot find module './context' or its corresponding type declarations.","category":1,"code":2307}]],[15,[{"start":78,"length":19,"messageText":"Module './CentrifugoDebug' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/centrifugo/src/components/CentrifugoDebug.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[18,[{"start":55,"length":10,"messageText":"Module './button' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/button.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":98,"length":19,"messageText":"Module './button-download' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/button-download.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":160,"length":19,"messageText":"Module './button-download' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/button-download.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":267,"length":8,"messageText":"Module './card' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/card.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":299,"length":9,"messageText":"Module './badge' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/badge.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":332,"length":9,"messageText":"Module './input' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/input.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":368,"length":12,"messageText":"Module './textarea' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/textarea.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":404,"length":9,"messageText":"Module './label' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/label.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":454,"length":11,"messageText":"Module './section' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/section.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":501,"length":23,"messageText":"Module './image-with-fallback' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/image-with-fallback.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":571,"length":12,"messageText":"Module './checkbox' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/checkbox.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":628,"length":15,"messageText":"Module './radio-group' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/radio-group.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":723,"length":10,"messageText":"Module './select' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/select.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":760,"length":12,"messageText":"Module './combobox' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/combobox.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":825,"length":12,"messageText":"Module './combobox' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/combobox.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":862,"length":10,"messageText":"Module './switch' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/switch.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":897,"length":10,"messageText":"Module './slider' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/slider.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":963,"length":13,"messageText":"Module './input-otp' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/input-otp.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1026,"length":13,"messageText":"Module './separator' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/separator.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1066,"length":12,"messageText":"Module './skeleton' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/skeleton.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1108,"length":16,"messageText":"Module './aspect-ratio' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/aspect-ratio.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1164,"length":15,"messageText":"Module './scroll-area' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/scroll-area.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1250,"length":13,"messageText":"Module './resizable' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/resizable.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1288,"length":10,"messageText":"Module './sticky' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/sticky.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1515,"length":19,"messageText":"Module './navigation-menu' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/navigation-menu.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1668,"length":14,"messageText":"Module './breadcrumb' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/breadcrumb.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1721,"length":25,"messageText":"Module './breadcrumb-navigation' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/breadcrumb-navigation.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1839,"length":25,"messageText":"Module './breadcrumb-navigation' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/breadcrumb-navigation.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":1983,"length":11,"messageText":"Module './menubar' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/menubar.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2145,"length":10,"messageText":"Module './dialog' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/dialog.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2343,"length":16,"messageText":"Module './alert-dialog' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/alert-dialog.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2417,"length":11,"messageText":"Module './popover' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/popover.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2548,"length":9,"messageText":"Module './sheet' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/sheet.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2685,"length":10,"messageText":"Module './drawer' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/drawer.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2759,"length":14,"messageText":"Module './hover-card' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/hover-card.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2848,"length":11,"messageText":"Module './tooltip' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/tooltip.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":2981,"length":9,"messageText":"Module './table' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/table.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3049,"length":8,"messageText":"Module './tabs' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/tabs.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3136,"length":13,"messageText":"Module './accordion' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/accordion.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3219,"length":15,"messageText":"Module './collapsible' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/collapsible.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3261,"length":12,"messageText":"Module './progress' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/progress.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3327,"length":10,"messageText":"Module './avatar' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/avatar.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3364,"length":12,"messageText":"Module './calendar' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/calendar.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3466,"length":12,"messageText":"Module './carousel' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/carousel.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3614,"length":14,"messageText":"Module './pagination' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/pagination.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3660,"length":18,"messageText":"Module './ssr-pagination' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/ssr-pagination.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3753,"length":21,"messageText":"Module './pagination-static' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/pagination-static.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3818,"length":21,"messageText":"Module './pagination-static' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/pagination-static.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3867,"length":14,"messageText":"Module './token-icon' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/token-icon.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":3919,"length":14,"messageText":"Module './token-icon' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/token-icon.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4067,"length":9,"messageText":"Module './chart' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/chart.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4128,"length":10,"messageText":"Module './toggle' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/toggle.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4185,"length":16,"messageText":"Module './toggle-group' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/toggle-group.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4345,"length":11,"messageText":"Module './command' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/command.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4636,"length":16,"messageText":"Module './context-menu' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/context-menu.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":4964,"length":17,"messageText":"Module './dropdown-menu' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/dropdown-menu.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5059,"length":9,"messageText":"Module './alert' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/alert.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5177,"length":9,"messageText":"Module './toast' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/toast.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5212,"length":11,"messageText":"Module './toaster' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/toaster.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5355,"length":8,"messageText":"Module './form' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/form.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5393,"length":16,"messageText":"Module './button-group' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/button-group.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5502,"length":9,"messageText":"Module './empty' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/empty.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5537,"length":11,"messageText":"Module './spinner' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/spinner.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5580,"length":7,"messageText":"Module './kbd' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/kbd.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5616,"length":15,"messageText":"Module './input-group' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/input-group.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5654,"length":8,"messageText":"Module './item' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/item.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":5686,"length":9,"messageText":"Module './field' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/field.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":6182,"length":11,"messageText":"Module './sidebar' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/sidebar.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":6223,"length":15,"messageText":"Module './phone-input' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/phone-input.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[20,[{"start":7,"length":6,"messageText":"Module '\"/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/node_modules/.pnpm/moment@2.30.1/node_modules/moment/ts3.1-typings/moment\"' can only be default-imported using the 'esModuleInterop' flag","category":1,"code":1259,"relatedInformation":[{"file":"../../node_modules/.pnpm/moment@2.30.1/node_modules/moment/ts3.1-typings/moment.d.ts","start":23282,"length":16,"messageText":"This module is declared with 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.","category":1,"code":2594}]}]],[21,[{"start":481,"length":6,"messageText":"Cannot find namespace 'NodeJS'.","category":1,"code":2503}]],[22,[{"start":727,"length":7,"code":2550,"category":1,"messageText":"Property 'entries' does not exist on type 'ObjectConstructor'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2017' or later."}]],[23,[{"start":267,"length":3,"messageText":"Cannot find name 'Set'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583},{"start":297,"length":3,"messageText":"Cannot find name 'Set'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583}]],[26,[{"start":143,"length":21,"messageText":"Module '../components/toast' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/components/toast.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":586,"length":16,"code":2339,"category":1,"messageText":"Property 'MAX_SAFE_INTEGER' does not exist on type 'NumberConstructor'."},{"start":1090,"length":3,"messageText":"Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583}]],[30,[{"start":492,"length":13,"messageText":"Module './useMobile' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/hooks/useMobile.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[31,[{"start":14,"length":14,"messageText":"Module './CTASection' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/CTASection.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":44,"length":18,"messageText":"Module './FeatureSection' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/FeatureSection.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":78,"length":8,"messageText":"Module './Hero' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/Hero.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":102,"length":21,"messageText":"Module './NewsletterSection' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/NewsletterSection.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":139,"length":16,"messageText":"Module './StatsSection' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/StatsSection.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":171,"length":13,"messageText":"Module './SuperHero' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/SuperHero.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":200,"length":22,"messageText":"Module './TestimonialSection' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/blocks/TestimonialSection.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[32,[{"start":35,"length":22,"messageText":"Module './AnimatedBackground' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/animations/AnimatedBackground.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":98,"length":22,"messageText":"Module './AnimatedBackground' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/animations/AnimatedBackground.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[37,[{"start":367,"length":12,"messageText":"Module './JsonTree' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/tools/JsonTree/index.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":417,"length":12,"messageText":"Module './JsonTree' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/tools/JsonTree/index.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":466,"length":11,"messageText":"Module './Mermaid' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/tools/Mermaid/index.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":517,"length":14,"messageText":"Module './PrettyCode' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/tools/PrettyCode/index.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":563,"length":14,"messageText":"Module './PrettyCode' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/tools/PrettyCode/index.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[38,[{"start":47,"length":17,"messageText":"Module './ThemeProvider' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/theme/ThemeProvider.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":94,"length":15,"messageText":"Module './ThemeToggle' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/theme/ThemeToggle.tsx', but '--jsx' is not set.","category":1,"code":6142},{"start":138,"length":14,"messageText":"Module './ForceTheme' was resolved to '/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/packages/ui/src/theme/ForceTheme.tsx', but '--jsx' is not set.","category":1,"code":6142}]],[40,[{"start":41,"length":8,"messageText":"Module '\"../../../../../../packages/centrifugo/node_modules/@types/react\"' has no exported member 'ReactSVG'.","category":1,"code":2305}]],[41,[{"start":130,"length":5,"messageText":"Module '\"/Users/markinmatrix/Documents/htdocs/@CARAPIS/encar_parser_new/@projects/django-cfg/projects/django-cfg-dev/src/django_admin/node_modules/.pnpm/@types+react@19.2.2/node_modules/@types/react/index\"' can only be default-imported using the 'esModuleInterop' flag","category":1,"code":1259,"relatedInformation":[{"file":"../../node_modules/.pnpm/@types+react@19.2.2/node_modules/@types/react/index.d.ts","start":2169,"length":15,"messageText":"This module is declared with 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.","category":1,"code":2594}]},{"start":1110,"length":72,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1189,"length":28,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1226,"length":29,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1266,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1330,"length":41,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1419,"length":77,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1533,"length":78,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1643,"length":33,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1736,"length":161,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":1912,"length":47,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2030,"length":43,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2120,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2184,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2251,"length":57,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2420,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2484,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2558,"length":57,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2743,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2807,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":2880,"length":55,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3028,"length":30,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3095,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3159,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3226,"length":52,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3408,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3472,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3551,"length":59,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3744,"length":51,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3808,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":3878,"length":60,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4120,"length":27,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4162,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4231,"length":59,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4514,"length":27,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4556,"length":41,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4614,"length":85,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4716,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":4844,"length":49,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5095,"length":27,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5137,"length":40,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5211,"length":49,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5453,"length":27,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5495,"length":61,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5584,"length":100,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5781,"length":30,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5863,"length":73,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":5949,"length":62,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6080,"length":50,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6180,"length":50,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6327,"length":29,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6504,"length":68,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6610,"length":5,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6674,"length":5,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6740,"length":5,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004},{"start":6817,"length":5,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004}]],[42,[{"file":false,"messageText":"Cannot find global value 'Promise'.","category":1,"code":2468},{"start":1100,"length":6,"messageText":"Cannot find namespace 'NodeJS'.","category":1,"code":2503},{"start":2568,"length":13,"messageText":"An async function or method in ES5 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your '--lib' option.","category":1,"code":2705},{"start":4214,"length":8,"code":2550,"category":1,"messageText":"Property 'includes' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later."},{"start":4275,"length":8,"code":2550,"category":1,"messageText":"Property 'includes' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later."},{"start":4335,"length":8,"code":2550,"category":1,"messageText":"Property 'includes' does not exist on type 'string'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later."},{"start":5425,"length":13,"messageText":"An async function or method in ES5 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your '--lib' option.","category":1,"code":2705},{"start":6260,"length":42,"messageText":"Cannot use JSX unless the '--jsx' flag is provided.","category":1,"code":17004}]],[46,[{"start":90,"length":3,"messageText":"Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583},{"start":571,"length":16,"messageText":"Cannot find name 'IterableIterator'.","category":1,"code":2304}]],[47,[{"start":1567,"length":3,"messageText":"Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583},{"start":36676,"length":16,"messageText":"Cannot find name 'IterableIterator'.","category":1,"code":2304},{"start":39333,"length":3,"messageText":"Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583}]],[48,[{"start":755,"length":3,"messageText":"Cannot find name 'Map'. Do you need to change your target library? Try changing the 'lib' compiler option to 'es2015' or later.","category":1,"code":2583}]]],"affectedFilesPendingEmit":[41,15,42,8,14,12,13,17,16],"emitSignatures":[8,12,13,14,15,16,17,41,42],"version":"5.9.3"}