hvp-shared 3.2.1 → 3.3.1
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/types/api-response.types.d.ts +8 -1
- package/dist/types/collaborator-responses.types.d.ts +106 -0
- package/dist/types/collaborator-responses.types.js +2 -0
- package/dist/types/error-codes.types.d.ts +124 -0
- package/dist/types/error-codes.types.js +132 -0
- package/dist/types/error-codes.types.test.d.ts +1 -0
- package/dist/types/error-codes.types.test.js +144 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/package.json +1 -1
|
@@ -153,7 +153,14 @@ export interface ApiCreatedSuccessResponse<T> extends ApiSuccessResponseBase<T>
|
|
|
153
153
|
*/
|
|
154
154
|
export interface ApiErrorDetail {
|
|
155
155
|
/**
|
|
156
|
-
*
|
|
156
|
+
* Domain-specific error code (machine-readable)
|
|
157
|
+
* Examples: "COLLABORATOR_NOT_FOUND", "INVALID_ACCESS_CODE", "DUPLICATE_EMAIL"
|
|
158
|
+
* Frontend uses this to react programmatically to specific errors
|
|
159
|
+
* See: ErrorCodes in error-codes.types.ts
|
|
160
|
+
*/
|
|
161
|
+
code?: string;
|
|
162
|
+
/**
|
|
163
|
+
* Error type (machine-readable category)
|
|
157
164
|
* Examples:
|
|
158
165
|
* - "ValidationError" - Input validation failed
|
|
159
166
|
* - "BusinessRuleError" - Domain rule violated
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { WebAppRole } from '../constants/web-app-roles';
|
|
2
|
+
import { AddressValidationProps } from '../validation/address.validation';
|
|
3
|
+
/**
|
|
4
|
+
* Public Collaborator Response
|
|
5
|
+
*
|
|
6
|
+
* Minimal data for public endpoints (no authentication required).
|
|
7
|
+
* Used for: Public website, service listings, team pages.
|
|
8
|
+
*
|
|
9
|
+
* @example GET /api/collaborators/public
|
|
10
|
+
*/
|
|
11
|
+
export interface PublicCollaboratorResponse {
|
|
12
|
+
id: string;
|
|
13
|
+
col_code: string;
|
|
14
|
+
first_name: string;
|
|
15
|
+
last_name: string;
|
|
16
|
+
photoURL?: string;
|
|
17
|
+
role: WebAppRole;
|
|
18
|
+
isActive: boolean;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Collaborator View Response
|
|
22
|
+
*
|
|
23
|
+
* Extended data for authenticated collaborators viewing other collaborators.
|
|
24
|
+
* Excludes sensitive information (fiscal data, salary, banking).
|
|
25
|
+
*
|
|
26
|
+
* Used for: Collaborators viewing team members, scheduling, contact info.
|
|
27
|
+
*
|
|
28
|
+
* @example GET /api/collaborators/:id (authenticated collaborator)
|
|
29
|
+
*/
|
|
30
|
+
export interface CollaboratorViewResponse {
|
|
31
|
+
id: string;
|
|
32
|
+
col_code: string;
|
|
33
|
+
first_name: string;
|
|
34
|
+
last_name: string;
|
|
35
|
+
email?: string;
|
|
36
|
+
phone?: string;
|
|
37
|
+
photoURL?: string;
|
|
38
|
+
birthDate?: Date;
|
|
39
|
+
role: WebAppRole;
|
|
40
|
+
isActive: boolean;
|
|
41
|
+
isDisplayedWeb: boolean;
|
|
42
|
+
isRegistered: boolean;
|
|
43
|
+
job?: string;
|
|
44
|
+
branch?: string;
|
|
45
|
+
hireDate?: Date;
|
|
46
|
+
address?: AddressValidationProps;
|
|
47
|
+
facebook?: string;
|
|
48
|
+
instagram?: string;
|
|
49
|
+
createdAt?: Date;
|
|
50
|
+
updatedAt?: Date;
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Admin Collaborator Response
|
|
54
|
+
*
|
|
55
|
+
* Complete data including all sensitive information.
|
|
56
|
+
* Only for admin users.
|
|
57
|
+
*
|
|
58
|
+
* Used for: Admin dashboard, payroll management, HR operations, CFDI generation.
|
|
59
|
+
*
|
|
60
|
+
* @example GET /api/collaborators/:id (admin authenticated)
|
|
61
|
+
*/
|
|
62
|
+
export interface AdminCollaboratorResponse {
|
|
63
|
+
id: string;
|
|
64
|
+
col_code: string;
|
|
65
|
+
first_name: string;
|
|
66
|
+
last_name: string;
|
|
67
|
+
second_last_name?: string;
|
|
68
|
+
email?: string;
|
|
69
|
+
phone?: string;
|
|
70
|
+
photoURL?: string;
|
|
71
|
+
birthDate?: Date;
|
|
72
|
+
role: WebAppRole;
|
|
73
|
+
isActive: boolean;
|
|
74
|
+
isDisplayedWeb: boolean;
|
|
75
|
+
isRegistered: boolean;
|
|
76
|
+
registeredDate?: Date;
|
|
77
|
+
job?: string;
|
|
78
|
+
branch?: string;
|
|
79
|
+
hireDate?: Date;
|
|
80
|
+
endDate?: Date;
|
|
81
|
+
address?: AddressValidationProps;
|
|
82
|
+
facebook?: string;
|
|
83
|
+
instagram?: string;
|
|
84
|
+
rfcCode?: string;
|
|
85
|
+
curp?: string;
|
|
86
|
+
imssNumber?: string;
|
|
87
|
+
useFiscalAddressSameAsMain: boolean;
|
|
88
|
+
fiscalAddress?: AddressValidationProps;
|
|
89
|
+
taxZipCode?: string;
|
|
90
|
+
contractType?: string;
|
|
91
|
+
regimeType?: string;
|
|
92
|
+
fiscalRegime?: string;
|
|
93
|
+
bank?: string;
|
|
94
|
+
bankAccount?: string;
|
|
95
|
+
baseSalary?: number;
|
|
96
|
+
dailySalary?: number;
|
|
97
|
+
accessCode?: string;
|
|
98
|
+
createdBy?: string;
|
|
99
|
+
updatedBy?: string;
|
|
100
|
+
createdAt?: Date;
|
|
101
|
+
updatedAt?: Date;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Union type for all collaborator response types
|
|
105
|
+
*/
|
|
106
|
+
export type CollaboratorResponse = PublicCollaboratorResponse | CollaboratorViewResponse | AdminCollaboratorResponse;
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error Codes - Shared Types
|
|
3
|
+
*
|
|
4
|
+
* These error codes are used by both frontend and backend to handle
|
|
5
|
+
* domain-specific errors programmatically.
|
|
6
|
+
*
|
|
7
|
+
* Design Pattern: Error Codes + Factory Methods (Modern Pattern)
|
|
8
|
+
* - Frontend can react to specific error codes
|
|
9
|
+
* - Backend throws domain errors with these codes
|
|
10
|
+
* - Reduces boilerplate by 90% compared to one-class-per-error
|
|
11
|
+
*
|
|
12
|
+
* See: resources/learning/20260107-error-handling-architecture-complete-analysis.md
|
|
13
|
+
*/
|
|
14
|
+
/**
|
|
15
|
+
* HTTP Status Codes for error responses
|
|
16
|
+
*/
|
|
17
|
+
export declare enum HttpStatus {
|
|
18
|
+
BAD_REQUEST = 400,
|
|
19
|
+
UNAUTHORIZED = 401,
|
|
20
|
+
FORBIDDEN = 403,
|
|
21
|
+
NOT_FOUND = 404,
|
|
22
|
+
CONFLICT = 409,
|
|
23
|
+
UNPROCESSABLE_ENTITY = 422,
|
|
24
|
+
INTERNAL_SERVER_ERROR = 500
|
|
25
|
+
}
|
|
26
|
+
/**
|
|
27
|
+
* Domain-specific error codes
|
|
28
|
+
* Format: RESOURCE_ERROR_TYPE
|
|
29
|
+
*/
|
|
30
|
+
export declare const ErrorCodes: {
|
|
31
|
+
readonly COLLABORATOR_NOT_FOUND: {
|
|
32
|
+
readonly code: "COLLABORATOR_NOT_FOUND";
|
|
33
|
+
readonly status: HttpStatus.NOT_FOUND;
|
|
34
|
+
readonly defaultMessage: "Collaborator not found";
|
|
35
|
+
};
|
|
36
|
+
readonly COLLABORATOR_ALREADY_REGISTERED: {
|
|
37
|
+
readonly code: "COLLABORATOR_ALREADY_REGISTERED";
|
|
38
|
+
readonly status: HttpStatus.CONFLICT;
|
|
39
|
+
readonly defaultMessage: "Collaborator is already registered";
|
|
40
|
+
};
|
|
41
|
+
readonly COLLABORATOR_INACTIVE: {
|
|
42
|
+
readonly code: "COLLABORATOR_INACTIVE";
|
|
43
|
+
readonly status: HttpStatus.FORBIDDEN;
|
|
44
|
+
readonly defaultMessage: "Collaborator is inactive";
|
|
45
|
+
};
|
|
46
|
+
readonly CANNOT_DELETE_ACTIVE_COLLABORATOR: {
|
|
47
|
+
readonly code: "CANNOT_DELETE_ACTIVE_COLLABORATOR";
|
|
48
|
+
readonly status: HttpStatus.CONFLICT;
|
|
49
|
+
readonly defaultMessage: "Cannot delete active collaborator";
|
|
50
|
+
};
|
|
51
|
+
readonly DUPLICATE_COLLABORATOR_CODE: {
|
|
52
|
+
readonly code: "DUPLICATE_COLLABORATOR_CODE";
|
|
53
|
+
readonly status: HttpStatus.CONFLICT;
|
|
54
|
+
readonly defaultMessage: "Collaborator code already exists";
|
|
55
|
+
};
|
|
56
|
+
readonly DUPLICATE_COLLABORATOR_EMAIL: {
|
|
57
|
+
readonly code: "DUPLICATE_COLLABORATOR_EMAIL";
|
|
58
|
+
readonly status: HttpStatus.CONFLICT;
|
|
59
|
+
readonly defaultMessage: "Email is already registered";
|
|
60
|
+
};
|
|
61
|
+
readonly INVALID_ACCESS_CODE: {
|
|
62
|
+
readonly code: "INVALID_ACCESS_CODE";
|
|
63
|
+
readonly status: HttpStatus.UNAUTHORIZED;
|
|
64
|
+
readonly defaultMessage: "Invalid access code";
|
|
65
|
+
};
|
|
66
|
+
readonly ACCESS_CODE_NOT_SET: {
|
|
67
|
+
readonly code: "ACCESS_CODE_NOT_SET";
|
|
68
|
+
readonly status: HttpStatus.UNPROCESSABLE_ENTITY;
|
|
69
|
+
readonly defaultMessage: "Access code not set for collaborator";
|
|
70
|
+
};
|
|
71
|
+
readonly INVALID_FISCAL_DATA: {
|
|
72
|
+
readonly code: "INVALID_FISCAL_DATA";
|
|
73
|
+
readonly status: HttpStatus.BAD_REQUEST;
|
|
74
|
+
readonly defaultMessage: "Invalid fiscal data";
|
|
75
|
+
};
|
|
76
|
+
readonly INVALID_CREDENTIALS: {
|
|
77
|
+
readonly code: "INVALID_CREDENTIALS";
|
|
78
|
+
readonly status: HttpStatus.UNAUTHORIZED;
|
|
79
|
+
readonly defaultMessage: "Invalid credentials";
|
|
80
|
+
};
|
|
81
|
+
readonly TOKEN_EXPIRED: {
|
|
82
|
+
readonly code: "TOKEN_EXPIRED";
|
|
83
|
+
readonly status: HttpStatus.UNAUTHORIZED;
|
|
84
|
+
readonly defaultMessage: "Token has expired";
|
|
85
|
+
};
|
|
86
|
+
readonly TOKEN_INVALID: {
|
|
87
|
+
readonly code: "TOKEN_INVALID";
|
|
88
|
+
readonly status: HttpStatus.UNAUTHORIZED;
|
|
89
|
+
readonly defaultMessage: "Invalid token";
|
|
90
|
+
};
|
|
91
|
+
readonly VALIDATION_ERROR: {
|
|
92
|
+
readonly code: "VALIDATION_ERROR";
|
|
93
|
+
readonly status: HttpStatus.BAD_REQUEST;
|
|
94
|
+
readonly defaultMessage: "Validation error";
|
|
95
|
+
};
|
|
96
|
+
readonly INTERNAL_ERROR: {
|
|
97
|
+
readonly code: "INTERNAL_ERROR";
|
|
98
|
+
readonly status: HttpStatus.INTERNAL_SERVER_ERROR;
|
|
99
|
+
readonly defaultMessage: "Internal server error";
|
|
100
|
+
};
|
|
101
|
+
readonly NOT_FOUND: {
|
|
102
|
+
readonly code: "NOT_FOUND";
|
|
103
|
+
readonly status: HttpStatus.NOT_FOUND;
|
|
104
|
+
readonly defaultMessage: "Resource not found";
|
|
105
|
+
};
|
|
106
|
+
readonly UNAUTHORIZED: {
|
|
107
|
+
readonly code: "UNAUTHORIZED";
|
|
108
|
+
readonly status: HttpStatus.UNAUTHORIZED;
|
|
109
|
+
readonly defaultMessage: "Unauthorized";
|
|
110
|
+
};
|
|
111
|
+
readonly FORBIDDEN: {
|
|
112
|
+
readonly code: "FORBIDDEN";
|
|
113
|
+
readonly status: HttpStatus.FORBIDDEN;
|
|
114
|
+
readonly defaultMessage: "Forbidden";
|
|
115
|
+
};
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* Error code type (union of all error code strings)
|
|
119
|
+
*/
|
|
120
|
+
export type ErrorCode = (typeof ErrorCodes)[keyof typeof ErrorCodes]['code'];
|
|
121
|
+
/**
|
|
122
|
+
* Error definition type
|
|
123
|
+
*/
|
|
124
|
+
export type ErrorDefinition = (typeof ErrorCodes)[keyof typeof ErrorCodes];
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Error Codes - Shared Types
|
|
4
|
+
*
|
|
5
|
+
* These error codes are used by both frontend and backend to handle
|
|
6
|
+
* domain-specific errors programmatically.
|
|
7
|
+
*
|
|
8
|
+
* Design Pattern: Error Codes + Factory Methods (Modern Pattern)
|
|
9
|
+
* - Frontend can react to specific error codes
|
|
10
|
+
* - Backend throws domain errors with these codes
|
|
11
|
+
* - Reduces boilerplate by 90% compared to one-class-per-error
|
|
12
|
+
*
|
|
13
|
+
* See: resources/learning/20260107-error-handling-architecture-complete-analysis.md
|
|
14
|
+
*/
|
|
15
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
16
|
+
exports.ErrorCodes = exports.HttpStatus = void 0;
|
|
17
|
+
/**
|
|
18
|
+
* HTTP Status Codes for error responses
|
|
19
|
+
*/
|
|
20
|
+
var HttpStatus;
|
|
21
|
+
(function (HttpStatus) {
|
|
22
|
+
HttpStatus[HttpStatus["BAD_REQUEST"] = 400] = "BAD_REQUEST";
|
|
23
|
+
HttpStatus[HttpStatus["UNAUTHORIZED"] = 401] = "UNAUTHORIZED";
|
|
24
|
+
HttpStatus[HttpStatus["FORBIDDEN"] = 403] = "FORBIDDEN";
|
|
25
|
+
HttpStatus[HttpStatus["NOT_FOUND"] = 404] = "NOT_FOUND";
|
|
26
|
+
HttpStatus[HttpStatus["CONFLICT"] = 409] = "CONFLICT";
|
|
27
|
+
HttpStatus[HttpStatus["UNPROCESSABLE_ENTITY"] = 422] = "UNPROCESSABLE_ENTITY";
|
|
28
|
+
HttpStatus[HttpStatus["INTERNAL_SERVER_ERROR"] = 500] = "INTERNAL_SERVER_ERROR";
|
|
29
|
+
})(HttpStatus || (exports.HttpStatus = HttpStatus = {}));
|
|
30
|
+
/**
|
|
31
|
+
* Domain-specific error codes
|
|
32
|
+
* Format: RESOURCE_ERROR_TYPE
|
|
33
|
+
*/
|
|
34
|
+
exports.ErrorCodes = {
|
|
35
|
+
// ====================================
|
|
36
|
+
// Collaborator Errors
|
|
37
|
+
// ====================================
|
|
38
|
+
COLLABORATOR_NOT_FOUND: {
|
|
39
|
+
code: 'COLLABORATOR_NOT_FOUND',
|
|
40
|
+
status: HttpStatus.NOT_FOUND,
|
|
41
|
+
defaultMessage: 'Collaborator not found',
|
|
42
|
+
},
|
|
43
|
+
COLLABORATOR_ALREADY_REGISTERED: {
|
|
44
|
+
code: 'COLLABORATOR_ALREADY_REGISTERED',
|
|
45
|
+
status: HttpStatus.CONFLICT,
|
|
46
|
+
defaultMessage: 'Collaborator is already registered',
|
|
47
|
+
},
|
|
48
|
+
COLLABORATOR_INACTIVE: {
|
|
49
|
+
code: 'COLLABORATOR_INACTIVE',
|
|
50
|
+
status: HttpStatus.FORBIDDEN,
|
|
51
|
+
defaultMessage: 'Collaborator is inactive',
|
|
52
|
+
},
|
|
53
|
+
CANNOT_DELETE_ACTIVE_COLLABORATOR: {
|
|
54
|
+
code: 'CANNOT_DELETE_ACTIVE_COLLABORATOR',
|
|
55
|
+
status: HttpStatus.CONFLICT,
|
|
56
|
+
defaultMessage: 'Cannot delete active collaborator',
|
|
57
|
+
},
|
|
58
|
+
DUPLICATE_COLLABORATOR_CODE: {
|
|
59
|
+
code: 'DUPLICATE_COLLABORATOR_CODE',
|
|
60
|
+
status: HttpStatus.CONFLICT,
|
|
61
|
+
defaultMessage: 'Collaborator code already exists',
|
|
62
|
+
},
|
|
63
|
+
DUPLICATE_COLLABORATOR_EMAIL: {
|
|
64
|
+
code: 'DUPLICATE_COLLABORATOR_EMAIL',
|
|
65
|
+
status: HttpStatus.CONFLICT,
|
|
66
|
+
defaultMessage: 'Email is already registered',
|
|
67
|
+
},
|
|
68
|
+
INVALID_ACCESS_CODE: {
|
|
69
|
+
code: 'INVALID_ACCESS_CODE',
|
|
70
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
71
|
+
defaultMessage: 'Invalid access code',
|
|
72
|
+
},
|
|
73
|
+
ACCESS_CODE_NOT_SET: {
|
|
74
|
+
code: 'ACCESS_CODE_NOT_SET',
|
|
75
|
+
status: HttpStatus.UNPROCESSABLE_ENTITY,
|
|
76
|
+
defaultMessage: 'Access code not set for collaborator',
|
|
77
|
+
},
|
|
78
|
+
INVALID_FISCAL_DATA: {
|
|
79
|
+
code: 'INVALID_FISCAL_DATA',
|
|
80
|
+
status: HttpStatus.BAD_REQUEST,
|
|
81
|
+
defaultMessage: 'Invalid fiscal data',
|
|
82
|
+
},
|
|
83
|
+
// ====================================
|
|
84
|
+
// Authentication Errors
|
|
85
|
+
// ====================================
|
|
86
|
+
INVALID_CREDENTIALS: {
|
|
87
|
+
code: 'INVALID_CREDENTIALS',
|
|
88
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
89
|
+
defaultMessage: 'Invalid credentials',
|
|
90
|
+
},
|
|
91
|
+
TOKEN_EXPIRED: {
|
|
92
|
+
code: 'TOKEN_EXPIRED',
|
|
93
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
94
|
+
defaultMessage: 'Token has expired',
|
|
95
|
+
},
|
|
96
|
+
TOKEN_INVALID: {
|
|
97
|
+
code: 'TOKEN_INVALID',
|
|
98
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
99
|
+
defaultMessage: 'Invalid token',
|
|
100
|
+
},
|
|
101
|
+
// ====================================
|
|
102
|
+
// Validation Errors
|
|
103
|
+
// ====================================
|
|
104
|
+
VALIDATION_ERROR: {
|
|
105
|
+
code: 'VALIDATION_ERROR',
|
|
106
|
+
status: HttpStatus.BAD_REQUEST,
|
|
107
|
+
defaultMessage: 'Validation error',
|
|
108
|
+
},
|
|
109
|
+
// ====================================
|
|
110
|
+
// Generic Errors
|
|
111
|
+
// ====================================
|
|
112
|
+
INTERNAL_ERROR: {
|
|
113
|
+
code: 'INTERNAL_ERROR',
|
|
114
|
+
status: HttpStatus.INTERNAL_SERVER_ERROR,
|
|
115
|
+
defaultMessage: 'Internal server error',
|
|
116
|
+
},
|
|
117
|
+
NOT_FOUND: {
|
|
118
|
+
code: 'NOT_FOUND',
|
|
119
|
+
status: HttpStatus.NOT_FOUND,
|
|
120
|
+
defaultMessage: 'Resource not found',
|
|
121
|
+
},
|
|
122
|
+
UNAUTHORIZED: {
|
|
123
|
+
code: 'UNAUTHORIZED',
|
|
124
|
+
status: HttpStatus.UNAUTHORIZED,
|
|
125
|
+
defaultMessage: 'Unauthorized',
|
|
126
|
+
},
|
|
127
|
+
FORBIDDEN: {
|
|
128
|
+
code: 'FORBIDDEN',
|
|
129
|
+
status: HttpStatus.FORBIDDEN,
|
|
130
|
+
defaultMessage: 'Forbidden',
|
|
131
|
+
},
|
|
132
|
+
};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
const error_codes_types_1 = require("./error-codes.types");
|
|
4
|
+
describe('ErrorCodes', () => {
|
|
5
|
+
describe('Structure', () => {
|
|
6
|
+
it('should have code, status, and defaultMessage for each error', () => {
|
|
7
|
+
Object.values(error_codes_types_1.ErrorCodes).forEach((errorDef) => {
|
|
8
|
+
expect(errorDef).toHaveProperty('code');
|
|
9
|
+
expect(errorDef).toHaveProperty('status');
|
|
10
|
+
expect(errorDef).toHaveProperty('defaultMessage');
|
|
11
|
+
expect(typeof errorDef.code).toBe('string');
|
|
12
|
+
expect(typeof errorDef.status).toBe('number');
|
|
13
|
+
expect(typeof errorDef.defaultMessage).toBe('string');
|
|
14
|
+
});
|
|
15
|
+
});
|
|
16
|
+
it('should have unique error codes', () => {
|
|
17
|
+
const codes = Object.values(error_codes_types_1.ErrorCodes).map(e => e.code);
|
|
18
|
+
const uniqueCodes = new Set(codes);
|
|
19
|
+
expect(codes.length).toBe(uniqueCodes.size);
|
|
20
|
+
});
|
|
21
|
+
it('should have valid HTTP status codes', () => {
|
|
22
|
+
Object.values(error_codes_types_1.ErrorCodes).forEach((errorDef) => {
|
|
23
|
+
expect(errorDef.status).toBeGreaterThanOrEqual(400);
|
|
24
|
+
expect(errorDef.status).toBeLessThan(600);
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
describe('Collaborator Errors', () => {
|
|
29
|
+
it('should have COLLABORATOR_NOT_FOUND with 404 status', () => {
|
|
30
|
+
expect(error_codes_types_1.ErrorCodes.COLLABORATOR_NOT_FOUND.code).toBe('COLLABORATOR_NOT_FOUND');
|
|
31
|
+
expect(error_codes_types_1.ErrorCodes.COLLABORATOR_NOT_FOUND.status).toBe(error_codes_types_1.HttpStatus.NOT_FOUND);
|
|
32
|
+
expect(error_codes_types_1.ErrorCodes.COLLABORATOR_NOT_FOUND.defaultMessage).toBeTruthy();
|
|
33
|
+
});
|
|
34
|
+
it('should have COLLABORATOR_ALREADY_REGISTERED with 409 status', () => {
|
|
35
|
+
expect(error_codes_types_1.ErrorCodes.COLLABORATOR_ALREADY_REGISTERED.code).toBe('COLLABORATOR_ALREADY_REGISTERED');
|
|
36
|
+
expect(error_codes_types_1.ErrorCodes.COLLABORATOR_ALREADY_REGISTERED.status).toBe(error_codes_types_1.HttpStatus.CONFLICT);
|
|
37
|
+
});
|
|
38
|
+
it('should have INVALID_ACCESS_CODE with 401 status', () => {
|
|
39
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_ACCESS_CODE.code).toBe('INVALID_ACCESS_CODE');
|
|
40
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_ACCESS_CODE.status).toBe(error_codes_types_1.HttpStatus.UNAUTHORIZED);
|
|
41
|
+
});
|
|
42
|
+
it('should have DUPLICATE_COLLABORATOR_CODE with 409 status', () => {
|
|
43
|
+
expect(error_codes_types_1.ErrorCodes.DUPLICATE_COLLABORATOR_CODE.code).toBe('DUPLICATE_COLLABORATOR_CODE');
|
|
44
|
+
expect(error_codes_types_1.ErrorCodes.DUPLICATE_COLLABORATOR_CODE.status).toBe(error_codes_types_1.HttpStatus.CONFLICT);
|
|
45
|
+
});
|
|
46
|
+
it('should have DUPLICATE_COLLABORATOR_EMAIL with 409 status', () => {
|
|
47
|
+
expect(error_codes_types_1.ErrorCodes.DUPLICATE_COLLABORATOR_EMAIL.code).toBe('DUPLICATE_COLLABORATOR_EMAIL');
|
|
48
|
+
expect(error_codes_types_1.ErrorCodes.DUPLICATE_COLLABORATOR_EMAIL.status).toBe(error_codes_types_1.HttpStatus.CONFLICT);
|
|
49
|
+
});
|
|
50
|
+
it('should have INVALID_FISCAL_DATA with 400 status', () => {
|
|
51
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_FISCAL_DATA.code).toBe('INVALID_FISCAL_DATA');
|
|
52
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_FISCAL_DATA.status).toBe(error_codes_types_1.HttpStatus.BAD_REQUEST);
|
|
53
|
+
});
|
|
54
|
+
});
|
|
55
|
+
describe('Authentication Errors', () => {
|
|
56
|
+
it('should have INVALID_CREDENTIALS with 401 status', () => {
|
|
57
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_CREDENTIALS.code).toBe('INVALID_CREDENTIALS');
|
|
58
|
+
expect(error_codes_types_1.ErrorCodes.INVALID_CREDENTIALS.status).toBe(error_codes_types_1.HttpStatus.UNAUTHORIZED);
|
|
59
|
+
});
|
|
60
|
+
it('should have TOKEN_EXPIRED with 401 status', () => {
|
|
61
|
+
expect(error_codes_types_1.ErrorCodes.TOKEN_EXPIRED.code).toBe('TOKEN_EXPIRED');
|
|
62
|
+
expect(error_codes_types_1.ErrorCodes.TOKEN_EXPIRED.status).toBe(error_codes_types_1.HttpStatus.UNAUTHORIZED);
|
|
63
|
+
});
|
|
64
|
+
});
|
|
65
|
+
describe('Generic Errors', () => {
|
|
66
|
+
it('should have NOT_FOUND with 404 status', () => {
|
|
67
|
+
expect(error_codes_types_1.ErrorCodes.NOT_FOUND.code).toBe('NOT_FOUND');
|
|
68
|
+
expect(error_codes_types_1.ErrorCodes.NOT_FOUND.status).toBe(error_codes_types_1.HttpStatus.NOT_FOUND);
|
|
69
|
+
});
|
|
70
|
+
it('should have INTERNAL_ERROR with 500 status', () => {
|
|
71
|
+
expect(error_codes_types_1.ErrorCodes.INTERNAL_ERROR.code).toBe('INTERNAL_ERROR');
|
|
72
|
+
expect(error_codes_types_1.ErrorCodes.INTERNAL_ERROR.status).toBe(error_codes_types_1.HttpStatus.INTERNAL_SERVER_ERROR);
|
|
73
|
+
});
|
|
74
|
+
});
|
|
75
|
+
});
|
|
76
|
+
describe('ErrorCode Type', () => {
|
|
77
|
+
it('should allow valid error code strings', () => {
|
|
78
|
+
const validCode = 'COLLABORATOR_NOT_FOUND';
|
|
79
|
+
expect(validCode).toBe('COLLABORATOR_NOT_FOUND');
|
|
80
|
+
});
|
|
81
|
+
it('should be a union of all error code strings', () => {
|
|
82
|
+
// Type test - this compiles if ErrorCode includes these
|
|
83
|
+
const codes = [
|
|
84
|
+
'COLLABORATOR_NOT_FOUND',
|
|
85
|
+
'INVALID_ACCESS_CODE',
|
|
86
|
+
'DUPLICATE_COLLABORATOR_EMAIL',
|
|
87
|
+
'INVALID_CREDENTIALS',
|
|
88
|
+
'NOT_FOUND',
|
|
89
|
+
];
|
|
90
|
+
expect(codes.length).toBe(5);
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
describe('ErrorDefinition Type', () => {
|
|
94
|
+
it('should match the structure of error definitions', () => {
|
|
95
|
+
const errorDef = {
|
|
96
|
+
code: 'COLLABORATOR_NOT_FOUND',
|
|
97
|
+
status: 404,
|
|
98
|
+
defaultMessage: 'Collaborator not found',
|
|
99
|
+
};
|
|
100
|
+
expect(errorDef.code).toBe('COLLABORATOR_NOT_FOUND');
|
|
101
|
+
expect(errorDef.status).toBe(404);
|
|
102
|
+
expect(errorDef.defaultMessage).toBe('Collaborator not found');
|
|
103
|
+
});
|
|
104
|
+
});
|
|
105
|
+
describe('HttpStatus Enum', () => {
|
|
106
|
+
it('should have correct HTTP status code values', () => {
|
|
107
|
+
expect(error_codes_types_1.HttpStatus.BAD_REQUEST).toBe(400);
|
|
108
|
+
expect(error_codes_types_1.HttpStatus.UNAUTHORIZED).toBe(401);
|
|
109
|
+
expect(error_codes_types_1.HttpStatus.FORBIDDEN).toBe(403);
|
|
110
|
+
expect(error_codes_types_1.HttpStatus.NOT_FOUND).toBe(404);
|
|
111
|
+
expect(error_codes_types_1.HttpStatus.CONFLICT).toBe(409);
|
|
112
|
+
expect(error_codes_types_1.HttpStatus.UNPROCESSABLE_ENTITY).toBe(422);
|
|
113
|
+
expect(error_codes_types_1.HttpStatus.INTERNAL_SERVER_ERROR).toBe(500);
|
|
114
|
+
});
|
|
115
|
+
});
|
|
116
|
+
describe('Usage Examples', () => {
|
|
117
|
+
it('should be usable for error handling', () => {
|
|
118
|
+
// Simulate backend usage
|
|
119
|
+
const errorDefinition = error_codes_types_1.ErrorCodes.COLLABORATOR_NOT_FOUND;
|
|
120
|
+
const response = {
|
|
121
|
+
ok: false,
|
|
122
|
+
status_code: errorDefinition.status,
|
|
123
|
+
error: {
|
|
124
|
+
code: errorDefinition.code,
|
|
125
|
+
message: errorDefinition.defaultMessage,
|
|
126
|
+
},
|
|
127
|
+
};
|
|
128
|
+
expect(response.status_code).toBe(404);
|
|
129
|
+
expect(response.error.code).toBe('COLLABORATOR_NOT_FOUND');
|
|
130
|
+
});
|
|
131
|
+
it('should be usable for frontend error detection', () => {
|
|
132
|
+
// Simulate frontend usage
|
|
133
|
+
const apiResponse = {
|
|
134
|
+
ok: false,
|
|
135
|
+
error: {
|
|
136
|
+
code: 'COLLABORATOR_NOT_FOUND',
|
|
137
|
+
},
|
|
138
|
+
};
|
|
139
|
+
if (apiResponse.error.code === error_codes_types_1.ErrorCodes.COLLABORATOR_NOT_FOUND.code) {
|
|
140
|
+
// Frontend can react specifically to this error
|
|
141
|
+
expect(true).toBe(true);
|
|
142
|
+
}
|
|
143
|
+
});
|
|
144
|
+
});
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
|
@@ -21,3 +21,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
21
21
|
__exportStar(require("./api-response.types"), exports);
|
|
22
22
|
__exportStar(require("./company-settings.types"), exports);
|
|
23
23
|
__exportStar(require("./collaborator-fiscal.types"), exports);
|
|
24
|
+
__exportStar(require("./error-codes.types"), exports);
|