b22e5baa5c
Build and Push Docker Image / build (push) Successful in 1m23s
- Implemented client-side validation functions for tax ID, VAT ID, IBAN, BIC, and website URL. - Added debug logging functionality to assist in development. - Created a comprehensive validation function for company form data. feat: initialize database with Prisma migrations - Added a server-side script to run Prisma migrations and check database health. - Ensured safe initialization of the database to prevent concurrent migrations. feat: comprehensive server-side error logging - Developed an error logging system that captures detailed error context, including request details and stack traces. - Implemented logging functions for different error types (route, action, database, API, startup). fix: validate user ID existence in audit logs - Updated the logging function to validate that the user ID exists in the database before logging actions. fix: update schemas for optional fields and validation - Modified schemas to allow for nullable fields and refined validation logic for tax ID, VAT ID, IBAN, and BIC. feat: enhance error boundary for better debugging - Improved error boundary to log detailed error information in development mode. - Added a debug panel to the main application layout for real-time error tracking. feat: implement company deletion functionality in admin routes - Added a new API route for deleting companies with appropriate logging. - Integrated delete confirmation in the admin interface for better user experience. fix: handle API errors gracefully - Wrapped API actions in try-catch blocks to log errors and return appropriate responses. feat: generate and save invoice PDFs - Implemented functionality to generate and save invoice PDFs upon status updates. - Added a new column in the database for storing the URL of the generated PDF. chore: update Docker image reference - Changed the Docker image reference to point to the new Git repository. chore: update package dependencies - Added @radix-ui/react-tooltip for enhanced UI components. - Updated package-lock.json to reflect new dependencies.
96 lines
3.3 KiB
Markdown
96 lines
3.3 KiB
Markdown
/**
|
|
* INTEGRATION EXAMPLE: How to use error logging in your existing routes
|
|
* This shows the new error-logger.server in real-world usage
|
|
*/
|
|
|
|
// Before (old code - minimal logging):
|
|
/*
|
|
export async function action({ request }: { request: Request }) {
|
|
const user = await getApiUser(request);
|
|
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
|
const body = await request.json();
|
|
const parsed = customerSchema.safeParse(body);
|
|
if (!parsed.success) return Response.json({ error: parsed.error.issues }, { status: 400 });
|
|
|
|
try {
|
|
const customer = await prisma.customer.create({ data: parsed.data });
|
|
await log({ userId: user.id, action: "CREATE_CUSTOMER", entity: "Customer", entityId: customer.id, request });
|
|
return Response.json(customer, { status: 201 });
|
|
} catch (error) {
|
|
console.error(error); // ❌ Not helpful for debugging
|
|
return Response.json({ error: "Internal server error" }, { status: 500 });
|
|
}
|
|
}
|
|
*/
|
|
|
|
// After (with comprehensive error logging):
|
|
import { getApiUser } from "@/session.server";
|
|
import prisma from "@/lib/prisma.server";
|
|
import { log } from "@/lib/logger.server";
|
|
import { logApiError } from "@/lib/error-logger.server";
|
|
import { customerSchema } from "@/lib/schemas";
|
|
|
|
export async function action({ request }: { request: Request }) {
|
|
const user = await getApiUser(request);
|
|
if (!user) return Response.json({ error: "Unauthorized" }, { status: 401 });
|
|
|
|
try {
|
|
const body = await request.json();
|
|
const parsed = customerSchema.safeParse(body);
|
|
if (!parsed.success) {
|
|
return Response.json({ error: parsed.error.issues }, { status: 400 });
|
|
}
|
|
|
|
const customer = await prisma.customer.create({ data: parsed.data });
|
|
await log({
|
|
userId: user.id,
|
|
action: "CREATE_CUSTOMER",
|
|
entity: "Customer",
|
|
entityId: customer.id,
|
|
request,
|
|
});
|
|
return Response.json(customer, { status: 201 });
|
|
} catch (error) {
|
|
// ✅ Now with full context: stack trace, request details, metadata
|
|
logApiError(error, {
|
|
request,
|
|
endpoint: "/api/customers",
|
|
userId: user.id,
|
|
statusCode: 500,
|
|
metadata: {
|
|
method: request.method,
|
|
},
|
|
});
|
|
return Response.json({ error: "Internal server error" }, { status: 500 });
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// WHAT YOU'LL SEE IN THE SERVER LOGS NOW:
|
|
// ============================================================================
|
|
|
|
/*
|
|
================================================================================
|
|
[API_ERROR] | 2026-05-02T22:15:45.789Z | duplicate entry for unique field 'email'
|
|
POST /api/customers | user: user-abc123 | ip: 192.168.1.100 | endpoint: /api/customers | statusCode: 500
|
|
Error: Customer with email 'john@example.com' already exists
|
|
at Object.create (file:///app/lib/customer.server.ts:25:13)
|
|
at action (file:///app/routes/api.customers.ts:30:7)
|
|
at processRequest (file:///app/routes/_middleware.ts:12:3)
|
|
|
|
Metadata: {
|
|
"method": "POST",
|
|
"endpoint": "/api/customers"
|
|
}
|
|
================================================================================
|
|
|
|
✓ You can now see:
|
|
- Exact error message with context
|
|
- HTTP method & endpoint
|
|
- User ID & IP address
|
|
- Stack trace for debugging
|
|
- Custom metadata
|
|
- Timestamp
|
|
*/
|