hvp-shared 2.0.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/README.md +36 -0
- package/dist/constants/mexican-states.d.ts +43 -0
- package/dist/constants/mexican-states.js +46 -0
- package/dist/constants.d.ts +7 -0
- package/dist/constants.js +33 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +23 -0
- package/dist/types/api-response.types.d.ts +322 -0
- package/dist/types/api-response.types.js +65 -0
- package/dist/types/company-settings.types.d.ts +51 -0
- package/dist/types/company-settings.types.js +2 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.js +28 -0
- package/dist/validation/__tests__/address.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/address.validation.test.js +143 -0
- package/dist/validation/__tests__/email.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/email.validation.test.js +102 -0
- package/dist/validation/__tests__/phone.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/phone.validation.test.js +75 -0
- package/dist/validation/__tests__/rfc.validation.test.d.ts +1 -0
- package/dist/validation/__tests__/rfc.validation.test.js +97 -0
- package/dist/validation/address.validation.d.ts +27 -0
- package/dist/validation/address.validation.js +51 -0
- package/dist/validation/email.validation.d.ts +20 -0
- package/dist/validation/email.validation.js +37 -0
- package/dist/validation/index.d.ts +8 -0
- package/dist/validation/index.js +24 -0
- package/dist/validation/phone.validation.d.ts +14 -0
- package/dist/validation/phone.validation.js +33 -0
- package/dist/validation/rfc.validation.d.ts +27 -0
- package/dist/validation/rfc.validation.js +41 -0
- package/package.json +30 -0
package/README.md
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
# hvp2021-shared
|
|
2
|
+
|
|
3
|
+
Shared types, constants, and utilities for HVP2021 backend and frontend.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install hvp2021-shared
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```typescript
|
|
14
|
+
import { ApiResponse, SimplePayroll, APP_NAME, UMA_2024_DAILY } from 'hvp2021-shared';
|
|
15
|
+
|
|
16
|
+
const response: ApiResponse<SimplePayroll> = {
|
|
17
|
+
ok: true,
|
|
18
|
+
data: {
|
|
19
|
+
id: '123',
|
|
20
|
+
employeeId: '456',
|
|
21
|
+
amount: UMA_2024_DAILY * 15
|
|
22
|
+
}
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
console.log(APP_NAME); // 'HVP2021'
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Build
|
|
32
|
+
npm run build
|
|
33
|
+
|
|
34
|
+
# Publish
|
|
35
|
+
npm publish
|
|
36
|
+
```
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mexican States - Official INEGI codes
|
|
3
|
+
* Used for address validation
|
|
4
|
+
*/
|
|
5
|
+
export declare const MEXICAN_STATES: {
|
|
6
|
+
readonly AGS: "Aguascalientes";
|
|
7
|
+
readonly BC: "Baja California";
|
|
8
|
+
readonly BCS: "Baja California Sur";
|
|
9
|
+
readonly CAMP: "Campeche";
|
|
10
|
+
readonly CHIS: "Chiapas";
|
|
11
|
+
readonly CHIH: "Chihuahua";
|
|
12
|
+
readonly COAH: "Coahuila";
|
|
13
|
+
readonly COL: "Colima";
|
|
14
|
+
readonly CDMX: "Ciudad de México";
|
|
15
|
+
readonly DGO: "Durango";
|
|
16
|
+
readonly GTO: "Guanajuato";
|
|
17
|
+
readonly GRO: "Guerrero";
|
|
18
|
+
readonly HGO: "Hidalgo";
|
|
19
|
+
readonly JAL: "Jalisco";
|
|
20
|
+
readonly MEX: "Estado de México";
|
|
21
|
+
readonly MICH: "Michoacán";
|
|
22
|
+
readonly MOR: "Morelos";
|
|
23
|
+
readonly NAY: "Nayarit";
|
|
24
|
+
readonly NL: "Nuevo León";
|
|
25
|
+
readonly OAX: "Oaxaca";
|
|
26
|
+
readonly PUE: "Puebla";
|
|
27
|
+
readonly QRO: "Querétaro";
|
|
28
|
+
readonly QROO: "Quintana Roo";
|
|
29
|
+
readonly SLP: "San Luis Potosí";
|
|
30
|
+
readonly SIN: "Sinaloa";
|
|
31
|
+
readonly SON: "Sonora";
|
|
32
|
+
readonly TAB: "Tabasco";
|
|
33
|
+
readonly TAMPS: "Tamaulipas";
|
|
34
|
+
readonly TLAX: "Tlaxcala";
|
|
35
|
+
readonly VER: "Veracruz";
|
|
36
|
+
readonly YUC: "Yucatán";
|
|
37
|
+
readonly ZAC: "Zacatecas";
|
|
38
|
+
};
|
|
39
|
+
export type MexicanStateCode = keyof typeof MEXICAN_STATES;
|
|
40
|
+
export declare const MEXICAN_STATES_ARRAY: {
|
|
41
|
+
code: MexicanStateCode;
|
|
42
|
+
name: "Aguascalientes" | "Baja California" | "Baja California Sur" | "Campeche" | "Chiapas" | "Chihuahua" | "Coahuila" | "Colima" | "Ciudad de México" | "Durango" | "Guanajuato" | "Guerrero" | "Hidalgo" | "Jalisco" | "Estado de México" | "Michoacán" | "Morelos" | "Nayarit" | "Nuevo León" | "Oaxaca" | "Puebla" | "Querétaro" | "Quintana Roo" | "San Luis Potosí" | "Sinaloa" | "Sonora" | "Tabasco" | "Tamaulipas" | "Tlaxcala" | "Veracruz" | "Yucatán" | "Zacatecas";
|
|
43
|
+
}[];
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MEXICAN_STATES_ARRAY = exports.MEXICAN_STATES = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Mexican States - Official INEGI codes
|
|
6
|
+
* Used for address validation
|
|
7
|
+
*/
|
|
8
|
+
exports.MEXICAN_STATES = {
|
|
9
|
+
AGS: 'Aguascalientes',
|
|
10
|
+
BC: 'Baja California',
|
|
11
|
+
BCS: 'Baja California Sur',
|
|
12
|
+
CAMP: 'Campeche',
|
|
13
|
+
CHIS: 'Chiapas',
|
|
14
|
+
CHIH: 'Chihuahua',
|
|
15
|
+
COAH: 'Coahuila',
|
|
16
|
+
COL: 'Colima',
|
|
17
|
+
CDMX: 'Ciudad de México',
|
|
18
|
+
DGO: 'Durango',
|
|
19
|
+
GTO: 'Guanajuato',
|
|
20
|
+
GRO: 'Guerrero',
|
|
21
|
+
HGO: 'Hidalgo',
|
|
22
|
+
JAL: 'Jalisco',
|
|
23
|
+
MEX: 'Estado de México',
|
|
24
|
+
MICH: 'Michoacán',
|
|
25
|
+
MOR: 'Morelos',
|
|
26
|
+
NAY: 'Nayarit',
|
|
27
|
+
NL: 'Nuevo León',
|
|
28
|
+
OAX: 'Oaxaca',
|
|
29
|
+
PUE: 'Puebla',
|
|
30
|
+
QRO: 'Querétaro',
|
|
31
|
+
QROO: 'Quintana Roo',
|
|
32
|
+
SLP: 'San Luis Potosí',
|
|
33
|
+
SIN: 'Sinaloa',
|
|
34
|
+
SON: 'Sonora',
|
|
35
|
+
TAB: 'Tabasco',
|
|
36
|
+
TAMPS: 'Tamaulipas',
|
|
37
|
+
TLAX: 'Tlaxcala',
|
|
38
|
+
VER: 'Veracruz',
|
|
39
|
+
YUC: 'Yucatán',
|
|
40
|
+
ZAC: 'Zacatecas'
|
|
41
|
+
};
|
|
42
|
+
// Helper array for frontend dropdowns
|
|
43
|
+
exports.MEXICAN_STATES_ARRAY = Object.entries(exports.MEXICAN_STATES).map(([code, name]) => ({
|
|
44
|
+
code: code,
|
|
45
|
+
name
|
|
46
|
+
}));
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared constants for HVP2021
|
|
4
|
+
*/
|
|
5
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
6
|
+
if (k2 === undefined) k2 = k;
|
|
7
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
8
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
9
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
10
|
+
}
|
|
11
|
+
Object.defineProperty(o, k2, desc);
|
|
12
|
+
}) : (function(o, m, k, k2) {
|
|
13
|
+
if (k2 === undefined) k2 = k;
|
|
14
|
+
o[k2] = m[k];
|
|
15
|
+
}));
|
|
16
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
17
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
18
|
+
};
|
|
19
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
+
exports.UMA_2024_DAILY = exports.VERSION = exports.APP_NAME = void 0;
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// Application Constants
|
|
23
|
+
// ============================================================================
|
|
24
|
+
exports.APP_NAME = 'HVP2021';
|
|
25
|
+
exports.VERSION = '1.0.0';
|
|
26
|
+
// ============================================================================
|
|
27
|
+
// Mexican Tax Constants (updated annually)
|
|
28
|
+
// ============================================================================
|
|
29
|
+
exports.UMA_2024_DAILY = 108.57;
|
|
30
|
+
// ============================================================================
|
|
31
|
+
// Mexican Geographic Data
|
|
32
|
+
// ============================================================================
|
|
33
|
+
__exportStar(require("./constants/mexican-states"), exports);
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* HVP2021 Shared Library
|
|
4
|
+
* Shared types and constants between backend and frontend
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
__exportStar(require("./types"), exports);
|
|
22
|
+
__exportStar(require("./constants"), exports);
|
|
23
|
+
__exportStar(require("./validation"), exports);
|
|
@@ -0,0 +1,322 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API Response Types - Industry Best Practices
|
|
3
|
+
*
|
|
4
|
+
* LEARNING POINTS:
|
|
5
|
+
*
|
|
6
|
+
* 1. **Discriminated Unions**:
|
|
7
|
+
* - TypeScript can narrow types based on discriminant field (`ok`)
|
|
8
|
+
* - if (response.ok) → TypeScript knows it's ApiSuccessResponse
|
|
9
|
+
* - if (!response.ok) → TypeScript knows it's ApiErrorResponse
|
|
10
|
+
*
|
|
11
|
+
* 2. **Base Types + Extensions**:
|
|
12
|
+
* - Common fields in base interface
|
|
13
|
+
* - Specific fields in extended interfaces
|
|
14
|
+
* - Keeps code DRY and maintainable
|
|
15
|
+
*
|
|
16
|
+
* 3. **Type Safety**:
|
|
17
|
+
* - No runtime checks needed for type narrowing
|
|
18
|
+
* - Compiler prevents accessing wrong fields
|
|
19
|
+
* - Example: Can't access response.data on error response
|
|
20
|
+
*
|
|
21
|
+
* 4. **Industry Standards**:
|
|
22
|
+
* - Based on JSON:API, REST best practices
|
|
23
|
+
* - Similar to what Google, Stripe, GitHub use
|
|
24
|
+
* - Extensible for future needs (versioning, etc.)
|
|
25
|
+
*/
|
|
26
|
+
/**
|
|
27
|
+
* Base interface for ALL API responses
|
|
28
|
+
* Contains fields that are ALWAYS present regardless of success/error
|
|
29
|
+
*/
|
|
30
|
+
interface ApiResponseBase {
|
|
31
|
+
/**
|
|
32
|
+
* HTTP status code (200, 201, 400, 404, 500, etc.)
|
|
33
|
+
* Mirrors the HTTP response status for consistency
|
|
34
|
+
*/
|
|
35
|
+
status_code: number;
|
|
36
|
+
/**
|
|
37
|
+
* Human-readable status string
|
|
38
|
+
* Examples: "OK", "CREATED", "BAD_REQUEST", "NOT_FOUND", "INTERNAL_ERROR"
|
|
39
|
+
*/
|
|
40
|
+
status: string;
|
|
41
|
+
/**
|
|
42
|
+
* Resource being operated on
|
|
43
|
+
* Examples: "company-settings", "collaborator", "payroll"
|
|
44
|
+
* Useful for logging, debugging, and client-side routing
|
|
45
|
+
*/
|
|
46
|
+
resource: string;
|
|
47
|
+
/**
|
|
48
|
+
* Operation being performed
|
|
49
|
+
* Examples: "get", "list", "create", "update", "delete"
|
|
50
|
+
*/
|
|
51
|
+
operation: string;
|
|
52
|
+
/**
|
|
53
|
+
* Timestamp when response was generated (ISO 8601)
|
|
54
|
+
* Useful for debugging, caching, and audit logs
|
|
55
|
+
*/
|
|
56
|
+
timestamp: string;
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Base success response
|
|
60
|
+
* Used when operation succeeds
|
|
61
|
+
*/
|
|
62
|
+
interface ApiSuccessResponseBase<T> extends ApiResponseBase {
|
|
63
|
+
/**
|
|
64
|
+
* Discriminant field - indicates success
|
|
65
|
+
* TypeScript uses this for type narrowing
|
|
66
|
+
*/
|
|
67
|
+
ok: true;
|
|
68
|
+
/**
|
|
69
|
+
* The actual data returned by the API
|
|
70
|
+
* Type T is the domain data (e.g., CompanySettingsResponse)
|
|
71
|
+
*/
|
|
72
|
+
data: T;
|
|
73
|
+
/**
|
|
74
|
+
* Optional message for user feedback
|
|
75
|
+
* Examples: "Settings updated successfully", "Collaborator created"
|
|
76
|
+
*/
|
|
77
|
+
message?: string;
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Success response for SINGLE resource (GET /resource/:id, PUT, PATCH)
|
|
81
|
+
*
|
|
82
|
+
* Used for:
|
|
83
|
+
* - GET /api/company-settings (singleton)
|
|
84
|
+
* - GET /api/collaborators/:id
|
|
85
|
+
* - PUT /api/company-settings
|
|
86
|
+
*
|
|
87
|
+
* No pagination metadata needed
|
|
88
|
+
*/
|
|
89
|
+
export interface ApiSingleSuccessResponse<T> extends ApiSuccessResponseBase<T> {
|
|
90
|
+
}
|
|
91
|
+
/**
|
|
92
|
+
* Success response for LIST of resources (GET /resources)
|
|
93
|
+
*
|
|
94
|
+
* Used for:
|
|
95
|
+
* - GET /api/collaborators
|
|
96
|
+
* - GET /api/payrolls
|
|
97
|
+
*
|
|
98
|
+
* Includes pagination metadata and navigation links
|
|
99
|
+
*/
|
|
100
|
+
export interface ApiListSuccessResponse<T> extends ApiSuccessResponseBase<T[]> {
|
|
101
|
+
/**
|
|
102
|
+
* Pagination metadata
|
|
103
|
+
* Helps frontend build pagination UI
|
|
104
|
+
*/
|
|
105
|
+
meta: {
|
|
106
|
+
/** Total number of items across all pages */
|
|
107
|
+
total: number;
|
|
108
|
+
/** Number of items in current response */
|
|
109
|
+
itemsOnPage: number;
|
|
110
|
+
/** Current page number (1-indexed) */
|
|
111
|
+
page: number;
|
|
112
|
+
/** Items per page limit */
|
|
113
|
+
limit: number;
|
|
114
|
+
/** Total number of pages */
|
|
115
|
+
totalPages: number;
|
|
116
|
+
};
|
|
117
|
+
/**
|
|
118
|
+
* HATEOAS-style navigation links
|
|
119
|
+
* Makes API self-documenting and easier to navigate
|
|
120
|
+
*/
|
|
121
|
+
links: {
|
|
122
|
+
/** URL to current page (for reference/caching) */
|
|
123
|
+
current: string;
|
|
124
|
+
/** URL to first page (optional - only if not on first page) */
|
|
125
|
+
first?: string;
|
|
126
|
+
/** URL to previous page (optional - only if not on first page) */
|
|
127
|
+
prev?: string;
|
|
128
|
+
/** URL to next page (optional - only if not on last page) */
|
|
129
|
+
next?: string;
|
|
130
|
+
/** URL to last page (optional - only if not on last page) */
|
|
131
|
+
last?: string;
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Success response for resource CREATION (POST)
|
|
136
|
+
*
|
|
137
|
+
* Used for:
|
|
138
|
+
* - POST /api/collaborators
|
|
139
|
+
* - POST /api/payrolls
|
|
140
|
+
*
|
|
141
|
+
* Returns 201 status and location header info
|
|
142
|
+
*/
|
|
143
|
+
export interface ApiCreatedSuccessResponse<T> extends ApiSuccessResponseBase<T> {
|
|
144
|
+
/**
|
|
145
|
+
* URL to the newly created resource
|
|
146
|
+
* Follows REST convention of returning location
|
|
147
|
+
*/
|
|
148
|
+
location: string;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Error detail object
|
|
152
|
+
* Provides structured information about what went wrong
|
|
153
|
+
*/
|
|
154
|
+
export interface ApiErrorDetail {
|
|
155
|
+
/**
|
|
156
|
+
* Error type (machine-readable)
|
|
157
|
+
* Examples:
|
|
158
|
+
* - "ValidationError" - Input validation failed
|
|
159
|
+
* - "BusinessRuleError" - Domain rule violated
|
|
160
|
+
* - "NotFoundError" - Resource doesn't exist
|
|
161
|
+
* - "UnauthorizedError" - Authentication required
|
|
162
|
+
* - "ForbiddenError" - Insufficient permissions
|
|
163
|
+
* - "ConflictError" - Resource state conflict
|
|
164
|
+
* - "InternalError" - Server error
|
|
165
|
+
*/
|
|
166
|
+
type: string;
|
|
167
|
+
/**
|
|
168
|
+
* Error message (human-readable, in Spanish for UI)
|
|
169
|
+
* Example: "El RFC es inválido. Debe tener 12 o 13 caracteres."
|
|
170
|
+
*/
|
|
171
|
+
message: string;
|
|
172
|
+
/**
|
|
173
|
+
* Additional error details (optional)
|
|
174
|
+
*
|
|
175
|
+
* For ValidationError:
|
|
176
|
+
* {
|
|
177
|
+
* field: "rfc",
|
|
178
|
+
* constraint: "matches",
|
|
179
|
+
* expected: "XXX######XXX",
|
|
180
|
+
* received: "invalid"
|
|
181
|
+
* }
|
|
182
|
+
*
|
|
183
|
+
* For BusinessRuleError:
|
|
184
|
+
* {
|
|
185
|
+
* rule: "cannot_delete_active_employment",
|
|
186
|
+
* reason: "Employment is currently active"
|
|
187
|
+
* }
|
|
188
|
+
*
|
|
189
|
+
* Type: unknown (requires type checking before use)
|
|
190
|
+
* Frontend must validate/cast before accessing properties
|
|
191
|
+
*/
|
|
192
|
+
details?: unknown;
|
|
193
|
+
/**
|
|
194
|
+
* Reference ID for tracking/logging (optional)
|
|
195
|
+
* Useful for debugging - user can provide this to support
|
|
196
|
+
* Example: "err_2024_01_02_a3f5k9"
|
|
197
|
+
*/
|
|
198
|
+
ref?: string;
|
|
199
|
+
/**
|
|
200
|
+
* Stack trace (only in development mode, never in production)
|
|
201
|
+
*/
|
|
202
|
+
stack?: string;
|
|
203
|
+
}
|
|
204
|
+
/**
|
|
205
|
+
* Error response
|
|
206
|
+
* Used when operation fails
|
|
207
|
+
*/
|
|
208
|
+
export interface ApiErrorResponse extends ApiResponseBase {
|
|
209
|
+
/**
|
|
210
|
+
* Discriminant field - indicates error
|
|
211
|
+
* TypeScript uses this for type narrowing
|
|
212
|
+
*/
|
|
213
|
+
ok: false;
|
|
214
|
+
/**
|
|
215
|
+
* Structured error information
|
|
216
|
+
*/
|
|
217
|
+
error: ApiErrorDetail;
|
|
218
|
+
}
|
|
219
|
+
/**
|
|
220
|
+
* Main API Response type - Discriminated Union
|
|
221
|
+
*
|
|
222
|
+
* This is what you should use in your code:
|
|
223
|
+
*
|
|
224
|
+
* ```typescript
|
|
225
|
+
* const response: ApiResponse<CompanySettingsResponse> = await fetch(...);
|
|
226
|
+
*
|
|
227
|
+
* if (response.ok) {
|
|
228
|
+
* // TypeScript knows: response is ApiSingleSuccessResponse<CompanySettingsResponse>
|
|
229
|
+
* console.log(response.data.rfc);
|
|
230
|
+
* } else {
|
|
231
|
+
* // TypeScript knows: response is ApiErrorResponse
|
|
232
|
+
* console.error(response.error.message);
|
|
233
|
+
* }
|
|
234
|
+
* ```
|
|
235
|
+
*
|
|
236
|
+
* For lists:
|
|
237
|
+
* ```typescript
|
|
238
|
+
* const response: ApiListResponse<Collaborator> = await fetch(...);
|
|
239
|
+
*
|
|
240
|
+
* if (response.ok) {
|
|
241
|
+
* // TypeScript knows: response is ApiListSuccessResponse<Collaborator>
|
|
242
|
+
* console.log(response.meta.total);
|
|
243
|
+
* console.log(response.data.length);
|
|
244
|
+
* }
|
|
245
|
+
* ```
|
|
246
|
+
*/
|
|
247
|
+
export type ApiResponse<T> = ApiSingleSuccessResponse<T> | ApiErrorResponse;
|
|
248
|
+
/**
|
|
249
|
+
* Convenience type for list responses
|
|
250
|
+
*/
|
|
251
|
+
export type ApiListResponse<T> = ApiListSuccessResponse<T> | ApiErrorResponse;
|
|
252
|
+
/**
|
|
253
|
+
* Convenience type for creation responses
|
|
254
|
+
*/
|
|
255
|
+
export type ApiCreatedResponse<T> = ApiCreatedSuccessResponse<T> | ApiErrorResponse;
|
|
256
|
+
/**
|
|
257
|
+
* Helper for building success responses
|
|
258
|
+
* Used in controllers/services to construct consistent responses
|
|
259
|
+
*/
|
|
260
|
+
export type ApiSuccessResponseParams<T> = {
|
|
261
|
+
status_code: number;
|
|
262
|
+
status: string;
|
|
263
|
+
resource: string;
|
|
264
|
+
operation: string;
|
|
265
|
+
data: T;
|
|
266
|
+
message?: string;
|
|
267
|
+
};
|
|
268
|
+
/**
|
|
269
|
+
* Helper for building list success responses
|
|
270
|
+
*/
|
|
271
|
+
export type ApiListSuccessResponseParams<T> = ApiSuccessResponseParams<T[]> & {
|
|
272
|
+
meta: ApiListSuccessResponse<T>['meta'];
|
|
273
|
+
links: ApiListSuccessResponse<T>['links'];
|
|
274
|
+
};
|
|
275
|
+
/**
|
|
276
|
+
* Helper for building created responses
|
|
277
|
+
*/
|
|
278
|
+
export type ApiCreatedSuccessResponseParams<T> = ApiSuccessResponseParams<T> & {
|
|
279
|
+
location: string;
|
|
280
|
+
};
|
|
281
|
+
/**
|
|
282
|
+
* Helper for building error responses
|
|
283
|
+
*/
|
|
284
|
+
export type ApiErrorResponseParams = {
|
|
285
|
+
status_code: number;
|
|
286
|
+
status: string;
|
|
287
|
+
resource: string;
|
|
288
|
+
operation: string;
|
|
289
|
+
error: ApiErrorDetail;
|
|
290
|
+
};
|
|
291
|
+
/**
|
|
292
|
+
* Standard HTTP status strings
|
|
293
|
+
* Use these for consistency across the API
|
|
294
|
+
*/
|
|
295
|
+
export declare const API_STATUS: {
|
|
296
|
+
readonly OK: "OK";
|
|
297
|
+
readonly CREATED: "CREATED";
|
|
298
|
+
readonly ACCEPTED: "ACCEPTED";
|
|
299
|
+
readonly NO_CONTENT: "NO_CONTENT";
|
|
300
|
+
readonly BAD_REQUEST: "BAD_REQUEST";
|
|
301
|
+
readonly UNAUTHORIZED: "UNAUTHORIZED";
|
|
302
|
+
readonly FORBIDDEN: "FORBIDDEN";
|
|
303
|
+
readonly NOT_FOUND: "NOT_FOUND";
|
|
304
|
+
readonly CONFLICT: "CONFLICT";
|
|
305
|
+
readonly UNPROCESSABLE_ENTITY: "UNPROCESSABLE_ENTITY";
|
|
306
|
+
readonly INTERNAL_ERROR: "INTERNAL_ERROR";
|
|
307
|
+
readonly SERVICE_UNAVAILABLE: "SERVICE_UNAVAILABLE";
|
|
308
|
+
};
|
|
309
|
+
/**
|
|
310
|
+
* Standard error types
|
|
311
|
+
* Use these for consistency in error handling
|
|
312
|
+
*/
|
|
313
|
+
export declare const ERROR_TYPES: {
|
|
314
|
+
readonly VALIDATION_ERROR: "ValidationError";
|
|
315
|
+
readonly BUSINESS_RULE_ERROR: "BusinessRuleError";
|
|
316
|
+
readonly NOT_FOUND_ERROR: "NotFoundError";
|
|
317
|
+
readonly UNAUTHORIZED_ERROR: "UnauthorizedError";
|
|
318
|
+
readonly FORBIDDEN_ERROR: "ForbiddenError";
|
|
319
|
+
readonly CONFLICT_ERROR: "ConflictError";
|
|
320
|
+
readonly INTERNAL_ERROR: "InternalError";
|
|
321
|
+
};
|
|
322
|
+
export {};
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API Response Types - Industry Best Practices
|
|
4
|
+
*
|
|
5
|
+
* LEARNING POINTS:
|
|
6
|
+
*
|
|
7
|
+
* 1. **Discriminated Unions**:
|
|
8
|
+
* - TypeScript can narrow types based on discriminant field (`ok`)
|
|
9
|
+
* - if (response.ok) → TypeScript knows it's ApiSuccessResponse
|
|
10
|
+
* - if (!response.ok) → TypeScript knows it's ApiErrorResponse
|
|
11
|
+
*
|
|
12
|
+
* 2. **Base Types + Extensions**:
|
|
13
|
+
* - Common fields in base interface
|
|
14
|
+
* - Specific fields in extended interfaces
|
|
15
|
+
* - Keeps code DRY and maintainable
|
|
16
|
+
*
|
|
17
|
+
* 3. **Type Safety**:
|
|
18
|
+
* - No runtime checks needed for type narrowing
|
|
19
|
+
* - Compiler prevents accessing wrong fields
|
|
20
|
+
* - Example: Can't access response.data on error response
|
|
21
|
+
*
|
|
22
|
+
* 4. **Industry Standards**:
|
|
23
|
+
* - Based on JSON:API, REST best practices
|
|
24
|
+
* - Similar to what Google, Stripe, GitHub use
|
|
25
|
+
* - Extensible for future needs (versioning, etc.)
|
|
26
|
+
*/
|
|
27
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
28
|
+
exports.ERROR_TYPES = exports.API_STATUS = void 0;
|
|
29
|
+
// ============================================================================
|
|
30
|
+
// COMMON STATUS STRINGS (Optional - for consistency)
|
|
31
|
+
// ============================================================================
|
|
32
|
+
/**
|
|
33
|
+
* Standard HTTP status strings
|
|
34
|
+
* Use these for consistency across the API
|
|
35
|
+
*/
|
|
36
|
+
exports.API_STATUS = {
|
|
37
|
+
// 2xx Success
|
|
38
|
+
OK: 'OK',
|
|
39
|
+
CREATED: 'CREATED',
|
|
40
|
+
ACCEPTED: 'ACCEPTED',
|
|
41
|
+
NO_CONTENT: 'NO_CONTENT',
|
|
42
|
+
// 4xx Client Errors
|
|
43
|
+
BAD_REQUEST: 'BAD_REQUEST',
|
|
44
|
+
UNAUTHORIZED: 'UNAUTHORIZED',
|
|
45
|
+
FORBIDDEN: 'FORBIDDEN',
|
|
46
|
+
NOT_FOUND: 'NOT_FOUND',
|
|
47
|
+
CONFLICT: 'CONFLICT',
|
|
48
|
+
UNPROCESSABLE_ENTITY: 'UNPROCESSABLE_ENTITY',
|
|
49
|
+
// 5xx Server Errors
|
|
50
|
+
INTERNAL_ERROR: 'INTERNAL_ERROR',
|
|
51
|
+
SERVICE_UNAVAILABLE: 'SERVICE_UNAVAILABLE'
|
|
52
|
+
};
|
|
53
|
+
/**
|
|
54
|
+
* Standard error types
|
|
55
|
+
* Use these for consistency in error handling
|
|
56
|
+
*/
|
|
57
|
+
exports.ERROR_TYPES = {
|
|
58
|
+
VALIDATION_ERROR: 'ValidationError',
|
|
59
|
+
BUSINESS_RULE_ERROR: 'BusinessRuleError',
|
|
60
|
+
NOT_FOUND_ERROR: 'NotFoundError',
|
|
61
|
+
UNAUTHORIZED_ERROR: 'UnauthorizedError',
|
|
62
|
+
FORBIDDEN_ERROR: 'ForbiddenError',
|
|
63
|
+
CONFLICT_ERROR: 'ConflictError',
|
|
64
|
+
INTERNAL_ERROR: 'InternalError'
|
|
65
|
+
};
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { MexicanStateCode } from '../constants/mexican-states';
|
|
2
|
+
/**
|
|
3
|
+
* API Contract: GET /api/company-settings
|
|
4
|
+
*
|
|
5
|
+
* This is the shape of data that travels over HTTP.
|
|
6
|
+
* NOT a domain entity - just a data transfer contract.
|
|
7
|
+
*/
|
|
8
|
+
export interface CompanySettingsResponse {
|
|
9
|
+
rfc: string;
|
|
10
|
+
businessName: string;
|
|
11
|
+
taxRegime: string;
|
|
12
|
+
street: string;
|
|
13
|
+
exteriorNumber: string;
|
|
14
|
+
interiorNumber?: string;
|
|
15
|
+
neighborhood: string;
|
|
16
|
+
city: string;
|
|
17
|
+
state: MexicanStateCode;
|
|
18
|
+
zipCode: string;
|
|
19
|
+
country: string;
|
|
20
|
+
email: string;
|
|
21
|
+
phone?: string;
|
|
22
|
+
facturamaApiKey?: string;
|
|
23
|
+
facturamaApiSecret?: string;
|
|
24
|
+
facturamaUseSandbox: boolean;
|
|
25
|
+
createdAt: string;
|
|
26
|
+
updatedAt: string;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* API Contract: PUT /api/company-settings
|
|
30
|
+
*
|
|
31
|
+
* Request body for updating company settings.
|
|
32
|
+
* Similar to Response but without metadata fields.
|
|
33
|
+
*/
|
|
34
|
+
export interface UpdateCompanySettingsRequest {
|
|
35
|
+
rfc: string;
|
|
36
|
+
businessName: string;
|
|
37
|
+
taxRegime: string;
|
|
38
|
+
street: string;
|
|
39
|
+
exteriorNumber: string;
|
|
40
|
+
interiorNumber?: string;
|
|
41
|
+
neighborhood: string;
|
|
42
|
+
city: string;
|
|
43
|
+
state: MexicanStateCode;
|
|
44
|
+
zipCode: string;
|
|
45
|
+
country: string;
|
|
46
|
+
email: string;
|
|
47
|
+
phone?: string;
|
|
48
|
+
facturamaApiKey?: string;
|
|
49
|
+
facturamaApiSecret?: string;
|
|
50
|
+
facturamaUseSandbox: boolean;
|
|
51
|
+
}
|
package/dist/types.d.ts
ADDED
package/dist/types.js
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* Shared types for HVP2021
|
|
4
|
+
* Used by both backend and frontend for type consistency
|
|
5
|
+
*/
|
|
6
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
+
if (k2 === undefined) k2 = k;
|
|
8
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
+
}
|
|
12
|
+
Object.defineProperty(o, k2, desc);
|
|
13
|
+
}) : (function(o, m, k, k2) {
|
|
14
|
+
if (k2 === undefined) k2 = k;
|
|
15
|
+
o[k2] = m[k];
|
|
16
|
+
}));
|
|
17
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
+
};
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
// ============================================================================
|
|
22
|
+
// API Response Types - Standardized format for all endpoints
|
|
23
|
+
// ============================================================================
|
|
24
|
+
__exportStar(require("./types/api-response.types"), exports);
|
|
25
|
+
// ============================================================================
|
|
26
|
+
// Domain Types - Business entities and DTOs
|
|
27
|
+
// ============================================================================
|
|
28
|
+
__exportStar(require("./types/company-settings.types"), exports);
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|