@crosspost/sdk 0.1.2 → 0.1.4
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 +21 -0
- package/README.md +308 -205
- package/dist/index.cjs +427 -170
- package/dist/index.d.cts +193 -37
- package/dist/index.d.ts +193 -37
- package/dist/index.js +404 -150
- package/package.json +1 -3
- package/src/api/activity.ts +77 -0
- package/src/api/system.ts +55 -0
- package/src/core/client.ts +20 -19
- package/src/core/config.ts +4 -4
- package/src/core/request.ts +112 -96
- package/src/index.ts +24 -14
- package/src/utils/error.ts +300 -0
- package/src/utils/cookie.ts +0 -75
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "@crosspost/sdk",
|
3
|
-
"version": "0.1.
|
3
|
+
"version": "0.1.4",
|
4
4
|
"description": "SDK for interacting with the Crosspost API",
|
5
5
|
"type": "module",
|
6
6
|
"main": "dist/index.cjs",
|
@@ -36,8 +36,6 @@
|
|
36
36
|
"author": "crosspost.near",
|
37
37
|
"license": "MIT",
|
38
38
|
"dependencies": {
|
39
|
-
"@types/js-cookie": "^3.0.6",
|
40
|
-
"js-cookie": "^3.0.5",
|
41
39
|
"near-sign-verify": "^0.1.1"
|
42
40
|
},
|
43
41
|
"devDependencies": {
|
@@ -0,0 +1,77 @@
|
|
1
|
+
import type {
|
2
|
+
AccountActivityQuery,
|
3
|
+
AccountActivityResponse,
|
4
|
+
AccountPostsQuery,
|
5
|
+
AccountPostsResponse,
|
6
|
+
ActivityLeaderboardQuery,
|
7
|
+
ActivityLeaderboardResponse,
|
8
|
+
} from '@crosspost/types';
|
9
|
+
import { makeRequest, type RequestOptions } from '../core/request.ts';
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Activity-related API operations
|
13
|
+
*/
|
14
|
+
export class ActivityApi {
|
15
|
+
private options: RequestOptions;
|
16
|
+
|
17
|
+
/**
|
18
|
+
* Creates an instance of ActivityApi
|
19
|
+
* @param options Request options
|
20
|
+
*/
|
21
|
+
constructor(options: RequestOptions) {
|
22
|
+
this.options = options;
|
23
|
+
}
|
24
|
+
|
25
|
+
/**
|
26
|
+
* Gets the global activity leaderboard
|
27
|
+
* @param query Optional query parameters
|
28
|
+
* @returns A promise resolving with the leaderboard response
|
29
|
+
*/
|
30
|
+
async getLeaderboard(query?: ActivityLeaderboardQuery): Promise<ActivityLeaderboardResponse> {
|
31
|
+
return makeRequest<ActivityLeaderboardResponse>(
|
32
|
+
'GET',
|
33
|
+
'/api/activity',
|
34
|
+
this.options,
|
35
|
+
undefined,
|
36
|
+
query,
|
37
|
+
);
|
38
|
+
}
|
39
|
+
|
40
|
+
/**
|
41
|
+
* Gets activity for a specific account
|
42
|
+
* @param signerId The NEAR account ID
|
43
|
+
* @param query Optional query parameters
|
44
|
+
* @returns A promise resolving with the account activity response
|
45
|
+
*/
|
46
|
+
async getAccountActivity(
|
47
|
+
signerId: string,
|
48
|
+
query?: AccountActivityQuery,
|
49
|
+
): Promise<AccountActivityResponse> {
|
50
|
+
return makeRequest<AccountActivityResponse>(
|
51
|
+
'GET',
|
52
|
+
`/api/activity/${signerId}`,
|
53
|
+
this.options,
|
54
|
+
undefined,
|
55
|
+
query,
|
56
|
+
);
|
57
|
+
}
|
58
|
+
|
59
|
+
/**
|
60
|
+
* Gets posts for a specific account
|
61
|
+
* @param signerId The NEAR account ID
|
62
|
+
* @param query Optional query parameters
|
63
|
+
* @returns A promise resolving with the account posts response
|
64
|
+
*/
|
65
|
+
async getAccountPosts(
|
66
|
+
signerId: string,
|
67
|
+
query?: AccountPostsQuery,
|
68
|
+
): Promise<AccountPostsResponse> {
|
69
|
+
return makeRequest<AccountPostsResponse>(
|
70
|
+
'GET',
|
71
|
+
`/api/activity/${signerId}/posts`,
|
72
|
+
this.options,
|
73
|
+
undefined,
|
74
|
+
query,
|
75
|
+
);
|
76
|
+
}
|
77
|
+
}
|
@@ -0,0 +1,55 @@
|
|
1
|
+
import type { EndpointRateLimitResponse, RateLimitResponse } from '@crosspost/types';
|
2
|
+
import { makeRequest, type RequestOptions } from '../core/request.ts';
|
3
|
+
|
4
|
+
/**
|
5
|
+
* System-related API operations
|
6
|
+
* Includes rate limits, health checks, and other system-related functionality
|
7
|
+
*/
|
8
|
+
export class SystemApi {
|
9
|
+
private options: RequestOptions;
|
10
|
+
|
11
|
+
/**
|
12
|
+
* Creates an instance of SystemApi
|
13
|
+
* @param options Request options
|
14
|
+
*/
|
15
|
+
constructor(options: RequestOptions) {
|
16
|
+
this.options = options;
|
17
|
+
}
|
18
|
+
|
19
|
+
/**
|
20
|
+
* Gets the current rate limit status
|
21
|
+
* @returns A promise resolving with the rate limit response
|
22
|
+
*/
|
23
|
+
async getRateLimits(): Promise<RateLimitResponse> {
|
24
|
+
return makeRequest<RateLimitResponse>(
|
25
|
+
'GET',
|
26
|
+
'/api/rate-limit',
|
27
|
+
this.options,
|
28
|
+
);
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Gets the rate limit status for a specific endpoint
|
33
|
+
* @param endpoint The endpoint to get rate limit for
|
34
|
+
* @returns A promise resolving with the endpoint rate limit response
|
35
|
+
*/
|
36
|
+
async getEndpointRateLimit(endpoint: string): Promise<EndpointRateLimitResponse> {
|
37
|
+
return makeRequest<EndpointRateLimitResponse>(
|
38
|
+
'GET',
|
39
|
+
`/api/rate-limit/${endpoint}`,
|
40
|
+
this.options,
|
41
|
+
);
|
42
|
+
}
|
43
|
+
|
44
|
+
/**
|
45
|
+
* Gets the health status of the API
|
46
|
+
* @returns A promise resolving with the health status
|
47
|
+
*/
|
48
|
+
async getHealthStatus(): Promise<{ status: string }> {
|
49
|
+
return makeRequest<{ status: string }>(
|
50
|
+
'GET',
|
51
|
+
'/health',
|
52
|
+
this.options,
|
53
|
+
);
|
54
|
+
}
|
55
|
+
}
|
package/src/core/client.ts
CHANGED
@@ -1,23 +1,19 @@
|
|
1
|
-
import type { NearAuthData
|
1
|
+
import type { NearAuthData } from 'near-sign-verify';
|
2
|
+
import { ActivityApi } from '../api/activity.ts';
|
2
3
|
import { AuthApi } from '../api/auth.ts';
|
3
4
|
import { PostApi } from '../api/post.ts';
|
5
|
+
import { SystemApi } from '../api/system.ts';
|
4
6
|
import { type CrosspostClientConfig, DEFAULT_CONFIG } from './config.ts';
|
5
7
|
import type { RequestOptions } from './request.ts';
|
6
|
-
import { getAuthFromCookie, storeAuthInCookie } from '../utils/cookie.ts';
|
7
8
|
|
8
9
|
/**
|
9
10
|
* Main client for interacting with the Crosspost API service.
|
10
11
|
*/
|
11
12
|
export class CrosspostClient {
|
12
|
-
/**
|
13
|
-
* Authentication-related API operations
|
14
|
-
*/
|
15
13
|
public readonly auth: AuthApi;
|
16
|
-
|
17
|
-
/**
|
18
|
-
* Post-related API operations
|
19
|
-
*/
|
20
14
|
public readonly post: PostApi;
|
15
|
+
public readonly activity: ActivityApi;
|
16
|
+
public readonly system: SystemApi;
|
21
17
|
|
22
18
|
private readonly options: RequestOptions;
|
23
19
|
|
@@ -30,29 +26,34 @@ export class CrosspostClient {
|
|
30
26
|
const timeout = config.timeout || DEFAULT_CONFIG.timeout;
|
31
27
|
const retries = config.retries ?? DEFAULT_CONFIG.retries;
|
32
28
|
|
33
|
-
|
34
|
-
const signature = config.signature || getAuthFromCookie();
|
29
|
+
const nearAuthData = config.nearAuthData;
|
35
30
|
|
36
31
|
this.options = {
|
37
32
|
baseUrl,
|
38
33
|
timeout,
|
39
34
|
retries,
|
40
|
-
|
35
|
+
nearAuthData,
|
41
36
|
};
|
42
37
|
|
43
38
|
this.auth = new AuthApi(this.options);
|
44
39
|
this.post = new PostApi(this.options);
|
40
|
+
this.activity = new ActivityApi(this.options);
|
41
|
+
this.system = new SystemApi(this.options);
|
45
42
|
}
|
46
43
|
|
47
44
|
/**
|
48
|
-
* Sets the authentication data (signature) for the client
|
49
|
-
* @param
|
45
|
+
* Sets the authentication data (signature) for the client
|
46
|
+
* @param nearAuthData The NEAR authentication data
|
50
47
|
*/
|
51
|
-
public
|
52
|
-
|
53
|
-
|
48
|
+
public setAuthentication(nearAuthData: NearAuthData): void {
|
49
|
+
this.options.nearAuthData = nearAuthData;
|
50
|
+
}
|
54
51
|
|
55
|
-
|
56
|
-
|
52
|
+
/**
|
53
|
+
* Checks if authentication data (signature) exists on client
|
54
|
+
* @param signature The NEAR authentication data
|
55
|
+
*/
|
56
|
+
public isAuthenticated(): boolean {
|
57
|
+
return !!this.options.nearAuthData;
|
57
58
|
}
|
58
59
|
}
|
package/src/core/config.ts
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
import type { NearAuthData
|
1
|
+
import type { NearAuthData } from 'near-sign-verify';
|
2
2
|
|
3
3
|
/**
|
4
4
|
* Configuration options for the CrosspostClient
|
@@ -6,13 +6,13 @@ import type { NearAuthData as NearSignatureData } from 'near-sign-verify';
|
|
6
6
|
export interface CrosspostClientConfig {
|
7
7
|
/**
|
8
8
|
* Base URL for the Crosspost API
|
9
|
-
* @default 'https://
|
9
|
+
* @default 'https://open-crosspost-proxy.deno.dev'
|
10
10
|
*/
|
11
11
|
baseUrl?: string;
|
12
12
|
/**
|
13
13
|
* NEAR authentication data obtained from near-sign-verify
|
14
14
|
*/
|
15
|
-
|
15
|
+
nearAuthData?: NearAuthData;
|
16
16
|
/**
|
17
17
|
* Request timeout in milliseconds
|
18
18
|
* @default 30000
|
@@ -28,7 +28,7 @@ export interface CrosspostClientConfig {
|
|
28
28
|
/**
|
29
29
|
* Default configuration values for the CrosspostClient
|
30
30
|
*/
|
31
|
-
export const DEFAULT_CONFIG: Required<Omit<CrosspostClientConfig, '
|
31
|
+
export const DEFAULT_CONFIG: Required<Omit<CrosspostClientConfig, 'nearAuthData'>> = {
|
32
32
|
baseUrl: 'https://open-crosspost-proxy.deno.dev/',
|
33
33
|
timeout: 30000,
|
34
34
|
retries: 2,
|
package/src/core/request.ts
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
import { ApiError, ApiErrorCode } from '@crosspost/types';
|
2
|
-
import { createAuthToken, type NearAuthData
|
3
|
-
import { createNetworkError, handleErrorResponse } from '../utils/error.ts';
|
4
|
-
import { CSRF_HEADER_NAME, getCsrfToken } from '../utils/cookie.ts';
|
2
|
+
import { createAuthToken, type NearAuthData } from 'near-sign-verify';
|
3
|
+
import { apiWrapper, createNetworkError, handleErrorResponse } from '../utils/error.ts';
|
5
4
|
|
6
5
|
/**
|
7
6
|
* Options for making a request to the API
|
@@ -15,7 +14,7 @@ export interface RequestOptions {
|
|
15
14
|
* NEAR authentication data for generating auth tokens
|
16
15
|
* Can be undefined if not authorize yet
|
17
16
|
*/
|
18
|
-
|
17
|
+
nearAuthData?: NearAuthData;
|
19
18
|
/**
|
20
19
|
* Request timeout in milliseconds
|
21
20
|
*/
|
@@ -40,119 +39,136 @@ export async function makeRequest<T>(
|
|
40
39
|
path: string,
|
41
40
|
options: RequestOptions,
|
42
41
|
data?: any,
|
42
|
+
query?: Record<string, any>,
|
43
43
|
): Promise<T> {
|
44
|
-
|
45
|
-
|
46
|
-
|
44
|
+
let url = `${options.baseUrl}${path.startsWith('/') ? path : `/${path}`}`;
|
45
|
+
|
46
|
+
// Add query parameters if provided
|
47
|
+
if (query && Object.keys(query).length > 0) {
|
48
|
+
const queryParams = new URLSearchParams();
|
49
|
+
for (const [key, value] of Object.entries(query)) {
|
50
|
+
if (value !== undefined && value !== null) {
|
51
|
+
queryParams.append(key, String(value));
|
52
|
+
}
|
53
|
+
}
|
54
|
+
const queryString = queryParams.toString();
|
55
|
+
if (queryString) {
|
56
|
+
url += `?${queryString}`;
|
57
|
+
}
|
58
|
+
}
|
47
59
|
// Check if authentication data is available
|
48
|
-
if (!options.
|
60
|
+
if (!options.nearAuthData) {
|
49
61
|
throw ApiError.unauthorized('Authentication required. Please provide NEAR signature.');
|
50
62
|
}
|
51
63
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
'Accept': 'application/json',
|
60
|
-
'Authorization': `Bearer ${createAuthToken(options.signature)}`,
|
61
|
-
};
|
62
|
-
|
63
|
-
// Add CSRF token for state-changing requests (non-GET)
|
64
|
-
if (method !== 'GET') {
|
65
|
-
const csrfToken = getCsrfToken();
|
66
|
-
if (csrfToken) {
|
67
|
-
headers[CSRF_HEADER_NAME] = csrfToken;
|
68
|
-
}
|
69
|
-
}
|
64
|
+
// Create a context object for error enrichment
|
65
|
+
const context = {
|
66
|
+
method,
|
67
|
+
path,
|
68
|
+
url,
|
69
|
+
retries: options.retries,
|
70
|
+
};
|
70
71
|
|
71
|
-
|
72
|
-
|
73
|
-
headers,
|
74
|
-
body: method !== 'GET' && data ? JSON.stringify(data) : undefined,
|
75
|
-
signal: controller.signal,
|
76
|
-
};
|
72
|
+
return apiWrapper(async () => {
|
73
|
+
let lastError: Error | null = null;
|
77
74
|
|
78
|
-
|
79
|
-
|
75
|
+
for (let attempt = 0; attempt <= options.retries; attempt++) {
|
76
|
+
const controller = new AbortController();
|
77
|
+
const timeoutId = setTimeout(() => controller.abort(), options.timeout);
|
80
78
|
|
81
|
-
let responseData: any;
|
82
79
|
try {
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
80
|
+
const headers: Record<string, string> = {
|
81
|
+
'Content-Type': 'application/json',
|
82
|
+
'Accept': 'application/json',
|
83
|
+
'Authorization': `Bearer ${createAuthToken(options.nearAuthData!)}`,
|
84
|
+
};
|
85
|
+
|
86
|
+
const requestOptions: RequestInit = {
|
87
|
+
method,
|
88
|
+
headers,
|
89
|
+
body: method !== 'GET' && data ? JSON.stringify(data) : undefined,
|
90
|
+
signal: controller.signal,
|
91
|
+
};
|
92
|
+
|
93
|
+
const response = await fetch(url, requestOptions);
|
94
|
+
clearTimeout(timeoutId); // Clear timeout if fetch completes
|
95
|
+
|
96
|
+
let responseData: any;
|
97
|
+
try {
|
98
|
+
responseData = await response.json();
|
99
|
+
} catch (jsonError) {
|
100
|
+
// If JSON parsing fails, throw a specific error or handle based on status
|
101
|
+
if (!response.ok) {
|
102
|
+
throw new ApiError(
|
103
|
+
`API request failed with status ${response.status} and non-JSON response`,
|
104
|
+
ApiErrorCode.NETWORK_ERROR,
|
105
|
+
response.status as any,
|
106
|
+
{ originalStatusText: response.statusText },
|
107
|
+
);
|
108
|
+
}
|
109
|
+
// If response was ok but JSON failed, maybe it was an empty 204 response?
|
110
|
+
if (response.status === 204) return {} as T; // Handle No Content
|
111
|
+
// Otherwise, throw a custom error
|
87
112
|
throw new ApiError(
|
88
|
-
`
|
89
|
-
|
113
|
+
`Failed to parse JSON response: ${
|
114
|
+
jsonError instanceof Error ? jsonError.message : String(jsonError)
|
115
|
+
}`,
|
116
|
+
ApiErrorCode.INTERNAL_ERROR,
|
90
117
|
response.status as any,
|
91
|
-
{ originalStatusText: response.statusText },
|
92
118
|
);
|
93
119
|
}
|
94
|
-
// If response was ok but JSON failed, maybe it was an empty 204 response?
|
95
|
-
if (response.status === 204) return {} as T; // Handle No Content
|
96
|
-
// Otherwise, rethrow JSON parse error or a custom error
|
97
|
-
throw new ApiError(
|
98
|
-
`Failed to parse JSON response: ${
|
99
|
-
jsonError instanceof Error ? jsonError.message : String(jsonError)
|
100
|
-
}`,
|
101
|
-
ApiErrorCode.INTERNAL_ERROR, // Or NETWORK_ERROR?
|
102
|
-
response.status as any,
|
103
|
-
);
|
104
|
-
}
|
105
120
|
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
121
|
+
if (!response.ok) {
|
122
|
+
lastError = handleErrorResponse(responseData, response.status);
|
123
|
+
// Retry only on 5xx errors or potentially recoverable errors if defined
|
124
|
+
const shouldRetry = response.status >= 500 ||
|
125
|
+
(lastError instanceof ApiError && lastError.recoverable);
|
126
|
+
if (shouldRetry && attempt < options.retries) {
|
127
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
|
128
|
+
continue; // Retry
|
129
|
+
}
|
130
|
+
throw lastError; // Throw error if not retrying or retries exhausted
|
114
131
|
}
|
115
|
-
throw lastError; // Throw error if not retrying or retries exhausted
|
116
|
-
}
|
117
132
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
133
|
+
// Handle cases where API indicates failure within a 2xx response
|
134
|
+
if (
|
135
|
+
responseData && typeof responseData === 'object' && 'success' in responseData &&
|
136
|
+
!responseData.success && responseData.error
|
137
|
+
) {
|
138
|
+
lastError = handleErrorResponse(responseData, response.status);
|
139
|
+
// Decide if this specific type of "successful" response with an error payload should be retried
|
140
|
+
const shouldRetry = lastError instanceof ApiError && lastError.recoverable;
|
141
|
+
if (shouldRetry && attempt < options.retries) {
|
142
|
+
await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
|
143
|
+
continue; // Retry
|
144
|
+
}
|
145
|
+
throw lastError;
|
146
|
+
}
|
147
|
+
|
148
|
+
return responseData as T;
|
149
|
+
} catch (error) {
|
150
|
+
clearTimeout(timeoutId); // Clear timeout on error
|
151
|
+
lastError = error instanceof Error ? error : new Error(String(error)); // Store the error
|
152
|
+
|
153
|
+
// Handle fetch/network errors specifically for retries
|
154
|
+
const isNetworkError = error instanceof TypeError ||
|
155
|
+
(error instanceof DOMException && error.name === 'AbortError');
|
156
|
+
if (isNetworkError && attempt < options.retries) {
|
127
157
|
await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
|
128
|
-
continue; // Retry
|
158
|
+
continue; // Retry network error
|
129
159
|
}
|
130
|
-
throw lastError;
|
131
|
-
}
|
132
160
|
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
// Handle fetch/network errors specifically for retries
|
139
|
-
const isNetworkError = error instanceof TypeError ||
|
140
|
-
(error instanceof DOMException && error.name === 'AbortError');
|
141
|
-
if (isNetworkError && attempt < options.retries) {
|
142
|
-
await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
|
143
|
-
continue; // Retry network error
|
144
|
-
}
|
161
|
+
// If it's not a known ApiError/PlatformError, wrap it
|
162
|
+
if (!(error instanceof ApiError)) {
|
163
|
+
throw createNetworkError(error, url, options.timeout);
|
164
|
+
}
|
145
165
|
|
146
|
-
|
147
|
-
if (!(error instanceof ApiError)) {
|
148
|
-
throw createNetworkError(error, url, options.timeout);
|
166
|
+
throw error; // Re-throw known ApiError or final network error
|
149
167
|
}
|
150
|
-
|
151
|
-
throw error; // Re-throw known ApiError or final network error
|
152
168
|
}
|
153
|
-
}
|
154
169
|
|
155
|
-
|
156
|
-
|
157
|
-
|
170
|
+
// Should not be reachable if retries >= 0, but needed for type safety
|
171
|
+
throw lastError ||
|
172
|
+
new ApiError('Request failed after multiple retries', ApiErrorCode.INTERNAL_ERROR, 500);
|
173
|
+
}, context);
|
158
174
|
}
|
package/src/index.ts
CHANGED
@@ -4,25 +4,35 @@
|
|
4
4
|
*/
|
5
5
|
|
6
6
|
// Export main client
|
7
|
-
export { CrosspostClient } from './core/client.
|
8
|
-
export { CrosspostClientConfig } from './core/config.
|
7
|
+
export { CrosspostClient } from './core/client.ts';
|
8
|
+
export type { CrosspostClientConfig } from './core/config.ts';
|
9
9
|
|
10
10
|
// Export API modules for advanced usage
|
11
|
-
export {
|
12
|
-
export {
|
11
|
+
export { ActivityApi } from './api/activity.ts';
|
12
|
+
export { AuthApi } from './api/auth.ts';
|
13
|
+
export { PostApi } from './api/post.ts';
|
14
|
+
export { SystemApi } from './api/system.ts';
|
13
15
|
|
14
16
|
// Export utility functions
|
15
|
-
export { createNetworkError, handleErrorResponse } from './utils/error.js';
|
16
17
|
export {
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
18
|
+
apiWrapper,
|
19
|
+
createNetworkError,
|
20
|
+
enrichErrorWithContext,
|
21
|
+
ERROR_CATEGORIES,
|
22
|
+
getErrorDetails,
|
23
|
+
getErrorMessage,
|
24
|
+
handleErrorResponse,
|
25
|
+
isAuthError,
|
26
|
+
isContentError,
|
27
|
+
isErrorOfCategory,
|
28
|
+
isMediaError,
|
29
|
+
isNetworkError,
|
30
|
+
isPlatformError,
|
31
|
+
isPostError,
|
32
|
+
isRateLimitError,
|
33
|
+
isRecoverableError,
|
34
|
+
isValidationError,
|
35
|
+
} from './utils/error.ts';
|
26
36
|
|
27
37
|
// Re-export types from @crosspost/types for convenience
|
28
38
|
export * from '@crosspost/types';
|