@djangocfg/monitor 2.1.216

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.
Files changed (62) hide show
  1. package/README.md +341 -0
  2. package/dist/client.cjs +1273 -0
  3. package/dist/client.cjs.map +1 -0
  4. package/dist/client.d.cts +123 -0
  5. package/dist/client.d.ts +123 -0
  6. package/dist/client.mjs +1243 -0
  7. package/dist/client.mjs.map +1 -0
  8. package/dist/index.cjs +18 -0
  9. package/dist/index.cjs.map +1 -0
  10. package/dist/index.d.cts +101 -0
  11. package/dist/index.d.ts +101 -0
  12. package/dist/index.mjs +1 -0
  13. package/dist/index.mjs.map +1 -0
  14. package/dist/server.cjs +947 -0
  15. package/dist/server.cjs.map +1 -0
  16. package/dist/server.d.cts +117 -0
  17. package/dist/server.d.ts +117 -0
  18. package/dist/server.mjs +917 -0
  19. package/dist/server.mjs.map +1 -0
  20. package/package.json +82 -0
  21. package/src/.claude/.sidecar/activity.jsonl +1 -0
  22. package/src/.claude/.sidecar/map_cache.json +38 -0
  23. package/src/.claude/.sidecar/usage.json +5 -0
  24. package/src/.claude/project-map.md +29 -0
  25. package/src/_api/BaseClient.ts +18 -0
  26. package/src/_api/generated/cfg_monitor/CLAUDE.md +60 -0
  27. package/src/_api/generated/cfg_monitor/_utils/fetchers/index.ts +30 -0
  28. package/src/_api/generated/cfg_monitor/_utils/fetchers/monitor.ts +51 -0
  29. package/src/_api/generated/cfg_monitor/_utils/hooks/index.ts +30 -0
  30. package/src/_api/generated/cfg_monitor/_utils/hooks/monitor.ts +43 -0
  31. package/src/_api/generated/cfg_monitor/_utils/schemas/FrontendEventIngestRequest.schema.ts +34 -0
  32. package/src/_api/generated/cfg_monitor/_utils/schemas/IngestBatchRequest.schema.ts +20 -0
  33. package/src/_api/generated/cfg_monitor/_utils/schemas/index.ts +22 -0
  34. package/src/_api/generated/cfg_monitor/api-instance.ts +181 -0
  35. package/src/_api/generated/cfg_monitor/client.ts +322 -0
  36. package/src/_api/generated/cfg_monitor/enums.ts +36 -0
  37. package/src/_api/generated/cfg_monitor/errors.ts +118 -0
  38. package/src/_api/generated/cfg_monitor/http.ts +137 -0
  39. package/src/_api/generated/cfg_monitor/index.ts +317 -0
  40. package/src/_api/generated/cfg_monitor/logger.ts +261 -0
  41. package/src/_api/generated/cfg_monitor/monitor/client.ts +25 -0
  42. package/src/_api/generated/cfg_monitor/monitor/index.ts +4 -0
  43. package/src/_api/generated/cfg_monitor/monitor/models.ts +48 -0
  44. package/src/_api/generated/cfg_monitor/retry.ts +177 -0
  45. package/src/_api/generated/cfg_monitor/schema.json +184 -0
  46. package/src/_api/generated/cfg_monitor/storage.ts +163 -0
  47. package/src/_api/generated/cfg_monitor/validation-events.ts +135 -0
  48. package/src/_api/index.ts +6 -0
  49. package/src/client/capture/console.ts +72 -0
  50. package/src/client/capture/fingerprint.ts +27 -0
  51. package/src/client/capture/js-errors.ts +70 -0
  52. package/src/client/capture/network.ts +47 -0
  53. package/src/client/capture/session.ts +33 -0
  54. package/src/client/capture/validation.ts +38 -0
  55. package/src/client/index.ts +72 -0
  56. package/src/client/store/index.ts +41 -0
  57. package/src/client/transport/ingest.ts +31 -0
  58. package/src/index.ts +12 -0
  59. package/src/server/index.ts +85 -0
  60. package/src/types/config.ts +33 -0
  61. package/src/types/events.ts +5 -0
  62. package/src/types/index.ts +6 -0
