hvp-shared 3.2.0 → 3.3.0
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/contracts/collaborator/index.d.ts +1 -0
- package/dist/contracts/collaborator/index.js +1 -1
- package/dist/contracts/collaborator/requests.d.ts +132 -0
- package/dist/contracts/collaborator/requests.js +2 -0
- package/dist/contracts/collaborator/responses.d.ts +9 -35
- package/dist/types/api-response.types.d.ts +8 -1
- 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
|
@@ -19,4 +19,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
19
19
|
};
|
|
20
20
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
21
|
__exportStar(require("./responses"), exports);
|
|
22
|
-
|
|
22
|
+
__exportStar(require("./requests"), exports);
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { WebAppRole } from '../../constants/collaborator.constants';
|
|
2
|
+
import { AddressValidationProps } from '../../validation/address.validation';
|
|
3
|
+
/**
|
|
4
|
+
* Create Collaborator Request
|
|
5
|
+
*
|
|
6
|
+
* Data required to create a new collaborator.
|
|
7
|
+
* Used by admin/manager roles.
|
|
8
|
+
*
|
|
9
|
+
* @example POST /api/collaborators/create
|
|
10
|
+
*/
|
|
11
|
+
export interface CreateCollaboratorRequest {
|
|
12
|
+
first_name: string;
|
|
13
|
+
last_name: string;
|
|
14
|
+
col_code: string;
|
|
15
|
+
role: WebAppRole;
|
|
16
|
+
isActive: boolean;
|
|
17
|
+
isDisplayedWeb: boolean;
|
|
18
|
+
isRegistered: boolean;
|
|
19
|
+
second_last_name?: string;
|
|
20
|
+
email?: string;
|
|
21
|
+
phone?: string;
|
|
22
|
+
photoURL?: string;
|
|
23
|
+
birthDate?: string;
|
|
24
|
+
job?: string;
|
|
25
|
+
branch?: string;
|
|
26
|
+
startDate?: string;
|
|
27
|
+
hireDate?: string;
|
|
28
|
+
endDate?: string;
|
|
29
|
+
address?: AddressValidationProps;
|
|
30
|
+
facebook?: string;
|
|
31
|
+
instagram?: string;
|
|
32
|
+
rfcCode?: string;
|
|
33
|
+
curp?: string;
|
|
34
|
+
imssNumber?: string;
|
|
35
|
+
useFiscalAddressSameAsMain?: boolean;
|
|
36
|
+
fiscalAddress?: AddressValidationProps;
|
|
37
|
+
taxZipCode?: string;
|
|
38
|
+
contractType?: string;
|
|
39
|
+
regimeType?: string;
|
|
40
|
+
fiscalRegime?: string;
|
|
41
|
+
bank?: string;
|
|
42
|
+
bankAccount?: string;
|
|
43
|
+
baseSalary?: number;
|
|
44
|
+
dailySalary?: number;
|
|
45
|
+
accessCode?: string;
|
|
46
|
+
password?: string;
|
|
47
|
+
}
|
|
48
|
+
/**
|
|
49
|
+
* Update Collaborator Request
|
|
50
|
+
*
|
|
51
|
+
* Partial data to update an existing collaborator.
|
|
52
|
+
* All fields optional - only provided fields will be updated.
|
|
53
|
+
*
|
|
54
|
+
* @example PATCH /api/collaborators/:id
|
|
55
|
+
*/
|
|
56
|
+
export interface UpdateCollaboratorRequest {
|
|
57
|
+
first_name?: string;
|
|
58
|
+
last_name?: string;
|
|
59
|
+
second_last_name?: string;
|
|
60
|
+
email?: string;
|
|
61
|
+
phone?: string;
|
|
62
|
+
photoURL?: string;
|
|
63
|
+
birthDate?: string;
|
|
64
|
+
role?: WebAppRole;
|
|
65
|
+
isActive?: boolean;
|
|
66
|
+
isDisplayedWeb?: boolean;
|
|
67
|
+
isRegistered?: boolean;
|
|
68
|
+
job?: string;
|
|
69
|
+
branch?: string;
|
|
70
|
+
startDate?: string;
|
|
71
|
+
hireDate?: string;
|
|
72
|
+
endDate?: string;
|
|
73
|
+
address?: AddressValidationProps;
|
|
74
|
+
facebook?: string;
|
|
75
|
+
instagram?: string;
|
|
76
|
+
rfcCode?: string;
|
|
77
|
+
curp?: string;
|
|
78
|
+
imssNumber?: string;
|
|
79
|
+
useFiscalAddressSameAsMain?: boolean;
|
|
80
|
+
fiscalAddress?: AddressValidationProps;
|
|
81
|
+
taxZipCode?: string;
|
|
82
|
+
contractType?: string;
|
|
83
|
+
regimeType?: string;
|
|
84
|
+
fiscalRegime?: string;
|
|
85
|
+
bank?: string;
|
|
86
|
+
bankAccount?: string;
|
|
87
|
+
baseSalary?: number;
|
|
88
|
+
dailySalary?: number;
|
|
89
|
+
accessCode?: string;
|
|
90
|
+
password?: string;
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Register Collaborator Request
|
|
94
|
+
*
|
|
95
|
+
* Public registration flow for collaborators.
|
|
96
|
+
* Collaborator provides col_code, accessCode, email and password to register.
|
|
97
|
+
*
|
|
98
|
+
* @example PATCH /api/collaborators/register
|
|
99
|
+
*/
|
|
100
|
+
export interface RegisterCollaboratorRequest {
|
|
101
|
+
col_code: string;
|
|
102
|
+
accessCode: string;
|
|
103
|
+
email: string;
|
|
104
|
+
password: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Update Many Collaborators Request
|
|
108
|
+
*
|
|
109
|
+
* Batch update multiple collaborators.
|
|
110
|
+
* Each item must include id + fields to update.
|
|
111
|
+
*
|
|
112
|
+
* @example PATCH /api/collaborators
|
|
113
|
+
*/
|
|
114
|
+
export interface UpdateManyCollaboratorsRequest {
|
|
115
|
+
collaborators: Array<{
|
|
116
|
+
id: string;
|
|
117
|
+
} & Partial<UpdateCollaboratorRequest>>;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Collaborator Query Filters
|
|
121
|
+
*
|
|
122
|
+
* Query parameters for filtering collaborators list.
|
|
123
|
+
*
|
|
124
|
+
* @example GET /api/collaborators?isActive=true&role=Colaborador
|
|
125
|
+
*/
|
|
126
|
+
export interface CollaboratorQueryFilters {
|
|
127
|
+
isActive?: boolean;
|
|
128
|
+
role?: WebAppRole;
|
|
129
|
+
branch?: string;
|
|
130
|
+
isRegistered?: boolean;
|
|
131
|
+
isDisplayedWeb?: boolean;
|
|
132
|
+
}
|
|
@@ -27,27 +27,22 @@ export interface PublicCollaboratorResponse {
|
|
|
27
27
|
*
|
|
28
28
|
* @example GET /api/collaborators/:id (authenticated collaborator)
|
|
29
29
|
*/
|
|
30
|
-
export interface CollaboratorViewResponse {
|
|
31
|
-
id: string;
|
|
32
|
-
col_code: string;
|
|
33
|
-
first_name: string;
|
|
34
|
-
last_name: string;
|
|
30
|
+
export interface CollaboratorViewResponse extends PublicCollaboratorResponse {
|
|
35
31
|
email?: string;
|
|
36
32
|
phone?: string;
|
|
37
|
-
|
|
38
|
-
birthDate?: Date;
|
|
39
|
-
role: WebAppRole;
|
|
40
|
-
isActive: boolean;
|
|
33
|
+
birthDate?: string;
|
|
41
34
|
isDisplayedWeb: boolean;
|
|
42
35
|
isRegistered: boolean;
|
|
43
36
|
job?: string;
|
|
44
37
|
branch?: string;
|
|
45
|
-
|
|
38
|
+
startDate?: string;
|
|
39
|
+
hireDate?: string;
|
|
40
|
+
endDate?: string;
|
|
46
41
|
address?: AddressValidationProps;
|
|
47
42
|
facebook?: string;
|
|
48
43
|
instagram?: string;
|
|
49
|
-
createdAt?:
|
|
50
|
-
updatedAt?:
|
|
44
|
+
createdAt?: string;
|
|
45
|
+
updatedAt?: string;
|
|
51
46
|
}
|
|
52
47
|
/**
|
|
53
48
|
* Admin Collaborator Response
|
|
@@ -59,28 +54,9 @@ export interface CollaboratorViewResponse {
|
|
|
59
54
|
*
|
|
60
55
|
* @example GET /api/collaborators/:id (admin authenticated)
|
|
61
56
|
*/
|
|
62
|
-
export interface AdminCollaboratorResponse {
|
|
63
|
-
id: string;
|
|
64
|
-
col_code: string;
|
|
65
|
-
first_name: string;
|
|
66
|
-
last_name: string;
|
|
57
|
+
export interface AdminCollaboratorResponse extends CollaboratorViewResponse {
|
|
67
58
|
second_last_name?: string;
|
|
68
|
-
|
|
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;
|
|
59
|
+
registeredDate?: string;
|
|
84
60
|
rfcCode?: string;
|
|
85
61
|
curp?: string;
|
|
86
62
|
imssNumber?: string;
|
|
@@ -97,8 +73,6 @@ export interface AdminCollaboratorResponse {
|
|
|
97
73
|
accessCode?: string;
|
|
98
74
|
createdBy?: string;
|
|
99
75
|
updatedBy?: string;
|
|
100
|
-
createdAt?: Date;
|
|
101
|
-
updatedAt?: Date;
|
|
102
76
|
}
|
|
103
77
|
/**
|
|
104
78
|
* Union type for all collaborator response types
|
|
@@ -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,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);
|