@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.
- package/LICENSE +21 -0
- package/README.md +442 -0
- package/dist/adapters/drizzle.cjs +123 -0
- package/dist/adapters/drizzle.cjs.map +1 -0
- package/dist/adapters/drizzle.d.cts +76 -0
- package/dist/adapters/drizzle.d.ts +76 -0
- package/dist/adapters/drizzle.js +99 -0
- package/dist/adapters/drizzle.js.map +1 -0
- package/dist/adapters/prisma.cjs +120 -0
- package/dist/adapters/prisma.cjs.map +1 -0
- package/dist/adapters/prisma.d.cts +75 -0
- package/dist/adapters/prisma.d.ts +75 -0
- package/dist/adapters/prisma.js +96 -0
- package/dist/adapters/prisma.js.map +1 -0
- package/dist/adapters/sql.cjs +206 -0
- package/dist/adapters/sql.cjs.map +1 -0
- package/dist/adapters/sql.d.cts +111 -0
- package/dist/adapters/sql.d.ts +111 -0
- package/dist/adapters/sql.js +182 -0
- package/dist/adapters/sql.js.map +1 -0
- package/dist/api/index.cjs +257 -0
- package/dist/api/index.cjs.map +1 -0
- package/dist/api/index.d.cts +137 -0
- package/dist/api/index.d.ts +137 -0
- package/dist/api/index.js +231 -0
- package/dist/api/index.js.map +1 -0
- package/dist/auth/clerk.cjs +60 -0
- package/dist/auth/clerk.cjs.map +1 -0
- package/dist/auth/clerk.d.cts +83 -0
- package/dist/auth/clerk.d.ts +83 -0
- package/dist/auth/clerk.js +36 -0
- package/dist/auth/clerk.js.map +1 -0
- package/dist/auth/next-auth.cjs +50 -0
- package/dist/auth/next-auth.cjs.map +1 -0
- package/dist/auth/next-auth.d.cts +53 -0
- package/dist/auth/next-auth.d.ts +53 -0
- package/dist/auth/next-auth.js +26 -0
- package/dist/auth/next-auth.js.map +1 -0
- package/dist/components/index.cjs +1175 -0
- package/dist/components/index.cjs.map +1 -0
- package/dist/components/index.d.cts +141 -0
- package/dist/components/index.d.ts +141 -0
- package/dist/components/index.js +1147 -0
- package/dist/components/index.js.map +1 -0
- package/dist/index.cjs +241 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +109 -0
- package/dist/index.d.ts +109 -0
- package/dist/index.js +212 -0
- package/dist/index.js.map +1 -0
- package/dist/schemas/drizzle.cjs +100 -0
- package/dist/schemas/drizzle.cjs.map +1 -0
- package/dist/schemas/drizzle.d.cts +32 -0
- package/dist/schemas/drizzle.d.ts +32 -0
- package/dist/schemas/drizzle.js +74 -0
- package/dist/schemas/drizzle.js.map +1 -0
- package/dist/types-C3x_Ry2e.d.cts +195 -0
- package/dist/types-C3x_Ry2e.d.ts +195 -0
- package/package.json +128 -0
- package/schemas/prisma.prisma +23 -0
- package/schemas/schema.sql +75 -0
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/api/index.ts
|
|
4
|
+
import { NextResponse } from "next/server";
|
|
5
|
+
|
|
6
|
+
// src/logger.ts
|
|
7
|
+
var config = null;
|
|
8
|
+
function getConfig() {
|
|
9
|
+
if (!config) {
|
|
10
|
+
throw new Error(
|
|
11
|
+
"[@vinetechke/next-error-logger] Logger not initialized. Call initErrorLogger() first."
|
|
12
|
+
);
|
|
13
|
+
}
|
|
14
|
+
return config;
|
|
15
|
+
}
|
|
16
|
+
function isInitialized() {
|
|
17
|
+
return config !== null;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// src/api/index.ts
|
|
21
|
+
function createLogAPIHandlers(config2) {
|
|
22
|
+
const { isAuthorized } = config2;
|
|
23
|
+
return {
|
|
24
|
+
/**
|
|
25
|
+
* GET /api/logs - List logs with filtering and pagination
|
|
26
|
+
*
|
|
27
|
+
* Query parameters:
|
|
28
|
+
* - page: Page number (default: 1)
|
|
29
|
+
* - limit: Items per page (default: 50)
|
|
30
|
+
* - level: Filter by level (error, warn, info, debug)
|
|
31
|
+
* - userId: Filter by user ID
|
|
32
|
+
* - search: Search in message, stack, path, userEmail
|
|
33
|
+
* - startDate: Filter logs after this date (ISO string)
|
|
34
|
+
* - endDate: Filter logs before this date (ISO string)
|
|
35
|
+
*/
|
|
36
|
+
GET: async (request) => {
|
|
37
|
+
if (!await isAuthorized(request)) {
|
|
38
|
+
return NextResponse.json(
|
|
39
|
+
{ error: "Unauthorized" },
|
|
40
|
+
{ status: 401 }
|
|
41
|
+
);
|
|
42
|
+
}
|
|
43
|
+
if (!isInitialized()) {
|
|
44
|
+
return NextResponse.json(
|
|
45
|
+
{ error: "Logger not initialized" },
|
|
46
|
+
{ status: 500 }
|
|
47
|
+
);
|
|
48
|
+
}
|
|
49
|
+
const cfg = getConfig();
|
|
50
|
+
const searchParams = request.nextUrl.searchParams;
|
|
51
|
+
try {
|
|
52
|
+
const options = {
|
|
53
|
+
page: parseInt(searchParams.get("page") || "1", 10),
|
|
54
|
+
limit: Math.min(
|
|
55
|
+
parseInt(searchParams.get("limit") || "50", 10),
|
|
56
|
+
100
|
|
57
|
+
),
|
|
58
|
+
level: searchParams.get("level"),
|
|
59
|
+
userId: searchParams.get("userId") || void 0,
|
|
60
|
+
search: searchParams.get("search") || void 0,
|
|
61
|
+
startDate: searchParams.get("startDate") ? new Date(searchParams.get("startDate")) : void 0,
|
|
62
|
+
endDate: searchParams.get("endDate") ? new Date(searchParams.get("endDate")) : void 0
|
|
63
|
+
};
|
|
64
|
+
const result = await cfg.adapter.findMany(options);
|
|
65
|
+
return NextResponse.json(result);
|
|
66
|
+
} catch (error) {
|
|
67
|
+
console.error("[@vinetechke/next-error-logger] API error:", error);
|
|
68
|
+
return NextResponse.json(
|
|
69
|
+
{ error: "Failed to fetch logs" },
|
|
70
|
+
{ status: 500 }
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
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: async (request) => {
|
|
82
|
+
if (!await isAuthorized(request)) {
|
|
83
|
+
return NextResponse.json(
|
|
84
|
+
{ error: "Unauthorized" },
|
|
85
|
+
{ status: 401 }
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (!isInitialized()) {
|
|
89
|
+
return NextResponse.json(
|
|
90
|
+
{ error: "Logger not initialized" },
|
|
91
|
+
{ status: 500 }
|
|
92
|
+
);
|
|
93
|
+
}
|
|
94
|
+
const cfg = getConfig();
|
|
95
|
+
try {
|
|
96
|
+
const body = await request.json().catch(() => ({}));
|
|
97
|
+
const count = await cfg.adapter.deleteMany({
|
|
98
|
+
before: body.before ? new Date(body.before) : void 0,
|
|
99
|
+
level: body.level
|
|
100
|
+
});
|
|
101
|
+
return NextResponse.json({ deleted: count });
|
|
102
|
+
} catch (error) {
|
|
103
|
+
console.error("[@vinetechke/next-error-logger] API error:", error);
|
|
104
|
+
return NextResponse.json(
|
|
105
|
+
{ error: "Failed to delete logs" },
|
|
106
|
+
{ status: 500 }
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
function createLogDetailAPIHandlers(config2) {
|
|
113
|
+
const { isAuthorized } = config2;
|
|
114
|
+
return {
|
|
115
|
+
/**
|
|
116
|
+
* GET /api/logs/[id] - Get a single log entry
|
|
117
|
+
*/
|
|
118
|
+
GET: async (request, { params }) => {
|
|
119
|
+
if (!await isAuthorized(request)) {
|
|
120
|
+
return NextResponse.json(
|
|
121
|
+
{ error: "Unauthorized" },
|
|
122
|
+
{ status: 401 }
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
if (!isInitialized()) {
|
|
126
|
+
return NextResponse.json(
|
|
127
|
+
{ error: "Logger not initialized" },
|
|
128
|
+
{ status: 500 }
|
|
129
|
+
);
|
|
130
|
+
}
|
|
131
|
+
const cfg = getConfig();
|
|
132
|
+
const { id } = await params;
|
|
133
|
+
try {
|
|
134
|
+
const log = await cfg.adapter.findById(id);
|
|
135
|
+
if (!log) {
|
|
136
|
+
return NextResponse.json(
|
|
137
|
+
{ error: "Not found" },
|
|
138
|
+
{ status: 404 }
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
return NextResponse.json(log);
|
|
142
|
+
} catch (error) {
|
|
143
|
+
console.error("[@vinetechke/next-error-logger] API error:", error);
|
|
144
|
+
return NextResponse.json(
|
|
145
|
+
{ error: "Failed to fetch log" },
|
|
146
|
+
{ status: 500 }
|
|
147
|
+
);
|
|
148
|
+
}
|
|
149
|
+
},
|
|
150
|
+
/**
|
|
151
|
+
* DELETE /api/logs/[id] - Delete a single log entry
|
|
152
|
+
*/
|
|
153
|
+
DELETE: async (request, { params }) => {
|
|
154
|
+
if (!await isAuthorized(request)) {
|
|
155
|
+
return NextResponse.json(
|
|
156
|
+
{ error: "Unauthorized" },
|
|
157
|
+
{ status: 401 }
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
if (!isInitialized()) {
|
|
161
|
+
return NextResponse.json(
|
|
162
|
+
{ error: "Logger not initialized" },
|
|
163
|
+
{ status: 500 }
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
const cfg = getConfig();
|
|
167
|
+
const { id } = await params;
|
|
168
|
+
try {
|
|
169
|
+
await cfg.adapter.delete(id);
|
|
170
|
+
return NextResponse.json({ success: true });
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error("[@vinetechke/next-error-logger] API error:", error);
|
|
173
|
+
return NextResponse.json(
|
|
174
|
+
{ error: "Failed to delete log" },
|
|
175
|
+
{ status: 500 }
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
function createLogStatsHandler(config2) {
|
|
182
|
+
const { isAuthorized } = config2;
|
|
183
|
+
return async (request) => {
|
|
184
|
+
if (!await isAuthorized(request)) {
|
|
185
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
186
|
+
}
|
|
187
|
+
if (!isInitialized()) {
|
|
188
|
+
return NextResponse.json(
|
|
189
|
+
{ error: "Logger not initialized" },
|
|
190
|
+
{ status: 500 }
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
const cfg = getConfig();
|
|
194
|
+
try {
|
|
195
|
+
const [errors, warnings, infos, debugs, total] = await Promise.all([
|
|
196
|
+
cfg.adapter.findMany({ level: "error", limit: 0 }).then((r) => r.total),
|
|
197
|
+
cfg.adapter.findMany({ level: "warn", limit: 0 }).then((r) => r.total),
|
|
198
|
+
cfg.adapter.findMany({ level: "info", limit: 0 }).then((r) => r.total),
|
|
199
|
+
cfg.adapter.findMany({ level: "debug", limit: 0 }).then((r) => r.total),
|
|
200
|
+
cfg.adapter.findMany({ limit: 0 }).then((r) => r.total)
|
|
201
|
+
]);
|
|
202
|
+
const oneDayAgo = new Date(Date.now() - 24 * 60 * 60 * 1e3);
|
|
203
|
+
const recentResult = await cfg.adapter.findMany({
|
|
204
|
+
startDate: oneDayAgo,
|
|
205
|
+
limit: 0
|
|
206
|
+
});
|
|
207
|
+
return NextResponse.json({
|
|
208
|
+
total,
|
|
209
|
+
byLevel: {
|
|
210
|
+
error: errors,
|
|
211
|
+
warn: warnings,
|
|
212
|
+
info: infos,
|
|
213
|
+
debug: debugs
|
|
214
|
+
},
|
|
215
|
+
last24Hours: recentResult.total
|
|
216
|
+
});
|
|
217
|
+
} catch (error) {
|
|
218
|
+
console.error("[@vinetechke/next-error-logger] API error:", error);
|
|
219
|
+
return NextResponse.json(
|
|
220
|
+
{ error: "Failed to fetch stats" },
|
|
221
|
+
{ status: 500 }
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
export {
|
|
227
|
+
createLogAPIHandlers,
|
|
228
|
+
createLogDetailAPIHandlers,
|
|
229
|
+
createLogStatsHandler
|
|
230
|
+
};
|
|
231
|
+
//# sourceMappingURL=index.js.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,60 @@
|
|
|
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/auth/clerk.ts
|
|
22
|
+
var clerk_exports = {};
|
|
23
|
+
__export(clerk_exports, {
|
|
24
|
+
createClerkAdapter: () => createClerkAdapter
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(clerk_exports);
|
|
27
|
+
function createClerkAdapter(config) {
|
|
28
|
+
const { auth, fetchUser } = config;
|
|
29
|
+
return {
|
|
30
|
+
async getUser() {
|
|
31
|
+
try {
|
|
32
|
+
const { userId } = await auth();
|
|
33
|
+
if (!userId) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
if (!fetchUser) {
|
|
37
|
+
return { id: userId };
|
|
38
|
+
}
|
|
39
|
+
const user = await fetchUser(userId);
|
|
40
|
+
if (!user) {
|
|
41
|
+
return { id: userId };
|
|
42
|
+
}
|
|
43
|
+
const email = user.emailAddresses?.[0]?.emailAddress;
|
|
44
|
+
const name = [user.firstName, user.lastName].filter(Boolean).join(" ") || void 0;
|
|
45
|
+
return {
|
|
46
|
+
id: user.id,
|
|
47
|
+
email,
|
|
48
|
+
name
|
|
49
|
+
};
|
|
50
|
+
} catch {
|
|
51
|
+
return null;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
57
|
+
0 && (module.exports = {
|
|
58
|
+
createClerkAdapter
|
|
59
|
+
});
|
|
60
|
+
//# sourceMappingURL=clerk.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/clerk.ts"],"sourcesContent":["import type { AuthAdapter } from '../types'\n\n/**\n * Clerk user interface (simplified)\n */\ninterface ClerkUser {\n id: string\n emailAddresses?: Array<{ emailAddress: string }>\n firstName?: string | null\n lastName?: string | null\n}\n\n/**\n * Clerk auth function type\n */\ntype ClerkAuthFn = () => Promise<{ userId: string | null }>\n\n/**\n * Clerk user fetcher type\n */\ntype ClerkUserFn = (userId: string) => Promise<ClerkUser | null>\n\n/**\n * Configuration for the Clerk adapter\n */\nexport interface ClerkAdapterConfig {\n /**\n * Clerk's auth() function from @clerk/nextjs/server\n */\n auth: ClerkAuthFn\n /**\n * Optional: Function to fetch full user details\n * If not provided, only userId will be captured\n *\n * @example\n * ```ts\n * import { clerkClient } from '@clerk/nextjs/server'\n *\n * const fetchUser = async (userId: string) => {\n * return clerkClient.users.getUser(userId)\n * }\n * ```\n */\n fetchUser?: ClerkUserFn\n}\n\n/**\n * Create a Clerk authentication adapter\n *\n * Automatically captures user context from Clerk sessions.\n *\n * @example\n * ```ts\n * // Basic usage (userId only)\n * import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'\n * import { auth } from '@clerk/nextjs/server'\n *\n * const authAdapter = createClerkAdapter({ auth })\n * ```\n *\n * @example\n * ```ts\n * // With full user details\n * import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'\n * import { auth, clerkClient } from '@clerk/nextjs/server'\n *\n * const authAdapter = createClerkAdapter({\n * auth,\n * fetchUser: async (userId) => {\n * return clerkClient.users.getUser(userId)\n * },\n * })\n *\n * // Initialize logger\n * initErrorLogger({\n * adapter: createPrismaAdapter(prisma),\n * authAdapter,\n * })\n * ```\n */\nexport function createClerkAdapter(config: ClerkAdapterConfig): AuthAdapter {\n const { auth, fetchUser } = config\n\n return {\n async getUser() {\n try {\n const { userId } = await auth()\n\n if (!userId) {\n return null\n }\n\n // If no fetchUser function provided, return just the ID\n if (!fetchUser) {\n return { id: userId }\n }\n\n // Fetch full user details\n const user = await fetchUser(userId)\n\n if (!user) {\n return { id: userId }\n }\n\n const email = user.emailAddresses?.[0]?.emailAddress\n const name =\n [user.firstName, user.lastName].filter(Boolean).join(' ') ||\n undefined\n\n return {\n id: user.id,\n email,\n name,\n }\n } catch {\n // Silently fail - user context is optional\n return null\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAgFO,SAAS,mBAAmB,QAAyC;AACxE,QAAM,EAAE,MAAM,UAAU,IAAI;AAE5B,SAAO;AAAA,IACH,MAAM,UAAU;AACZ,UAAI;AACA,cAAM,EAAE,OAAO,IAAI,MAAM,KAAK;AAE9B,YAAI,CAAC,QAAQ;AACT,iBAAO;AAAA,QACX;AAGA,YAAI,CAAC,WAAW;AACZ,iBAAO,EAAE,IAAI,OAAO;AAAA,QACxB;AAGA,cAAM,OAAO,MAAM,UAAU,MAAM;AAEnC,YAAI,CAAC,MAAM;AACP,iBAAO,EAAE,IAAI,OAAO;AAAA,QACxB;AAEA,cAAM,QAAQ,KAAK,iBAAiB,CAAC,GAAG;AACxC,cAAM,OACF,CAAC,KAAK,WAAW,KAAK,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KACxD;AAEJ,eAAO;AAAA,UACH,IAAI,KAAK;AAAA,UACT;AAAA,UACA;AAAA,QACJ;AAAA,MACJ,QAAQ;AAEJ,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AACJ;","names":[]}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { A as AuthAdapter } from '../types-C3x_Ry2e.cjs';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clerk user interface (simplified)
|
|
5
|
+
*/
|
|
6
|
+
interface ClerkUser {
|
|
7
|
+
id: string;
|
|
8
|
+
emailAddresses?: Array<{
|
|
9
|
+
emailAddress: string;
|
|
10
|
+
}>;
|
|
11
|
+
firstName?: string | null;
|
|
12
|
+
lastName?: string | null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Clerk auth function type
|
|
16
|
+
*/
|
|
17
|
+
type ClerkAuthFn = () => Promise<{
|
|
18
|
+
userId: string | null;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Clerk user fetcher type
|
|
22
|
+
*/
|
|
23
|
+
type ClerkUserFn = (userId: string) => Promise<ClerkUser | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for the Clerk adapter
|
|
26
|
+
*/
|
|
27
|
+
interface ClerkAdapterConfig {
|
|
28
|
+
/**
|
|
29
|
+
* Clerk's auth() function from @clerk/nextjs/server
|
|
30
|
+
*/
|
|
31
|
+
auth: ClerkAuthFn;
|
|
32
|
+
/**
|
|
33
|
+
* Optional: Function to fetch full user details
|
|
34
|
+
* If not provided, only userId will be captured
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { clerkClient } from '@clerk/nextjs/server'
|
|
39
|
+
*
|
|
40
|
+
* const fetchUser = async (userId: string) => {
|
|
41
|
+
* return clerkClient.users.getUser(userId)
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
fetchUser?: ClerkUserFn;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a Clerk authentication adapter
|
|
49
|
+
*
|
|
50
|
+
* Automatically captures user context from Clerk sessions.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* // Basic usage (userId only)
|
|
55
|
+
* import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'
|
|
56
|
+
* import { auth } from '@clerk/nextjs/server'
|
|
57
|
+
*
|
|
58
|
+
* const authAdapter = createClerkAdapter({ auth })
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* // With full user details
|
|
64
|
+
* import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'
|
|
65
|
+
* import { auth, clerkClient } from '@clerk/nextjs/server'
|
|
66
|
+
*
|
|
67
|
+
* const authAdapter = createClerkAdapter({
|
|
68
|
+
* auth,
|
|
69
|
+
* fetchUser: async (userId) => {
|
|
70
|
+
* return clerkClient.users.getUser(userId)
|
|
71
|
+
* },
|
|
72
|
+
* })
|
|
73
|
+
*
|
|
74
|
+
* // Initialize logger
|
|
75
|
+
* initErrorLogger({
|
|
76
|
+
* adapter: createPrismaAdapter(prisma),
|
|
77
|
+
* authAdapter,
|
|
78
|
+
* })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
declare function createClerkAdapter(config: ClerkAdapterConfig): AuthAdapter;
|
|
82
|
+
|
|
83
|
+
export { type ClerkAdapterConfig, createClerkAdapter };
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { A as AuthAdapter } from '../types-C3x_Ry2e.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Clerk user interface (simplified)
|
|
5
|
+
*/
|
|
6
|
+
interface ClerkUser {
|
|
7
|
+
id: string;
|
|
8
|
+
emailAddresses?: Array<{
|
|
9
|
+
emailAddress: string;
|
|
10
|
+
}>;
|
|
11
|
+
firstName?: string | null;
|
|
12
|
+
lastName?: string | null;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* Clerk auth function type
|
|
16
|
+
*/
|
|
17
|
+
type ClerkAuthFn = () => Promise<{
|
|
18
|
+
userId: string | null;
|
|
19
|
+
}>;
|
|
20
|
+
/**
|
|
21
|
+
* Clerk user fetcher type
|
|
22
|
+
*/
|
|
23
|
+
type ClerkUserFn = (userId: string) => Promise<ClerkUser | null>;
|
|
24
|
+
/**
|
|
25
|
+
* Configuration for the Clerk adapter
|
|
26
|
+
*/
|
|
27
|
+
interface ClerkAdapterConfig {
|
|
28
|
+
/**
|
|
29
|
+
* Clerk's auth() function from @clerk/nextjs/server
|
|
30
|
+
*/
|
|
31
|
+
auth: ClerkAuthFn;
|
|
32
|
+
/**
|
|
33
|
+
* Optional: Function to fetch full user details
|
|
34
|
+
* If not provided, only userId will be captured
|
|
35
|
+
*
|
|
36
|
+
* @example
|
|
37
|
+
* ```ts
|
|
38
|
+
* import { clerkClient } from '@clerk/nextjs/server'
|
|
39
|
+
*
|
|
40
|
+
* const fetchUser = async (userId: string) => {
|
|
41
|
+
* return clerkClient.users.getUser(userId)
|
|
42
|
+
* }
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
fetchUser?: ClerkUserFn;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Create a Clerk authentication adapter
|
|
49
|
+
*
|
|
50
|
+
* Automatically captures user context from Clerk sessions.
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```ts
|
|
54
|
+
* // Basic usage (userId only)
|
|
55
|
+
* import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'
|
|
56
|
+
* import { auth } from '@clerk/nextjs/server'
|
|
57
|
+
*
|
|
58
|
+
* const authAdapter = createClerkAdapter({ auth })
|
|
59
|
+
* ```
|
|
60
|
+
*
|
|
61
|
+
* @example
|
|
62
|
+
* ```ts
|
|
63
|
+
* // With full user details
|
|
64
|
+
* import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'
|
|
65
|
+
* import { auth, clerkClient } from '@clerk/nextjs/server'
|
|
66
|
+
*
|
|
67
|
+
* const authAdapter = createClerkAdapter({
|
|
68
|
+
* auth,
|
|
69
|
+
* fetchUser: async (userId) => {
|
|
70
|
+
* return clerkClient.users.getUser(userId)
|
|
71
|
+
* },
|
|
72
|
+
* })
|
|
73
|
+
*
|
|
74
|
+
* // Initialize logger
|
|
75
|
+
* initErrorLogger({
|
|
76
|
+
* adapter: createPrismaAdapter(prisma),
|
|
77
|
+
* authAdapter,
|
|
78
|
+
* })
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
declare function createClerkAdapter(config: ClerkAdapterConfig): AuthAdapter;
|
|
82
|
+
|
|
83
|
+
export { type ClerkAdapterConfig, createClerkAdapter };
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"use client";
|
|
2
|
+
|
|
3
|
+
// src/auth/clerk.ts
|
|
4
|
+
function createClerkAdapter(config) {
|
|
5
|
+
const { auth, fetchUser } = config;
|
|
6
|
+
return {
|
|
7
|
+
async getUser() {
|
|
8
|
+
try {
|
|
9
|
+
const { userId } = await auth();
|
|
10
|
+
if (!userId) {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
if (!fetchUser) {
|
|
14
|
+
return { id: userId };
|
|
15
|
+
}
|
|
16
|
+
const user = await fetchUser(userId);
|
|
17
|
+
if (!user) {
|
|
18
|
+
return { id: userId };
|
|
19
|
+
}
|
|
20
|
+
const email = user.emailAddresses?.[0]?.emailAddress;
|
|
21
|
+
const name = [user.firstName, user.lastName].filter(Boolean).join(" ") || void 0;
|
|
22
|
+
return {
|
|
23
|
+
id: user.id,
|
|
24
|
+
email,
|
|
25
|
+
name
|
|
26
|
+
};
|
|
27
|
+
} catch {
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export {
|
|
34
|
+
createClerkAdapter
|
|
35
|
+
};
|
|
36
|
+
//# sourceMappingURL=clerk.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/clerk.ts"],"sourcesContent":["import type { AuthAdapter } from '../types'\n\n/**\n * Clerk user interface (simplified)\n */\ninterface ClerkUser {\n id: string\n emailAddresses?: Array<{ emailAddress: string }>\n firstName?: string | null\n lastName?: string | null\n}\n\n/**\n * Clerk auth function type\n */\ntype ClerkAuthFn = () => Promise<{ userId: string | null }>\n\n/**\n * Clerk user fetcher type\n */\ntype ClerkUserFn = (userId: string) => Promise<ClerkUser | null>\n\n/**\n * Configuration for the Clerk adapter\n */\nexport interface ClerkAdapterConfig {\n /**\n * Clerk's auth() function from @clerk/nextjs/server\n */\n auth: ClerkAuthFn\n /**\n * Optional: Function to fetch full user details\n * If not provided, only userId will be captured\n *\n * @example\n * ```ts\n * import { clerkClient } from '@clerk/nextjs/server'\n *\n * const fetchUser = async (userId: string) => {\n * return clerkClient.users.getUser(userId)\n * }\n * ```\n */\n fetchUser?: ClerkUserFn\n}\n\n/**\n * Create a Clerk authentication adapter\n *\n * Automatically captures user context from Clerk sessions.\n *\n * @example\n * ```ts\n * // Basic usage (userId only)\n * import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'\n * import { auth } from '@clerk/nextjs/server'\n *\n * const authAdapter = createClerkAdapter({ auth })\n * ```\n *\n * @example\n * ```ts\n * // With full user details\n * import { createClerkAdapter } from '@vinetechke/next-error-logger/auth/clerk'\n * import { auth, clerkClient } from '@clerk/nextjs/server'\n *\n * const authAdapter = createClerkAdapter({\n * auth,\n * fetchUser: async (userId) => {\n * return clerkClient.users.getUser(userId)\n * },\n * })\n *\n * // Initialize logger\n * initErrorLogger({\n * adapter: createPrismaAdapter(prisma),\n * authAdapter,\n * })\n * ```\n */\nexport function createClerkAdapter(config: ClerkAdapterConfig): AuthAdapter {\n const { auth, fetchUser } = config\n\n return {\n async getUser() {\n try {\n const { userId } = await auth()\n\n if (!userId) {\n return null\n }\n\n // If no fetchUser function provided, return just the ID\n if (!fetchUser) {\n return { id: userId }\n }\n\n // Fetch full user details\n const user = await fetchUser(userId)\n\n if (!user) {\n return { id: userId }\n }\n\n const email = user.emailAddresses?.[0]?.emailAddress\n const name =\n [user.firstName, user.lastName].filter(Boolean).join(' ') ||\n undefined\n\n return {\n id: user.id,\n email,\n name,\n }\n } catch {\n // Silently fail - user context is optional\n return null\n }\n },\n }\n}\n"],"mappings":";;;AAgFO,SAAS,mBAAmB,QAAyC;AACxE,QAAM,EAAE,MAAM,UAAU,IAAI;AAE5B,SAAO;AAAA,IACH,MAAM,UAAU;AACZ,UAAI;AACA,cAAM,EAAE,OAAO,IAAI,MAAM,KAAK;AAE9B,YAAI,CAAC,QAAQ;AACT,iBAAO;AAAA,QACX;AAGA,YAAI,CAAC,WAAW;AACZ,iBAAO,EAAE,IAAI,OAAO;AAAA,QACxB;AAGA,cAAM,OAAO,MAAM,UAAU,MAAM;AAEnC,YAAI,CAAC,MAAM;AACP,iBAAO,EAAE,IAAI,OAAO;AAAA,QACxB;AAEA,cAAM,QAAQ,KAAK,iBAAiB,CAAC,GAAG;AACxC,cAAM,OACF,CAAC,KAAK,WAAW,KAAK,QAAQ,EAAE,OAAO,OAAO,EAAE,KAAK,GAAG,KACxD;AAEJ,eAAO;AAAA,UACH,IAAI,KAAK;AAAA,UACT;AAAA,UACA;AAAA,QACJ;AAAA,MACJ,QAAQ;AAEJ,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AACJ;","names":[]}
|
|
@@ -0,0 +1,50 @@
|
|
|
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/auth/next-auth.ts
|
|
22
|
+
var next_auth_exports = {};
|
|
23
|
+
__export(next_auth_exports, {
|
|
24
|
+
createNextAuthAdapter: () => createNextAuthAdapter
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(next_auth_exports);
|
|
27
|
+
function createNextAuthAdapter(authFn) {
|
|
28
|
+
return {
|
|
29
|
+
async getUser() {
|
|
30
|
+
try {
|
|
31
|
+
const session = await authFn();
|
|
32
|
+
if (!session?.user?.id) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
id: session.user.id,
|
|
37
|
+
email: session.user.email || void 0,
|
|
38
|
+
name: session.user.name || void 0
|
|
39
|
+
};
|
|
40
|
+
} catch {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
47
|
+
0 && (module.exports = {
|
|
48
|
+
createNextAuthAdapter
|
|
49
|
+
});
|
|
50
|
+
//# sourceMappingURL=next-auth.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../../src/auth/next-auth.ts"],"sourcesContent":["import type { AuthAdapter } from '../types'\n\n/**\n * NextAuth session interface\n */\ninterface NextAuthSession {\n user?: {\n id?: string\n email?: string | null\n name?: string | null\n } | null\n}\n\n/**\n * NextAuth auth function type\n */\ntype NextAuthFn = () => Promise<NextAuthSession | null>\n\n/**\n * Create a NextAuth authentication adapter\n *\n * Automatically captures user context from NextAuth sessions.\n *\n * @example\n * ```ts\n * // With NextAuth v5 (Auth.js)\n * import { createNextAuthAdapter } from '@vinetechke/next-error-logger/auth/next-auth'\n * import { auth } from '@/auth' // Your NextAuth config\n *\n * const authAdapter = createNextAuthAdapter(auth)\n *\n * // Initialize logger\n * initErrorLogger({\n * adapter: createPrismaAdapter(prisma),\n * authAdapter,\n * })\n * ```\n *\n * @example\n * ```ts\n * // With NextAuth v4\n * import { createNextAuthAdapter } from '@vinetechke/next-error-logger/auth/next-auth'\n * import { getServerSession } from 'next-auth'\n * import { authOptions } from '@/app/api/auth/[...nextauth]/route'\n *\n * const authAdapter = createNextAuthAdapter(async () => {\n * return getServerSession(authOptions)\n * })\n * ```\n *\n * @param authFn - Your NextAuth auth() function or a wrapper that returns the session\n */\nexport function createNextAuthAdapter(authFn: NextAuthFn): AuthAdapter {\n return {\n async getUser() {\n try {\n const session = await authFn()\n\n if (!session?.user?.id) {\n return null\n }\n\n return {\n id: session.user.id,\n email: session.user.email || undefined,\n name: session.user.name || undefined,\n }\n } catch {\n // Silently fail - user context is optional\n return null\n }\n },\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAoDO,SAAS,sBAAsB,QAAiC;AACnE,SAAO;AAAA,IACH,MAAM,UAAU;AACZ,UAAI;AACA,cAAM,UAAU,MAAM,OAAO;AAE7B,YAAI,CAAC,SAAS,MAAM,IAAI;AACpB,iBAAO;AAAA,QACX;AAEA,eAAO;AAAA,UACH,IAAI,QAAQ,KAAK;AAAA,UACjB,OAAO,QAAQ,KAAK,SAAS;AAAA,UAC7B,MAAM,QAAQ,KAAK,QAAQ;AAAA,QAC/B;AAAA,MACJ,QAAQ;AAEJ,eAAO;AAAA,MACX;AAAA,IACJ;AAAA,EACJ;AACJ;","names":[]}
|