@postrun/react 0.1.0 → 1.0.0

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/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@ import * as react from 'react';
2
2
  import { ReactNode, CSSProperties } from 'react';
3
3
  import * as _tanstack_react_query from '@tanstack/react-query';
4
4
  import { QueryClient, QueryKey } from '@tanstack/react-query';
5
- import { PostrunClient, ListProfilesQuery, ConnectablePlatform, MediaTarget, MediaKind, CreateMediaInput, MediaResource, ListPostsQuery, ComposePostInput, XPostVariant, LinkedInPostVariant } from '@postrun/js';
5
+ import { PostrunClient, ListProfilesQuery, DiscoverableAccountList, Connection, ConnectionKind, ConnectionStatus, ListMediaQuery, ListPostsQuery, ConnectablePlatform, MediaResource, MediaTarget, MediaKind, Metadata, ComposePostInput, XPostVariant, LinkedInPostVariant } from '@postrun/js';
6
6
  import { TwitterComponents } from 'react-tweet';
7
7
 
8
8
  /**
@@ -191,33 +191,232 @@ declare function useDeleteProfile(): _tanstack_react_query.UseMutationResult<{
191
191
  deleted: true;
192
192
  }, Error, string, unknown>;
193
193
 
194
- interface ConnectParams {
194
+ /**
195
+ * The pure orchestration behind the embedded (no-redirect) connect flow. It is
196
+ * the in-app twin of the hosted `/connect` runner's machine, sharing its exact
197
+ * shape — grant → correlate by the Nango `connectionId` → discover → pick →
198
+ * select — and its two invariants:
199
+ *
200
+ * 1. It NEVER throws: every path resolves to one typed `ConnectOutcome`, so the
201
+ * hook can map it straight to a UI state and a seam can't crash a host app.
202
+ * 2. Correlation is EXACT: `nango.auth()` resolves with the Nango `connectionId`,
203
+ * the SAME value the auth webhook stores as `nango_connection_id`. We poll the
204
+ * connections list filtered by that id, so the row this grant produced is found
205
+ * unambiguously — a concurrent connect on the same profile can't be mis-picked.
206
+ *
207
+ * All seams (the Nango grant, the host's account picker, the four API calls) are
208
+ * INJECTED, so the whole machine unit-tests without a DOM, a network, or a real
209
+ * `nango.auth()`. The hook (`useConnect`) wires the real seams onto it.
210
+ */
211
+ /** One account offered for selection — the element type of the accounts list. */
212
+ type DiscoverableAccount = DiscoverableAccountList['data'][number];
213
+ /** Why a connect attempt ended in `error` — actionable reasons for the host. */
214
+ type ConnectErrorReason = 'popup_blocked' | 'auth_failed' | 'connection_not_found' | 'select_failed' | 'reauth_required';
215
+ /**
216
+ * The single outcome of a connect attempt. `active` carries the activated
217
+ * connection (so the host can call `onConnected`); `connected_pending` means the
218
+ * grant succeeded but no account is bound yet (slow webhook, out-of-band binding,
219
+ * or no reachable accounts) — the host refetches its list, it is NOT an error.
220
+ */
221
+ type ConnectOutcome = {
222
+ status: 'active';
223
+ connection: Connection;
224
+ } | {
225
+ status: 'connected_pending';
226
+ } | {
227
+ status: 'cancelled';
228
+ } | {
229
+ status: 'error';
230
+ reason: ConnectErrorReason;
231
+ };
232
+
233
+ /** The connection-list filter that keys the cache (social/ads + lifecycle). */
234
+ interface ConnectionsFilter {
235
+ kind?: ConnectionKind;
236
+ status?: ConnectionStatus;
237
+ }
238
+ /**
239
+ * Query-key factory for profiles. Hierarchical so a mutation can invalidate at
240
+ * the right granularity: `lists()` after a create, `detail(id)` after an update.
241
+ */
242
+ declare const profileKeys: {
243
+ all: readonly ["postrun", "profiles"];
244
+ lists: () => readonly ["postrun", "profiles", "list"];
245
+ list: (query?: ListProfilesQuery) => readonly ["postrun", "profiles", "list", {
246
+ limit?: number;
247
+ offset?: number;
248
+ external_id?: string;
249
+ metadata?: {
250
+ [key: string]: string | number | boolean;
251
+ };
252
+ }];
253
+ infinite: (query?: Omit<ListProfilesQuery, "limit" | "offset">) => readonly ["postrun", "profiles", "list", "infinite", Omit<{
254
+ limit?: number;
255
+ offset?: number;
256
+ external_id?: string;
257
+ metadata?: {
258
+ [key: string]: string | number | boolean;
259
+ };
260
+ }, "limit" | "offset">];
261
+ details: () => readonly ["postrun", "profiles", "detail"];
262
+ detail: (id: string) => readonly ["postrun", "profiles", "detail", string];
263
+ };
264
+ /** Query-key factory for posts (list filtered by query; detail by id). */
265
+ declare const postKeys: {
266
+ all: readonly ["postrun", "posts"];
267
+ lists: () => readonly ["postrun", "posts", "list"];
268
+ list: (query?: ListPostsQuery) => readonly ["postrun", "posts", "list", {
269
+ limit?: number;
270
+ offset?: number;
271
+ profile_id?: string;
272
+ external_id?: string;
273
+ metadata?: {
274
+ [key: string]: string | number | boolean;
275
+ };
276
+ scheduled_after?: string;
277
+ scheduled_before?: string;
278
+ updated_after?: string;
279
+ status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
280
+ }];
281
+ infinite: (query?: Omit<ListPostsQuery, "limit" | "offset">) => readonly ["postrun", "posts", "list", "infinite", Omit<{
282
+ limit?: number;
283
+ offset?: number;
284
+ profile_id?: string;
285
+ external_id?: string;
286
+ metadata?: {
287
+ [key: string]: string | number | boolean;
288
+ };
289
+ scheduled_after?: string;
290
+ scheduled_before?: string;
291
+ updated_after?: string;
292
+ status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
293
+ }, "limit" | "offset">];
294
+ details: () => readonly ["postrun", "posts", "detail"];
295
+ detail: (id: string) => readonly ["postrun", "posts", "detail", string];
296
+ };
297
+ /** Query-key factory for media assets (list filtered by query; detail by id). */
298
+ declare const mediaKeys: {
299
+ all: readonly ["postrun", "media"];
300
+ lists: () => readonly ["postrun", "media", "list"];
301
+ list: (query?: ListMediaQuery) => readonly ["postrun", "media", "list", {
302
+ limit?: number;
303
+ offset?: number;
304
+ profile_id?: string;
305
+ status?: "uploading" | "processing" | "ready" | "failed";
306
+ kind?: "image" | "video" | "gif" | "document";
307
+ external_id?: string;
308
+ metadata?: {
309
+ [key: string]: string | number | boolean;
310
+ };
311
+ }];
312
+ infinite: (query?: Omit<ListMediaQuery, "limit" | "offset">) => readonly ["postrun", "media", "list", "infinite", Omit<{
313
+ limit?: number;
314
+ offset?: number;
315
+ profile_id?: string;
316
+ status?: "uploading" | "processing" | "ready" | "failed";
317
+ kind?: "image" | "video" | "gif" | "document";
318
+ external_id?: string;
319
+ metadata?: {
320
+ [key: string]: string | number | boolean;
321
+ };
322
+ }, "limit" | "offset">];
323
+ details: () => readonly ["postrun", "media", "detail"];
324
+ detail: (id: string) => readonly ["postrun", "media", "detail", string];
325
+ };
326
+ /** Query-key factory for connections (lists keyed by owning profile). */
327
+ declare const connectionKeys: {
328
+ all: readonly ["postrun", "connections"];
329
+ lists: () => readonly ["postrun", "connections", "list"];
330
+ list: (profileId: string, filter?: ConnectionsFilter) => readonly ["postrun", "connections", "list", string, ConnectionsFilter];
331
+ details: () => readonly ["postrun", "connections", "detail"];
332
+ detail: (id: string) => readonly ["postrun", "connections", "detail", string];
333
+ accounts: (id: string) => readonly ["postrun", "connections", "accounts", string];
334
+ };
335
+
336
+ interface UseConnectParams {
195
337
  /** The profile to attach the new connection to. */
196
338
  profileId: string;
197
339
  /** The platform to connect (X, LinkedIn, Meta, …). */
198
340
  platform: ConnectablePlatform;
341
+ /** Called once a connection is fully ACTIVE (an account is bound). */
342
+ onConnected?: (connection: Connection) => void;
199
343
  }
