-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathutils.ts
More file actions
93 lines (84 loc) · 2.41 KB
/
Copy pathutils.ts
File metadata and controls
93 lines (84 loc) · 2.41 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
import { clsx, type ClassValue } from "clsx"
import { twMerge } from "tailwind-merge"
import type { ActionResult } from "./types";
type PrismaLikeKnownRequestError = {
code: string;
meta?: {
target?: string | string[];
};
};
function isPrismaLikeKnownRequestError(
error: unknown
): error is PrismaLikeKnownRequestError {
return (
typeof error === "object" &&
error !== null &&
"code" in error &&
typeof (error as { code: unknown }).code === "string" &&
(error as { code: string }).code.startsWith("P")
);
}
function formatPrismaErrorMessage(error: PrismaLikeKnownRequestError): string {
switch (error.code) {
case "P2000":
return "A field contains a value that is too long.";
case "P2002": {
const target = error.meta?.target;
const fields = Array.isArray(target)
? target.join(", ")
: typeof target === "string"
? target
: null;
return fields
? `A record with this ${fields} already exists.`
: "A record with these details already exists.";
}
case "P2003":
return "This action references related data that no longer exists.";
case "P2011":
return "A required field is missing.";
case "P2014":
return "This record is referenced by other records and cannot be deleted.";
case "P2015":
return "The related record could not be found.";
case "P2024":
return "Database connection timeout. Please try again.";
case "P2025":
return "The requested record was not found.";
case "P2027":
return "Multiple database errors occurred. Please try again.";
default:
return "A database operation failed. Please try again.";
}
}
function formatActionError(error: unknown): string {
if (isPrismaLikeKnownRequestError(error)) {
return formatPrismaErrorMessage(error);
}
if (error instanceof Error) {
return error.message;
}
return "Unknown error";
}
export function cn(...inputs: ClassValue[]) {
return twMerge(clsx(inputs))
}
export function validateName(name: string): string {
const trimmed = name.trim();
if (!trimmed) {
throw new Error("Name cannot be empty");
}
return trimmed;
}
export async function wrapAction<T>(
fn: () => Promise<T>
): Promise<ActionResult<T>> {
try {
return { success: true, data: await fn() };
} catch (error) {
return {
success: false,
error: formatActionError(error),
};
}
}