@crosspost/sdk 0.1.2
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 +274 -0
- package/dist/index.cjs +5485 -0
- package/dist/index.d.cts +236 -0
- package/dist/index.d.ts +236 -0
- package/dist/index.js +5350 -0
- package/mod.ts +9 -0
- package/package.json +53 -0
- package/src/api/auth.ts +132 -0
- package/src/api/post.ts +142 -0
- package/src/core/client.ts +58 -0
- package/src/core/config.ts +35 -0
- package/src/core/request.ts +158 -0
- package/src/index.ts +28 -0
- package/src/utils/cookie.ts +75 -0
- package/src/utils/error.ts +77 -0
package/README.md
ADDED
@@ -0,0 +1,274 @@
|
|
1
|
+
# @crosspost/sdk
|
2
|
+
|
3
|
+
SDK for interacting with the Crosspost API.
|
4
|
+
|
5
|
+
## Overview
|
6
|
+
|
7
|
+
This package provides a client for interacting with the Crosspost API, allowing you to easily
|
8
|
+
integrate social media posting capabilities into your applications. The SDK is designed to be
|
9
|
+
flexible and easy to use, with support for multiple authentication methods and platforms.
|
10
|
+
|
11
|
+
## Features
|
12
|
+
|
13
|
+
- Unified client for all supported platforms
|
14
|
+
- Flexible authentication:
|
15
|
+
- Direct `nearAuthData` injection
|
16
|
+
- Automatic cookie-based authentication (`__crosspost_auth`)
|
17
|
+
- Explicit authentication via `setAuthentication` method
|
18
|
+
- Platform-specific clients (Twitter, with more to come)
|
19
|
+
- Type-safe request/response handling using `@crosspost/types`
|
20
|
+
- Comprehensive error handling with specific `ApiError` and `PlatformError` types
|
21
|
+
- CSRF protection via Double Submit Cookie pattern
|
22
|
+
|
23
|
+
## Installation
|
24
|
+
|
25
|
+
```bash
|
26
|
+
bun install @crosspost/sdk
|
27
|
+
```
|
28
|
+
|
29
|
+
## Usage
|
30
|
+
|
31
|
+
### Initializing the SDK
|
32
|
+
|
33
|
+
The SDK can be initialized in several ways depending on how you manage authentication:
|
34
|
+
|
35
|
+
**1. Cookie-Based Authentication (Recommended for Browsers)**
|
36
|
+
|
37
|
+
If the user has previously authenticated via the API, the SDK can automatically use the
|
38
|
+
authentication data stored in the `__crosspost_auth` cookie.
|
39
|
+
|
40
|
+
```typescript
|
41
|
+
import { CrosspostClient } from '@crosspost/sdk';
|
42
|
+
|
43
|
+
// Client will automatically try to load auth from the cookie
|
44
|
+
const client = new CrosspostClient({
|
45
|
+
baseUrl: 'https://your-crosspost-api.com', // Optional: Defaults to official API
|
46
|
+
});
|
47
|
+
|
48
|
+
// If the cookie exists and is valid, requests will be authenticated.
|
49
|
+
// If not, authenticated requests will throw an ApiError.
|
50
|
+
```
|
51
|
+
|
52
|
+
The cookie is stored with secure attributes:
|
53
|
+
|
54
|
+
- `secure: true` - Only sent over HTTPS
|
55
|
+
- `sameSite: 'lax'` - Provides CSRF protection while allowing top-level navigation
|
56
|
+
- `path: '/'` - Available across the entire domain
|
57
|
+
- `expires: 30 days` - Persists for 30 days
|
58
|
+
|
59
|
+
**2. Direct Authentication**
|
60
|
+
|
61
|
+
Provide the `nearAuthData` object directly if you have obtained it through other means (e.g.,
|
62
|
+
server-side flow, manual signing).
|
63
|
+
|
64
|
+
```typescript
|
65
|
+
import { CrosspostClient } from '@crosspost/sdk';
|
66
|
+
import type { NearAuthData } from 'near-sign-verify'; // Assuming this type exists
|
67
|
+
|
68
|
+
const nearAuthData: NearAuthData = {
|
69
|
+
account_id: 'example.near',
|
70
|
+
public_key: 'ed25519:...',
|
71
|
+
signature: '...',
|
72
|
+
message: '...',
|
73
|
+
nonce: '...',
|
74
|
+
recipient: 'crosspost-api.near',
|
75
|
+
// callback_url and state are optional
|
76
|
+
};
|
77
|
+
|
78
|
+
const client = new CrosspostClient({
|
79
|
+
baseUrl: 'https://your-crosspost-api.com',
|
80
|
+
nearAuthData: nearAuthData,
|
81
|
+
});
|
82
|
+
```
|
83
|
+
|
84
|
+
**3. Explicit Authentication**
|
85
|
+
|
86
|
+
Initialize the client without authentication and set it later, for example, after a user logs in via
|
87
|
+
a NEAR wallet connection. This method also stores the authentication data in the `__crosspost_auth`
|
88
|
+
cookie for future use.
|
89
|
+
|
90
|
+
```typescript
|
91
|
+
import { CrosspostClient } from '@crosspost/sdk';
|
92
|
+
import type { NearAuthData } from 'near-sign-verify';
|
93
|
+
|
94
|
+
const client = new CrosspostClient({
|
95
|
+
baseUrl: 'https://your-crosspost-api.com',
|
96
|
+
});
|
97
|
+
|
98
|
+
// Later, after obtaining the signature...
|
99
|
+
async function handleAuthentication(nearAuthData: NearAuthData) {
|
100
|
+
try {
|
101
|
+
// This sets the auth data in the client and stores it in the cookie
|
102
|
+
await client.setAuthentication(nearAuthData);
|
103
|
+
console.log('Authentication successful and stored.');
|
104
|
+
// Client is now ready for authenticated requests
|
105
|
+
} catch (error) {
|
106
|
+
console.error('Authentication failed:', error);
|
107
|
+
}
|
108
|
+
}
|
109
|
+
```
|
110
|
+
|
111
|
+
### Making Authenticated Requests (Example: Twitter Client)
|
112
|
+
|
113
|
+
```typescript
|
114
|
+
// Create a post
|
115
|
+
const createPostResponse = await client.twitter.createPost({
|
116
|
+
content: {
|
117
|
+
text: 'Hello from Crosspost SDK!',
|
118
|
+
},
|
119
|
+
});
|
120
|
+
|
121
|
+
console.log(`Post created with ID: ${createPostResponse.id}`);
|
122
|
+
|
123
|
+
// Create a post with media
|
124
|
+
const createPostWithMediaResponse = await client.twitter.createPost({
|
125
|
+
content: {
|
126
|
+
text: 'Check out this image!',
|
127
|
+
media: [
|
128
|
+
{
|
129
|
+
type: 'image',
|
130
|
+
url: 'https://example.com/image.jpg',
|
131
|
+
},
|
132
|
+
],
|
133
|
+
},
|
134
|
+
});
|
135
|
+
|
136
|
+
// Like a post
|
137
|
+
await client.twitter.likePost({
|
138
|
+
postId: '1234567890',
|
139
|
+
});
|
140
|
+
|
141
|
+
// Repost a post
|
142
|
+
await client.twitter.repost({
|
143
|
+
postId: '1234567890',
|
144
|
+
});
|
145
|
+
|
146
|
+
// Reply to a post
|
147
|
+
await client.twitter.reply({
|
148
|
+
postId: '1234567890',
|
149
|
+
content: {
|
150
|
+
text: 'This is a reply!',
|
151
|
+
},
|
152
|
+
});
|
153
|
+
|
154
|
+
// Delete a post
|
155
|
+
await client.twitter.deletePost({
|
156
|
+
postId: '1234567890',
|
157
|
+
});
|
158
|
+
```
|
159
|
+
|
160
|
+
### Error Handling
|
161
|
+
|
162
|
+
```typescript
|
163
|
+
import { ApiError, ApiErrorCode, CrosspostClient, PlatformError } from '@crosspost/sdk';
|
164
|
+
|
165
|
+
try {
|
166
|
+
// Ensure client is authenticated (either via cookie or direct data)
|
167
|
+
const response = await client.post.createPost({ // Assuming a generic post API exists
|
168
|
+
targets: [{ platform: 'twitter', userId: 'twitter_user_id' }], // Example target
|
169
|
+
content: {
|
170
|
+
text: 'Hello from Crosspost SDK!',
|
171
|
+
},
|
172
|
+
});
|
173
|
+
|
174
|
+
console.log(`Post created with ID: ${response.id}`);
|
175
|
+
} catch (error) {
|
176
|
+
if (error instanceof ApiError) {
|
177
|
+
// Handle authentication errors
|
178
|
+
if (error.code === ApiErrorCode.UNAUTHORIZED) {
|
179
|
+
console.error('Authentication required. Please sign in with your NEAR wallet.');
|
180
|
+
// Redirect to authentication flow or show login UI
|
181
|
+
} else {
|
182
|
+
console.error(`API Error: ${error.message}`);
|
183
|
+
console.error(`Error Code: ${error.code}`); // e.g., RATE_LIMITED
|
184
|
+
console.error(`Status: ${error.status}`); // HTTP status code
|
185
|
+
console.error(`Details:`, error.details); // Additional context
|
186
|
+
console.error(`Recoverable: ${error.recoverable}`);
|
187
|
+
}
|
188
|
+
} else if (error instanceof PlatformError) {
|
189
|
+
// Handle errors specific to a platform (e.g., Twitter API error)
|
190
|
+
console.error(`Platform Error (${error.platform}): ${error.message}`);
|
191
|
+
console.error(`Original Error:`, error.originalError);
|
192
|
+
} else {
|
193
|
+
console.error(`Unexpected error:`, error);
|
194
|
+
}
|
195
|
+
}
|
196
|
+
```
|
197
|
+
|
198
|
+
## API Reference
|
199
|
+
|
200
|
+
### `CrosspostClient`
|
201
|
+
|
202
|
+
The main client for interacting with the Crosspost API.
|
203
|
+
|
204
|
+
#### Constructor
|
205
|
+
|
206
|
+
```typescript
|
207
|
+
constructor(config?: CrosspostClientConfig)
|
208
|
+
```
|
209
|
+
|
210
|
+
`CrosspostClientConfig` Options:
|
211
|
+
|
212
|
+
- `baseUrl?: string`: Base URL of the Crosspost API. Defaults to the official endpoint.
|
213
|
+
- `nearAuthData?: NearAuthData`: NEAR authentication data object. If not provided, the client
|
214
|
+
attempts to load from the `__crosspost_auth` cookie.
|
215
|
+
- `timeout?: number`: Request timeout in milliseconds (default: 30000).
|
216
|
+
- `retries?: number`: Number of retries for failed requests (network/5xx errors) (default: 2).
|
217
|
+
|
218
|
+
#### Methods
|
219
|
+
|
220
|
+
- `setAuthentication(nearAuthData: NearAuthData): Promise<void>`: Sets the provided `NearAuthData`
|
221
|
+
in the client and stores it in the `__crosspost_auth` cookie for future use.
|
222
|
+
|
223
|
+
#### Properties
|
224
|
+
|
225
|
+
- `auth`: Instance of `AuthApi` for authentication-related operations.
|
226
|
+
- `post`: Instance of `PostApi` for post-related operations.
|
227
|
+
|
228
|
+
### API Modules
|
229
|
+
|
230
|
+
#### `AuthApi` (`client.auth`)
|
231
|
+
|
232
|
+
- `authorizeNearAccount(): Promise<NearAuthorizationResponse>`: Authorizes the current NEAR account
|
233
|
+
(requires `nearAuthData` to be set).
|
234
|
+
- `getNearAuthorizationStatus(): Promise<NearAuthorizationResponse>`: Checks if the current NEAR
|
235
|
+
account is authorized.
|
236
|
+
- `loginToPlatform(platform, options?): Promise<EnhancedApiResponse<any>>`: Initiates the OAuth
|
237
|
+
login flow for a platform.
|
238
|
+
- `refreshToken(platform): Promise<EnhancedApiResponse<any>>`: Refreshes the platform token.
|
239
|
+
- `refreshProfile(platform): Promise<EnhancedApiResponse<any>>`: Refreshes the user's profile from
|
240
|
+
the platform.
|
241
|
+
- `getAuthStatus(platform): Promise<AuthStatusResponse>`: Gets the authentication status for a
|
242
|
+
specific platform.
|
243
|
+
- `revokeAuth(platform): Promise<AuthRevokeResponse>`: Revokes access for a specific platform.
|
244
|
+
- `getConnectedAccounts(): Promise<ConnectedAccountsResponse>`: Lists all platform accounts
|
245
|
+
connected to the NEAR account.
|
246
|
+
|
247
|
+
#### `PostApi` (`client.post`)
|
248
|
+
|
249
|
+
- `createPost(request: CreatePostRequest): Promise<CreatePostResponse>`: Creates a new post.
|
250
|
+
- `repost(request: RepostRequest): Promise<RepostResponse>`: Reposts an existing post.
|
251
|
+
- `quotePost(request: QuotePostRequest): Promise<QuotePostResponse>`: Quotes an existing post.
|
252
|
+
- `replyToPost(request: ReplyToPostRequest): Promise<ReplyToPostResponse>`: Replies to an existing
|
253
|
+
post.
|
254
|
+
- `likePost(request: LikePostRequest): Promise<LikePostResponse>`: Likes a post.
|
255
|
+
- `unlikePost(request: UnlikePostRequest): Promise<UnlikePostResponse>`: Unlikes a post.
|
256
|
+
- `deletePost(request: DeletePostRequest): Promise<DeletePostResponse>`: Deletes one or more posts.
|
257
|
+
|
258
|
+
### CSRF Protection
|
259
|
+
|
260
|
+
The SDK supports the Double Submit Cookie pattern for CSRF protection:
|
261
|
+
|
262
|
+
1. The backend API sets a CSRF token in a non-HttpOnly cookie named `XSRF-TOKEN`
|
263
|
+
2. The SDK automatically reads this token and includes it in the `X-CSRF-Token` header for all
|
264
|
+
state-changing requests (non-GET)
|
265
|
+
3. The backend API validates that the token in the header matches the token in the cookie
|
266
|
+
|
267
|
+
This protection is automatically enabled when the backend API is configured to use CSRF tokens.
|
268
|
+
|
269
|
+
_(Note: Specific platform clients like `client.twitter` might be deprecated in favor of using the
|
270
|
+
generic `client.post` API with platform targets specified in the request body.)_
|
271
|
+
|
272
|
+
## License
|
273
|
+
|
274
|
+
MIT
|