@vinetechke/next-error-logger 0.1.0-beta.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.
Files changed (61) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +442 -0
  3. package/dist/adapters/drizzle.cjs +123 -0
  4. package/dist/adapters/drizzle.cjs.map +1 -0
  5. package/dist/adapters/drizzle.d.cts +76 -0
  6. package/dist/adapters/drizzle.d.ts +76 -0
  7. package/dist/adapters/drizzle.js +99 -0
  8. package/dist/adapters/drizzle.js.map +1 -0
  9. package/dist/adapters/prisma.cjs +120 -0
  10. package/dist/adapters/prisma.cjs.map +1 -0
  11. package/dist/adapters/prisma.d.cts +75 -0
  12. package/dist/adapters/prisma.d.ts +75 -0
  13. package/dist/adapters/prisma.js +96 -0
  14. package/dist/adapters/prisma.js.map +1 -0
  15. package/dist/adapters/sql.cjs +206 -0
  16. package/dist/adapters/sql.cjs.map +1 -0
  17. package/dist/adapters/sql.d.cts +111 -0
  18. package/dist/adapters/sql.d.ts +111 -0
  19. package/dist/adapters/sql.js +182 -0
  20. package/dist/adapters/sql.js.map +1 -0
  21. package/dist/api/index.cjs +257 -0
  22. package/dist/api/index.cjs.map +1 -0
  23. package/dist/api/index.d.cts +137 -0
  24. package/dist/api/index.d.ts +137 -0
  25. package/dist/api/index.js +231 -0
  26. package/dist/api/index.js.map +1 -0
  27. package/dist/auth/clerk.cjs +60 -0
  28. package/dist/auth/clerk.cjs.map +1 -0
  29. package/dist/auth/clerk.d.cts +83 -0
  30. package/dist/auth/clerk.d.ts +83 -0
  31. package/dist/auth/clerk.js +36 -0
  32. package/dist/auth/clerk.js.map +1 -0
  33. package/dist/auth/next-auth.cjs +50 -0
  34. package/dist/auth/next-auth.cjs.map +1 -0
  35. package/dist/auth/next-auth.d.cts +53 -0
  36. package/dist/auth/next-auth.d.ts +53 -0
  37. package/dist/auth/next-auth.js +26 -0
  38. package/dist/auth/next-auth.js.map +1 -0
  39. package/dist/components/index.cjs +1175 -0
  40. package/dist/components/index.cjs.map +1 -0
  41. package/dist/components/index.d.cts +141 -0
  42. package/dist/components/index.d.ts +141 -0
  43. package/dist/components/index.js +1147 -0
  44. package/dist/components/index.js.map +1 -0
  45. package/dist/index.cjs +241 -0
  46. package/dist/index.cjs.map +1 -0
  47. package/dist/index.d.cts +109 -0
  48. package/dist/index.d.ts +109 -0
  49. package/dist/index.js +212 -0
  50. package/dist/index.js.map +1 -0
  51. package/dist/schemas/drizzle.cjs +100 -0
  52. package/dist/schemas/drizzle.cjs.map +1 -0
  53. package/dist/schemas/drizzle.d.cts +32 -0
  54. package/dist/schemas/drizzle.d.ts +32 -0
  55. package/dist/schemas/drizzle.js +74 -0
  56. package/dist/schemas/drizzle.js.map +1 -0
  57. package/dist/types-C3x_Ry2e.d.cts +195 -0
  58. package/dist/types-C3x_Ry2e.d.ts +195 -0
  59. package/package.json +128 -0
  60. package/schemas/prisma.prisma +23 -0
  61. package/schemas/schema.sql +75 -0
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Log severity levels
3
+ */
4
+ type LogLevel = 'error' | 'warn' | 'info' | 'debug';
5
+ /**
6
+ * Represents a single error log entry stored in the database
7
+ */
8
+ interface ErrorLogEntry {
9
+ /** Unique identifier for the log entry */
10
+ id: string;
11
+ /** Severity level of the log */
12
+ level: LogLevel;
13
+ /** Human-readable error message */
14
+ message: string;
15
+ /** Full stack trace (for errors) */
16
+ stack?: string | null;
17
+ /** ID of the user who encountered the error */
18
+ userId?: string | null;
19
+ /** Email of the user who encountered the error */
20
+ userEmail?: string | null;
21
+ /** Display name of the user */
22
+ userName?: string | null;
23
+ /** URL path where the error occurred */
24
+ path?: string | null;
25
+ /** HTTP method (GET, POST, etc.) */
26
+ method?: string | null;
27
+ /** Browser/client user agent string */
28
+ userAgent?: string | null;
29
+ /** Client IP address */
30
+ ip?: string | null;
31
+ /** Additional custom metadata */
32
+ metadata?: Record<string, unknown> | null;
33
+ /** Timestamp when the error occurred */
34
+ createdAt: Date;
35
+ }
36
+ /**
37
+ * Configuration options for the error logger
38
+ */
39
+ interface ErrorLoggerConfig {
40
+ /** Database adapter for storing logs */
41
+ adapter: DatabaseAdapter;
42
+ /** Auth adapter for automatically capturing user context (optional) */
43
+ authAdapter?: AuthAdapter;
44
+ /** Number of days to retain logs (default: 30) */
45
+ retentionDays?: number;
46
+ /** Log levels to capture (default: all levels) */
47
+ levels?: LogLevel[];
48
+ /** Enable console output in development (default: true) */
49
+ consoleInDev?: boolean;
50
+ }
51
+ /**
52
+ * Database adapter interface - implement this for custom database support
53
+ */
54
+ interface DatabaseAdapter {
55
+ /**
56
+ * Create a new log entry
57
+ * @param entry - The log entry data (without id and createdAt)
58
+ * @returns The created log entry with id and createdAt
59
+ */
60
+ create(entry: Omit<ErrorLogEntry, 'id' | 'createdAt'>): Promise<ErrorLogEntry>;
61
+ /**
62
+ * Find multiple log entries with filtering and pagination
63
+ * @param options - Query options
64
+ * @returns Object containing logs array and total count
65
+ */
66
+ findMany(options: QueryOptions): Promise<{
67
+ logs: ErrorLogEntry[];
68
+ total: number;
69
+ }>;
70
+ /**
71
+ * Find a single log entry by ID
72
+ * @param id - The log entry ID
73
+ * @returns The log entry or null if not found
74
+ */
75
+ findById(id: string): Promise<ErrorLogEntry | null>;
76
+ /**
77
+ * Delete a single log entry
78
+ * @param id - The log entry ID
79
+ */
80
+ delete(id: string): Promise<void>;
81
+ /**
82
+ * Delete multiple log entries
83
+ * @param options - Filter options for deletion
84
+ * @returns Number of deleted entries
85
+ */
86
+ deleteMany(options: {
87
+ before?: Date;
88
+ level?: LogLevel;
89
+ }): Promise<number>;
90
+ }
91
+ /**
92
+ * Auth adapter interface - implement this for custom auth providers
93
+ */
94
+ interface AuthAdapter {
95
+ /**
96
+ * Get the current authenticated user
97
+ * @returns User object or null if not authenticated
98
+ */
99
+ getUser(): Promise<{
100
+ id: string;
101
+ email?: string;
102
+ name?: string;
103
+ } | null>;
104
+ }
105
+ /**
106
+ * Query options for filtering and paginating log entries
107
+ */
108
+ interface QueryOptions {
109
+ /** Page number (1-indexed, default: 1) */
110
+ page?: number;
111
+ /** Number of items per page (default: 50) */
112
+ limit?: number;
113
+ /** Filter by log level */
114
+ level?: LogLevel;
115
+ /** Filter by user ID */
116
+ userId?: string;
117
+ /** Search term for message, stack, or path */
118
+ search?: string;
119
+ /** Filter logs after this date */
120
+ startDate?: Date;
121
+ /** Filter logs before this date */
122
+ endDate?: Date;
123
+ /** Field to sort by (default: createdAt) */
124
+ orderBy?: 'createdAt' | 'level';
125
+ /** Sort direction (default: desc) */
126
+ order?: 'asc' | 'desc';
127
+ }
128
+ /**
129
+ * Context information extracted from a request
130
+ */
131
+ interface RequestContext {
132
+ /** URL path */
133
+ path?: string;
134
+ /** HTTP method */
135
+ method?: string;
136
+ /** User agent string */
137
+ userAgent?: string;
138
+ /** Client IP address */
139
+ ip?: string;
140
+ /** Additional custom metadata */
141
+ metadata?: Record<string, unknown>;
142
+ }
143
+ /**
144
+ * Result of a logging operation
145
+ */
146
+ interface LogResult {
147
+ /** Whether the log was successfully stored */
148
+ success: boolean;
149
+ /** The created log entry (if successful) */
150
+ entry?: ErrorLogEntry;
151
+ /** Error message (if failed) */
152
+ error?: string;
153
+ }
154
+ /**
155
+ * Props for the LogViewer component
156
+ */
157
+ interface LogViewerProps {
158
+ /** Base path for the logs API (default: /api/logs) */
159
+ apiBasePath?: string;
160
+ /** Additional CSS classes */
161
+ className?: string;
162
+ /** Number of logs per page (default: 50) */
163
+ pageSize?: number;
164
+ /** Custom theme colors */
165
+ theme?: LogViewerTheme;
166
+ /** Callback when a log is selected */
167
+ onLogSelect?: (log: ErrorLogEntry) => void;
168
+ /** Whether to show the delete button */
169
+ showDelete?: boolean;
170
+ /** Whether to auto-refresh (in seconds, 0 to disable) */
171
+ autoRefresh?: number;
172
+ }
173
+ /**
174
+ * Theme configuration for the LogViewer component
175
+ */
176
+ interface LogViewerTheme {
177
+ /** Background color for error level badge */
178
+ errorBg?: string;
179
+ /** Text color for error level badge */
180
+ errorText?: string;
181
+ /** Background color for warn level badge */
182
+ warnBg?: string;
183
+ /** Text color for warn level badge */
184
+ warnText?: string;
185
+ /** Background color for info level badge */
186
+ infoBg?: string;
187
+ /** Text color for info level badge */
188
+ infoText?: string;
189
+ /** Background color for debug level badge */
190
+ debugBg?: string;
191
+ /** Text color for debug level badge */
192
+ debugText?: string;
193
+ }
194
+
195
+ export type { AuthAdapter as A, DatabaseAdapter as D, ErrorLoggerConfig as E, LogResult as L, QueryOptions as Q, RequestContext as R, ErrorLogEntry as a, LogLevel as b, LogViewerProps as c, LogViewerTheme as d };
@@ -0,0 +1,195 @@
1
+ /**
2
+ * Log severity levels
3
+ */
4
+ type LogLevel = 'error' | 'warn' | 'info' | 'debug';
5
+ /**
6
+ * Represents a single error log entry stored in the database
7
+ */
8
+ interface ErrorLogEntry {
9
+ /** Unique identifier for the log entry */
10
+ id: string;
11
+ /** Severity level of the log */
12
+ level: LogLevel;
13
+ /** Human-readable error message */
14
+ message: string;
15
+ /** Full stack trace (for errors) */
16
+ stack?: string | null;
17
+ /** ID of the user who encountered the error */
18
+ userId?: string | null;
19
+ /** Email of the user who encountered the error */
20
+ userEmail?: string | null;
21
+ /** Display name of the user */
22
+ userName?: string | null;
23
+ /** URL path where the error occurred */
24
+ path?: string | null;
25
+ /** HTTP method (GET, POST, etc.) */
26
+ method?: string | null;
27
+ /** Browser/client user agent string */
28
+ userAgent?: string | null;
29
+ /** Client IP address */
30
+ ip?: string | null;
31
+ /** Additional custom metadata */
32
+ metadata?: Record<string, unknown> | null;
33
+ /** Timestamp when the error occurred */
34
+ createdAt: Date;
35
+ }
36
+ /**
37
+ * Configuration options for the error logger
38
+ */
39
+ interface ErrorLoggerConfig {
40
+ /** Database adapter for storing logs */
41
+ adapter: DatabaseAdapter;
42
+ /** Auth adapter for automatically capturing user context (optional) */
43
+ authAdapter?: AuthAdapter;
44
+ /** Number of days to retain logs (default: 30) */
45
+ retentionDays?: number;
46
+ /** Log levels to capture (default: all levels) */
47
+ levels?: LogLevel[];
48
+ /** Enable console output in development (default: true) */
49
+ consoleInDev?: boolean;
50
+ }
51
+ /**
52
+ * Database adapter interface - implement this for custom database support
53
+ */
54
+ interface DatabaseAdapter {
55
+ /**
56
+ * Create a new log entry
57
+ * @param entry - The log entry data (without id and createdAt)
58
+ * @returns The created log entry with id and createdAt
59
+ */
60
+ create(entry: Omit<ErrorLogEntry, 'id' | 'createdAt'>): Promise<ErrorLogEntry>;
61
+ /**
62
+ * Find multiple log entries with filtering and pagination
63
+ * @param options - Query options
64
+ * @returns Object containing logs array and total count
65
+ */
66
+ findMany(options: QueryOptions): Promise<{
67
+ logs: ErrorLogEntry[];
68
+ total: number;
69
+ }>;
70
+ /**
71
+ * Find a single log entry by ID
72
+ * @param id - The log entry ID
73
+ * @returns The log entry or null if not found
74
+ */
75
+ findById(id: string): Promise<ErrorLogEntry | null>;
76
+ /**
77
+ * Delete a single log entry
78
+ * @param id - The log entry ID
79
+ */
80
+ delete(id: string): Promise<void>;
81
+ /**
82
+ * Delete multiple log entries
83
+ * @param options - Filter options for deletion
84
+ * @returns Number of deleted entries
85
+ */
86
+ deleteMany(options: {
87
+ before?: Date;
88
+ level?: LogLevel;
89
+ }): Promise<number>;
90
+ }
91
+ /**
92
+ * Auth adapter interface - implement this for custom auth providers
93
+ */
94
+ interface AuthAdapter {
95
+ /**
96
+ * Get the current authenticated user
97
+ * @returns User object or null if not authenticated
98
+ */
99
+ getUser(): Promise<{
100
+ id: string;
101
+ email?: string;
102
+ name?: string;
103
+ } | null>;
104
+ }
105
+ /**
106
+ * Query options for filtering and paginating log entries
107
+ */
108
+ interface QueryOptions {
109
+ /** Page number (1-indexed, default: 1) */
110
+ page?: number;
111
+ /** Number of items per page (default: 50) */
112
+ limit?: number;
113
+ /** Filter by log level */
114
+ level?: LogLevel;
115
+ /** Filter by user ID */
116
+ userId?: string;
117
+ /** Search term for message, stack, or path */
118
+ search?: string;
119
+ /** Filter logs after this date */
120
+ startDate?: Date;
121
+ /** Filter logs before this date */
122
+ endDate?: Date;
123
+ /** Field to sort by (default: createdAt) */
124
+ orderBy?: 'createdAt' | 'level';
125
+ /** Sort direction (default: desc) */
126
+ order?: 'asc' | 'desc';
127
+ }
128
+ /**
129
+ * Context information extracted from a request
130
+ */
131
+ interface RequestContext {
132
+ /** URL path */
133
+ path?: string;
134
+ /** HTTP method */
135
+ method?: string;
136
+ /** User agent string */
137
+ userAgent?: string;
138
+ /** Client IP address */
139
+ ip?: string;
140
+ /** Additional custom metadata */
141
+ metadata?: Record<string, unknown>;
142
+ }
143
+ /**
144
+ * Result of a logging operation
145
+ */
146
+ interface LogResult {
147
+ /** Whether the log was successfully stored */
148
+ success: boolean;
149
+ /** The created log entry (if successful) */
150
+ entry?: ErrorLogEntry;
151
+ /** Error message (if failed) */
152
+ error?: string;
153
+ }
154
+ /**
155
+ * Props for the LogViewer component
156
+ */
157
+ interface LogViewerProps {
158
+ /** Base path for the logs API (default: /api/logs) */
159
+ apiBasePath?: string;
160
+ /** Additional CSS classes */
161
+ className?: string;
162
+ /** Number of logs per page (default: 50) */
163
+ pageSize?: number;
164
+ /** Custom theme colors */
165
+ theme?: LogViewerTheme;
166
+ /** Callback when a log is selected */
167
+ onLogSelect?: (log: ErrorLogEntry) => void;
168
+ /** Whether to show the delete button */
169
+ showDelete?: boolean;
170
+ /** Whether to auto-refresh (in seconds, 0 to disable) */
171
+ autoRefresh?: number;
172
+ }
173
+ /**
174
+ * Theme configuration for the LogViewer component
175
+ */
176
+ interface LogViewerTheme {
177
+ /** Background color for error level badge */
178
+ errorBg?: string;
179
+ /** Text color for error level badge */
180
+ errorText?: string;
181
+ /** Background color for warn level badge */
182
+ warnBg?: string;
183
+ /** Text color for warn level badge */
184
+ warnText?: string;
185
+ /** Background color for info level badge */
186
+ infoBg?: string;
187
+ /** Text color for info level badge */
188
+ infoText?: string;
189
+ /** Background color for debug level badge */
190
+ debugBg?: string;
191
+ /** Text color for debug level badge */
192
+ debugText?: string;
193
+ }
194
+
195
+ export type { AuthAdapter as A, DatabaseAdapter as D, ErrorLoggerConfig as E, LogResult as L, QueryOptions as Q, RequestContext as R, ErrorLogEntry as a, LogLevel as b, LogViewerProps as c, LogViewerTheme as d };
package/package.json ADDED
@@ -0,0 +1,128 @@
1
+ {
2
+ "name": "@vinetechke/next-error-logger",
3
+ "version": "0.1.0-beta.1",
4
+ "description": "Simple error logging for Next.js apps with user context, multiple database adapters, and a built-in dashboard.",
5
+ "author": "VineTechKE",
6
+ "license": "MIT",
7
+ "repository": {
8
+ "type": "git",
9
+ "url": "https://github.com/vinetechke/next-error-logger"
10
+ },
11
+ "keywords": [
12
+ "nextjs",
13
+ "error-logging",
14
+ "monitoring",
15
+ "dashboard",
16
+ "prisma",
17
+ "drizzle",
18
+ "typescript",
19
+ "react"
20
+ ],
21
+ "type": "module",
22
+ "main": "./dist/index.cjs",
23
+ "module": "./dist/index.js",
24
+ "types": "./dist/index.d.ts",
25
+ "exports": {
26
+ ".": {
27
+ "types": "./dist/index.d.ts",
28
+ "import": "./dist/index.js",
29
+ "require": "./dist/index.cjs"
30
+ },
31
+ "./components": {
32
+ "types": "./dist/components/index.d.ts",
33
+ "import": "./dist/components/index.js",
34
+ "require": "./dist/components/index.cjs"
35
+ },
36
+ "./adapters/prisma": {
37
+ "types": "./dist/adapters/prisma.d.ts",
38
+ "import": "./dist/adapters/prisma.js",
39
+ "require": "./dist/adapters/prisma.cjs"
40
+ },
41
+ "./adapters/drizzle": {
42
+ "types": "./dist/adapters/drizzle.d.ts",
43
+ "import": "./dist/adapters/drizzle.js",
44
+ "require": "./dist/adapters/drizzle.cjs"
45
+ },
46
+ "./adapters/sql": {
47
+ "types": "./dist/adapters/sql.d.ts",
48
+ "import": "./dist/adapters/sql.js",
49
+ "require": "./dist/adapters/sql.cjs"
50
+ },
51
+ "./auth/next-auth": {
52
+ "types": "./dist/auth/next-auth.d.ts",
53
+ "import": "./dist/auth/next-auth.js",
54
+ "require": "./dist/auth/next-auth.cjs"
55
+ },
56
+ "./auth/clerk": {
57
+ "types": "./dist/auth/clerk.d.ts",
58
+ "import": "./dist/auth/clerk.js",
59
+ "require": "./dist/auth/clerk.cjs"
60
+ },
61
+ "./api": {
62
+ "types": "./dist/api/index.d.ts",
63
+ "import": "./dist/api/index.js",
64
+ "require": "./dist/api/index.cjs"
65
+ },
66
+ "./schemas/prisma": "./schemas/prisma.prisma",
67
+ "./schemas/drizzle": {
68
+ "types": "./dist/schemas/drizzle.d.ts",
69
+ "import": "./dist/schemas/drizzle.js",
70
+ "require": "./dist/schemas/drizzle.cjs"
71
+ },
72
+ "./schemas/sql": "./schemas/schema.sql"
73
+ },
74
+ "files": [
75
+ "dist",
76
+ "schemas",
77
+ "README.md",
78
+ "LICENSE"
79
+ ],
80
+ "scripts": {
81
+ "build": "tsup",
82
+ "dev": "tsup --watch",
83
+ "lint": "eslint src/",
84
+ "lint:fix": "eslint src/ --fix",
85
+ "format": "prettier --write \"src/**/*.{ts,tsx}\"",
86
+ "format:check": "prettier --check \"src/**/*.{ts,tsx}\"",
87
+ "typecheck": "tsc --noEmit",
88
+ "test": "vitest run",
89
+ "test:watch": "vitest",
90
+ "test:coverage": "vitest run --coverage",
91
+ "prepublishOnly": "pnpm build && pnpm test"
92
+ },
93
+ "peerDependencies": {
94
+ "next": ">=14.0.0",
95
+ "react": ">=18.0.0",
96
+ "react-dom": ">=18.0.0"
97
+ },
98
+ "peerDependenciesMeta": {
99
+ "@prisma/client": {
100
+ "optional": true
101
+ },
102
+ "drizzle-orm": {
103
+ "optional": true
104
+ },
105
+ "next-auth": {
106
+ "optional": true
107
+ },
108
+ "@clerk/nextjs": {
109
+ "optional": true
110
+ }
111
+ },
112
+ "devDependencies": {
113
+ "@faker-js/faker": "^10.3.0",
114
+ "@testing-library/react": "^14.0.0",
115
+ "@types/node": "^20.0.0",
116
+ "@types/react": "^18.0.0",
117
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
118
+ "@typescript-eslint/parser": "^7.0.0",
119
+ "@vitest/coverage-v8": "^1.0.0",
120
+ "eslint": "^8.0.0",
121
+ "jsdom": "^24.0.0",
122
+ "prettier": "^3.0.0",
123
+ "tsup": "^8.0.0",
124
+ "typescript": "^5.0.0",
125
+ "vitest": "^1.0.0"
126
+ },
127
+ "packageManager": "pnpm@10.27.0+sha512.72d699da16b1179c14ba9e64dc71c9a40988cbdc65c264cb0e489db7de917f20dcf4d64d8723625f2969ba52d4b7e2a1170682d9ac2a5dcaeaab732b7e16f04a"
128
+ }
@@ -0,0 +1,23 @@
1
+ // @vinetechke/next-error-logger - Prisma Schema
2
+ // Copy this model to your schema.prisma file
3
+
4
+ model ErrorLog {
5
+ id String @id @default(cuid())
6
+ level String // error, warn, info, debug
7
+ message String @db.Text
8
+ stack String? @db.Text
9
+ userId String?
10
+ userEmail String?
11
+ userName String?
12
+ path String?
13
+ method String?
14
+ userAgent String?
15
+ ip String?
16
+ metadata Json?
17
+ createdAt DateTime @default(now())
18
+
19
+ @@index([level])
20
+ @@index([userId])
21
+ @@index([createdAt])
22
+ @@map("error_logs")
23
+ }
@@ -0,0 +1,75 @@
1
+ -- @vinetechke/next-error-logger - SQL Schema
2
+ -- Choose the appropriate schema for your database
3
+
4
+ -- ============================================
5
+ -- PostgreSQL
6
+ -- ============================================
7
+ CREATE TABLE error_logs (
8
+ id TEXT PRIMARY KEY,
9
+ level TEXT NOT NULL,
10
+ message TEXT NOT NULL,
11
+ stack TEXT,
12
+ user_id TEXT,
13
+ user_email TEXT,
14
+ user_name TEXT,
15
+ path TEXT,
16
+ method TEXT,
17
+ user_agent TEXT,
18
+ ip TEXT,
19
+ metadata JSONB,
20
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT NOW()
21
+ );
22
+
23
+ CREATE INDEX idx_error_logs_level ON error_logs(level);
24
+ CREATE INDEX idx_error_logs_user_id ON error_logs(user_id);
25
+ CREATE INDEX idx_error_logs_created_at ON error_logs(created_at);
26
+
27
+ -- ============================================
28
+ -- MySQL
29
+ -- ============================================
30
+ /*
31
+ CREATE TABLE error_logs (
32
+ id VARCHAR(36) PRIMARY KEY,
33
+ level VARCHAR(10) NOT NULL,
34
+ message TEXT NOT NULL,
35
+ stack TEXT,
36
+ user_id VARCHAR(255),
37
+ user_email VARCHAR(255),
38
+ user_name VARCHAR(255),
39
+ path VARCHAR(500),
40
+ method VARCHAR(10),
41
+ user_agent TEXT,
42
+ ip VARCHAR(45),
43
+ metadata JSON,
44
+ created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
45
+ );
46
+
47
+ CREATE INDEX idx_error_logs_level ON error_logs(level);
48
+ CREATE INDEX idx_error_logs_user_id ON error_logs(user_id);
49
+ CREATE INDEX idx_error_logs_created_at ON error_logs(created_at);
50
+ */
51
+
52
+ -- ============================================
53
+ -- SQLite
54
+ -- ============================================
55
+ /*
56
+ CREATE TABLE error_logs (
57
+ id TEXT PRIMARY KEY,
58
+ level TEXT NOT NULL,
59
+ message TEXT NOT NULL,
60
+ stack TEXT,
61
+ user_id TEXT,
62
+ user_email TEXT,
63
+ user_name TEXT,
64
+ path TEXT,
65
+ method TEXT,
66
+ user_agent TEXT,
67
+ ip TEXT,
68
+ metadata TEXT,
69
+ created_at TEXT DEFAULT (datetime('now'))
70
+ );
71
+
72
+ CREATE INDEX idx_error_logs_level ON error_logs(level);
73
+ CREATE INDEX idx_error_logs_user_id ON error_logs(user_id);
74
+ CREATE INDEX idx_error_logs_created_at ON error_logs(created_at);
75
+ */