@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,257 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/api/index.ts
22
+ var api_exports = {};
23
+ __export(api_exports, {
24
+ createLogAPIHandlers: () => createLogAPIHandlers,
25
+ createLogDetailAPIHandlers: () => createLogDetailAPIHandlers,
26
+ createLogStatsHandler: () => createLogStatsHandler
27
+ });
28
+ module.exports = __toCommonJS(api_exports);
29
+ var import_server = require("next/server");
30
+
31
+ // src/logger.ts
32
+ var config = null;
33
+ function getConfig() {
34
+ if (!config) {
35
+ throw new Error(
36
+ "[@vinetechke/next-error-logger] Logger not initialized. Call initErrorLogger() first."
37
+ );
38
+ }
39
+ return config;
40
+ }
41
+ function isInitialized() {
42
+ return config !== null;
43
+ }
44
+
45
+ // src/api/index.ts
46
+ function createLogAPIHandlers(config2) {
47
+ const { isAuthorized } = config2;
48
+ return {
49
+ /**
50
+ * GET /api/logs - List logs with filtering and pagination
51
+ *
52
+ * Query parameters:
53
+ * - page: Page number (default: 1)
54
+ * - limit: Items per page (default: 50)
55
+ * - level: Filter by level (error, warn, info, debug)
56
+ * - userId: Filter by user ID
57
+ * - search: Search in message, stack, path, userEmail
58
+ * - startDate: Filter logs after this date (ISO string)
59
+ * - endDate: Filter logs before this date (ISO string)
60
+ */
61
+ GET: async (request) => {
62
+ if (!await isAuthorized(request)) {
63
+ return import_server.NextResponse.json(
64
+ { error: "Unauthorized" },
65
+ { status: 401 }
66
+ );
67
+ }
68
+ if (!isInitialized()) {
69
+ return import_server.NextResponse.json(
70
+ { error: "Logger not initialized" },
71
+ { status: 500 }
72
+ );
73
+ }
74
+ const cfg = getConfig();
75
+ const searchParams = request.nextUrl.searchParams;
76
+ try {
77
+ const options = {
78
+ page: parseInt(searchParams.get("page") || "1", 10),
79
+ limit: Math.min(
80
+ parseInt(searchParams.get("limit") || "50", 10),
81
+ 100
82
+ ),
83
+ level: searchParams.get("level"),
84
+ userId: searchParams.get("userId") || void 0,
85
+ search: searchParams.get("search") || void 0,
86
+ startDate: searchParams.get("startDate") ? new Date(searchParams.get("startDate")) : void 0,
87
+ endDate: searchParams.get("endDate") ? new Date(searchParams.get("endDate")) : void 0
88
+ };
89
+ const result = await cfg.adapter.findMany(options);
90
+ return import_server.NextResponse.json(result);
91
+ } catch (error) {
92
+ console.error("[@vinetechke/next-error-logger] API error:", error);
93
+ return import_server.NextResponse.json(
94
+ { error: "Failed to fetch logs" },
95
+ { status: 500 }
96
+ );
97
+ }
98
+ },
99
+ /**
100
+ * DELETE /api/logs - Clear logs
101
+ *
102
+ * Body parameters:
103
+ * - before: Delete logs before this date (ISO string)
104
+ * - level: Delete logs with this level only
105
+ */
106
+ DELETE: async (request) => {
107
+ if (!await isAuthorized(request)) {
108
+ return import_server.NextResponse.json(
109
+ { error: "Unauthorized" },
110
+ { status: 401 }
111
+ );
112
+ }
113
+ if (!isInitialized()) {
114
+ return import_server.NextResponse.json(
115
+ { error: "Logger not initialized" },
116
+ { status: 500 }
117
+ );
118
+ }
119
+ const cfg = getConfig();
120
+ try {
121
+ const body = await request.json().catch(() => ({}));
122
+ const count = await cfg.adapter.deleteMany({
123
+ before: body.before ? new Date(body.before) : void 0,
124
+ level: body.level
125
+ });
126
+ return import_server.NextResponse.json({ deleted: count });
127
+ } catch (error) {
128
+ console.error("[@vinetechke/next-error-logger] API error:", error);
129
+ return import_server.NextResponse.json(
130
+ { error: "Failed to delete logs" },
131
+ { status: 500 }
132
+ );
133
+ }
134
+ }
135
+ };
136
+ }
137
+ function createLogDetailAPIHandlers(config2) {
138
+ const { isAuthorized } = config2;
139
+ return {
140
+ /**
141
+ * GET /api/logs/[id] - Get a single log entry
142
+ */
143
+ GET: async (request, { params }) => {
144
+ if (!await isAuthorized(request)) {
145
+ return import_server.NextResponse.json(
146
+ { error: "Unauthorized" },
147
+ { status: 401 }
148
+ );
149
+ }
150
+ if (!isInitialized()) {
151
+ return import_server.NextResponse.json(
152
+ { error: "Logger not initialized" },
153
+ { status: 500 }
154
+ );
155
+ }
156
+ const cfg = getConfig();
157
+ const { id } = await params;
158
+ try {
159
+ const log = await cfg.adapter.findById(id);
160
+ if (!log) {
161
+ return import_server.NextResponse.json(
162
+ { error: "Not found" },
163
+ { status: 404 }
164
+ );
165
+ }
166
+ return import_server.NextResponse.json(log);
167
+ } catch (error) {
168
+ console.error("[@vinetechke/next-error-logger] API error:", error);
169
+ return import_server.NextResponse.json(
170
+ { error: "Failed to fetch log" },
171
+ { status: 500 }
172
+ );
173
+ }
174
+ },
175
+ /**
176
+ * DELETE /api/logs/[id] - Delete a single log entry
177
+ */
178
+ DELETE: async (request, { params }) => {
179
+ if (!await isAuthorized(request)) {
180
+ return import_server.NextResponse.json(
181
+ { error: "Unauthorized" },
182
+ { status: 401 }
183
+ );
184
+ }
185
+ if (!isInitialized()) {
186
+ return import_server.NextResponse.json(
187
+ { error: "Logger not initialized" },
188
+ { status: 500 }
189
+ );
190
+ }
191
+ const cfg = getConfig();
192
+ const { id } = await params;
193
+ try {
194
+ await cfg.adapter.delete(id);
195
+ return import_server.NextResponse.json({ success: true });
196
+ } catch (error) {
197
+ console.error("[@vinetechke/next-error-logger] API error:", error);
198
+ return import_server.NextResponse.json(
199
+ { error: "Failed to delete log" },
200
+ { status: 500 }
201
+ );
202
+ }
203
+ }
204
+ };
205
+ }
206
+ function createLogStatsHandler(config2) {
207
+ const { isAuthorized } = config2;
208
+ return async (request) => {
209
+ if (!await isAuthorized(request)) {
210
+ return import_server.NextResponse.json({ error: "Unauthorized" }, { status: 401 });
211
+ }
212
+ if (!isInitialized()) {
213
+ return import_server.NextResponse.json(
214
+ { error: "Logger not initialized" },
215
+ { status: 500 }
216
+ );
217
+ }
218
+ const cfg = getConfig();
219
+ try {
220
+ const [errors, warnings, infos, debugs, total] = await Promise.all([
221
+ cfg.adapter.findMany({ level: "error", limit: 0 }).then((r) => r.total),
222
+ cfg.adapter.findMany({ level: "warn", limit: 0 }).then((r) => r.total),
223
+ cfg.adapter.findMany({ level: "info", limit: 0 }).then((r) => r.total),
224
+ cfg.adapter.findMany({ level: "debug", limit: 0 }).then((r) => r.total),
225
+ cfg.adapter.findMany({ limit: 0 }).then((r) => r.total)
226
+ ]);
227
+ const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3);
228
+ const recentResult = await cfg.adapter.findMany({
229
+ startDate: oneDayAgo,
230
+ limit: 0
231
+ });
232
+ return import_server.NextResponse.json({
233
+ total,
234
+ byLevel: {
235
+ error: errors,
236
+ warn: warnings,
237
+ info: infos,
238
+ debug: debugs
239
+ },
240
+ last24Hours: recentResult.total
241
+ });
242
+ } catch (error) {
243
+ console.error("[@vinetechke/next-error-logger] API error:", error);
244
+ return import_server.NextResponse.json(
245
+ { error: "Failed to fetch stats" },
246
+ { status: 500 }
247
+ );
248
+ }
249
+ };
250
+ }
251
+ // Annotate the CommonJS export names for ESM import in node:
252
+ 0 && (module.exports = {
253
+ createLogAPIHandlers,
254
+ createLogDetailAPIHandlers,
255
+ createLogStatsHandler
256
+ });
257
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/api/index.ts","../../src/logger.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server'\nimport { getConfig, isInitialized } from '../logger'\nimport type { LogLevel } from '../types'\n\n/**\n * Configuration for API route handlers\n */\nexport interface APIHandlerConfig {\n /**\n * Function to check if user is authorized to view logs\n * Return true to allow access, false to deny\n *\n * @example\n * ```ts\n * const config = {\n * isAuthorized: async (request) => {\n * const session = await auth()\n * return session?.user?.role === 'admin'\n * }\n * }\n * ```\n */\n isAuthorized: (request: NextRequest) => Promise<boolean>\n}\n\n/**\n * Create API route handlers for the error logger\n *\n * Creates GET, DELETE handlers for listing, fetching, and deleting logs.\n *\n * @example\n * ```ts\n * // app/api/admin/logs/route.ts\n * import { createLogAPIHandlers } from '@vinetechke/next-error-logger/api'\n * import { auth } from '@/auth'\n *\n * const { GET, DELETE } = createLogAPIHandlers({\n * isAuthorized: async () => {\n * const session = await auth()\n * return session?.user?.role === 'ADMIN'\n * },\n * })\n *\n * export { GET, DELETE }\n * ```\n *\n * @example\n * ```ts\n * // app/api/admin/logs/[id]/route.ts\n * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'\n * import { auth } from '@/auth'\n *\n * const { GET, DELETE } = createLogDetailAPIHandlers({\n * isAuthorized: async () => {\n * const session = await auth()\n * return session?.user?.role === 'ADMIN'\n * },\n * })\n *\n * export { GET, DELETE }\n * ```\n */\nexport function createLogAPIHandlers(config: APIHandlerConfig) {\n const { isAuthorized } = config\n\n return {\n /**\n * GET /api/logs - List logs with filtering and pagination\n *\n * Query parameters:\n * - page: Page number (default: 1)\n * - limit: Items per page (default: 50)\n * - level: Filter by level (error, warn, info, debug)\n * - userId: Filter by user ID\n * - search: Search in message, stack, path, userEmail\n * - startDate: Filter logs after this date (ISO string)\n * - endDate: Filter logs before this date (ISO string)\n */\n GET: async (request: NextRequest): Promise<NextResponse> => {\n // Check authorization\n if (!(await isAuthorized(request))) {\n return NextResponse.json(\n { error: 'Unauthorized' },\n { status: 401 },\n )\n }\n\n // Check if logger is initialized\n if (!isInitialized()) {\n return NextResponse.json(\n { error: 'Logger not initialized' },\n { status: 500 },\n )\n }\n\n const cfg = getConfig()\n const searchParams = request.nextUrl.searchParams\n\n try {\n const options = {\n page: parseInt(searchParams.get('page') || '1', 10),\n limit: Math.min(\n parseInt(searchParams.get('limit') || '50', 10),\n 100,\n ),\n level: searchParams.get('level') as LogLevel | undefined,\n userId: searchParams.get('userId') || undefined,\n search: searchParams.get('search') || undefined,\n startDate: searchParams.get('startDate')\n ? new Date(searchParams.get('startDate')!)\n : undefined,\n endDate: searchParams.get('endDate')\n ? new Date(searchParams.get('endDate')!)\n : undefined,\n }\n\n const result = await cfg.adapter.findMany(options)\n\n return NextResponse.json(result)\n } catch (error) {\n console.error('[@vinetechke/next-error-logger] API error:', error)\n return NextResponse.json(\n { error: 'Failed to fetch logs' },\n { status: 500 },\n )\n }\n },\n\n /**\n * DELETE /api/logs - Clear logs\n *\n * Body parameters:\n * - before: Delete logs before this date (ISO string)\n * - level: Delete logs with this level only\n */\n DELETE: async (request: NextRequest): Promise<NextResponse> => {\n // Check authorization\n if (!(await isAuthorized(request))) {\n return NextResponse.json(\n { error: 'Unauthorized' },\n { status: 401 },\n )\n }\n\n // Check if logger is initialized\n if (!isInitialized()) {\n return NextResponse.json(\n { error: 'Logger not initialized' },\n { status: 500 },\n )\n }\n\n const cfg = getConfig()\n\n try {\n const body = await request.json().catch(() => ({}))\n\n const count = await cfg.adapter.deleteMany({\n before: body.before ? new Date(body.before) : undefined,\n level: body.level as LogLevel | undefined,\n })\n\n return NextResponse.json({ deleted: count })\n } catch (error) {\n console.error('[@vinetechke/next-error-logger] API error:', error)\n return NextResponse.json(\n { error: 'Failed to delete logs' },\n { status: 500 },\n )\n }\n },\n }\n}\n\n/**\n * Create API route handlers for individual log entries\n *\n * @example\n * ```ts\n * // app/api/admin/logs/[id]/route.ts\n * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'\n *\n * const { GET, DELETE } = createLogDetailAPIHandlers({\n * isAuthorized: async () => {\n * const session = await auth()\n * return session?.user?.role === 'ADMIN'\n * },\n * })\n *\n * export { GET, DELETE }\n * ```\n */\nexport function createLogDetailAPIHandlers(config: APIHandlerConfig) {\n const { isAuthorized } = config\n\n return {\n /**\n * GET /api/logs/[id] - Get a single log entry\n */\n GET: async (\n request: NextRequest,\n { params }: { params: Promise<{ id: string }> },\n ): Promise<NextResponse> => {\n // Check authorization\n if (!(await isAuthorized(request))) {\n return NextResponse.json(\n { error: 'Unauthorized' },\n { status: 401 },\n )\n }\n\n // Check if logger is initialized\n if (!isInitialized()) {\n return NextResponse.json(\n { error: 'Logger not initialized' },\n { status: 500 },\n )\n }\n\n const cfg = getConfig()\n const { id } = await params\n\n try {\n const log = await cfg.adapter.findById(id)\n\n if (!log) {\n return NextResponse.json(\n { error: 'Not found' },\n { status: 404 },\n )\n }\n\n return NextResponse.json(log)\n } catch (error) {\n console.error('[@vinetechke/next-error-logger] API error:', error)\n return NextResponse.json(\n { error: 'Failed to fetch log' },\n { status: 500 },\n )\n }\n },\n\n /**\n * DELETE /api/logs/[id] - Delete a single log entry\n */\n DELETE: async (\n request: NextRequest,\n { params }: { params: Promise<{ id: string }> },\n ): Promise<NextResponse> => {\n // Check authorization\n if (!(await isAuthorized(request))) {\n return NextResponse.json(\n { error: 'Unauthorized' },\n { status: 401 },\n )\n }\n\n // Check if logger is initialized\n if (!isInitialized()) {\n return NextResponse.json(\n { error: 'Logger not initialized' },\n { status: 500 },\n )\n }\n\n const cfg = getConfig()\n const { id } = await params\n\n try {\n await cfg.adapter.delete(id)\n return NextResponse.json({ success: true })\n } catch (error) {\n console.error('[@vinetechke/next-error-logger] API error:', error)\n return NextResponse.json(\n { error: 'Failed to delete log' },\n { status: 500 },\n )\n }\n },\n }\n}\n\n/**\n * Get log statistics\n *\n * @example\n * ```ts\n * // app/api/admin/logs/stats/route.ts\n * import { createLogStatsHandler } from '@vinetechke/next-error-logger/api'\n *\n * export const GET = createLogStatsHandler({\n * isAuthorized: async () => {\n * const session = await auth()\n * return session?.user?.role === 'ADMIN'\n * },\n * })\n * ```\n */\nexport function createLogStatsHandler(config: APIHandlerConfig) {\n const { isAuthorized } = config\n\n return async (request: NextRequest): Promise<NextResponse> => {\n // Check authorization\n if (!(await isAuthorized(request))) {\n return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })\n }\n\n // Check if logger is initialized\n if (!isInitialized()) {\n return NextResponse.json(\n { error: 'Logger not initialized' },\n { status: 500 },\n )\n }\n\n const cfg = getConfig()\n\n try {\n // Get counts for each level\n const [errors, warnings, infos, debugs, total] = await Promise.all([\n cfg.adapter\n .findMany({ level: 'error', limit: 0 })\n .then(r => r.total),\n cfg.adapter\n .findMany({ level: 'warn', limit: 0 })\n .then(r => r.total),\n cfg.adapter\n .findMany({ level: 'info', limit: 0 })\n .then(r => r.total),\n cfg.adapter\n .findMany({ level: 'debug', limit: 0 })\n .then(r => r.total),\n cfg.adapter.findMany({ limit: 0 }).then(r => r.total),\n ])\n\n // Get recent logs (last 24 hours)\n const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1000)\n const recentResult = await cfg.adapter.findMany({\n startDate: oneDayAgo,\n limit: 0,\n })\n\n return NextResponse.json({\n total,\n byLevel: {\n error: errors,\n warn: warnings,\n info: infos,\n debug: debugs,\n },\n last24Hours: recentResult.total,\n })\n } catch (error) {\n console.error('[@vinetechke/next-error-logger] API error:', error)\n return NextResponse.json(\n { error: 'Failed to fetch stats' },\n { status: 500 },\n )\n }\n }\n}\n","import type {\n ErrorLoggerConfig,\n LogLevel,\n ErrorLogEntry,\n RequestContext,\n LogResult,\n} from './types'\n\nlet config: ErrorLoggerConfig | null = null\n\n/**\n * Initialize the error logger with your configuration\n * Must be called before using errorLogger\n *\n * @example\n * ```ts\n * import { initErrorLogger } from '@vinetechke/next-error-logger'\n * import { createPrismaAdapter } from '@vinetechke/next-error-logger/adapters/prisma'\n * import { createNextAuthAdapter } from '@vinetechke/next-error-logger/auth/next-auth'\n * import { prisma } from '@/lib/prisma'\n * import { auth } from '@/auth'\n *\n * initErrorLogger({\n * adapter: createPrismaAdapter(prisma),\n * authAdapter: createNextAuthAdapter(auth),\n * retentionDays: 30,\n * })\n * ```\n */\nexport function initErrorLogger(cfg: ErrorLoggerConfig): void {\n config = {\n consoleInDev: true,\n retentionDays: 30,\n ...cfg,\n }\n}\n\n/**\n * Get the current logger configuration\n * @throws Error if logger is not initialized\n */\nexport function getConfig(): ErrorLoggerConfig {\n if (!config) {\n throw new Error(\n '[@vinetechke/next-error-logger] Logger not initialized. Call initErrorLogger() first.',\n )\n }\n return config\n}\n\n/**\n * Check if logger is initialized\n */\nexport function isInitialized(): boolean {\n return config !== null\n}\n\n/**\n * Internal logging function\n */\nasync function log(\n level: LogLevel,\n message: string,\n error?: Error | null,\n context?: RequestContext,\n): Promise<LogResult> {\n try {\n const cfg = getConfig()\n\n // Check if this level should be captured\n if (cfg.levels && !cfg.levels.includes(level)) {\n return { success: true }\n }\n\n // Console output in development\n if (cfg.consoleInDev && process.env.NODE_ENV === 'development') {\n const consoleMethod =\n level === 'error' ? 'error' : level === 'warn' ? 'warn' : 'log'\n console[consoleMethod](\n `[${level.toUpperCase()}]`,\n message,\n error || '',\n context || '',\n )\n }\n\n // Get user context if auth adapter is provided\n let user: { id: string; email?: string; name?: string } | null = null\n if (cfg.authAdapter) {\n try {\n user = await cfg.authAdapter.getUser()\n } catch {\n // Silently ignore auth errors - user context is optional\n }\n }\n\n // Create the log entry\n const entry = await cfg.adapter.create({\n level,\n message,\n stack: error?.stack || null,\n userId: user?.id || null,\n userEmail: user?.email || null,\n userName: user?.name || null,\n path: context?.path || null,\n method: context?.method || null,\n userAgent: context?.userAgent || null,\n ip: context?.ip || null,\n metadata: context?.metadata || null,\n })\n\n return { success: true, entry }\n } catch (err) {\n // Don't throw on logging failures - just return error result\n console.error('[@vinetechke/next-error-logger] Failed to log:', err)\n return {\n success: false,\n error: err instanceof Error ? err.message : 'Unknown error',\n }\n }\n}\n\n/**\n * Extract request context from a Next.js Request object\n */\nfunction extractRequestContext(request: Request): RequestContext {\n const url = new URL(request.url)\n return {\n path: url.pathname,\n method: request.method,\n userAgent: request.headers.get('user-agent') || undefined,\n ip:\n request.headers.get('x-forwarded-for')?.split(',')[0]?.trim() ||\n request.headers.get('x-real-ip') ||\n undefined,\n }\n}\n\n/**\n * Main error logger instance\n *\n * @example\n * ```ts\n * // Simple logging\n * await errorLogger.error('Something went wrong', error)\n * await errorLogger.warn('Deprecated API used')\n * await errorLogger.info('User completed checkout')\n *\n * // With request context (in API routes)\n * const log = errorLogger.fromRequest(request)\n * await log.error('API failed', error, { orderId: '123' })\n * ```\n */\nexport const errorLogger = {\n /**\n * Log an error with optional Error object and context\n */\n error: (\n message: string,\n error?: Error,\n context?: RequestContext,\n ): Promise<LogResult> => log('error', message, error, context),\n\n /**\n * Log a warning with optional Error object and context\n */\n warn: (\n message: string,\n error?: Error,\n context?: RequestContext,\n ): Promise<LogResult> => log('warn', message, error, context),\n\n /**\n * Log an info message with optional context\n */\n info: (message: string, context?: RequestContext): Promise<LogResult> =>\n log('info', message, null, context),\n\n /**\n * Log a debug message with optional context\n */\n debug: (message: string, context?: RequestContext): Promise<LogResult> =>\n log('debug', message, null, context),\n\n /**\n * Create a logger instance bound to a specific request\n * Automatically extracts path, method, user agent, and IP\n *\n * @example\n * ```ts\n * export async function POST(request: Request) {\n * const log = errorLogger.fromRequest(request)\n *\n * try {\n * // ... your code\n * } catch (error) {\n * await log.error('Failed to process', error as Error, { orderId: '123' })\n * return new Response('Error', { status: 500 })\n * }\n * }\n * ```\n */\n fromRequest: (request: Request) => {\n const baseContext = extractRequestContext(request)\n\n return {\n error: (\n message: string,\n error?: Error,\n metadata?: Record<string, unknown>,\n ): Promise<LogResult> =>\n log('error', message, error, { ...baseContext, metadata }),\n\n warn: (\n message: string,\n metadata?: Record<string, unknown>,\n ): Promise<LogResult> =>\n log('warn', message, null, { ...baseContext, metadata }),\n\n info: (\n message: string,\n metadata?: Record<string, unknown>,\n ): Promise<LogResult> =>\n log('info', message, null, { ...baseContext, metadata }),\n\n debug: (\n message: string,\n metadata?: Record<string, unknown>,\n ): Promise<LogResult> =>\n log('debug', message, null, { ...baseContext, metadata }),\n }\n },\n\n /**\n * Log with explicit user context (when auth adapter is not available)\n *\n * @example\n * ```ts\n * await errorLogger.withUser({ id: 'user-123', email: 'user@example.com' })\n * .error('User action failed', error)\n * ```\n */\n withUser: (user: { id: string; email?: string; name?: string }) => {\n return {\n error: async (\n message: string,\n error?: Error,\n context?: RequestContext,\n ): Promise<LogResult> => {\n const cfg = getConfig()\n try {\n const entry = await cfg.adapter.create({\n level: 'error',\n message,\n stack: error?.stack || null,\n userId: user.id,\n userEmail: user.email || null,\n userName: user.name || null,\n path: context?.path || null,\n method: context?.method || null,\n userAgent: context?.userAgent || null,\n ip: context?.ip || null,\n metadata: context?.metadata || null,\n })\n return { success: true, entry }\n } catch (err) {\n return {\n success: false,\n error:\n err instanceof Error\n ? err.message\n : 'Unknown error',\n }\n }\n },\n\n warn: async (\n message: string,\n context?: RequestContext,\n ): Promise<LogResult> => {\n const cfg = getConfig()\n try {\n const entry = await cfg.adapter.create({\n level: 'warn',\n message,\n stack: null,\n userId: user.id,\n userEmail: user.email || null,\n userName: user.name || null,\n path: context?.path || null,\n method: context?.method || null,\n userAgent: context?.userAgent || null,\n ip: context?.ip || null,\n metadata: context?.metadata || null,\n })\n return { success: true, entry }\n } catch (err) {\n return {\n success: false,\n error:\n err instanceof Error\n ? err.message\n : 'Unknown error',\n }\n }\n },\n\n info: async (\n message: string,\n context?: RequestContext,\n ): Promise<LogResult> => {\n const cfg = getConfig()\n try {\n const entry = await cfg.adapter.create({\n level: 'info',\n message,\n stack: null,\n userId: user.id,\n userEmail: user.email || null,\n userName: user.name || null,\n path: context?.path || null,\n method: context?.method || null,\n userAgent: context?.userAgent || null,\n ip: context?.ip || null,\n metadata: context?.metadata || null,\n })\n return { success: true, entry }\n } catch (err) {\n return {\n success: false,\n error:\n err instanceof Error\n ? err.message\n : 'Unknown error',\n }\n }\n },\n }\n },\n}\n"],"mappings":"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","names":["config"]}
@@ -0,0 +1,137 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Configuration for API route handlers
5
+ */
6
+ interface APIHandlerConfig {
7
+ /**
8
+ * Function to check if user is authorized to view logs
9
+ * Return true to allow access, false to deny
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const config = {
14
+ * isAuthorized: async (request) => {
15
+ * const session = await auth()
16
+ * return session?.user?.role === 'admin'
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ isAuthorized: (request: NextRequest) => Promise<boolean>;
22
+ }
23
+ /**
24
+ * Create API route handlers for the error logger
25
+ *
26
+ * Creates GET, DELETE handlers for listing, fetching, and deleting logs.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // app/api/admin/logs/route.ts
31
+ * import { createLogAPIHandlers } from '@vinetechke/next-error-logger/api'
32
+ * import { auth } from '@/auth'
33
+ *
34
+ * const { GET, DELETE } = createLogAPIHandlers({
35
+ * isAuthorized: async () => {
36
+ * const session = await auth()
37
+ * return session?.user?.role === 'ADMIN'
38
+ * },
39
+ * })
40
+ *
41
+ * export { GET, DELETE }
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * // app/api/admin/logs/[id]/route.ts
47
+ * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'
48
+ * import { auth } from '@/auth'
49
+ *
50
+ * const { GET, DELETE } = createLogDetailAPIHandlers({
51
+ * isAuthorized: async () => {
52
+ * const session = await auth()
53
+ * return session?.user?.role === 'ADMIN'
54
+ * },
55
+ * })
56
+ *
57
+ * export { GET, DELETE }
58
+ * ```
59
+ */
60
+ declare function createLogAPIHandlers(config: APIHandlerConfig): {
61
+ /**
62
+ * GET /api/logs - List logs with filtering and pagination
63
+ *
64
+ * Query parameters:
65
+ * - page: Page number (default: 1)
66
+ * - limit: Items per page (default: 50)
67
+ * - level: Filter by level (error, warn, info, debug)
68
+ * - userId: Filter by user ID
69
+ * - search: Search in message, stack, path, userEmail
70
+ * - startDate: Filter logs after this date (ISO string)
71
+ * - endDate: Filter logs before this date (ISO string)
72
+ */
73
+ GET: (request: NextRequest) => Promise<NextResponse>;
74
+ /**
75
+ * DELETE /api/logs - Clear logs
76
+ *
77
+ * Body parameters:
78
+ * - before: Delete logs before this date (ISO string)
79
+ * - level: Delete logs with this level only
80
+ */
81
+ DELETE: (request: NextRequest) => Promise<NextResponse>;
82
+ };
83
+ /**
84
+ * Create API route handlers for individual log entries
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * // app/api/admin/logs/[id]/route.ts
89
+ * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'
90
+ *
91
+ * const { GET, DELETE } = createLogDetailAPIHandlers({
92
+ * isAuthorized: async () => {
93
+ * const session = await auth()
94
+ * return session?.user?.role === 'ADMIN'
95
+ * },
96
+ * })
97
+ *
98
+ * export { GET, DELETE }
99
+ * ```
100
+ */
101
+ declare function createLogDetailAPIHandlers(config: APIHandlerConfig): {
102
+ /**
103
+ * GET /api/logs/[id] - Get a single log entry
104
+ */
105
+ GET: (request: NextRequest, { params }: {
106
+ params: Promise<{
107
+ id: string;
108
+ }>;
109
+ }) => Promise<NextResponse>;
110
+ /**
111
+ * DELETE /api/logs/[id] - Delete a single log entry
112
+ */
113
+ DELETE: (request: NextRequest, { params }: {
114
+ params: Promise<{
115
+ id: string;
116
+ }>;
117
+ }) => Promise<NextResponse>;
118
+ };
119
+ /**
120
+ * Get log statistics
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * // app/api/admin/logs/stats/route.ts
125
+ * import { createLogStatsHandler } from '@vinetechke/next-error-logger/api'
126
+ *
127
+ * export const GET = createLogStatsHandler({
128
+ * isAuthorized: async () => {
129
+ * const session = await auth()
130
+ * return session?.user?.role === 'ADMIN'
131
+ * },
132
+ * })
133
+ * ```
134
+ */
135
+ declare function createLogStatsHandler(config: APIHandlerConfig): (request: NextRequest) => Promise<NextResponse>;
136
+
137
+ export { type APIHandlerConfig, createLogAPIHandlers, createLogDetailAPIHandlers, createLogStatsHandler };
@@ -0,0 +1,137 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Configuration for API route handlers
5
+ */
6
+ interface APIHandlerConfig {
7
+ /**
8
+ * Function to check if user is authorized to view logs
9
+ * Return true to allow access, false to deny
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const config = {
14
+ * isAuthorized: async (request) => {
15
+ * const session = await auth()
16
+ * return session?.user?.role === 'admin'
17
+ * }
18
+ * }
19
+ * ```
20
+ */
21
+ isAuthorized: (request: NextRequest) => Promise<boolean>;
22
+ }
23
+ /**
24
+ * Create API route handlers for the error logger
25
+ *
26
+ * Creates GET, DELETE handlers for listing, fetching, and deleting logs.
27
+ *
28
+ * @example
29
+ * ```ts
30
+ * // app/api/admin/logs/route.ts
31
+ * import { createLogAPIHandlers } from '@vinetechke/next-error-logger/api'
32
+ * import { auth } from '@/auth'
33
+ *
34
+ * const { GET, DELETE } = createLogAPIHandlers({
35
+ * isAuthorized: async () => {
36
+ * const session = await auth()
37
+ * return session?.user?.role === 'ADMIN'
38
+ * },
39
+ * })
40
+ *
41
+ * export { GET, DELETE }
42
+ * ```
43
+ *
44
+ * @example
45
+ * ```ts
46
+ * // app/api/admin/logs/[id]/route.ts
47
+ * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'
48
+ * import { auth } from '@/auth'
49
+ *
50
+ * const { GET, DELETE } = createLogDetailAPIHandlers({
51
+ * isAuthorized: async () => {
52
+ * const session = await auth()
53
+ * return session?.user?.role === 'ADMIN'
54
+ * },
55
+ * })
56
+ *
57
+ * export { GET, DELETE }
58
+ * ```
59
+ */
60
+ declare function createLogAPIHandlers(config: APIHandlerConfig): {
61
+ /**
62
+ * GET /api/logs - List logs with filtering and pagination
63
+ *
64
+ * Query parameters:
65
+ * - page: Page number (default: 1)
66
+ * - limit: Items per page (default: 50)
67
+ * - level: Filter by level (error, warn, info, debug)
68
+ * - userId: Filter by user ID
69
+ * - search: Search in message, stack, path, userEmail
70
+ * - startDate: Filter logs after this date (ISO string)
71
+ * - endDate: Filter logs before this date (ISO string)
72
+ */
73
+ GET: (request: NextRequest) => Promise<NextResponse>;
74
+ /**
75
+ * DELETE /api/logs - Clear logs
76
+ *
77
+ * Body parameters:
78
+ * - before: Delete logs before this date (ISO string)
79
+ * - level: Delete logs with this level only
80
+ */
81
+ DELETE: (request: NextRequest) => Promise<NextResponse>;
82
+ };
83
+ /**
84
+ * Create API route handlers for individual log entries
85
+ *
86
+ * @example
87
+ * ```ts
88
+ * // app/api/admin/logs/[id]/route.ts
89
+ * import { createLogDetailAPIHandlers } from '@vinetechke/next-error-logger/api'
90
+ *
91
+ * const { GET, DELETE } = createLogDetailAPIHandlers({
92
+ * isAuthorized: async () => {
93
+ * const session = await auth()
94
+ * return session?.user?.role === 'ADMIN'
95
+ * },
96
+ * })
97
+ *
98
+ * export { GET, DELETE }
99
+ * ```
100
+ */
101
+ declare function createLogDetailAPIHandlers(config: APIHandlerConfig): {
102
+ /**
103
+ * GET /api/logs/[id] - Get a single log entry
104
+ */
105
+ GET: (request: NextRequest, { params }: {
106
+ params: Promise<{
107
+ id: string;
108
+ }>;
109
+ }) => Promise<NextResponse>;
110
+ /**
111
+ * DELETE /api/logs/[id] - Delete a single log entry
112
+ */
113
+ DELETE: (request: NextRequest, { params }: {
114
+ params: Promise<{
115
+ id: string;
116
+ }>;
117
+ }) => Promise<NextResponse>;
118
+ };
119
+ /**
120
+ * Get log statistics
121
+ *
122
+ * @example
123
+ * ```ts
124
+ * // app/api/admin/logs/stats/route.ts
125
+ * import { createLogStatsHandler } from '@vinetechke/next-error-logger/api'
126
+ *
127
+ * export const GET = createLogStatsHandler({
128
+ * isAuthorized: async () => {
129
+ * const session = await auth()
130
+ * return session?.user?.role === 'ADMIN'
131
+ * },
132
+ * })
133
+ * ```
134
+ */
135
+ declare function createLogStatsHandler(config: APIHandlerConfig): (request: NextRequest) => Promise<NextResponse>;
136
+
137
+ export { type APIHandlerConfig, createLogAPIHandlers, createLogDetailAPIHandlers, createLogStatsHandler };