@zernio/node 0.1.58
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/LICENSE +190 -0
- package/README.md +481 -0
- package/dist/index.d.mts +8503 -0
- package/dist/index.d.ts +8503 -0
- package/dist/index.js +1870 -0
- package/dist/index.mjs +1841 -0
- package/package.json +84 -0
- package/src/client.ts +674 -0
- package/src/errors.ts +144 -0
- package/src/generated/index.ts +3 -0
- package/src/generated/sdk.gen.ts +2259 -0
- package/src/generated/types.gen.ts +8708 -0
- package/src/index.ts +34 -0
package/src/errors.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Base error class for Late API errors
|
|
3
|
+
*/
|
|
4
|
+
export class LateApiError extends Error {
|
|
5
|
+
public readonly statusCode: number;
|
|
6
|
+
public readonly code?: string;
|
|
7
|
+
public readonly details?: Record<string, unknown>;
|
|
8
|
+
|
|
9
|
+
constructor(
|
|
10
|
+
message: string,
|
|
11
|
+
statusCode: number,
|
|
12
|
+
code?: string,
|
|
13
|
+
details?: Record<string, unknown>
|
|
14
|
+
) {
|
|
15
|
+
super(message);
|
|
16
|
+
this.name = 'LateApiError';
|
|
17
|
+
this.statusCode = statusCode;
|
|
18
|
+
this.code = code;
|
|
19
|
+
this.details = details;
|
|
20
|
+
|
|
21
|
+
// Maintains proper stack trace for where error was thrown
|
|
22
|
+
if (Error.captureStackTrace) {
|
|
23
|
+
Error.captureStackTrace(this, LateApiError);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Check if this is a rate limit error
|
|
29
|
+
*/
|
|
30
|
+
isRateLimited(): boolean {
|
|
31
|
+
return this.statusCode === 429;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Check if this is an authentication error
|
|
36
|
+
*/
|
|
37
|
+
isAuthError(): boolean {
|
|
38
|
+
return this.statusCode === 401;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Check if this is a permission/access error
|
|
43
|
+
*/
|
|
44
|
+
isForbidden(): boolean {
|
|
45
|
+
return this.statusCode === 403;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Check if this is a not found error
|
|
50
|
+
*/
|
|
51
|
+
isNotFound(): boolean {
|
|
52
|
+
return this.statusCode === 404;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check if this is a validation error
|
|
57
|
+
*/
|
|
58
|
+
isValidationError(): boolean {
|
|
59
|
+
return this.statusCode === 400;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Check if this is a payment required error
|
|
64
|
+
*/
|
|
65
|
+
isPaymentRequired(): boolean {
|
|
66
|
+
return this.statusCode === 402;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Rate limit error with additional rate limit info
|
|
72
|
+
*/
|
|
73
|
+
export class RateLimitError extends LateApiError {
|
|
74
|
+
public readonly limit?: number;
|
|
75
|
+
public readonly remaining?: number;
|
|
76
|
+
public readonly resetAt?: Date;
|
|
77
|
+
|
|
78
|
+
constructor(
|
|
79
|
+
message: string,
|
|
80
|
+
limit?: number,
|
|
81
|
+
remaining?: number,
|
|
82
|
+
resetAt?: Date
|
|
83
|
+
) {
|
|
84
|
+
super(message, 429, 'rate_limit_exceeded');
|
|
85
|
+
this.name = 'RateLimitError';
|
|
86
|
+
this.limit = limit;
|
|
87
|
+
this.remaining = remaining;
|
|
88
|
+
this.resetAt = resetAt;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Get seconds until rate limit resets
|
|
93
|
+
*/
|
|
94
|
+
getSecondsUntilReset(): number | undefined {
|
|
95
|
+
if (!this.resetAt) return undefined;
|
|
96
|
+
return Math.max(0, Math.ceil((this.resetAt.getTime() - Date.now()) / 1000));
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Validation error with field-specific details
|
|
102
|
+
*/
|
|
103
|
+
export class ValidationError extends LateApiError {
|
|
104
|
+
public readonly fields?: Record<string, string[]>;
|
|
105
|
+
|
|
106
|
+
constructor(message: string, fields?: Record<string, string[]>) {
|
|
107
|
+
super(message, 400, 'validation_error', { fields });
|
|
108
|
+
this.name = 'ValidationError';
|
|
109
|
+
this.fields = fields;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Parse an error response from the API
|
|
115
|
+
*/
|
|
116
|
+
export function parseApiError(
|
|
117
|
+
response: Response,
|
|
118
|
+
body?: { error?: string; message?: string; code?: string; details?: Record<string, unknown> }
|
|
119
|
+
): LateApiError {
|
|
120
|
+
const message = body?.error || body?.message || response.statusText || 'Unknown error';
|
|
121
|
+
const code = body?.code;
|
|
122
|
+
const details = body?.details;
|
|
123
|
+
|
|
124
|
+
// Handle rate limit errors
|
|
125
|
+
if (response.status === 429) {
|
|
126
|
+
const limit = response.headers.get('X-RateLimit-Limit');
|
|
127
|
+
const remaining = response.headers.get('X-RateLimit-Remaining');
|
|
128
|
+
const reset = response.headers.get('X-RateLimit-Reset');
|
|
129
|
+
|
|
130
|
+
return new RateLimitError(
|
|
131
|
+
message,
|
|
132
|
+
limit ? parseInt(limit, 10) : undefined,
|
|
133
|
+
remaining ? parseInt(remaining, 10) : undefined,
|
|
134
|
+
reset ? new Date(parseInt(reset, 10) * 1000) : undefined
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Handle validation errors
|
|
139
|
+
if (response.status === 400 && details?.fields) {
|
|
140
|
+
return new ValidationError(message, details.fields as Record<string, string[]>);
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
return new LateApiError(message, response.status, code, details);
|
|
144
|
+
}
|