@happyvertical/social 0.74.8
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/AGENT.md +33 -0
- package/LICENSE +7 -0
- package/README.md +485 -0
- package/dist/index.d.ts +1114 -0
- package/dist/index.js +2695 -0
- package/dist/index.js.map +1 -0
- package/metadata.json +29 -0
- package/package.json +55 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,1114 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth authorization options
|
|
3
|
+
*/
|
|
4
|
+
export declare interface AuthorizationOptions {
|
|
5
|
+
/**
|
|
6
|
+
* OAuth scopes to request
|
|
7
|
+
*/
|
|
8
|
+
scopes?: string[];
|
|
9
|
+
/**
|
|
10
|
+
* State parameter for CSRF protection
|
|
11
|
+
*/
|
|
12
|
+
state?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Code verifier for PKCE
|
|
15
|
+
*/
|
|
16
|
+
codeVerifier?: string;
|
|
17
|
+
/**
|
|
18
|
+
* Redirect URI
|
|
19
|
+
*/
|
|
20
|
+
redirectUri?: string;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* OAuth authorization result
|
|
25
|
+
*/
|
|
26
|
+
export declare interface AuthorizationResult {
|
|
27
|
+
/**
|
|
28
|
+
* Authorization URL to redirect user to
|
|
29
|
+
*/
|
|
30
|
+
url: string;
|
|
31
|
+
/**
|
|
32
|
+
* State parameter (for verification)
|
|
33
|
+
*/
|
|
34
|
+
state: string;
|
|
35
|
+
/**
|
|
36
|
+
* Code verifier (for PKCE, store securely)
|
|
37
|
+
*/
|
|
38
|
+
codeVerifier?: string;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Authentication result
|
|
43
|
+
*/
|
|
44
|
+
export declare interface AuthResult {
|
|
45
|
+
/**
|
|
46
|
+
* Access token
|
|
47
|
+
*/
|
|
48
|
+
accessToken: string;
|
|
49
|
+
/**
|
|
50
|
+
* Refresh token (if available)
|
|
51
|
+
*/
|
|
52
|
+
refreshToken?: string;
|
|
53
|
+
/**
|
|
54
|
+
* Token expiration time
|
|
55
|
+
*/
|
|
56
|
+
expiresAt?: Date;
|
|
57
|
+
/**
|
|
58
|
+
* Token type (usually 'Bearer')
|
|
59
|
+
*/
|
|
60
|
+
tokenType?: string;
|
|
61
|
+
/**
|
|
62
|
+
* Granted scopes
|
|
63
|
+
*/
|
|
64
|
+
scopes?: string[];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* Base configuration for social platform adapters
|
|
69
|
+
*/
|
|
70
|
+
export declare interface BaseSocialConfig {
|
|
71
|
+
/**
|
|
72
|
+
* Platform type
|
|
73
|
+
*/
|
|
74
|
+
type: SocialPlatformType;
|
|
75
|
+
/**
|
|
76
|
+
* Rate limiting configuration (applies at SDK level)
|
|
77
|
+
*/
|
|
78
|
+
rateLimit?: {
|
|
79
|
+
/**
|
|
80
|
+
* Maximum requests per minute
|
|
81
|
+
*/
|
|
82
|
+
requestsPerMinute?: number;
|
|
83
|
+
/**
|
|
84
|
+
* Maximum concurrent requests
|
|
85
|
+
*/
|
|
86
|
+
maxConcurrent?: number;
|
|
87
|
+
};
|
|
88
|
+
/**
|
|
89
|
+
* Request timeout in milliseconds
|
|
90
|
+
* @default 30000
|
|
91
|
+
*/
|
|
92
|
+
timeout?: number;
|
|
93
|
+
/**
|
|
94
|
+
* Controls whether publish calls create public content.
|
|
95
|
+
* Defaults to public for backward compatibility.
|
|
96
|
+
*/
|
|
97
|
+
publishMode?: PublishMode;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Bluesky adapter for publishing via AT Protocol
|
|
102
|
+
*
|
|
103
|
+
* @example
|
|
104
|
+
* ```typescript
|
|
105
|
+
* const bluesky = new BlueskyAdapter({
|
|
106
|
+
* type: 'bluesky',
|
|
107
|
+
* identifier: 'myhandle.bsky.social',
|
|
108
|
+
* password: 'app-password', // Use app password, not main password
|
|
109
|
+
* });
|
|
110
|
+
*
|
|
111
|
+
* await bluesky.authenticate();
|
|
112
|
+
*
|
|
113
|
+
* const result = await bluesky.publishText({
|
|
114
|
+
* text: 'Breaking news from Bentley!',
|
|
115
|
+
* linkUrl: 'https://example.com/article',
|
|
116
|
+
* });
|
|
117
|
+
* ```
|
|
118
|
+
*/
|
|
119
|
+
export declare class BlueskyAdapter implements SocialPlatform {
|
|
120
|
+
readonly platform: "bluesky";
|
|
121
|
+
private config;
|
|
122
|
+
private session?;
|
|
123
|
+
constructor(config: BlueskyConfig);
|
|
124
|
+
private get pdsUrl();
|
|
125
|
+
authenticate(): Promise<AuthResult>;
|
|
126
|
+
refreshToken(refreshJwt: string): Promise<AuthResult>;
|
|
127
|
+
publishVideo(_video: VideoPost): Promise<PostResult>;
|
|
128
|
+
publishImage(image: ImagePost): Promise<PostResult>;
|
|
129
|
+
publishText(text: TextPost): Promise<PostResult>;
|
|
130
|
+
publishLink(link: LinkPost): Promise<PostResult>;
|
|
131
|
+
private createPost;
|
|
132
|
+
getPost(postId: string): Promise<Post>;
|
|
133
|
+
deletePost(postId: string): Promise<void>;
|
|
134
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
135
|
+
getCapabilities(): PlatformCapabilities;
|
|
136
|
+
/**
|
|
137
|
+
* Get reply reference for threading
|
|
138
|
+
*/
|
|
139
|
+
private getReplyRef;
|
|
140
|
+
/**
|
|
141
|
+
* Build post text with hashtags
|
|
142
|
+
*/
|
|
143
|
+
private buildPostText;
|
|
144
|
+
/**
|
|
145
|
+
* Handle API errors
|
|
146
|
+
*/
|
|
147
|
+
private handleError;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Bluesky configuration
|
|
152
|
+
*/
|
|
153
|
+
export declare interface BlueskyConfig extends BaseSocialConfig {
|
|
154
|
+
type: 'bluesky';
|
|
155
|
+
/**
|
|
156
|
+
* Handle or DID
|
|
157
|
+
*/
|
|
158
|
+
identifier: string;
|
|
159
|
+
/**
|
|
160
|
+
* App password (not main password)
|
|
161
|
+
*/
|
|
162
|
+
password: string;
|
|
163
|
+
/**
|
|
164
|
+
* PDS URL (optional, defaults to bsky.social)
|
|
165
|
+
*/
|
|
166
|
+
pdsUrl?: string;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
/**
|
|
170
|
+
* OAuth code exchange parameters
|
|
171
|
+
*/
|
|
172
|
+
export declare interface CodeExchangeParams {
|
|
173
|
+
/**
|
|
174
|
+
* Authorization code from callback
|
|
175
|
+
*/
|
|
176
|
+
code: string;
|
|
177
|
+
/**
|
|
178
|
+
* State parameter (for verification)
|
|
179
|
+
*/
|
|
180
|
+
state?: string;
|
|
181
|
+
/**
|
|
182
|
+
* Code verifier (for PKCE)
|
|
183
|
+
*/
|
|
184
|
+
codeVerifier?: string;
|
|
185
|
+
/**
|
|
186
|
+
* Redirect URI (must match authorization request)
|
|
187
|
+
*/
|
|
188
|
+
redirectUri?: string;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
/**
|
|
192
|
+
* Facebook Page adapter for publishing feed posts and Page videos.
|
|
193
|
+
*/
|
|
194
|
+
export declare class FacebookPageAdapter implements SocialPlatform {
|
|
195
|
+
readonly platform: "facebook";
|
|
196
|
+
private config;
|
|
197
|
+
constructor(config: FacebookPageConfig);
|
|
198
|
+
private get graphUrl();
|
|
199
|
+
authenticate(): Promise<AuthResult>;
|
|
200
|
+
refreshToken(_refreshToken: string): Promise<AuthResult>;
|
|
201
|
+
publishText(text: TextPost): Promise<PostResult>;
|
|
202
|
+
publishLink(link: LinkPost): Promise<PostResult>;
|
|
203
|
+
publishImage(image: ImagePost): Promise<PostResult>;
|
|
204
|
+
publishVideo(video: VideoPost): Promise<PostResult>;
|
|
205
|
+
getPost(postId: string): Promise<Post>;
|
|
206
|
+
deletePost(postId: string): Promise<void>;
|
|
207
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
208
|
+
getCapabilities(): PlatformCapabilities;
|
|
209
|
+
private createFeedPost;
|
|
210
|
+
private toPostResult;
|
|
211
|
+
private safetyFeedFields;
|
|
212
|
+
private safetyResultStatus;
|
|
213
|
+
private buildPostText;
|
|
214
|
+
private parseInsights;
|
|
215
|
+
private sumPositiveReactions;
|
|
216
|
+
private handleError;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Facebook Page configuration
|
|
221
|
+
*/
|
|
222
|
+
export declare interface FacebookPageConfig extends BaseSocialConfig {
|
|
223
|
+
type: 'facebook';
|
|
224
|
+
/**
|
|
225
|
+
* Page access token with pages_manage_posts permission
|
|
226
|
+
*/
|
|
227
|
+
accessToken: string;
|
|
228
|
+
/**
|
|
229
|
+
* Facebook Page ID
|
|
230
|
+
*/
|
|
231
|
+
pageId: string;
|
|
232
|
+
/**
|
|
233
|
+
* Optional Graph API version.
|
|
234
|
+
* @default v24.0
|
|
235
|
+
*/
|
|
236
|
+
apiVersion?: string;
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Factory function to create a social platform adapter
|
|
241
|
+
*
|
|
242
|
+
* @example
|
|
243
|
+
* ```typescript
|
|
244
|
+
* import { getSocial } from '@happyvertical/social';
|
|
245
|
+
*
|
|
246
|
+
* // YouTube
|
|
247
|
+
* const youtube = await getSocial({
|
|
248
|
+
* type: 'youtube',
|
|
249
|
+
* clientId: 'your-client-id',
|
|
250
|
+
* clientSecret: 'your-client-secret',
|
|
251
|
+
* accessToken: 'user-access-token',
|
|
252
|
+
* });
|
|
253
|
+
*
|
|
254
|
+
* // Bluesky
|
|
255
|
+
* const bluesky = await getSocial({
|
|
256
|
+
* type: 'bluesky',
|
|
257
|
+
* identifier: 'handle.bsky.social',
|
|
258
|
+
* password: 'app-password',
|
|
259
|
+
* });
|
|
260
|
+
*
|
|
261
|
+
* // X (Twitter)
|
|
262
|
+
* const x = await getSocial({
|
|
263
|
+
* type: 'x',
|
|
264
|
+
* apiKey: 'consumer-key',
|
|
265
|
+
* apiSecret: 'consumer-secret',
|
|
266
|
+
* accessToken: 'user-access-token',
|
|
267
|
+
* accessSecret: 'user-access-secret',
|
|
268
|
+
* });
|
|
269
|
+
*
|
|
270
|
+
* // Threads
|
|
271
|
+
* const threads = await getSocial({
|
|
272
|
+
* type: 'threads',
|
|
273
|
+
* accessToken: 'user-access-token',
|
|
274
|
+
* userId: 'threads-user-id',
|
|
275
|
+
* });
|
|
276
|
+
*
|
|
277
|
+
* // Publish text
|
|
278
|
+
* const result = await youtube.publishText({
|
|
279
|
+
* text: 'Hello from Bentley!',
|
|
280
|
+
* });
|
|
281
|
+
* ```
|
|
282
|
+
*/
|
|
283
|
+
export declare function getSocial(config: SocialConfig): Promise<SocialPlatform>;
|
|
284
|
+
|
|
285
|
+
/**
|
|
286
|
+
* Create multiple social platform adapters at once
|
|
287
|
+
*
|
|
288
|
+
* @example
|
|
289
|
+
* ```typescript
|
|
290
|
+
* import { getSocialMulti } from '@happyvertical/social';
|
|
291
|
+
*
|
|
292
|
+
* const adapters = await getSocialMulti([
|
|
293
|
+
* { type: 'youtube', clientId: '...', clientSecret: '...', accessToken: '...' },
|
|
294
|
+
* { type: 'bluesky', identifier: '...', password: '...' },
|
|
295
|
+
* ]);
|
|
296
|
+
*
|
|
297
|
+
* // Publish to all platforms
|
|
298
|
+
* const results = await Promise.all(
|
|
299
|
+
* adapters.map(adapter => adapter.publishText({ text: 'Hello!' }))
|
|
300
|
+
* );
|
|
301
|
+
* ```
|
|
302
|
+
*/
|
|
303
|
+
export declare function getSocialMulti(configs: SocialConfig[]): Promise<SocialPlatform[]>;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Image post content
|
|
307
|
+
*/
|
|
308
|
+
export declare interface ImagePost {
|
|
309
|
+
/**
|
|
310
|
+
* Image file buffer or URL
|
|
311
|
+
*/
|
|
312
|
+
file: Buffer | string;
|
|
313
|
+
/**
|
|
314
|
+
* MIME type for the image file. Detected from URLs and common buffer
|
|
315
|
+
* signatures when omitted.
|
|
316
|
+
*/
|
|
317
|
+
mimeType?: string;
|
|
318
|
+
/**
|
|
319
|
+
* Alt text for accessibility
|
|
320
|
+
*/
|
|
321
|
+
altText?: string;
|
|
322
|
+
/**
|
|
323
|
+
* Post description/caption
|
|
324
|
+
*/
|
|
325
|
+
description?: string;
|
|
326
|
+
/**
|
|
327
|
+
* Hashtags to include
|
|
328
|
+
*/
|
|
329
|
+
tags?: string[];
|
|
330
|
+
/**
|
|
331
|
+
* Link URL to include
|
|
332
|
+
*/
|
|
333
|
+
linkUrl?: string;
|
|
334
|
+
/**
|
|
335
|
+
* Scheduled publish time
|
|
336
|
+
*/
|
|
337
|
+
scheduledAt?: Date;
|
|
338
|
+
/**
|
|
339
|
+
* Override the adapter/account default link behavior for this post.
|
|
340
|
+
*/
|
|
341
|
+
linkBehavior?: LinkBehavior;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
/**
|
|
345
|
+
* How adapters should attach links to posts.
|
|
346
|
+
*/
|
|
347
|
+
export declare type LinkBehavior = 'inline' | 'attachment' | 'reply' | 'none';
|
|
348
|
+
|
|
349
|
+
/**
|
|
350
|
+
* Link post content
|
|
351
|
+
*/
|
|
352
|
+
export declare interface LinkPost {
|
|
353
|
+
/**
|
|
354
|
+
* URL to share
|
|
355
|
+
*/
|
|
356
|
+
url: string;
|
|
357
|
+
/**
|
|
358
|
+
* Post text/caption
|
|
359
|
+
*/
|
|
360
|
+
text?: string;
|
|
361
|
+
/**
|
|
362
|
+
* Link title for platforms that support link cards
|
|
363
|
+
*/
|
|
364
|
+
title?: string;
|
|
365
|
+
/**
|
|
366
|
+
* Link description for platforms that support link cards
|
|
367
|
+
*/
|
|
368
|
+
description?: string;
|
|
369
|
+
/**
|
|
370
|
+
* Hashtags to include
|
|
371
|
+
*/
|
|
372
|
+
tags?: string[];
|
|
373
|
+
/**
|
|
374
|
+
* Scheduled publish time
|
|
375
|
+
*/
|
|
376
|
+
scheduledAt?: Date;
|
|
377
|
+
/**
|
|
378
|
+
* Override the adapter/account default link behavior for this post.
|
|
379
|
+
*/
|
|
380
|
+
linkBehavior?: LinkBehavior;
|
|
381
|
+
}
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Platform capabilities
|
|
385
|
+
*/
|
|
386
|
+
export declare interface PlatformCapabilities {
|
|
387
|
+
/**
|
|
388
|
+
* Supports video posts
|
|
389
|
+
*/
|
|
390
|
+
video: boolean;
|
|
391
|
+
/**
|
|
392
|
+
* Supports image posts
|
|
393
|
+
*/
|
|
394
|
+
image: boolean;
|
|
395
|
+
/**
|
|
396
|
+
* Supports text-only posts
|
|
397
|
+
*/
|
|
398
|
+
text: boolean;
|
|
399
|
+
/**
|
|
400
|
+
* Supports first-class link posts or link attachments
|
|
401
|
+
*/
|
|
402
|
+
link: boolean;
|
|
403
|
+
/**
|
|
404
|
+
* Supports native link attachments/cards instead of plain inline URLs
|
|
405
|
+
*/
|
|
406
|
+
linkAttachment?: boolean;
|
|
407
|
+
/**
|
|
408
|
+
* Supports scheduled posting
|
|
409
|
+
*/
|
|
410
|
+
scheduling: boolean;
|
|
411
|
+
/**
|
|
412
|
+
* Supports analytics retrieval
|
|
413
|
+
*/
|
|
414
|
+
analytics: boolean;
|
|
415
|
+
/**
|
|
416
|
+
* Analytics can include raw platform payloads
|
|
417
|
+
*/
|
|
418
|
+
rawAnalytics?: boolean;
|
|
419
|
+
/**
|
|
420
|
+
* Safety modes supported by this adapter.
|
|
421
|
+
*/
|
|
422
|
+
publishModes?: PublishMode[];
|
|
423
|
+
/**
|
|
424
|
+
* Supports a non-public remote staging step before final publish.
|
|
425
|
+
*/
|
|
426
|
+
staging?: boolean;
|
|
427
|
+
/**
|
|
428
|
+
* Supports creating private, unpublished, or scheduled platform content.
|
|
429
|
+
*/
|
|
430
|
+
privatePublishing?: boolean;
|
|
431
|
+
/**
|
|
432
|
+
* Media publishing requires a publicly accessible URL, not a Buffer upload
|
|
433
|
+
*/
|
|
434
|
+
requiresPublicMediaUrl?: boolean;
|
|
435
|
+
/**
|
|
436
|
+
* Maximum video duration in seconds
|
|
437
|
+
*/
|
|
438
|
+
maxVideoLength: number;
|
|
439
|
+
/**
|
|
440
|
+
* Maximum video file size in bytes
|
|
441
|
+
*/
|
|
442
|
+
maxVideoSize: number;
|
|
443
|
+
/**
|
|
444
|
+
* Supported video formats
|
|
445
|
+
*/
|
|
446
|
+
supportedVideoFormats: string[];
|
|
447
|
+
/**
|
|
448
|
+
* Supported aspect ratios
|
|
449
|
+
*/
|
|
450
|
+
aspectRatios: string[];
|
|
451
|
+
/**
|
|
452
|
+
* Maximum text length
|
|
453
|
+
*/
|
|
454
|
+
maxTextLength: number;
|
|
455
|
+
/**
|
|
456
|
+
* Maximum number of hashtags
|
|
457
|
+
*/
|
|
458
|
+
maxHashtags?: number;
|
|
459
|
+
/**
|
|
460
|
+
* Supported high-level post types
|
|
461
|
+
*/
|
|
462
|
+
supportedPostTypes?: Array<'text' | 'image' | 'video' | 'link'>;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Retrieved post data
|
|
467
|
+
*/
|
|
468
|
+
export declare interface Post {
|
|
469
|
+
/**
|
|
470
|
+
* Platform-specific post ID
|
|
471
|
+
*/
|
|
472
|
+
id: string;
|
|
473
|
+
/**
|
|
474
|
+
* Public URL of the post
|
|
475
|
+
*/
|
|
476
|
+
url: string;
|
|
477
|
+
/**
|
|
478
|
+
* Post type
|
|
479
|
+
*/
|
|
480
|
+
type: 'video' | 'image' | 'text' | 'link';
|
|
481
|
+
/**
|
|
482
|
+
* Post title (if applicable)
|
|
483
|
+
*/
|
|
484
|
+
title?: string;
|
|
485
|
+
/**
|
|
486
|
+
* Post description/caption
|
|
487
|
+
*/
|
|
488
|
+
description?: string;
|
|
489
|
+
/**
|
|
490
|
+
* When the post was published
|
|
491
|
+
*/
|
|
492
|
+
publishedAt: Date;
|
|
493
|
+
/**
|
|
494
|
+
* Current visibility
|
|
495
|
+
*/
|
|
496
|
+
visibility: 'public' | 'unlisted' | 'private';
|
|
497
|
+
/**
|
|
498
|
+
* Basic analytics
|
|
499
|
+
*/
|
|
500
|
+
analytics?: PostAnalytics;
|
|
501
|
+
}
|
|
502
|
+
|
|
503
|
+
/**
|
|
504
|
+
* Post analytics
|
|
505
|
+
*/
|
|
506
|
+
export declare interface PostAnalytics {
|
|
507
|
+
/**
|
|
508
|
+
* View/impression count
|
|
509
|
+
*/
|
|
510
|
+
views?: number;
|
|
511
|
+
/**
|
|
512
|
+
* Impression count when the platform distinguishes it from views
|
|
513
|
+
*/
|
|
514
|
+
impressions?: number;
|
|
515
|
+
/**
|
|
516
|
+
* Like/favorite count
|
|
517
|
+
*/
|
|
518
|
+
likes?: number;
|
|
519
|
+
/**
|
|
520
|
+
* Comment count
|
|
521
|
+
*/
|
|
522
|
+
comments?: number;
|
|
523
|
+
/**
|
|
524
|
+
* Share/repost count
|
|
525
|
+
*/
|
|
526
|
+
shares?: number;
|
|
527
|
+
/**
|
|
528
|
+
* Click count (for links)
|
|
529
|
+
*/
|
|
530
|
+
clicks?: number;
|
|
531
|
+
/**
|
|
532
|
+
* Raw platform analytics payload for debugging and future reporting
|
|
533
|
+
*/
|
|
534
|
+
raw?: unknown;
|
|
535
|
+
/**
|
|
536
|
+
* When analytics were last updated
|
|
537
|
+
*/
|
|
538
|
+
lastUpdated?: Date;
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
/**
|
|
542
|
+
* Result from publishing a post
|
|
543
|
+
*/
|
|
544
|
+
export declare interface PostResult {
|
|
545
|
+
/**
|
|
546
|
+
* Platform-specific post ID
|
|
547
|
+
*/
|
|
548
|
+
id: string;
|
|
549
|
+
/**
|
|
550
|
+
* Public URL of the post
|
|
551
|
+
*/
|
|
552
|
+
url: string;
|
|
553
|
+
/**
|
|
554
|
+
* Publication status
|
|
555
|
+
*/
|
|
556
|
+
status: 'published' | 'scheduled' | 'processing' | 'staged' | 'dry_run';
|
|
557
|
+
/**
|
|
558
|
+
* When the post was/will be published
|
|
559
|
+
*/
|
|
560
|
+
publishedAt?: Date;
|
|
561
|
+
/**
|
|
562
|
+
* Scheduled time (if scheduled)
|
|
563
|
+
*/
|
|
564
|
+
scheduledAt?: Date;
|
|
565
|
+
/**
|
|
566
|
+
* Platform-specific metadata
|
|
567
|
+
*/
|
|
568
|
+
metadata?: Record<string, any>;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
/**
|
|
572
|
+
* Safety mode for publish operations.
|
|
573
|
+
* - dry_run: Build and validate payloads without platform API writes
|
|
574
|
+
* - stage_remote: Use non-public staging endpoints where available
|
|
575
|
+
* - private_or_scheduled: Create a non-public/private/scheduled platform object where available
|
|
576
|
+
* - public: Publish publicly
|
|
577
|
+
*/
|
|
578
|
+
export declare type PublishMode = 'dry_run' | 'stage_remote' | 'private_or_scheduled' | 'public';
|
|
579
|
+
|
|
580
|
+
/**
|
|
581
|
+
* Publish content to multiple platforms at once
|
|
582
|
+
*
|
|
583
|
+
* @example
|
|
584
|
+
* ```typescript
|
|
585
|
+
* import { publishToAll, getSocialMulti } from '@happyvertical/social';
|
|
586
|
+
*
|
|
587
|
+
* const adapters = await getSocialMulti([...]);
|
|
588
|
+
*
|
|
589
|
+
* const results = await publishToAll(adapters, {
|
|
590
|
+
* type: 'text',
|
|
591
|
+
* text: 'Breaking news from Bentley!',
|
|
592
|
+
* linkUrl: 'https://example.com/article',
|
|
593
|
+
* tags: ['news', 'local'],
|
|
594
|
+
* });
|
|
595
|
+
* ```
|
|
596
|
+
*/
|
|
597
|
+
export declare function publishToAll(adapters: SocialPlatform[], content: {
|
|
598
|
+
type: 'text' | 'image' | 'video' | 'link';
|
|
599
|
+
text?: string;
|
|
600
|
+
description?: string;
|
|
601
|
+
file?: Buffer | string;
|
|
602
|
+
title?: string;
|
|
603
|
+
linkUrl?: string;
|
|
604
|
+
url?: string;
|
|
605
|
+
tags?: string[];
|
|
606
|
+
altText?: string;
|
|
607
|
+
mimeType?: string;
|
|
608
|
+
thumbnail?: Buffer | string;
|
|
609
|
+
thumbnailMimeType?: string;
|
|
610
|
+
}): Promise<Map<string, {
|
|
611
|
+
success: boolean;
|
|
612
|
+
result?: unknown;
|
|
613
|
+
error?: Error;
|
|
614
|
+
}>>;
|
|
615
|
+
|
|
616
|
+
/**
|
|
617
|
+
* Authentication error
|
|
618
|
+
*/
|
|
619
|
+
export declare class SocialAuthError extends SocialError {
|
|
620
|
+
constructor(platform: SocialPlatformType, message?: string);
|
|
621
|
+
}
|
|
622
|
+
|
|
623
|
+
/**
|
|
624
|
+
* Union of all platform configurations
|
|
625
|
+
*/
|
|
626
|
+
export declare type SocialConfig = YouTubeConfig | ThreadsConfig | FacebookPageConfig | XConfig | BlueskyConfig;
|
|
627
|
+
|
|
628
|
+
/**
|
|
629
|
+
* Error thrown by social platform operations
|
|
630
|
+
*/
|
|
631
|
+
export declare class SocialError extends Error {
|
|
632
|
+
code: string;
|
|
633
|
+
platform?: SocialPlatformType | undefined;
|
|
634
|
+
statusCode?: number | undefined;
|
|
635
|
+
constructor(message: string, code: string, platform?: SocialPlatformType | undefined, statusCode?: number | undefined);
|
|
636
|
+
}
|
|
637
|
+
|
|
638
|
+
/**
|
|
639
|
+
* Social platform interface
|
|
640
|
+
*/
|
|
641
|
+
export declare interface SocialPlatform {
|
|
642
|
+
/**
|
|
643
|
+
* Platform type
|
|
644
|
+
*/
|
|
645
|
+
readonly platform: SocialPlatformType;
|
|
646
|
+
/**
|
|
647
|
+
* Authenticate or refresh authentication
|
|
648
|
+
*/
|
|
649
|
+
authenticate(credentials?: Record<string, string>): Promise<AuthResult>;
|
|
650
|
+
/**
|
|
651
|
+
* Refresh expired token
|
|
652
|
+
*/
|
|
653
|
+
refreshToken(refreshToken: string): Promise<AuthResult>;
|
|
654
|
+
/**
|
|
655
|
+
* Publish a video post
|
|
656
|
+
*/
|
|
657
|
+
publishVideo(video: VideoPost): Promise<PostResult>;
|
|
658
|
+
/**
|
|
659
|
+
* Publish an image post
|
|
660
|
+
*/
|
|
661
|
+
publishImage(image: ImagePost): Promise<PostResult>;
|
|
662
|
+
/**
|
|
663
|
+
* Publish a text post
|
|
664
|
+
*/
|
|
665
|
+
publishText(text: TextPost): Promise<PostResult>;
|
|
666
|
+
/**
|
|
667
|
+
* Publish a link post
|
|
668
|
+
*/
|
|
669
|
+
publishLink(link: LinkPost): Promise<PostResult>;
|
|
670
|
+
/**
|
|
671
|
+
* Get a post by ID
|
|
672
|
+
*/
|
|
673
|
+
getPost(postId: string): Promise<Post>;
|
|
674
|
+
/**
|
|
675
|
+
* Delete a post
|
|
676
|
+
*/
|
|
677
|
+
deletePost(postId: string): Promise<void>;
|
|
678
|
+
/**
|
|
679
|
+
* Get analytics for a post
|
|
680
|
+
*/
|
|
681
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
682
|
+
/**
|
|
683
|
+
* Get platform capabilities
|
|
684
|
+
*/
|
|
685
|
+
getCapabilities(): PlatformCapabilities;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
/**
|
|
689
|
+
* Social Platform Types
|
|
690
|
+
*
|
|
691
|
+
* Unified interface for publishing to social media platforms.
|
|
692
|
+
*/
|
|
693
|
+
/**
|
|
694
|
+
* Supported social platforms
|
|
695
|
+
*/
|
|
696
|
+
export declare type SocialPlatformType = 'youtube' | 'threads' | 'x' | 'bluesky' | 'facebook';
|
|
697
|
+
|
|
698
|
+
/**
|
|
699
|
+
* Rate limit error
|
|
700
|
+
*/
|
|
701
|
+
export declare class SocialRateLimitError extends SocialError {
|
|
702
|
+
retryAfter?: number | undefined;
|
|
703
|
+
constructor(platform: SocialPlatformType, retryAfter?: number | undefined);
|
|
704
|
+
}
|
|
705
|
+
|
|
706
|
+
/**
|
|
707
|
+
* Text post content
|
|
708
|
+
*/
|
|
709
|
+
export declare interface TextPost {
|
|
710
|
+
/**
|
|
711
|
+
* Post text content
|
|
712
|
+
*/
|
|
713
|
+
text: string;
|
|
714
|
+
/**
|
|
715
|
+
* Hashtags to include
|
|
716
|
+
*/
|
|
717
|
+
tags?: string[];
|
|
718
|
+
/**
|
|
719
|
+
* Link URL to include
|
|
720
|
+
*/
|
|
721
|
+
linkUrl?: string;
|
|
722
|
+
/**
|
|
723
|
+
* Scheduled publish time
|
|
724
|
+
*/
|
|
725
|
+
scheduledAt?: Date;
|
|
726
|
+
/**
|
|
727
|
+
* Reply to post ID (for threads/replies)
|
|
728
|
+
*/
|
|
729
|
+
replyTo?: string;
|
|
730
|
+
/**
|
|
731
|
+
* Override the adapter/account default link behavior for this post.
|
|
732
|
+
*/
|
|
733
|
+
linkBehavior?: LinkBehavior;
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
/**
|
|
737
|
+
* Threads adapter for publishing via Meta Graph API
|
|
738
|
+
*
|
|
739
|
+
* @example
|
|
740
|
+
* ```typescript
|
|
741
|
+
* const threads = new ThreadsAdapter({
|
|
742
|
+
* type: 'threads',
|
|
743
|
+
* accessToken: 'user-access-token',
|
|
744
|
+
* userId: 'threads-user-id',
|
|
745
|
+
* });
|
|
746
|
+
*
|
|
747
|
+
* await threads.authenticate();
|
|
748
|
+
*
|
|
749
|
+
* const result = await threads.publishText({
|
|
750
|
+
* text: 'Breaking news from Bentley!',
|
|
751
|
+
* linkUrl: 'https://example.com/article',
|
|
752
|
+
* });
|
|
753
|
+
* ```
|
|
754
|
+
*/
|
|
755
|
+
export declare class ThreadsAdapter implements SocialPlatform {
|
|
756
|
+
readonly platform: "threads";
|
|
757
|
+
private config;
|
|
758
|
+
constructor(config: ThreadsConfig);
|
|
759
|
+
authenticate(): Promise<AuthResult>;
|
|
760
|
+
refreshToken(_refreshToken: string): Promise<AuthResult>;
|
|
761
|
+
publishVideo(video: VideoPost): Promise<PostResult>;
|
|
762
|
+
publishImage(image: ImagePost): Promise<PostResult>;
|
|
763
|
+
publishText(text: TextPost): Promise<PostResult>;
|
|
764
|
+
publishLink(link: LinkPost): Promise<PostResult>;
|
|
765
|
+
/**
|
|
766
|
+
* Wait for media container to finish processing
|
|
767
|
+
*/
|
|
768
|
+
private waitForContainer;
|
|
769
|
+
/**
|
|
770
|
+
* Publish a prepared container
|
|
771
|
+
*/
|
|
772
|
+
private publishContainer;
|
|
773
|
+
/**
|
|
774
|
+
* Upload buffer to temporary storage and return URL
|
|
775
|
+
* Note: In production, this would upload to a CDN or storage service
|
|
776
|
+
*/
|
|
777
|
+
private uploadToTempStorage;
|
|
778
|
+
getPost(postId: string): Promise<Post>;
|
|
779
|
+
deletePost(_postId: string): Promise<void>;
|
|
780
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
781
|
+
getCapabilities(): PlatformCapabilities;
|
|
782
|
+
/**
|
|
783
|
+
* Build post text with hashtags and link
|
|
784
|
+
*/
|
|
785
|
+
private buildPostText;
|
|
786
|
+
/**
|
|
787
|
+
* Parse insights data into PostAnalytics
|
|
788
|
+
*/
|
|
789
|
+
private parseInsights;
|
|
790
|
+
/**
|
|
791
|
+
* Map Threads media type to our type
|
|
792
|
+
*/
|
|
793
|
+
private mapMediaType;
|
|
794
|
+
/**
|
|
795
|
+
* Handle API errors
|
|
796
|
+
*/
|
|
797
|
+
private handleError;
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
/**
|
|
801
|
+
* Threads (Meta) configuration
|
|
802
|
+
*/
|
|
803
|
+
export declare interface ThreadsConfig extends BaseSocialConfig {
|
|
804
|
+
type: 'threads';
|
|
805
|
+
/**
|
|
806
|
+
* Access token from Meta OAuth
|
|
807
|
+
*/
|
|
808
|
+
accessToken: string;
|
|
809
|
+
/**
|
|
810
|
+
* Instagram/Threads user ID
|
|
811
|
+
*/
|
|
812
|
+
userId: string;
|
|
813
|
+
}
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Video post content
|
|
817
|
+
*/
|
|
818
|
+
export declare interface VideoPost {
|
|
819
|
+
/**
|
|
820
|
+
* Video file buffer or URL
|
|
821
|
+
*/
|
|
822
|
+
file: Buffer | string;
|
|
823
|
+
/**
|
|
824
|
+
* MIME type for the video file. Detected from URLs and common buffer
|
|
825
|
+
* signatures when omitted.
|
|
826
|
+
*/
|
|
827
|
+
mimeType?: string;
|
|
828
|
+
/**
|
|
829
|
+
* Video title (YouTube, some platforms)
|
|
830
|
+
*/
|
|
831
|
+
title?: string;
|
|
832
|
+
/**
|
|
833
|
+
* Post description/caption
|
|
834
|
+
*/
|
|
835
|
+
description?: string;
|
|
836
|
+
/**
|
|
837
|
+
* Custom thumbnail image
|
|
838
|
+
*/
|
|
839
|
+
thumbnail?: Buffer | string;
|
|
840
|
+
/**
|
|
841
|
+
* MIME type for the thumbnail image. Detected from URLs and common buffer
|
|
842
|
+
* signatures when omitted.
|
|
843
|
+
*/
|
|
844
|
+
thumbnailMimeType?: string;
|
|
845
|
+
/**
|
|
846
|
+
* Hashtags to include
|
|
847
|
+
*/
|
|
848
|
+
tags?: string[];
|
|
849
|
+
/**
|
|
850
|
+
* Link URL to include (e.g., article link)
|
|
851
|
+
*/
|
|
852
|
+
linkUrl?: string;
|
|
853
|
+
/**
|
|
854
|
+
* Visibility setting
|
|
855
|
+
* @default 'public'
|
|
856
|
+
*/
|
|
857
|
+
visibility?: 'public' | 'unlisted' | 'private';
|
|
858
|
+
/**
|
|
859
|
+
* Scheduled publish time (if supported)
|
|
860
|
+
*/
|
|
861
|
+
scheduledAt?: Date;
|
|
862
|
+
/**
|
|
863
|
+
* Category ID (YouTube)
|
|
864
|
+
*/
|
|
865
|
+
categoryId?: string;
|
|
866
|
+
/**
|
|
867
|
+
* Whether this is a Short (YouTube)
|
|
868
|
+
*/
|
|
869
|
+
isShort?: boolean;
|
|
870
|
+
/**
|
|
871
|
+
* Override the adapter/account default link behavior for this post.
|
|
872
|
+
*/
|
|
873
|
+
linkBehavior?: LinkBehavior;
|
|
874
|
+
}
|
|
875
|
+
|
|
876
|
+
/**
|
|
877
|
+
* X (Twitter) adapter for publishing
|
|
878
|
+
*
|
|
879
|
+
* @example
|
|
880
|
+
* ```typescript
|
|
881
|
+
* const x = new XAdapter({
|
|
882
|
+
* type: 'x',
|
|
883
|
+
* apiKey: 'consumer-key',
|
|
884
|
+
* apiSecret: 'consumer-secret',
|
|
885
|
+
* accessToken: 'user-access-token',
|
|
886
|
+
* accessSecret: 'user-access-secret',
|
|
887
|
+
* });
|
|
888
|
+
*
|
|
889
|
+
* await x.authenticate();
|
|
890
|
+
*
|
|
891
|
+
* const result = await x.publishText({
|
|
892
|
+
* text: 'Breaking news from Bentley!',
|
|
893
|
+
* linkUrl: 'https://example.com/article',
|
|
894
|
+
* });
|
|
895
|
+
* ```
|
|
896
|
+
*/
|
|
897
|
+
export declare class XAdapter implements SocialPlatform {
|
|
898
|
+
readonly platform: "x";
|
|
899
|
+
private config;
|
|
900
|
+
private logger;
|
|
901
|
+
constructor(config: XConfig);
|
|
902
|
+
/**
|
|
903
|
+
* Generate OAuth 1.0a signature for request
|
|
904
|
+
*/
|
|
905
|
+
private generateOAuthSignature;
|
|
906
|
+
private generateNonce;
|
|
907
|
+
private percentEncode;
|
|
908
|
+
private hmacSha1;
|
|
909
|
+
authenticate(): Promise<AuthResult>;
|
|
910
|
+
refreshToken(refreshToken: string): Promise<AuthResult>;
|
|
911
|
+
private basicAuthHeader;
|
|
912
|
+
publishVideo(video: VideoPost): Promise<PostResult>;
|
|
913
|
+
publishImage(image: ImagePost): Promise<PostResult>;
|
|
914
|
+
publishText(text: TextPost): Promise<PostResult>;
|
|
915
|
+
publishLink(link: LinkPost): Promise<PostResult>;
|
|
916
|
+
/**
|
|
917
|
+
* Upload media to Twitter
|
|
918
|
+
*/
|
|
919
|
+
private uploadMedia;
|
|
920
|
+
private readMediaData;
|
|
921
|
+
/**
|
|
922
|
+
* Upload media using X API v2 and OAuth 2.0 user context.
|
|
923
|
+
*/
|
|
924
|
+
private uploadMediaV2;
|
|
925
|
+
/**
|
|
926
|
+
* Upload media using legacy OAuth 1.0a upload endpoints.
|
|
927
|
+
*/
|
|
928
|
+
private uploadMediaOAuth1;
|
|
929
|
+
/**
|
|
930
|
+
* Wait for media processing to complete
|
|
931
|
+
*/
|
|
932
|
+
private waitForProcessing;
|
|
933
|
+
/**
|
|
934
|
+
* Set alt text for uploaded media
|
|
935
|
+
* Uses JSON body as required by metadata/create endpoint
|
|
936
|
+
*/
|
|
937
|
+
private setMediaAltText;
|
|
938
|
+
/**
|
|
939
|
+
* Post link as reply (algorithm-friendly pattern)
|
|
940
|
+
*/
|
|
941
|
+
private postLinkReply;
|
|
942
|
+
getPost(postId: string): Promise<Post>;
|
|
943
|
+
deletePost(postId: string): Promise<void>;
|
|
944
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
945
|
+
getCapabilities(): PlatformCapabilities;
|
|
946
|
+
private resolveLinkBehavior;
|
|
947
|
+
private usesOAuth2;
|
|
948
|
+
private requireOAuth1Config;
|
|
949
|
+
/**
|
|
950
|
+
* Build post text with hashtags
|
|
951
|
+
*/
|
|
952
|
+
private buildPostText;
|
|
953
|
+
private truncatePostText;
|
|
954
|
+
private resolvePostType;
|
|
955
|
+
private inferMediaTypeFromKey;
|
|
956
|
+
/**
|
|
957
|
+
* Make authenticated request to Twitter API v2
|
|
958
|
+
*/
|
|
959
|
+
private makeRequest;
|
|
960
|
+
private makeBearerUploadRequest;
|
|
961
|
+
/**
|
|
962
|
+
* Make authenticated request to Twitter Upload API
|
|
963
|
+
*/
|
|
964
|
+
private makeUploadRequest;
|
|
965
|
+
/**
|
|
966
|
+
* Handle API errors
|
|
967
|
+
*/
|
|
968
|
+
private handleError;
|
|
969
|
+
}
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* X (Twitter) configuration
|
|
973
|
+
*/
|
|
974
|
+
export declare interface XConfig extends BaseSocialConfig {
|
|
975
|
+
type: 'x';
|
|
976
|
+
/**
|
|
977
|
+
* Authentication mode. OAuth 2.0 is used when accessSecret is omitted.
|
|
978
|
+
*
|
|
979
|
+
* @default 'oauth1' when accessSecret is present, otherwise 'oauth2'
|
|
980
|
+
*/
|
|
981
|
+
authType?: 'oauth1' | 'oauth2';
|
|
982
|
+
/**
|
|
983
|
+
* API key (consumer key) for OAuth 1.0a.
|
|
984
|
+
*/
|
|
985
|
+
apiKey?: string;
|
|
986
|
+
/**
|
|
987
|
+
* API secret (consumer secret) for OAuth 1.0a.
|
|
988
|
+
*/
|
|
989
|
+
apiSecret?: string;
|
|
990
|
+
/**
|
|
991
|
+
* User access token.
|
|
992
|
+
*/
|
|
993
|
+
accessToken: string;
|
|
994
|
+
/**
|
|
995
|
+
* User access token secret for OAuth 1.0a.
|
|
996
|
+
*/
|
|
997
|
+
accessSecret?: string;
|
|
998
|
+
/**
|
|
999
|
+
* OAuth 2.0 client ID for refresh-token flows.
|
|
1000
|
+
*/
|
|
1001
|
+
clientId?: string;
|
|
1002
|
+
/**
|
|
1003
|
+
* OAuth 2.0 client secret for confidential clients.
|
|
1004
|
+
*/
|
|
1005
|
+
clientSecret?: string;
|
|
1006
|
+
/**
|
|
1007
|
+
* OAuth 2.0 refresh token.
|
|
1008
|
+
*/
|
|
1009
|
+
refreshToken?: string;
|
|
1010
|
+
/**
|
|
1011
|
+
* Default handling for links.
|
|
1012
|
+
* @default 'inline'
|
|
1013
|
+
*/
|
|
1014
|
+
linkBehavior?: LinkBehavior;
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
/**
|
|
1018
|
+
* YouTube adapter for video publishing
|
|
1019
|
+
*
|
|
1020
|
+
* @example
|
|
1021
|
+
* ```typescript
|
|
1022
|
+
* const youtube = new YouTubeAdapter({
|
|
1023
|
+
* type: 'youtube',
|
|
1024
|
+
* clientId: 'your-client-id',
|
|
1025
|
+
* clientSecret: 'your-client-secret',
|
|
1026
|
+
* accessToken: 'user-access-token',
|
|
1027
|
+
* refreshToken: 'user-refresh-token',
|
|
1028
|
+
* });
|
|
1029
|
+
*
|
|
1030
|
+
* const result = await youtube.publishVideo({
|
|
1031
|
+
* file: videoBuffer,
|
|
1032
|
+
* title: 'Breaking News',
|
|
1033
|
+
* description: 'Latest updates...',
|
|
1034
|
+
* tags: ['news', 'local'],
|
|
1035
|
+
* isShort: true,
|
|
1036
|
+
* });
|
|
1037
|
+
* ```
|
|
1038
|
+
*/
|
|
1039
|
+
export declare class YouTubeAdapter implements SocialPlatform {
|
|
1040
|
+
readonly platform: "youtube";
|
|
1041
|
+
private config;
|
|
1042
|
+
private logger;
|
|
1043
|
+
private currentAccessToken?;
|
|
1044
|
+
constructor(config: YouTubeConfig);
|
|
1045
|
+
/**
|
|
1046
|
+
* Generate OAuth authorization URL
|
|
1047
|
+
*/
|
|
1048
|
+
getAuthorizationUrl(options?: AuthorizationOptions): AuthorizationResult;
|
|
1049
|
+
/**
|
|
1050
|
+
* Exchange authorization code for tokens
|
|
1051
|
+
*/
|
|
1052
|
+
exchangeCode(params: CodeExchangeParams): Promise<AuthResult>;
|
|
1053
|
+
authenticate(): Promise<AuthResult>;
|
|
1054
|
+
refreshToken(refreshToken: string): Promise<AuthResult>;
|
|
1055
|
+
publishVideo(video: VideoPost): Promise<PostResult>;
|
|
1056
|
+
/**
|
|
1057
|
+
* Upload custom thumbnail
|
|
1058
|
+
* @returns true if upload succeeded, false otherwise
|
|
1059
|
+
*/
|
|
1060
|
+
private uploadThumbnail;
|
|
1061
|
+
publishImage(_image: ImagePost): Promise<PostResult>;
|
|
1062
|
+
publishText(_text: TextPost): Promise<PostResult>;
|
|
1063
|
+
publishLink(_link: LinkPost): Promise<PostResult>;
|
|
1064
|
+
getPost(postId: string): Promise<Post>;
|
|
1065
|
+
deletePost(postId: string): Promise<void>;
|
|
1066
|
+
getAnalytics(postId: string): Promise<PostAnalytics>;
|
|
1067
|
+
getCapabilities(): PlatformCapabilities;
|
|
1068
|
+
/**
|
|
1069
|
+
* Build description with link and hashtags
|
|
1070
|
+
*/
|
|
1071
|
+
private buildDescription;
|
|
1072
|
+
private parseMetric;
|
|
1073
|
+
/**
|
|
1074
|
+
* Handle API errors
|
|
1075
|
+
*/
|
|
1076
|
+
private handleError;
|
|
1077
|
+
/**
|
|
1078
|
+
* Generate PKCE code verifier
|
|
1079
|
+
*/
|
|
1080
|
+
private generateCodeVerifier;
|
|
1081
|
+
/**
|
|
1082
|
+
* Generate PKCE code challenge from verifier using S256
|
|
1083
|
+
*/
|
|
1084
|
+
private generateCodeChallenge;
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* YouTube configuration
|
|
1089
|
+
*/
|
|
1090
|
+
export declare interface YouTubeConfig extends BaseSocialConfig {
|
|
1091
|
+
type: 'youtube';
|
|
1092
|
+
/**
|
|
1093
|
+
* OAuth2 client ID
|
|
1094
|
+
*/
|
|
1095
|
+
clientId: string;
|
|
1096
|
+
/**
|
|
1097
|
+
* OAuth2 client secret
|
|
1098
|
+
*/
|
|
1099
|
+
clientSecret: string;
|
|
1100
|
+
/**
|
|
1101
|
+
* Access token (from OAuth flow)
|
|
1102
|
+
*/
|
|
1103
|
+
accessToken?: string;
|
|
1104
|
+
/**
|
|
1105
|
+
* Refresh token (from OAuth flow)
|
|
1106
|
+
*/
|
|
1107
|
+
refreshToken?: string;
|
|
1108
|
+
/**
|
|
1109
|
+
* Redirect URI for OAuth
|
|
1110
|
+
*/
|
|
1111
|
+
redirectUri?: string;
|
|
1112
|
+
}
|
|
1113
|
+
|
|
1114
|
+
export { }
|