200
344
  /**
201
- * Start a connect flow: mint a session and redirect the browser to the hosted
202
- * connect URL on postrun.ai, where the full white-labeled OAuth journey runs and
203
- * the user is returned to the host app. Bare-bones by design — the OAuth UI is
204
- * ours and hosted, so the host app just calls `mutate({ profileId, platform })`.
205
- * On return, the new connection appears via `useConnections`.
345
+ * The connect flow's UI state. `connected_pending` is a TERMINAL success state
346
+ * the grant landed but no account is bound yet (a slow webhook, an out-of-band
347
+ * binding, or no reachable accounts); the host shows "almost there" and refetches
348
+ * its connections list. It is NOT an error and must not hang in `connecting`.
349
+ */
350
+ type ConnectState = {
351
+ phase: 'preparing';
352
+ } | {
353
+ phase: 'idle';
354
+ } | {
355
+ phase: 'connecting';
356
+ } | {
357
+ phase: 'picking';
358
+ accounts: DiscoverableAccount[];
359
+ } | {
360
+ phase: 'active';
361
+ connection: Connection;
362
+ } | {
363
+ phase: 'connected_pending';
364
+ } | {
365
+ phase: 'cancelled';
366
+ } | {
367
+ phase: 'error';
368
+ reason: ConnectErrorReason;
369
+ };
370
+ interface UseConnectResult {
371
+ /** The current flow state — drive your button + picker + status off `phase`. */
372
+ state: ConnectState;
373
+ /**
374
+ * Start the OAuth flow. MUST be called directly in the user's click handler
375
+ * (no `await` before it): it opens the OAuth popup synchronously, so the
376
+ * browser keeps it inside the user gesture. A no-op until the session is ready
377
+ * (state `preparing`) — disable the button until `phase` is `idle`.
378
+ */
379
+ start: () => void;
380
+ /** When `phase` is `picking`, activate the connection with the chosen account. */
381
+ select: (externalAccountId: string) => void;
382
+ /** Return to a fresh, ready state (re-mints the session) — e.g. a "try again". */
383
+ reset: () => void;
384
+ }
385
+ /**
386
+ * Embedded one-click connect — the customer's OWN button drives the whole OAuth
387
+ * flow IN-APP (no redirect to our hosted page). `nango.auth()` opens a popup that
388
+ * resolves in-page, then the account picker (for multi-account platforms) renders
389
+ * inside the host app via `state.accounts` + `select()`. White-label, one click.
390
+ *
391
+ * The Plaid pattern: the Nango session is PRE-MINTED on mount (and on `reset`),
392
+ * because `nango.auth()` opens its popup synchronously — minting in the click
393
+ * would push `window.open` out of the user gesture and the browser would block
394
+ * the popup. `start()` therefore fires `nango.auth()` with the already-held token
395
+ * and zero `await` before it.
396
+ *
397
+ * The hosted `/connect` page remains the fallback for callers NOT using this SDK
398
+ * (a plain link to `hosted_connect_url`); this hook never redirects.
399
+ */
400
+ declare function useConnect({ profileId, platform, onConnected, }: UseConnectParams): UseConnectResult;
401
+ /**
402
+ * List a profile's connected accounts. Pass a `filter` to narrow by `kind`
403
+ * (`posting` = social, `ads`) or `status` — e.g. a composer fetches
404
+ * `{ kind: 'posting' }` to show only the social accounts it can publish to.
206
405
  */
