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

3.9 KiB

/**

  • 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" }

*/