@@ -0,0 +1,25 @@
1
+ // @ts-nocheck
2
+ import * as Models from "./models";
3
+
4
+
5
+ /**
6
+ * API endpoints for Monitor.
7
+ */
8
+ export class Monitor {
9
+ private client: any;
10
+
11
+ constructor(client: any) {
12
+ this.client = client;
13
+ }
14
+
15
+ /**
16
+ * Ingest browser events
17
+ *
18
+ * Accepts a batch of up to 50 frontend events. No authentication required.
19
+ */
20
+ async ingestCreate(data: Models.IngestBatchRequest): Promise<any> {
21
+ const response = await this.client.request('POST', "/cfg/monitor/ingest/", { body: data });
22
+ return response;
23
+ }
24
+
25
+ }
@@ -0,0 +1,4 @@
1
+ // @ts-nocheck
2
+ // Auto-generated by DjangoCFG - see CLAUDE.md
3
+ export * from "./client";
4
+ export * as Models from "./models";
@@ -0,0 +1,48 @@
1
+ // @ts-nocheck
2
+ // Auto-generated by DjangoCFG - see CLAUDE.md
3
+ import * as Enums from "../enums";
4
+
5
+ /**
6
+ * Wraps a list of events. Enforces max batch size.
7
+ *
8
+ * Request model (no read-only fields).
9
+ */
10
+ export interface IngestBatchRequest {
11
+ events: Array<FrontendEventIngestRequest>;
12
+ }
13
+
14
+ /**
15
+ * Validates a single event from the browser.
16
+ *
17
+ * Request model (no read-only fields).
18
+ */
19
+ export interface FrontendEventIngestRequest {
20
+ /** * `ERROR` - Error
21
+ * `WARNING` - Warning
22
+ * `INFO` - Info
23
+ * `PAGE_VIEW` - Page View
24
+ * `PERFORMANCE` - Performance
25
+ * `NETWORK_ERROR` - Network Error
26
+ * `JS_ERROR` - JS Error
27
+ * `CONSOLE` - Console */
28
+ event_type: Enums.FrontendEventIngestRequestEventType;
29
+ message: string;
30
+ /** * `error` - Error
31
+ * `warn` - Warning
32
+ * `info` - Info
33
+ * `debug` - Debug */
34
+ level?: Enums.FrontendEventIngestRequestLevel;
35
+ stack_trace?: string;
36
+ url?: string;
37
+ fingerprint?: string;
38
+ http_status?: number | null;
39
+ http_method?: string;
40
+ http_url?: string;
41
+ user_agent?: string;
42
+ session_id?: string | null;
43
+ browser_fingerprint?: string;
44
+ extra?: Record<string, any>;
45
+ project_name?: string;
46
+ environment?: string;
47
+ }
48
+
@@ -0,0 +1,177 @@
1
+ // @ts-nocheck
2
+ // Auto-generated by DjangoCFG - see CLAUDE.md
3
+ /**
4
+ * Retry Configuration and Utilities
5
+ *
6
+ * Provides automatic retry logic for failed HTTP requests using p-retry.
7
+ * Retries only on network errors and server errors (5xx), not client errors (4xx).
8
+ */
9
+
10
+ import pRetry, { AbortError } from 'p-retry';
11
+ import { APIError, NetworkError } from './errors';
12
+
13
+ /**
14
+ * Information about a failed retry attempt.
15
+ */
16
+ export interface FailedAttemptInfo {
17
+ /** The error that caused the failure */
18
+ error: Error;
19
+ /** The attempt number (1-indexed) */
20
+ attemptNumber: number;
21
+ /** Number of retries left */
22
+ retriesLeft: number;
23
+ }
24
+
25
+ /**
26
+ * Retry configuration options.
27
+ *
28
+ * Uses exponential backoff with jitter by default to avoid thundering herd.
29
+ */
30
+ export interface RetryConfig {
31
+ /**
32
+ * Maximum number of retry attempts.
33
+ * @default 3
34
+ */
35
+ retries?: number;
36
+
37
+ /**
38
+ * Exponential backoff factor.
39
+ * @default 2
40
+ */
41
+ factor?: number;
42
+
43
+ /**
44
+ * Minimum wait time between retries (ms).
45
+ * @default 1000
46
+ */
47
+ minTimeout?: number;
48
+
49
+ /**
50
+ * Maximum wait time between retries (ms).
51
+ * @default 60000
52
+ */
53
+ maxTimeout?: number;
54
+
55
+ /**
56
+ * Add randomness to wait times (jitter).
57
+ * Helps avoid thundering herd problem.
58
+ * @default true
59
+ */
60
+ randomize?: boolean;
61
+
62
+ /**
63
+ * Callback called on each failed attempt.
64
+ */
65
+ onFailedAttempt?: (info: FailedAttemptInfo) => void;
66
+ }
67
+
68
+ /**
69
+ * Default retry configuration.
70
+ */
71
+ export const DEFAULT_RETRY_CONFIG: Required<RetryConfig> = {
72
+ retries: 3,
73
+ factor: 2,
74
+ minTimeout: 1000,
75
+ maxTimeout: 60000,
76
+ randomize: true,
77
+ onFailedAttempt: () => {},
78
+ };
79
+
80
+ /**
81
+ * Determine if an error should trigger a retry.
82
+ *
83
+ * Retries on:
84
+ * - Network errors (connection refused, timeout, etc.)
85
+ * - Server errors (5xx status codes)
86
+ * - Rate limiting (429 status code)
87
+ *
88
+ * Does NOT retry on:
89
+ * - Client errors (4xx except 429)
90
+ * - Authentication errors (401, 403)
91
+ * - Not found (404)
92
+ *
93
+ * @param error - The error to check
94
+ * @returns true if should retry, false otherwise
95
+ */
96
+ export function shouldRetry(error: any): boolean {
97
+ // Always retry network errors
98
+ if (error instanceof NetworkError) {
99
+ return true;
100
+ }
101
+
102
+ // For API errors, check status code
103
+ if (error instanceof APIError) {
104
+ const status = error.statusCode;
105
+
106
+ // Retry on 5xx server errors
107
+ if (status >= 500 && status < 600) {
108
+ return true;
109
+ }
110
+
111
+ // Retry on 429 (rate limit)
112
+ if (status === 429) {
113
+ return true;
114
+ }
115
+
116
+ // Do NOT retry on 4xx client errors
117
+ return false;
118
+ }
119
+
120
+ // Retry on unknown errors (might be network issues)
121
+ return true;
122
+ }
123
+
124
+ /**
125
+ * Wrap a function with retry logic.
126
+ *
127
+ * @param fn - Async function to retry
128
+ * @param config - Retry configuration
129
+ * @returns Result of the function
130
+ *
131
+ * @example
132
+ * ```typescript
133
+ * const result = await withRetry(
134
+ * async () => fetch('https://api.example.com/users'),
135
+ * { retries: 5, minTimeout: 2000 }
136
+ * );
137
+ * ```
138
+ */
139
+ export async function withRetry<T>(
140
+ fn: () => Promise<T>,
141
+ config?: RetryConfig
142
+ ): Promise<T> {
143
+ const finalConfig = { ...DEFAULT_RETRY_CONFIG, ...config };
144
+
145
+ return pRetry(
146
+ async () => {
147
+ try {
148
+ return await fn();
149
+ } catch (error) {
150
+ // Check if we should retry this error
151
+ if (!shouldRetry(error)) {
152
+ // Abort retry immediately for non-retryable errors
153
+ throw new AbortError(error as Error);
154
+ }
155
+
156
+ // Re-throw error to trigger retry
157
+ throw error;
158
+ }
159
+ },
160
+ {
161
+ retries: finalConfig.retries,
162
+ factor: finalConfig.factor,
163
+ minTimeout: finalConfig.minTimeout,
164
+ maxTimeout: finalConfig.maxTimeout,
165
+ randomize: finalConfig.randomize,
166
+ onFailedAttempt: finalConfig.onFailedAttempt ? (error) => {
167
+ // Adapt p-retry's FailedAttemptError to our FailedAttemptInfo
168
+ const pRetryError = error as any; // p-retry's internal type
169
+ finalConfig.onFailedAttempt!({
170
+ error: pRetryError as Error,
171
+ attemptNumber: pRetryError.attemptNumber,
172
+ retriesLeft: pRetryError.retriesLeft,
173
+ });
174
+ } : undefined,
175
+ }
176
+ );
177
+ }
@@ -0,0 +1,184 @@
1
+ {
2
+ "openapi": "3.1.0",
3
+ "info": {
4
+ "title": "Django CFG API",
5
+ "version": "1.0.0",
6
+ "description": "Complete API documentation for Django CFG Demo Project",
7
+ "x-django-metadata": {
8
+ "group": "cfg_monitor",
9
+ "apps": [
10
+ "django_cfg_monitor"
11
+ ],
12
+ "generator": "django-client",
13
+ "generator_version": "1.0.0"
14
+ }
15
+ },
16
+ "paths": {
17
+ "/cfg/monitor/ingest/": {
18
+ "post": {
19
+ "operationId": "cfg_monitor_ingest_create",
20
+ "description": "Accepts a batch of up to 50 frontend events. No authentication required.",
21
+ "summary": "Ingest browser events",
22
+ "tags": [
23
+ "monitor"
24
+ ],
25
+ "requestBody": {
26
+ "content": {
27
+ "application/json": {
28
+ "schema": {
29
+ "$ref": "#/components/schemas/IngestBatchRequest"
30
+ }
31
+ },
32
+ "application/x-www-form-urlencoded": {
33
+ "schema": {
34
+ "$ref": "#/components/schemas/IngestBatchRequest"
35
+ }
36
+ },
37
+ "multipart/form-data": {
38
+ "schema": {
39
+ "$ref": "#/components/schemas/IngestBatchRequest"
40
+ }
41
+ }
42
+ },
43
+ "required": true
44
+ },
45
+ "security": [
46
+ {}
47
+ ],
48
+ "responses": {
49
+ "202": {
50
+ "description": "Accepted"
51
+ }
52
+ },
53
+ "x-async-capable": false
54
+ }
55
+ }
56
+ },
57
+ "components": {
58
+ "schemas": {
59
+ "FrontendEventIngestRequest": {
60
+ "type": "object",
61
+ "description": "Validates a single event from the browser.",
62
+ "properties": {
63
+ "event_type": {
64
+ "enum": [
65
+ "ERROR",
66
+ "WARNING",
67
+ "INFO",
68
+ "PAGE_VIEW",
69
+ "PERFORMANCE",
70
+ "NETWORK_ERROR",
71
+ "JS_ERROR",
72
+ "CONSOLE"
73
+ ],
74
+ "type": "string",
75
+ "description": "* `ERROR` - Error\n* `WARNING` - Warning\n* `INFO` - Info\n* `PAGE_VIEW` - Page View\n* `PERFORMANCE` - Performance\n* `NETWORK_ERROR` - Network Error\n* `JS_ERROR` - JS Error\n* `CONSOLE` - Console",
76
+ "x-spec-enum-id": "de9da4754700e7fc"
77
+ },
78
+ "message": {
79
+ "type": "string",
80
+ "minLength": 1,
81
+ "maxLength": 5000
82
+ },
83
+ "level": {
84
+ "enum": [
85
+ "error",
86
+ "warn",
87
+ "info",
88
+ "debug"
89
+ ],
90
+ "type": "string",
91
+ "description": "* `error` - Error\n* `warn` - Warning\n* `info` - Info\n* `debug` - Debug",
92
+ "x-spec-enum-id": "bef029ce9fe8228d",
93
+ "default": "info"
94
+ },
95
+ "stack_trace": {
96
+ "type": "string",
97
+ "default": "",
98
+ "maxLength": 20000
99
+ },
100
+ "url": {
101
+ "type": "string",
102
+ "default": "",
103
+ "maxLength": 2000
104
+ },
105
+ "fingerprint": {
106
+ "type": "string",
107
+ "default": "",
108
+ "maxLength": 64
109
+ },
110
+ "http_status": {
111
+ "type": [
112
+ "integer",
113
+ "null"
114
+ ]
115
+ },
116
+ "http_method": {
117
+ "type": "string",
118
+ "default": "",
119
+ "maxLength": 10
120
+ },
121
+ "http_url": {
122
+ "type": "string",
123
+ "default": "",
124
+ "maxLength": 2000
125
+ },
126
+ "user_agent": {
127
+ "type": "string",
128
+ "default": "",
129
+ "maxLength": 500
130
+ },
131
+ "session_id": {
132
+ "type": [
133
+ "string",
134
+ "null"
135
+ ],
136
+ "format": "uuid"
137
+ },
138
+ "browser_fingerprint": {
139
+ "type": "string",
140
+ "default": "",
141
+ "maxLength": 64
142
+ },
143
+ "extra": {},
144
+ "project_name": {
145
+ "type": "string",
146
+ "default": "",
147
+ "maxLength": 100
148
+ },
149
+ "environment": {
150
+ "type": "string",
151
+ "default": "",
152
+ "maxLength": 20
153
+ }
154
+ },
155
+ "required": [
156
+ "event_type",
157
+ "message"
158
+ ]
159
+ },
160
+ "IngestBatchRequest": {
161
+ "type": "object",
162
+ "description": "Wraps a list of events. Enforces max batch size.",
163
+ "properties": {
164
+ "events": {
165
+ "type": "array",
166
+ "items": {
167
+ "$ref": "#/components/schemas/FrontendEventIngestRequest"
168
+ },
169
+ "maxItems": 50,
170
+ "minItems": 1
171
+ }
172
+ },
173
+ "required": [
174
+ "events"
175
+ ]
176
+ }
177
+ }
178
+ },
179
+ "servers": [
180
+ {
181
+ "url": "http://localhost:8000"
182
+ }
183
+ ]
184
+ }
@@ -0,0 +1,163 @@
1
+ // @ts-nocheck
2
+ // Auto-generated by DjangoCFG - see CLAUDE.md
3
+ /**
4
+ * Storage adapters for cross-platform token storage.
5
+ *
6
+ * Supports:
7
+ * - LocalStorage (browser)
8
+ * - Cookies (SSR/browser)
9
+ * - Memory (Node.js/Electron/testing)
10
+ */
11
+
12
+ import type { APILogger } from './logger';
13
+
14
+ /**
15
+ * Storage adapter interface for cross-platform token storage.
16
+ */
17
+ export interface StorageAdapter {
18
+ getItem(key: string): string | null;
19
+ setItem(key: string, value: string): void;
20
+ removeItem(key: string): void;
21
+ }
22
+
23
+ /**
24
+ * LocalStorage adapter with safe try-catch for browser environments.
25
+ * Works in modern browsers with localStorage support.
26
+ *
27
+ * Note: This adapter uses window.localStorage and should only be used in browser/client environments.
28
+ * For server-side usage, use MemoryStorageAdapter or CookieStorageAdapter instead.
29
+ */
30
+ export class LocalStorageAdapter implements StorageAdapter {
31
+ private logger?: APILogger;
32
+
33
+ constructor(logger?: APILogger) {
34
+ this.logger = logger;
35
+ }
36
+
37
+ getItem(key: string): string | null {
38
+ try {
39
+ if (typeof window !== 'undefined' && window.localStorage) {
40
+ const value = localStorage.getItem(key);
41
+ this.logger?.debug(`LocalStorage.getItem("${key}"): ${value ? 'found' : 'not found'}`);
42
+ return value;
43
+ }
44
+ this.logger?.warn('LocalStorage not available: window.localStorage is undefined');
45
+ } catch (error) {
46
+ this.logger?.error('LocalStorage.getItem failed:', error);
47
+ }
48
+ return null;
49
+ }
50
+
51
+ setItem(key: string, value: string): void {
52
+ try {
53
+ if (typeof window !== 'undefined' && window.localStorage) {
54
+ localStorage.setItem(key, value);
55
+ this.logger?.debug(`LocalStorage.setItem("${key}"): success`);
56
+ } else {
57
+ this.logger?.warn('LocalStorage not available: window.localStorage is undefined');
58
+ }
59
+ } catch (error) {
60
+ this.logger?.error('LocalStorage.setItem failed:', error);
61
+ }
62
+ }
63
+
64
+ removeItem(key: string): void {
65
+ try {
66
+ if (typeof window !== 'undefined' && window.localStorage) {
67
+ localStorage.removeItem(key);
68
+ this.logger?.debug(`LocalStorage.removeItem("${key}"): success`);
69
+ } else {
70
+ this.logger?.warn('LocalStorage not available: window.localStorage is undefined');
71
+ }
72
+ } catch (error) {
73
+ this.logger?.error('LocalStorage.removeItem failed:', error);
74
+ }
75
+ }
76
+ }
77
+
78
+ /**
79
+ * Cookie-based storage adapter for SSR and browser environments.
80
+ * Useful for Next.js, Nuxt.js, and other SSR frameworks.
81
+ */
82
+ export class CookieStorageAdapter implements StorageAdapter {
83
+ private logger?: APILogger;
84
+
85
+ constructor(logger?: APILogger) {
86
+ this.logger = logger;
87
+ }
88
+
89
+ getItem(key: string): string | null {
90
+ try {
91
+ if (typeof document === 'undefined') {
92
+ this.logger?.warn('Cookies not available: document is undefined (SSR context?)');
93
+ return null;
94
+ }
95
+ const value = `; ${document.cookie}`;
96
+ const parts = value.split(`; ${key}=`);
97
+ if (parts.length === 2) {
98
+ const result = parts.pop()?.split(';').shift() || null;
99
+ this.logger?.debug(`CookieStorage.getItem("${key}"): ${result ? 'found' : 'not found'}`);
100
+ return result;
101
+ }
102
+ this.logger?.debug(`CookieStorage.getItem("${key}"): not found`);
103
+ } catch (error) {
104
+ this.logger?.error('CookieStorage.getItem failed:', error);
105
+ }
106
+ return null;
107
+ }
108
+
109
+ setItem(key: string, value: string): void {
110
+ try {
111
+ if (typeof document !== 'undefined') {
112
+ document.cookie = `${key}=${value}; path=/; max-age=31536000`;
113
+ this.logger?.debug(`CookieStorage.setItem("${key}"): success`);
114
+ } else {
115
+ this.logger?.warn('Cookies not available: document is undefined (SSR context?)');
116
+ }
117
+ } catch (error) {
118
+ this.logger?.error('CookieStorage.setItem failed:', error);
119
+ }
120
+ }
121
+
122
+ removeItem(key: string): void {
123
+ try {
124
+ if (typeof document !== 'undefined') {
125
+ document.cookie = `${key}=; path=/; expires=Thu, 01 Jan 1970 00:00:00 GMT`;
126
+ this.logger?.debug(`CookieStorage.removeItem("${key}"): success`);
127
+ } else {
128
+ this.logger?.warn('Cookies not available: document is undefined (SSR context?)');
129
+ }
130
+ } catch (error) {
131
+ this.logger?.error('CookieStorage.removeItem failed:', error);
132
+ }
133
+ }
134
+ }
135
+
136
+ /**
137
+ * In-memory storage adapter for Node.js, Electron, and testing environments.
138
+ * Data is stored in RAM and cleared when process exits.
139
+ */
140
+ export class MemoryStorageAdapter implements StorageAdapter {
141
+ private storage: Map<string, string> = new Map();
142
+ private logger?: APILogger;
143
+
144
+ constructor(logger?: APILogger) {
145
+ this.logger = logger;
146
+ }
147
+
148
+ getItem(key: string): string | null {
149
+ const value = this.storage.get(key) || null;
150
+ this.logger?.debug(`MemoryStorage.getItem("${key}"): ${value ? 'found' : 'not found'}`);
151
+ return value;
152
+ }
153
+
154
+ setItem(key: string, value: string): void {
155
+ this.storage.set(key, value);
156
+ this.logger?.debug(`MemoryStorage.setItem("${key}"): success`);
157
+ }
158
+
159
+ removeItem(key: string): void {
160
+ this.storage.delete(key);
161
+ this.logger?.debug(`MemoryStorage.removeItem("${key}"): success`);
162
+ }
163
+ }