@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/README.md +59 -5
- package/dist/index.cjs +421 -117
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +483 -124
- package/dist/index.d.ts +483 -124
- package/dist/index.js +417 -118
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/dist/index.d.cts
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,
|
|
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
|
-
|
|
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
|
-
*
|
|
202
|
-
*
|
|
203
|
-
*
|
|
204
|
-
*
|
|
205
|
-
|
|
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
|
|
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
|
-
/**
|
|
557
|
+
/** Optional override — omit and the API auto-detects the kind from the bytes. */
|
|
283
558
|
kind?: MediaKind;
|
|
284
|
-
/**
|
|
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?:
|
|
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
|
|
294
|
-
*
|
|
295
|
-
* bytes with live `progress` + retry,
|
|
296
|
-
* `media.per_platform` (per-target
|
|
297
|
-
*
|
|
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
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
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
|
-
}
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
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
|
-
}
|
|
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
|
|
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 };
|