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.
137 lines
3.9 KiB
Markdown
137 lines
3.9 KiB
Markdown
/**
|
|
* Error Logging Usage Examples
|
|
*
|
|
* Use these patterns in your routes to get better error debugging
|
|
*/
|
|
|
|
// ============================================================================
|
|
// PATTERN 1: In a loader (data fetching)
|
|
// ============================================================================
|
|
|
|
import { json, type LoaderFunction } from "react-router";
|
|
import { logRouteError } from "@/lib/error-logger.server";
|
|
import prisma from "@/lib/prisma.server";
|
|
|
|
export const loader: LoaderFunction = async ({ request, params }) => {
|
|
try {
|
|
const company = await prisma.company.findUnique({
|
|
where: { id: params.id },
|
|
});
|
|
|
|
if (!company) {
|
|
throw new Error(`Company not found: ${params.id}`);
|
|
}
|
|
|
|
return json({ company });
|
|
} catch (error) {
|
|
logRouteError(error, {
|
|
request,
|
|
route: request.url,
|
|
userId: params.userId, // if available
|
|
metadata: {
|
|
companyId: params.id,
|
|
},
|
|
});
|
|
throw error; // Re-throw to let React Router handle it
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// PATTERN 2: In an action (mutation/form submission)
|
|
// ============================================================================
|
|
|
|
import { logActionError } from "@/lib/error-logger.server";
|
|
|
|
export const action: LoaderFunction = async ({ request, params }) => {
|
|
try {
|
|
const formData = await request.formData();
|
|
const result = await prisma.company.update({
|
|
where: { id: params.id },
|
|
data: { name: formData.get("name") },
|
|
});
|
|
return json({ success: true, result });
|
|
} catch (error) {
|
|
logActionError(error, {
|
|
request,
|
|
action: "UPDATE_COMPANY",
|
|
metadata: {
|
|
companyId: params.id,
|
|
method: request.method,
|
|
},
|
|
});
|
|
throw error;
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// PATTERN 3: In an API route (POST/PUT/DELETE)
|
|
// ============================================================================
|
|
|
|
import { logApiError } from "@/lib/error-logger.server";
|
|
|
|
export const action: LoaderFunction = async ({ request }) => {
|
|
try {
|
|
const data = await request.json();
|
|
|
|
// Validate
|
|
if (!data.name) {
|
|
return json(
|
|
{ error: "Name is required" },
|
|
{ status: 400 }
|
|
);
|
|
}
|
|
|
|
// Process
|
|
const result = await prisma.company.create({ data });
|
|
return json({ success: true, result }, { status: 201 });
|
|
} catch (error) {
|
|
logApiError(error, {
|
|
request,
|
|
endpoint: "/api/companies",
|
|
statusCode: 500,
|
|
metadata: {
|
|
method: request.method,
|
|
},
|
|
});
|
|
return json(
|
|
{ error: "Internal server error" },
|
|
{ status: 500 }
|
|
);
|
|
}
|
|
};
|
|
|
|
// ============================================================================
|
|
// PATTERN 4: Database operations with error context
|
|
// ============================================================================
|
|
|
|
import { logDatabaseError } from "@/lib/error-logger.server";
|
|
|
|
async function fetchCompanyWithUsers(companyId: string) {
|
|
try {
|
|
return await prisma.company.findUnique({
|
|
where: { id: companyId },
|
|
include: { users: true },
|
|
});
|
|
} catch (error) {
|
|
logDatabaseError(error, "company.findUnique", {
|
|
metadata: { companyId },
|
|
});
|
|
throw error;
|
|
}
|
|
}
|
|
|
|
// ============================================================================
|
|
// OUTPUT EXAMPLE (Server Console)
|
|
// ============================================================================
|
|
|
|
/*
|
|
================================================================================
|
|
[ROUTE_ERROR] | 2026-05-02T22:10:30.123Z | Company not found | route: /companies/123 | GET /companies/123 | user: user-id-456
|
|
Stack at Object.loader (file:///app/routes/companies.$id.tsx:12:13)
|
|
at process._tickCallback (internal/timers.ts:203:26)
|
|
Metadata: {
|
|
"companyId": "123"
|
|
}
|
|
================================================================================
|
|
*/
|