Files
hwinkel b22e5baa5c
Build and Push Docker Image / build (push) Successful in 1m23s
feat: add client-side validation utilities and debugging tools
- 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.
2026-05-03 08:46:58 +02:00

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"
}
================================================================================
*/