207
- declare function useConnect(): _tanstack_react_query.UseMutationResult<{
208
- connect_session_token: string;
209
- connect_url: string;
210
- expires_at: string;
211
- }, Error, ConnectParams, unknown>;
212
- /** List a profile's connected accounts. */
213
- declare function useConnections(profileId: string): _tanstack_react_query.UseQueryResult<NoInfer<{
406
+ declare function useConnections(profileId: string, filter?: ConnectionsFilter): _tanstack_react_query.UseQueryResult<NoInfer<{
214
407
  object: "list";
215
408
  data: Array<{
216
409
  id: string;
217
410
  profile_id: string;
218
411
  platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
412
+ kind: "posting" | "ads";
413
+ status: "pending" | "active" | "needs_reauth";
219
414
  external_account_id: string | null;
220
415
  external_account_name: string | null;
416
+ username: string | null;
417
+ avatar_url: string | null;
418
+ profile_url: string | null;
419
+ reauth_at: string | null;
221
420
  currency: string | null;
222
421
  created_at: string | null;
223
422
  updated_at: string | null;
@@ -232,8 +431,14 @@ declare function useConnection(id: string): _tanstack_react_query.UseQueryResult
232
431
  id: string;
233
432
  profile_id: string;
234
433
  platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
434
+ kind: "posting" | "ads";
435
+ status: "pending" | "active" | "needs_reauth";
235
436
  external_account_id: string | null;
236
437
  external_account_name: string | null;
438
+ username: string | null;
439
+ avatar_url: string | null;
440
+ profile_url: string | null;
441
+ reauth_at: string | null;
237
442
  currency: string | null;
238
443
  created_at: string | null;
239
444
  updated_at: string | null;
@@ -245,9 +450,15 @@ declare function useDiscoverableAccounts(id: string): _tanstack_react_query.UseQ
245
450
  external_account_id: string;
246
451
  name: string | null;
247
452
  currency: string | null;
453
+ username?: string | null;
454
+ avatar_url?: string | null;
455
+ profile_url?: string | null;
248
456
  instagram?: {
249
457
  external_account_id: string;
250
458
  name: string | null;
459
+ username?: string | null;
460
+ avatar_url?: string | null;
461
+ profile_url?: string | null;
251
462
  } | null;
252
463
  }>;
253
464
  }>, Error>;
@@ -256,8 +467,14 @@ declare function useSelectAccount(): _tanstack_react_query.UseMutationResult<{
256
467
  id: string;
257
468
  profile_id: string;
258
469
  platform: "meta_ads" | "google_ads" | "tiktok_ads" | "x" | "linkedin" | "facebook_page" | "instagram" | "tiktok";
470
+ kind: "posting" | "ads";
471
+ status: "pending" | "active" | "needs_reauth";
259
472
  external_account_id: string | null;
260
473
  external_account_name: string | null;
474
+ username: string | null;
475
+ avatar_url: string | null;
476
+ profile_url: string | null;
477
+ reauth_at: string | null;
261
478
  currency: string | null;
262
479
  created_at: string | null;
263
480
  updated_at: string | null;
@@ -273,44 +490,218 @@ declare function useDisconnect(): _tanstack_react_query.UseMutationResult<{
273
490
  deleted: true;
274
491
  }, Error, string, unknown>;
275
492
 
493
+ /** The flow state + actions handed to your render-prop. */
494
+ interface ConnectRenderApi {
495
+ /** The current flow state — switch on `state.phase` to render your UI. */
496
+ state: ConnectState;
497
+ /**
498
+ * Begin connecting. Call this DIRECTLY from your button's `onClick` — it opens
499
+ * the OAuth popup synchronously, so don't `await` anything before it. A no-op
500
+ * until the session is ready (`state.phase === 'preparing'`).
501
+ */
502
+ start: () => void;
503
+ /** When `state.phase === 'picking'`, activate with the chosen account id. */
504
+ select: (externalAccountId: string) => void;
505
+ /** Reset to a fresh, ready state (e.g. a "try again" after an error/cancel). */
506
+ reset: () => void;
507
+ }
508
+ interface ConnectProps {
509
+ /** The profile to attach the new connection to. */
510
+ profileId: string;
511
+ /** The platform to connect (X, LinkedIn, Meta, …). */
512
+ platform: ConnectablePlatform;
513
+ /** Called once a connection is fully ACTIVE (an account is bound). */
514
+ onConnected?: (connection: Connection) => void;
515
+ /** Render your own button + picker + status from the flow state. */
516
+ children: (api: ConnectRenderApi) => ReactNode;
517
+ }
518
+ /**
519
+ * Headless one-click connect. Wraps `useConnect` and hands you the flow state +
520
+ * actions via a render-prop, so you own EVERY pixel (your button, your account
521
+ * picker, your brand marks, your styling) while the SDK runs the embedded OAuth
522
+ * popup + account binding — no redirect, no second click.
523
+ *
524
+ * ```tsx
525
+ * <Connect profileId={id} platform="x" onConnected={refetch}>
526
+ * {({ state, start, select }) =>
527
+ * state.phase === 'picking' ? (
528
+ * <ul>
529
+ * {state.accounts.map((a) => (
530
+ * <li key={a.external_account_id}>
531
+ * <button onClick={() => select(a.external_account_id)}>
532
+ * {a.name ?? a.external_account_id}
533
+ * </button>
534
+ * </li>
535
+ * ))}
536
+ * </ul>
537
+ * ) : (
538
+ * <button onClick={start} disabled={state.phase !== 'idle'}>
539
+ * Connect X
540
+ * </button>
541
+ * )
542
+ * }
543
+ * </Connect>
544
+ * ```
545
+ *
546
+ * The trigger MUST call `start()` directly in the click (it opens the popup
547
+ * synchronously). Mount `<Connect>` inside a `<PostrunProvider>`.
548
+ */
549
+ declare function Connect({ profileId, platform, onConnected, children, }: ConnectProps): ReactNode;
550
+
276
551
  type MediaUploadStatus = 'idle' | 'uploading' | 'processing' | 'ready' | 'failed';
277
552
  interface MediaUploadOptions {
278
553
  /** Profile that owns the asset. */
279
554
  profileId: string;
280
555
  /** Platforms to validate + render for (omit to add later via useUpdateMedia). */
281
556
  targets?: MediaTarget[];
282
- /** Override the kind inferred from the file's MIME. */
557
+ /** Optional override — omit and the API auto-detects the kind from the bytes. */
283
558
  kind?: MediaKind;
284
- /** The file's MIME type. Defaults to `file.type`; required when that's empty. */
559
+ /**
560
+ * Optional override — omit and the API auto-detects the MIME from the bytes.
561
+ * Still useful for a legacy Office binary (.doc/.ppt) whose magic bytes can't be
562
+ * disambiguated by the server sniff.
563
+ */
285
564
  contentType?: string;
286
565
  /** Store as-is with zero processing. */
287
566
  raw?: boolean;
288
567
  altText?: string;
289
568
  externalId?: string;
290
- metadata?: CreateMediaInput['metadata'];
569
+ metadata?: Metadata;
570
+ }
571
+ /** One file's slot in an upload — its own live status, progress, and settled
572
+ * asset. `status` is never `idle` (an item exists only once uploading). */
573
+ interface MediaUploadItem {
574
+ /** Stable local id (NOT the asset id) — use as the React key and for `remove`. */
575
+ id: string;
576
+ file: File;
577
+ status: Exclude<MediaUploadStatus, 'idle'>;
578
+ /** 0–1 client-side BYTE-upload bar. `media.progress.{stage,percent}` is the
579
+ * live SERVER pipeline bar. */
580
+ progress: number;
581
+ media: MediaResource | null;
582
+ error: unknown;
583
+ }
584
+ interface UseMediaUploadResult {
585
+ /** Every file added, in add-order, with its live state. */
586
+ items: readonly MediaUploadItem[];
587
+ /** The settled-ready assets, in item order — what you attach to a post. */
588
+ ready: readonly MediaResource[];
589
+ /** True while any item is still uploading or processing. */
590
+ isUploading: boolean;
591
+ /**
592
+ * Upload ONE file or MANY under `options`, gated by `concurrency`. The reactive
593
+ * `items` update live for UI; the returned promise is for imperative flows —
594
+ * it resolves to the settled (`ready`|`failed`) resources for THIS batch, in
595
+ * add-order, EXCLUDING any item removed/aborted mid-flight. Single-file usage:
596
+ * `const [asset] = await add(file, opts)`.
597
+ */
598
+ add: (files: File | FileList | readonly File[], options: MediaUploadOptions) => Promise<MediaResource[]>;
599
+ /** Drop an item by local id — aborts it if still in flight. */
600
+ remove: (id: string) => void;
601
+ /** Abort everything and clear the list. */
602
+ reset: () => void;
603
+ }
604
+ interface UseMediaUploadOptions {
605
+ /**
606
+ * How many files upload at once; the rest queue (default 3). Fixed for the
607
+ * hook's lifetime — set it once when you call the hook.
608
+ */
609
+ concurrency?: number;
291
610
  }
292
611
  /**
293
- * Upload a file and get back a platform-validated asset. The hook owns the whole
294
- * journey: infer kind/content_type from the `File`, create the asset, PUT the
295
- * bytes with live `progress` + retry, poll until processing settles, and expose
296
- * `media.per_platform` (per-target status, url, warnings, errors). `cancel()`
297
- * aborts an in-flight upload.
612
+ * Upload one OR many files and get back platform-validated assets. The hook owns
613
+ * the whole journey per file: create the asset (the API auto-detects
614
+ * kind/content_type from the bytes), PUT the bytes with live `progress` + retry,
615
+ * poll until processing settles, and expose `media.per_platform` (per-target
616
+ * status, url, warnings,
617
+ * errors). Every file gets its own `MediaUploadItem` slot in `items`; `ready` is
618
+ * the settled assets to attach to a post; `remove`/`reset` abort in-flight work.
619
+ * Uploads run through ONE shared `p-limit` gate so only `concurrency` (default 3)
620
+ * are in flight at once — global across `add` calls, not per-call.
621
+ *
622
+ * Single-file usage: `const [asset] = await add(file, opts)` (or read `ready[0]`).
298
623
  */
299
- declare function useMediaUpload(): {
300
- upload: (file: File, options: MediaUploadOptions) => Promise<MediaResource>;
301
- cancel: () => void | undefined;
302
- reset: () => void;
303
- status: MediaUploadStatus;
304
- progress: number;
305
- media: {
624
+ declare function useMediaUpload(options?: UseMediaUploadOptions): UseMediaUploadResult;
625
+ /** Retrieve a media asset; auto-polls while it is still uploading/processing. */
626
+ declare function useMedia(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
627
+ id: string;
628
+ object: "media";
629
+ profile_id: string;
630
+ kind: "image" | "video" | "gif" | "document" | null;
631
+ content_type: string | null;
632
+ status: "uploading" | "processing" | "ready" | "failed";
633
+ progress: {
634
+ stage: "queued" | "analyzing" | "transcoding" | "done";
635
+ percent: number;
636
+ };
637
+ raw: boolean;
638
+ error: {
639
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
640
+ message: string;
641
+ hint?: string;
642
+ allowed?: Array<string>;
643
+ got?: string;
644
+ } | null;
645
+ source: {
646
+ format: string;
647
+ bytes: number;
648
+ width: number | null;
649
+ height: number | null;
650
+ duration_ms: number | null;
651
+ } | null;
652
+ alt_text: string | null;
653
+ per_platform: {
654
+ [key: string]: {
655
+ status: "processing" | "ready" | "failed";
656
+ url: string | null;
657
+ width: number | null;
658
+ height: number | null;
659
+ bytes: number | null;
660
+ warnings: Array<{
661
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
662
+ message: string;
663
+ hint?: string;
664
+ allowed?: Array<string>;
665
+ got?: string;
666
+ }>;
667
+ errors: Array<{
668
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
669
+ message: string;
670
+ hint?: string;
671
+ allowed?: Array<string>;
672
+ got?: string;
673
+ }>;
674
+ };
675
+ };
676
+ external_id: string | null;
677
+ metadata: {
678
+ [key: string]: string | number | boolean;
679
+ };
680
+ created_at: string;
681
+ updated_at: string;
682
+ }>, Error>;
683
+ /**
684
+ * List media assets under the account, newest first. Filter by `profile_id`,
685
+ * `status`, `kind`, your own `external_id`, or `metadata` (exact-match
686
+ * containment), with offset `limit`/`offset` pagination. Returns one page; use
687
+ * `useMediaInfinite` for a load-more feed.
688
+ */
689
+ declare function useMediaList(query?: ListMediaQuery): _tanstack_react_query.UseQueryResult<NoInfer<{
690
+ object: "list";
691
+ data: Array<{
306
692
  id: string;
307
693
  object: "media";
308
694
  profile_id: string;
309
- kind: "image" | "video" | "gif" | "document";
695
+ kind: "image" | "video" | "gif" | "document" | null;
696
+ content_type: string | null;
310
697
  status: "uploading" | "processing" | "ready" | "failed";
698
+ progress: {
699
+ stage: "queued" | "analyzing" | "transcoding" | "done";
700
+ percent: number;
701
+ };
311
702
  raw: boolean;
312
703
  error: {
313
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
704
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
314
705
  message: string;
315
706
  hint?: string;
316
707
  allowed?: Array<string>;
@@ -332,14 +723,14 @@ declare function useMediaUpload(): {
332
723
  height: number | null;
333
724
  bytes: number | null;
334
725
  warnings: Array<{
335
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
726
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
336
727
  message: string;
337
728
  hint?: string;
338
729
  allowed?: Array<string>;
339
730
  got?: string;
340
731
  }>;
341
732
  errors: Array<{
342
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
733
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
343
734
  message: string;
344
735
  hint?: string;
345
736
  allowed?: Array<string>;
@@ -353,19 +744,33 @@ declare function useMediaUpload(): {
353
744
  };
354
745
  created_at: string;
355
746
  updated_at: string;
356
- } | null;
357
- error: unknown;
358
- };
359
- /** Retrieve a media asset; auto-polls while it is still uploading/processing. */
360
- declare function useMedia(id: string): _tanstack_react_query.UseQueryResult<NoInfer<{
747
+ }>;
748
+ total: number;
749
+ limit: number;
750
+ offset: number;
751
+ has_more: boolean;
752
+ }>, Error>;
753
+ /**
754
+ * Load-more / infinite-scroll view over the media list — same filters as
755
+ * `useMediaList` minus pagination, which the helper drives. Returns
756
+ * `{ items, total, loadMore, hasMore, … }`.
757
+ */
758
+ declare function useMediaInfinite(filters?: Omit<ListMediaQuery, 'limit' | 'offset'>, options?: {
759
+ pageSize?: number;
760
+ }): InfiniteList<{
361
761
  id: string;
362
762
  object: "media";
363
763
  profile_id: string;
364
- kind: "image" | "video" | "gif" | "document";
764
+ kind: "image" | "video" | "gif" | "document" | null;
765
+ content_type: string | null;
365
766
  status: "uploading" | "processing" | "ready" | "failed";
767
+ progress: {
768
+ stage: "queued" | "analyzing" | "transcoding" | "done";
769
+ percent: number;
770
+ };
366
771
  raw: boolean;
367
772
  error: {
368
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
773
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
369
774
  message: string;
370
775
  hint?: string;
371
776
  allowed?: Array<string>;
@@ -387,14 +792,14 @@ declare function useMedia(id: string): _tanstack_react_query.UseQueryResult<NoIn
387
792
  height: number | null;
388
793
  bytes: number | null;
389
794
  warnings: Array<{
390
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
795
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
391
796
  message: string;
392
797
  hint?: string;
393
798
  allowed?: Array<string>;
394
799
  got?: string;
395
800
  }>;
396
801
  errors: Array<{
397
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
802
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
398
803
  message: string;
399
804
  hint?: string;
400
805
  allowed?: Array<string>;
@@ -408,17 +813,22 @@ declare function useMedia(id: string): _tanstack_react_query.UseQueryResult<NoIn
408
813
  };
409
814
  created_at: string;
410
815
  updated_at: string;
411
- }>, Error>;
816
+ }>;
412
817
  /** Update a media asset: alt text / metadata / external_id, or extend targets. */
413
818
  declare function useUpdateMedia(): _tanstack_react_query.UseMutationResult<{
414
819
  id: string;
415
820
  object: "media";
416
821
  profile_id: string;
417
- kind: "image" | "video" | "gif" | "document";
822
+ kind: "image" | "video" | "gif" | "document" | null;
823
+ content_type: string | null;
418
824
  status: "uploading" | "processing" | "ready" | "failed";
825
+ progress: {
826
+ stage: "queued" | "analyzing" | "transcoding" | "done";
827
+ percent: number;
828
+ };
419
829
  raw: boolean;
420
830
  error: {
421
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
831
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
422
832
  message: string;
423
833
  hint?: string;
424
834
  allowed?: Array<string>;
@@ -440,14 +850,14 @@ declare function useUpdateMedia(): _tanstack_react_query.UseMutationResult<{
440
850
  height: number | null;
441
851
  bytes: number | null;
442
852
  warnings: Array<{
443
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
853
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
444
854
  message: string;
445
855
  hint?: string;
446
856
  allowed?: Array<string>;
447
857
  got?: string;
448
858
  }>;
449
859
  errors: Array<{
450
- code: "media_unprobeable" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
860
+ code: "media_unprobeable" | "media_format_indeterminate" | "media_too_large" | "media_aspect_ratio_unsupported" | "media_resolution_too_low" | "media_gif_unsupported" | "media_format_recompressed" | "media_resolution_downscaled" | "video_container_unsupported" | "video_codec_unsupported" | "video_audio_codec_unsupported" | "video_too_large" | "video_too_small" | "video_dimensions_unsupported" | "video_dimensions_too_large" | "video_fps_unsupported" | "video_fps_too_low" | "video_aspect_unsupported" | "video_duration_too_short" | "video_duration_exceeds_max" | "video_transform_failed" | "media_fetch_failed" | "document_format_unsupported" | "document_too_large" | "document_too_many_pages" | "media_unsupported";
451
861
  message: string;
452
862
  hint?: string;
453
863
  allowed?: Array<string>;
@@ -829,7 +1239,7 @@ declare function useCreatePost(profileId: string): {
829
1239
  } | undefined;
830
1240
  reset: () => void;
831
1241
  isReady: boolean;
832
- connectedChannels: ("x" | "linkedin" | "facebook_page" | "instagram")[];
1242
+ connectedChannels: ("x" | "linkedin" | "facebook_page" | "instagram" | "tiktok")[];
833
1243
  };
834
1244
  /**
835
1245
  * Update a post by id. Pass a light edit directly (`{ schedule_at }`,
@@ -1002,6 +1412,30 @@ declare function useUpdatePost(postId: string): _tanstack_react_query.UseMutatio
1002
1412
  settings?: {
1003
1413
  link?: string;
1004
1414
  };
1415
+ } | {
1416
+ platform: "tiktok";
1417
+ post_type: "video" | "single_image" | "carousel";
1418
+ connection_id: string;
1419
+ body?: string;
1420
+ media?: Array<{
1421
+ media_id: string;
1422
+ crop_box?: {
1423
+ [key: string]: unknown;
1424
+ } | null;
1425
+ alt_text_override?: string | null;
1426
+ }>;
1427
+ settings?: {
1428
+ privacy_level?: "PUBLIC_TO_EVERYONE" | "MUTUAL_FOLLOW_FRIENDS" | "FOLLOWER_OF_CREATOR" | "SELF_ONLY";
1429
+ disable_comment?: boolean;
1430
+ disable_duet?: boolean;
1431
+ disable_stitch?: boolean;
1432
+ video_cover_timestamp_ms?: number;
1433
+ photo_cover_index?: number;
1434
+ auto_add_music?: boolean;
1435
+ brand_content_toggle?: boolean;
1436
+ brand_organic_toggle?: boolean;
1437
+ is_aigc?: boolean;
1438
+ };
1005
1439
  }>;
1006
1440
  }, unknown>;
1007
1441
  /** Delete a post by id; on success the lists refresh and its detail is dropped. */
@@ -1011,81 +1445,6 @@ declare function useDeletePost(): _tanstack_react_query.UseMutationResult<{
1011
1445
  deleted: true;
1012
1446
  }, Error, string, unknown>;
1013
1447
 
1014
- /**
1015
- * Query-key factory for profiles. Hierarchical so a mutation can invalidate at
1016
- * the right granularity: `lists()` after a create, `detail(id)` after an update.
1017
- */
1018
- declare const profileKeys: {
1019
- all: readonly ["postrun", "profiles"];
1020
- lists: () => readonly ["postrun", "profiles", "list"];
1021
- list: (query?: ListProfilesQuery) => readonly ["postrun", "profiles", "list", {
1022
- limit?: number;
1023
- offset?: number;
1024
- external_id?: string;
1025
- metadata?: {
1026
- [key: string]: string | number | boolean;
1027
- };
1028
- }];
1029
- infinite: (query?: ListProfilesQuery) => readonly ["postrun", "profiles", "list", "infinite", {
1030
- limit?: number;
1031
- offset?: number;
1032
- external_id?: string;
1033
- metadata?: {
1034
- [key: string]: string | number | boolean;
1035
- };
1036
- }];
1037
- details: () => readonly ["postrun", "profiles", "detail"];
1038
- detail: (id: string) => readonly ["postrun", "profiles", "detail", string];
1039
- };
1040
- /** Query-key factory for posts (list filtered by query; detail by id). */
1041
- declare const postKeys: {
1042
- all: readonly ["postrun", "posts"];
1043
- lists: () => readonly ["postrun", "posts", "list"];
1044
- list: (query?: ListPostsQuery) => readonly ["postrun", "posts", "list", {
1045
- limit?: number;
1046
- offset?: number;
1047
- profile_id?: string;
1048
- external_id?: string;
1049
- metadata?: {
1050
- [key: string]: string | number | boolean;
1051
- };
1052
- scheduled_after?: string;
1053
- scheduled_before?: string;
1054
- updated_after?: string;
1055
- status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
1056
- }];
1057
- infinite: (query?: ListPostsQuery) => readonly ["postrun", "posts", "list", "infinite", {
1058
- limit?: number;
1059
- offset?: number;
1060
- profile_id?: string;
1061
- external_id?: string;
1062
- metadata?: {
1063
- [key: string]: string | number | boolean;
1064
- };
1065
- scheduled_after?: string;
1066
- scheduled_before?: string;
1067
- updated_after?: string;
1068
- status?: Array<"draft" | "scheduled" | "publishing" | "partially_published" | "published" | "failed">;
1069
- }];
1070
- details: () => readonly ["postrun", "posts", "detail"];
1071
- detail: (id: string) => readonly ["postrun", "posts", "detail", string];
1072
- };
1073
- /** Query-key factory for media assets (single-asset only; no list endpoint yet). */
1074
- declare const mediaKeys: {
1075
- all: readonly ["postrun", "media"];
1076
- details: () => readonly ["postrun", "media", "detail"];
1077
- detail: (id: string) => readonly ["postrun", "media", "detail", string];
1078
- };
1079
- /** Query-key factory for connections (lists keyed by owning profile). */
1080
- declare const connectionKeys: {
1081
- all: readonly ["postrun", "connections"];
1082
- lists: () => readonly ["postrun", "connections", "list"];
1083
- list: (profileId: string) => readonly ["postrun", "connections", "list", string];
1084
- details: () => readonly ["postrun", "connections", "detail"];
1085
- detail: (id: string) => readonly ["postrun", "connections", "detail", string];
1086
- accounts: (id: string) => readonly ["postrun", "connections", "accounts", string];
1087
- };
1088
-
1089
1448
  /**
1090
1449
  * Public input types for the post-preview components. These describe data the
1091
1450
  * CUSTOMER supplies for presentation — NOT shapes from our OpenAPI contract — so
@@ -1234,4 +1593,4 @@ declare function LinkedInPostPreviewImpl({ variant, author, media, theme, time,
1234
1593
  * absorbs unstable media arrays). */
1235
1594
  declare const LinkedInPostPreview: react.MemoExoticComponent<typeof LinkedInPostPreviewImpl>;
1236
1595
 
1237
- export { type CalendarFilters, type ConnectParams, type InfiniteList, LinkedInPostPreview, type LinkedInPostPreviewProps, type LinkedInPreviewAuthor, type LiveOptions, type MediaUploadOptions, type MediaUploadStatus, type PostrunContextValue, PostrunProvider, type PostrunProviderProps, type PreviewMedia, type PreviewMediaKind, UploadError, XPostPreview, type XPostPreviewProps, type XPreviewAuthor, type XPreviewMedia, type XPreviewQuotedTweet, connectionKeys, mediaKeys, postKeys, profileKeys, useCalendar, useConnect, useConnection, useConnections, useCreatePost, useCreateProfile, useDeleteMedia, useDeletePost, useDeleteProfile, useDisconnect, useDiscoverableAccounts, useInfiniteList, useMedia, useMediaUpload, usePost, usePostrun, usePosts, usePostsInfinite, useProfile, useProfiles, useProfilesInfinite, useSelectAccount, useUpdateMedia, useUpdatePost, useUpdateProfile };
1596
+ export { type CalendarFilters, Connect, type ConnectErrorReason, type ConnectOutcome, type ConnectProps, type ConnectRenderApi, type ConnectState, type ConnectionsFilter, type DiscoverableAccount, type InfiniteList, LinkedInPostPreview, type LinkedInPostPreviewProps, type LinkedInPreviewAuthor, type LiveOptions, type MediaUploadItem, type MediaUploadOptions, type MediaUploadStatus, type PostrunContextValue, PostrunProvider, type PostrunProviderProps, type PreviewMedia, type PreviewMediaKind, UploadError, type UseConnectParams, type UseConnectResult, type UseMediaUploadOptions, type UseMediaUploadResult, XPostPreview, type XPostPreviewProps, type XPreviewAuthor, type XPreviewMedia, type XPreviewQuotedTweet, connectionKeys, mediaKeys, postKeys, profileKeys, useCalendar, useConnect, useConnection, useConnections, useCreatePost, useCreateProfile, useDeleteMedia, useDeletePost, useDeleteProfile, useDisconnect, useDiscoverableAccounts, useInfiniteList, useMedia, useMediaInfinite, useMediaList, useMediaUpload, usePost, usePostrun, usePosts, usePostsInfinite, useProfile, useProfiles, useProfilesInfinite, useSelectAccount, useUpdateMedia, useUpdatePost, useUpdateProfile };