@crosspost/sdk 0.1.5 → 0.1.7

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@crosspost/sdk",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "SDK for interacting with the Crosspost API",
5
5
  "type": "module",
6
6
  "main": "dist/index.cjs",
package/src/api/auth.ts CHANGED
@@ -1,8 +1,8 @@
1
1
  import type {
2
+ ApiResponse,
2
3
  AuthRevokeResponse,
3
4
  AuthStatusResponse,
4
5
  ConnectedAccountsResponse,
5
- EnhancedApiResponse,
6
6
  NearAuthorizationResponse,
7
7
  Platform,
8
8
  } from '@crosspost/types';
@@ -57,8 +57,8 @@ export class AuthApi {
57
57
  async loginToPlatform(
58
58
  platform: Platform,
59
59
  options?: { successUrl?: string; errorUrl?: string },
60
- ): Promise<EnhancedApiResponse<any>> { // TODO: Refine response type based on actual API
61
- return makeRequest<EnhancedApiResponse<any>>(
60
+ ): Promise<ApiResponse<any>> { // TODO: Refine response type based on actual API
61
+ return makeRequest<ApiResponse<any>>(
62
62
  'POST',
63
63
  `/auth/${platform}/login`,
64
64
  this.options,
@@ -71,8 +71,8 @@ export class AuthApi {
71
71
  * @param platform The target platform.
72
72
  * @returns A promise resolving with the refresh response.
73
73
  */
74
- async refreshToken(platform: Platform): Promise<EnhancedApiResponse<any>> { // TODO: Refine response type
75
- return makeRequest<EnhancedApiResponse<any>>(
74
+ async refreshToken(platform: Platform): Promise<ApiResponse<any>> { // TODO: Refine response type
75
+ return makeRequest<ApiResponse<any>>(
76
76
  'POST',
77
77
  `/auth/${platform}/refresh`,
78
78
  this.options,
@@ -84,8 +84,8 @@ export class AuthApi {
84
84
  * @param platform The target platform.
85
85
  * @returns A promise resolving with the profile refresh response.
86
86
  */
87
- async refreshProfile(platform: Platform): Promise<EnhancedApiResponse<any>> { // TODO: Refine response type
88
- return makeRequest<EnhancedApiResponse<any>>(
87
+ async refreshProfile(platform: Platform): Promise<ApiResponse<any>> { // TODO: Refine response type
88
+ return makeRequest<ApiResponse<any>>(
89
89
  'POST',
90
90
  `/auth/${platform}/refresh-profile`,
91
91
  this.options,
package/src/api/post.ts CHANGED
@@ -14,7 +14,6 @@ import type {
14
14
  UnlikePostRequest,
15
15
  UnlikePostResponse,
16
16
  } from '@crosspost/types';
17
- import { ApiError, ApiErrorCode } from '@crosspost/types';
18
17
  import { makeRequest, type RequestOptions } from '../core/request.ts';
19
18
 
20
19
  /**
@@ -93,10 +92,9 @@ export class PostApi {
93
92
  * @returns A promise resolving with the like response.
94
93
  */
95
94
  async likePost(request: LikePostRequest): Promise<LikePostResponse> {
96
- // API endpoint uses postId in the path
97
95
  return makeRequest<LikePostResponse>(
98
96
  'POST',
99
- `/api/post/like/${request.postId}`,
97
+ `/api/post/like`,
100
98
  this.options,
101
99
  request,
102
100
  );
@@ -108,10 +106,9 @@ export class PostApi {
108
106
  * @returns A promise resolving with the unlike response.
109
107
  */
110
108
  async unlikePost(request: UnlikePostRequest): Promise<UnlikePostResponse> {
111
- // API endpoint uses postId in the path
112
109
  return makeRequest<UnlikePostResponse>(
113
110
  'DELETE',
114
- `/api/post/like/${request.postId}`,
111
+ `/api/post/like`,
115
112
  this.options,
116
113
  request,
117
114
  );
@@ -123,18 +120,9 @@ export class PostApi {
123
120
  * @returns A promise resolving with the delete response.
124
121
  */
125
122
  async deletePost(request: DeletePostRequest): Promise<DeletePostResponse> {
126
- // API endpoint uses postId in the path, assuming the first post ID for the URL
127
- const postId = request.posts[0]?.postId || '';
128
- if (!postId) {
129
- throw new ApiError(
130
- 'Post ID is required for deletion path',
131
- ApiErrorCode.VALIDATION_ERROR,
132
- 400,
133
- );
134
- }
135
123
  return makeRequest<DeletePostResponse>(
136
124
  'DELETE',
137
- `/api/post/${postId}`,
125
+ `/api/post`,
138
126
  this.options,
139
127
  request,
140
128
  );
package/src/api/system.ts CHANGED
@@ -1,4 +1,4 @@
1
- import type { EndpointRateLimitResponse, RateLimitResponse } from '@crosspost/types';
1
+ import type { ApiResponse, EndpointRateLimitResponse, RateLimitResponse } from '@crosspost/types';
2
2
  import { makeRequest, type RequestOptions } from '../core/request.ts';
3
3
 
4
4
  /**
@@ -45,8 +45,8 @@ export class SystemApi {
45
45
  * Gets the health status of the API
46
46
  * @returns A promise resolving with the health status
47
47
  */
48
- async getHealthStatus(): Promise<{ status: string }> {
49
- return makeRequest<{ status: string }>(
48
+ async getHealthStatus(): Promise<ApiResponse<{ status: string }>> {
49
+ return makeRequest<ApiResponse<{ status: string }>>(
50
50
  'GET',
51
51
  '/health',
52
52
  this.options,
@@ -1,6 +1,11 @@
1
- import { ApiError, ApiErrorCode } from '@crosspost/types';
1
+ import { ApiErrorCode, type StatusCode } from '@crosspost/types';
2
2
  import { createAuthToken, type NearAuthData } from 'near-sign-verify';
3
- import { apiWrapper, createNetworkError, handleErrorResponse } from '../utils/error.ts';
3
+ import {
4
+ apiWrapper,
5
+ createNetworkError,
6
+ CrosspostError,
7
+ handleErrorResponse,
8
+ } from '../utils/error.ts';
4
9
 
5
10
  /**
6
11
  * Options for making a request to the API
@@ -56,10 +61,6 @@ export async function makeRequest<T>(
56
61
  url += `?${queryString}`;
57
62
  }
58
63
  }
59
- // Check if authentication data is available
60
- if (!options.nearAuthData) {
61
- throw ApiError.unauthorized('Authentication required. Please provide NEAR signature.');
62
- }
63
64
 
64
65
  // Create a context object for error enrichment
65
66
  const context = {
@@ -97,32 +98,30 @@ export async function makeRequest<T>(
97
98
  try {
98
99
  responseData = await response.json();
99
100
  } catch (jsonError) {
100
- // If JSON parsing fails, throw a specific error or handle based on status
101
+ // If JSON parsing fails, did API throw an error?
101
102
  if (!response.ok) {
102
- throw new ApiError(
103
+ throw new CrosspostError(
103
104
  `API request failed with status ${response.status} and non-JSON response`,
104
105
  ApiErrorCode.NETWORK_ERROR,
105
- response.status as any,
106
+ response.status as StatusCode,
106
107
  { originalStatusText: response.statusText },
107
108
  );
108
109
  }
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
110
  // Otherwise, throw a custom error
112
- throw new ApiError(
111
+ throw new CrosspostError(
113
112
  `Failed to parse JSON response: ${
114
113
  jsonError instanceof Error ? jsonError.message : String(jsonError)
115
114
  }`,
116
115
  ApiErrorCode.INTERNAL_ERROR,
117
- response.status as any,
116
+ response.status as StatusCode,
118
117
  );
119
118
  }
120
119
 
121
120
  if (!response.ok) {
122
121
  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);
122
+ // Only retry rate limit errors
123
+ const shouldRetry = lastError instanceof CrosspostError &&
124
+ lastError.code === ApiErrorCode.RATE_LIMITED;
126
125
  if (shouldRetry && attempt < options.retries) {
127
126
  await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
128
127
  continue; // Retry
@@ -130,22 +129,24 @@ export async function makeRequest<T>(
130
129
  throw lastError; // Throw error if not retrying or retries exhausted
131
130
  }
132
131
 
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
132
+ // Handle response based on success flag
133
+ if (responseData && typeof responseData === 'object' && 'success' in responseData) {
134
+ if (responseData.success) {
135
+ // Success response - return the data
136
+ return responseData.data as T;
137
+ } else {
138
+ // Error response - handle with our error utilities
139
+ lastError = handleErrorResponse(responseData, response.status);
140
+ // Only retry rate limit errors
141
+ const shouldRetry = lastError instanceof CrosspostError &&
142
+ lastError.code === ApiErrorCode.RATE_LIMITED;
143
+ if (shouldRetry && attempt < options.retries) {
144
+ await new Promise((resolve) => setTimeout(resolve, 1000 * Math.pow(2, attempt))); // Exponential backoff
145
+ continue; // Retry
146
+ }
147
+ throw lastError;
144
148
  }
145
- throw lastError;
146
149
  }
147
-
148
- return responseData as T;
149
150
  } catch (error) {
150
151
  clearTimeout(timeoutId); // Clear timeout on error
151
152
  lastError = error instanceof Error ? error : new Error(String(error)); // Store the error
@@ -159,7 +160,7 @@ export async function makeRequest<T>(
159
160
  }
160
161
 
161
162
  // If it's not a known ApiError/PlatformError, wrap it
162
- if (!(error instanceof ApiError)) {
163
+ if (!(error instanceof CrosspostError)) {
163
164
  throw createNetworkError(error, url, options.timeout);
164
165
  }
165
166
 
@@ -169,6 +170,6 @@ export async function makeRequest<T>(
169
170
 
170
171
  // Should not be reachable if retries >= 0, but needed for type safety
171
172
  throw lastError ||
172
- new ApiError('Request failed after multiple retries', ApiErrorCode.INTERNAL_ERROR, 500);
173
+ new CrosspostError('Request failed after multiple retries', ApiErrorCode.INTERNAL_ERROR, 500);
173
174
  }, context);
174
175
  }
package/src/index.ts CHANGED
@@ -1,30 +1,20 @@
1
- /**
2
- * @crosspost/sdk
3
- * SDK for interacting with the Crosspost API
4
- */
5
-
6
- // Export main client
7
1
  export { CrosspostClient } from './core/client.ts';
8
2
  export type { CrosspostClientConfig } from './core/config.ts';
9
3
 
10
- // Export API modules for advanced usage
11
4
  export { ActivityApi } from './api/activity.ts';
12
5
  export { AuthApi } from './api/auth.ts';
13
6
  export { PostApi } from './api/post.ts';
14
7
  export { SystemApi } from './api/system.ts';
15
8
 
16
- // Export utility functions
17
9
  export {
18
10
  apiWrapper,
19
11
  createNetworkError,
20
12
  enrichErrorWithContext,
21
- ERROR_CATEGORIES,
22
13
  getErrorDetails,
23
14
  getErrorMessage,
24
15
  handleErrorResponse,
25
16
  isAuthError,
26
17
  isContentError,
27
- isErrorOfCategory,
28
18
  isMediaError,
29
19
  isNetworkError,
30
20
  isPlatformError,