@valentine-efagene/qshelter-common 2.0.149 → 2.0.151
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated/client/commonInputTypes.d.ts +30 -0
- package/dist/generated/client/enums.d.ts +7 -0
- package/dist/generated/client/enums.js +6 -0
- package/dist/generated/client/internal/class.js +2 -2
- package/dist/generated/client/internal/prismaNamespace.d.ts +4 -2
- package/dist/generated/client/internal/prismaNamespace.js +0 -2
- package/dist/generated/client/internal/prismaNamespaceBrowser.d.ts +0 -2
- package/dist/generated/client/internal/prismaNamespaceBrowser.js +0 -2
- package/dist/generated/client/models/Property.d.ts +59 -120
- package/dist/src/middleware/error-handler.d.ts +1 -1
- package/dist/src/middleware/error-handler.js +85 -1
- package/package.json +1 -1
- package/prisma/migrations/20260125090213_remove_is_published_use_status_enum/migration.sql +10 -0
- package/prisma/schema.prisma +8 -2
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { Request, Response, NextFunction } from 'express';
|
|
2
2
|
/**
|
|
3
3
|
* Global error handler middleware for Express applications.
|
|
4
|
-
* Handles ZodError, AppError, and generic errors with appropriate responses.
|
|
4
|
+
* Handles ZodError, AppError, Prisma errors, and generic errors with appropriate responses.
|
|
5
5
|
*/
|
|
6
6
|
export declare function errorHandler(err: Error, req: Request, res: Response, next: NextFunction): Response<any, Record<string, any>>;
|
|
@@ -1,10 +1,83 @@
|
|
|
1
1
|
import { ZodError } from 'zod';
|
|
2
2
|
import { AppError } from '../utils/errors';
|
|
3
|
+
/**
|
|
4
|
+
* Extract a user-friendly field name from Prisma's target array.
|
|
5
|
+
* Handles composite unique constraints like `tenantId_cacNumber`.
|
|
6
|
+
*/
|
|
7
|
+
function extractFieldName(target) {
|
|
8
|
+
// Filter out common fields that are not user-facing
|
|
9
|
+
const userFacingFields = target.filter((f) => !['tenantId', 'id', 'createdAt', 'updatedAt'].includes(f));
|
|
10
|
+
if (userFacingFields.length === 0) {
|
|
11
|
+
// Fallback: use the last target field and make it readable
|
|
12
|
+
const lastField = target[target.length - 1];
|
|
13
|
+
return lastField.replace(/([A-Z])/g, ' $1').trim().toLowerCase();
|
|
14
|
+
}
|
|
15
|
+
// Convert camelCase to readable format
|
|
16
|
+
return userFacingFields
|
|
17
|
+
.map((f) => f.replace(/([A-Z])/g, ' $1').trim().toLowerCase())
|
|
18
|
+
.join(', ');
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Handle Prisma-specific errors with user-friendly messages.
|
|
22
|
+
*/
|
|
23
|
+
function handlePrismaError(err) {
|
|
24
|
+
// Check if this is a Prisma error (has code property)
|
|
25
|
+
if (!err.code || typeof err.code !== 'string' || !err.code.startsWith('P')) {
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
switch (err.code) {
|
|
29
|
+
case 'P2002': {
|
|
30
|
+
// Unique constraint violation
|
|
31
|
+
const target = err.meta?.target;
|
|
32
|
+
const modelName = err.meta?.modelName;
|
|
33
|
+
if (target && target.length > 0) {
|
|
34
|
+
const fieldName = extractFieldName(target);
|
|
35
|
+
const entity = modelName || 'Record';
|
|
36
|
+
return {
|
|
37
|
+
statusCode: 409,
|
|
38
|
+
message: `A ${entity.toLowerCase()} with this ${fieldName} already exists`,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
return {
|
|
42
|
+
statusCode: 409,
|
|
43
|
+
message: 'A record with these values already exists',
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
case 'P2003': {
|
|
47
|
+
// Foreign key constraint violation
|
|
48
|
+
const field = err.meta?.field_name;
|
|
49
|
+
return {
|
|
50
|
+
statusCode: 400,
|
|
51
|
+
message: field
|
|
52
|
+
? `Referenced ${field.replace(/([A-Z])/g, ' $1').trim().toLowerCase()} does not exist`
|
|
53
|
+
: 'Referenced record does not exist',
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
case 'P2025': {
|
|
57
|
+
// Record not found for update/delete
|
|
58
|
+
return {
|
|
59
|
+
statusCode: 404,
|
|
60
|
+
message: 'Record not found',
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
case 'P2014': {
|
|
64
|
+
// Required relation violation
|
|
65
|
+
return {
|
|
66
|
+
statusCode: 400,
|
|
67
|
+
message: 'This operation would violate a required relation',
|
|
68
|
+
};
|
|
69
|
+
}
|
|
70
|
+
default:
|
|
71
|
+
// Unknown Prisma error - log it but return generic message
|
|
72
|
+
return null;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
3
75
|
/**
|
|
4
76
|
* Global error handler middleware for Express applications.
|
|
5
|
-
* Handles ZodError, AppError, and generic errors with appropriate responses.
|
|
77
|
+
* Handles ZodError, AppError, Prisma errors, and generic errors with appropriate responses.
|
|
6
78
|
*/
|
|
7
79
|
export function errorHandler(err, req, res, next) {
|
|
80
|
+
// Handle Zod validation errors
|
|
8
81
|
if (err instanceof ZodError) {
|
|
9
82
|
return res.status(400).json({
|
|
10
83
|
success: false,
|
|
@@ -13,6 +86,7 @@ export function errorHandler(err, req, res, next) {
|
|
|
13
86
|
details: err.issues,
|
|
14
87
|
});
|
|
15
88
|
}
|
|
89
|
+
// Handle custom application errors
|
|
16
90
|
if (err instanceof AppError) {
|
|
17
91
|
return res.status(err.statusCode).json({
|
|
18
92
|
success: false,
|
|
@@ -20,6 +94,16 @@ export function errorHandler(err, req, res, next) {
|
|
|
20
94
|
error: err.message,
|
|
21
95
|
});
|
|
22
96
|
}
|
|
97
|
+
// Handle Prisma errors
|
|
98
|
+
const prismaError = handlePrismaError(err);
|
|
99
|
+
if (prismaError) {
|
|
100
|
+
return res.status(prismaError.statusCode).json({
|
|
101
|
+
success: false,
|
|
102
|
+
message: prismaError.message,
|
|
103
|
+
error: prismaError.message,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
// Unhandled error - log and return generic message
|
|
23
107
|
console.error('Unhandled error:', err);
|
|
24
108
|
return res.status(500).json({
|
|
25
109
|
success: false,
|
package/package.json
CHANGED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/*
|
|
2
|
+
Warnings:
|
|
3
|
+
|
|
4
|
+
- You are about to drop the column `isPublished` on the `properties` table. All the data in the column will be lost.
|
|
5
|
+
- You are about to alter the column `status` on the `properties` table. The data in that column could be lost. The data in that column will be cast from `VarChar(191)` to `Enum(EnumId(5))`.
|
|
6
|
+
|
|
7
|
+
*/
|
|
8
|
+
-- AlterTable
|
|
9
|
+
ALTER TABLE `properties` DROP COLUMN `isPublished`,
|
|
10
|
+
MODIFY `status` ENUM('DRAFT', 'PUBLISHED', 'SOLD_OUT', 'ARCHIVED') NOT NULL DEFAULT 'DRAFT';
|
package/prisma/schema.prisma
CHANGED
|
@@ -51,6 +51,13 @@ enum PaymentFrequency {
|
|
|
51
51
|
CUSTOM
|
|
52
52
|
}
|
|
53
53
|
|
|
54
|
+
enum PropertyStatus {
|
|
55
|
+
DRAFT
|
|
56
|
+
PUBLISHED
|
|
57
|
+
SOLD_OUT
|
|
58
|
+
ARCHIVED
|
|
59
|
+
}
|
|
60
|
+
|
|
54
61
|
enum ApplicationStatus {
|
|
55
62
|
DRAFT
|
|
56
63
|
PENDING
|
|
@@ -1112,11 +1119,10 @@ model Property {
|
|
|
1112
1119
|
streetAddress String?
|
|
1113
1120
|
longitude Float?
|
|
1114
1121
|
latitude Float?
|
|
1115
|
-
status
|
|
1122
|
+
status PropertyStatus @default(DRAFT)
|
|
1116
1123
|
description String? @db.Text
|
|
1117
1124
|
displayImageId String?
|
|
1118
1125
|
displayImage PropertyMedia? @relation("DisplayImage", fields: [displayImageId], references: [id], onDelete: SetNull)
|
|
1119
|
-
isPublished Boolean @default(false)
|
|
1120
1126
|
publishedAt DateTime?
|
|
1121
1127
|
createdAt DateTime @default(now())
|
|
1122
1128
|
updatedAt DateTime @updatedAt
|