@crosspost/sdk 0.1.2 → 0.1.3
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 +287 -176
- package/dist/index.cjs +438 -94
- package/dist/index.d.cts +193 -12
- package/dist/index.d.ts +193 -12
- package/dist/index.js +418 -92
- package/package.json +1 -1
- package/src/api/activity.ts +77 -0
- package/src/api/system.ts +55 -0
- package/src/core/client.ts +19 -16
- package/src/core/config.ts +4 -4
- package/src/core/request.ts +120 -94
- package/src/index.ts +25 -6
- package/src/utils/cookie.ts +21 -5
- package/src/utils/error-utils.ts +310 -0
@@ -0,0 +1,310 @@
|
|
1
|
+
import { ApiError, ApiErrorCode, Platform, PlatformError } from '@crosspost/types';
|
2
|
+
import { handleErrorResponse as baseHandleErrorResponse } from './error.ts';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* Error categories grouped by type for better organization and usage
|
6
|
+
*/
|
7
|
+
export const ERROR_CATEGORIES = {
|
8
|
+
AUTH: [
|
9
|
+
ApiErrorCode.UNAUTHORIZED,
|
10
|
+
ApiErrorCode.FORBIDDEN,
|
11
|
+
],
|
12
|
+
VALIDATION: [
|
13
|
+
ApiErrorCode.VALIDATION_ERROR,
|
14
|
+
ApiErrorCode.INVALID_REQUEST,
|
15
|
+
],
|
16
|
+
NETWORK: [
|
17
|
+
ApiErrorCode.NETWORK_ERROR,
|
18
|
+
],
|
19
|
+
PLATFORM: [
|
20
|
+
ApiErrorCode.PLATFORM_ERROR,
|
21
|
+
ApiErrorCode.PLATFORM_UNAVAILABLE,
|
22
|
+
],
|
23
|
+
CONTENT: [
|
24
|
+
ApiErrorCode.CONTENT_POLICY_VIOLATION,
|
25
|
+
ApiErrorCode.DUPLICATE_CONTENT,
|
26
|
+
],
|
27
|
+
RATE_LIMIT: [
|
28
|
+
ApiErrorCode.RATE_LIMITED,
|
29
|
+
],
|
30
|
+
POST: [
|
31
|
+
ApiErrorCode.POST_CREATION_FAILED,
|
32
|
+
ApiErrorCode.THREAD_CREATION_FAILED,
|
33
|
+
ApiErrorCode.POST_DELETION_FAILED,
|
34
|
+
ApiErrorCode.POST_INTERACTION_FAILED,
|
35
|
+
],
|
36
|
+
MEDIA: [
|
37
|
+
ApiErrorCode.MEDIA_UPLOAD_FAILED,
|
38
|
+
],
|
39
|
+
};
|
40
|
+
|
41
|
+
/**
|
42
|
+
* Check if an error belongs to a specific category
|
43
|
+
*
|
44
|
+
* @param error The error to check
|
45
|
+
* @param category The category to check against
|
46
|
+
* @returns True if the error belongs to the category, false otherwise
|
47
|
+
*/
|
48
|
+
export function isErrorOfCategory(error: unknown, category: ApiErrorCode[]): boolean {
|
49
|
+
if (error instanceof ApiError) {
|
50
|
+
return category.includes(error.code);
|
51
|
+
}
|
52
|
+
|
53
|
+
if (error instanceof PlatformError) {
|
54
|
+
return category.includes(error.code);
|
55
|
+
}
|
56
|
+
|
57
|
+
// Fallback for error-like objects with code property
|
58
|
+
if (error && typeof error === 'object' && 'code' in error) {
|
59
|
+
return category.includes((error as any).code);
|
60
|
+
}
|
61
|
+
|
62
|
+
return false;
|
63
|
+
}
|
64
|
+
|
65
|
+
/**
|
66
|
+
* Check if an error is an authentication error
|
67
|
+
*
|
68
|
+
* @param error The error to check
|
69
|
+
* @returns True if the error is an authentication error, false otherwise
|
70
|
+
*/
|
71
|
+
export function isAuthError(error: unknown): boolean {
|
72
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.AUTH);
|
73
|
+
}
|
74
|
+
|
75
|
+
/**
|
76
|
+
* Check if an error is a validation error
|
77
|
+
*
|
78
|
+
* @param error The error to check
|
79
|
+
* @returns True if the error is a validation error, false otherwise
|
80
|
+
*/
|
81
|
+
export function isValidationError(error: unknown): boolean {
|
82
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.VALIDATION);
|
83
|
+
}
|
84
|
+
|
85
|
+
/**
|
86
|
+
* Check if an error is a network error
|
87
|
+
*
|
88
|
+
* @param error The error to check
|
89
|
+
* @returns True if the error is a network error, false otherwise
|
90
|
+
*/
|
91
|
+
export function isNetworkError(error: unknown): boolean {
|
92
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.NETWORK);
|
93
|
+
}
|
94
|
+
|
95
|
+
/**
|
96
|
+
* Check if an error is a platform error
|
97
|
+
*
|
98
|
+
* @param error The error to check
|
99
|
+
* @returns True if the error is a platform error, false otherwise
|
100
|
+
*/
|
101
|
+
export function isPlatformError(error: unknown): boolean {
|
102
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.PLATFORM) || error instanceof PlatformError;
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Check if an error is a content policy error
|
107
|
+
*
|
108
|
+
* @param error The error to check
|
109
|
+
* @returns True if the error is a content policy error, false otherwise
|
110
|
+
*/
|
111
|
+
export function isContentError(error: unknown): boolean {
|
112
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.CONTENT);
|
113
|
+
}
|
114
|
+
|
115
|
+
/**
|
116
|
+
* Check if an error is a rate limit error
|
117
|
+
*
|
118
|
+
* @param error The error to check
|
119
|
+
* @returns True if the error is a rate limit error, false otherwise
|
120
|
+
*/
|
121
|
+
export function isRateLimitError(error: unknown): boolean {
|
122
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.RATE_LIMIT);
|
123
|
+
}
|
124
|
+
|
125
|
+
/**
|
126
|
+
* Check if an error is a post-related error
|
127
|
+
*
|
128
|
+
* @param error The error to check
|
129
|
+
* @returns True if the error is a post-related error, false otherwise
|
130
|
+
*/
|
131
|
+
export function isPostError(error: unknown): boolean {
|
132
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.POST);
|
133
|
+
}
|
134
|
+
|
135
|
+
/**
|
136
|
+
* Check if an error is a media-related error
|
137
|
+
*
|
138
|
+
* @param error The error to check
|
139
|
+
* @returns True if the error is a media-related error, false otherwise
|
140
|
+
*/
|
141
|
+
export function isMediaError(error: unknown): boolean {
|
142
|
+
return isErrorOfCategory(error, ERROR_CATEGORIES.MEDIA);
|
143
|
+
}
|
144
|
+
|
145
|
+
/**
|
146
|
+
* Check if an error is recoverable
|
147
|
+
*
|
148
|
+
* @param error The error to check
|
149
|
+
* @returns True if the error is recoverable, false otherwise
|
150
|
+
*/
|
151
|
+
export function isRecoverableError(error: unknown): boolean {
|
152
|
+
if (error instanceof ApiError || error instanceof PlatformError) {
|
153
|
+
return error.recoverable;
|
154
|
+
}
|
155
|
+
|
156
|
+
return false;
|
157
|
+
}
|
158
|
+
|
159
|
+
/**
|
160
|
+
* Get a user-friendly error message
|
161
|
+
*
|
162
|
+
* @param error The error to get the message from
|
163
|
+
* @param defaultMessage The default message to return if no message is found
|
164
|
+
* @returns The error message
|
165
|
+
*/
|
166
|
+
export function getErrorMessage(
|
167
|
+
error: unknown,
|
168
|
+
defaultMessage: string = 'An error occurred',
|
169
|
+
): string {
|
170
|
+
if (error instanceof Error) {
|
171
|
+
return error.message || defaultMessage;
|
172
|
+
}
|
173
|
+
|
174
|
+
if (typeof error === 'string') {
|
175
|
+
return error;
|
176
|
+
}
|
177
|
+
|
178
|
+
if (error && typeof error === 'object' && 'message' in error) {
|
179
|
+
return (error as any).message || defaultMessage;
|
180
|
+
}
|
181
|
+
|
182
|
+
return defaultMessage;
|
183
|
+
}
|
184
|
+
|
185
|
+
/**
|
186
|
+
* Extract error details if available
|
187
|
+
*
|
188
|
+
* @param error The error to extract details from
|
189
|
+
* @returns The error details or undefined if none are found
|
190
|
+
*/
|
191
|
+
export function getErrorDetails(error: unknown): Record<string, any> | undefined {
|
192
|
+
if (error instanceof ApiError || error instanceof PlatformError) {
|
193
|
+
return error.details;
|
194
|
+
}
|
195
|
+
|
196
|
+
if (error && typeof error === 'object' && 'details' in error) {
|
197
|
+
return (error as any).details;
|
198
|
+
}
|
199
|
+
|
200
|
+
return undefined;
|
201
|
+
}
|
202
|
+
|
203
|
+
/**
|
204
|
+
* Enrich an error with additional context
|
205
|
+
*
|
206
|
+
* @param error The error to enrich
|
207
|
+
* @param context The context to add to the error
|
208
|
+
* @returns The enriched error
|
209
|
+
*/
|
210
|
+
export function enrichErrorWithContext(
|
211
|
+
error: unknown,
|
212
|
+
context: Record<string, any>,
|
213
|
+
): Error {
|
214
|
+
if (error instanceof ApiError) {
|
215
|
+
// Create a new ApiError with the merged details since details is read-only
|
216
|
+
return new ApiError(
|
217
|
+
error.message,
|
218
|
+
error.code,
|
219
|
+
error.status,
|
220
|
+
{ ...(error.details || {}), ...context },
|
221
|
+
error.recoverable,
|
222
|
+
);
|
223
|
+
}
|
224
|
+
|
225
|
+
if (error instanceof PlatformError) {
|
226
|
+
// Create a new PlatformError with the merged details since details is read-only
|
227
|
+
return new PlatformError(
|
228
|
+
error.message,
|
229
|
+
error.platform,
|
230
|
+
error.code,
|
231
|
+
error.recoverable,
|
232
|
+
error.originalError,
|
233
|
+
error.status,
|
234
|
+
error.userId,
|
235
|
+
{ ...(error.details || {}), ...context },
|
236
|
+
);
|
237
|
+
}
|
238
|
+
|
239
|
+
// For regular errors or non-Error objects, create a new ApiError with the context
|
240
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
241
|
+
return new ApiError(
|
242
|
+
errorMessage || 'An error occurred',
|
243
|
+
ApiErrorCode.INTERNAL_ERROR,
|
244
|
+
500,
|
245
|
+
{ originalError: error, ...context },
|
246
|
+
false,
|
247
|
+
);
|
248
|
+
}
|
249
|
+
|
250
|
+
/**
|
251
|
+
* Re-export the handleErrorResponse function from error.ts
|
252
|
+
* for backward compatibility
|
253
|
+
*/
|
254
|
+
export function handleErrorResponse(data: any, status: number): ApiError | PlatformError {
|
255
|
+
return baseHandleErrorResponse(data, status);
|
256
|
+
}
|
257
|
+
|
258
|
+
/**
|
259
|
+
* Wrapper for API calls with consistent error handling
|
260
|
+
*
|
261
|
+
* @param apiCall The API call to wrap
|
262
|
+
* @param context Optional context to add to any errors
|
263
|
+
* @returns The result of the API call
|
264
|
+
* @throws An enriched error if the API call fails
|
265
|
+
*/
|
266
|
+
export async function apiWrapper<T>(
|
267
|
+
apiCall: () => Promise<T>,
|
268
|
+
context?: Record<string, any>,
|
269
|
+
): Promise<T> {
|
270
|
+
try {
|
271
|
+
return await apiCall();
|
272
|
+
} catch (error) {
|
273
|
+
// If it's a Response object, use handleErrorResponse
|
274
|
+
if (error instanceof Response) {
|
275
|
+
try {
|
276
|
+
const errorData = await error.json();
|
277
|
+
throw enrichErrorWithContext(
|
278
|
+
handleErrorResponse(errorData, error.status),
|
279
|
+
context || {},
|
280
|
+
);
|
281
|
+
} catch (jsonError) {
|
282
|
+
// If JSON parsing fails, create a generic error
|
283
|
+
if (jsonError instanceof Error && jsonError.name === 'SyntaxError') {
|
284
|
+
throw enrichErrorWithContext(
|
285
|
+
new ApiError(
|
286
|
+
`API request failed with status ${error.status} and non-JSON response`,
|
287
|
+
ApiErrorCode.NETWORK_ERROR,
|
288
|
+
error.status as any,
|
289
|
+
{ originalResponse: error.statusText },
|
290
|
+
),
|
291
|
+
context || {},
|
292
|
+
);
|
293
|
+
}
|
294
|
+
// If it's already an enriched error from handleErrorResponse, just throw it
|
295
|
+
throw jsonError;
|
296
|
+
}
|
297
|
+
}
|
298
|
+
|
299
|
+
// If it's already an ApiError or PlatformError, just add context
|
300
|
+
if (error instanceof ApiError || error instanceof PlatformError) {
|
301
|
+
throw enrichErrorWithContext(error, context || {});
|
302
|
+
}
|
303
|
+
|
304
|
+
// Otherwise wrap it in an ApiError
|
305
|
+
throw enrichErrorWithContext(
|
306
|
+
error instanceof Error ? error : new Error(String(error)),
|
307
|
+
context || {},
|
308
|
+
);
|
309
|
+
}
|
310
|
+
}
|