← Public packages
@kentcdodds/x
X API v2 helpers for tweets, search, legacy DMs, and encrypted X Chat via a Fly XDK sidecar.
src/types.ts
450 lines · 11.1 KB · TypeScriptimport type { QueryInput, XAuthMode } from './openapi-client.ts'
export type { QueryInput, XAuthMode }
export type JsonRecord = Record<string, unknown>
/**
* Multi-account selection for OAuth user-context calls.
* Convention: omit for default integration `x`; `account: 'brand'` → `x-brand`.
* Prefer `integration` when you already know the exact saved integration name.
*/
export type XAccountParams = {
account?: string
integration?: string
}
export type ResolvedXOAuth = {
integrationName: string
/** Null for the default `x` integration. */
account: string | null
/** Legacy secret mirror name when present; null for connection-stored tokens. */
accessTokenSecretName: string | null
/** Legacy secret mirror name when present; null for connection-stored tokens. */
refreshTokenSecretName: string | null
/** Non-secret OAuth client id, stored inline on the integration's OAuth app. */
clientId: string
accessTokenPlaceholder: string | null
refreshTokenPlaceholder: string | null
}
export type XAccountSummary = {
/** Null for the default `x` integration. */
account: string | null
integration: string
default: boolean
accessTokenSecretName: string | null
useWhen: string
}
export type XUser = JsonRecord & {
id?: string
name?: string
username?: string
verified?: boolean
description?: string
created_at?: string
public_metrics?: JsonRecord
url?: string
location?: string
}
export type XPost = JsonRecord & {
id?: string
text?: string
author_id?: string
created_at?: string
conversation_id?: string
public_metrics?: JsonRecord
referenced_tweets?: unknown[]
entities?: JsonRecord
note_tweet?: JsonRecord
}
export type XApiResponse<T = unknown> = {
data?: T
includes?: JsonRecord
meta?: JsonRecord
errors?: unknown[]
title?: string
detail?: string
type?: string
status?: number
rateLimit?: XRateLimitInfo
}
export type XRateLimitInfo = {
limit?: string | null
remaining?: string | null
reset?: string | null
}
export type XDryRunResult = {
dryRun: true
action?: string
method?: string
url?: string
authMode?: XAuthMode
body?: unknown
payload?: JsonRecord
requiresConfirm: true
/** Present on create-post / reply-post dry-run and confirm results. */
mode?: 'reply' | 'standalone'
/** Parent tweet id when mode is reply. */
inReplyToTweetId?: string
parentId?: string
/** Reply text before leading @handle strip (create-post / reply-post). */
originalText?: string
/** Text that will be / was sent (after reply @handle strip when applicable). */
text?: string
/** Leading @handles removed because X auto-prefixes reply-chain mentions. */
strippedHandles?: string[]
/** User ids omitted from X auto reply-chain mentions (create-post / reply-post). */
excludeReplyUserIds?: string[]
/** Snake alias echoed alongside excludeReplyUserIds. */
exclude_reply_user_ids?: string[]
}
export type XRequestParams = XAccountParams & {
path: string
method?: string
query?: QueryInput
body?: JsonRecord | null
authMode?: XAuthMode
dryRun?: boolean
confirm?: boolean
refreshOnUnauthorized?: boolean
accessToken?: string
}
export type XRefreshTokenParams = XAccountParams & {
internal?: boolean
}
export type XGetMeParams = XAccountParams & {
userFields?: string
}
export type XGetUserByUsernameParams = XAccountParams & {
username: string
userFields?: string
authMode?: XAuthMode
}
export type XSearchRecentParams = XAccountParams & {
query: string
maxResults?: number
max_results?: number
/** Maps to X API `tweet.fields`. */
postFields?: string
expansions?: string
userFields?: string
authMode?: XAuthMode
}
export type XGetUserPostsParams = XAccountParams & {
id: string
maxResults?: number
max_results?: number
paginationToken?: string
pagination_token?: string
/** Maps to X API `tweet.fields` (resource is still tweets). */
postFields?: string
expansions?: string
/**
* When true, request `exclude=retweets,replies` and also drop residual
* `RT @` / leading-`@` reply patterns that the exclude query sometimes leaves.
*/
originalsOnly?: boolean
/** Passed through as X API `exclude` (e.g. `retweets,replies`). Ignored when originalsOnly sets it. */
exclude?: string
authMode?: XAuthMode
}
export type XGetPostParams = XAccountParams & {
id?: string
postId?: string
/** x.com / twitter.com status URL — id is parsed from the path. */
url?: string
/** Maps to X API `tweet.fields`. */
postFields?: string
expansions?: string
userFields?: string
authMode?: XAuthMode
/**
* When true, also GET `/tweets/:id/quote_tweets` (small page).
* Default false — quote_tweets is rate-limited; expand referenced quoted post via expansions instead.
*/
includeQuotePosts?: boolean
/** max_results for quote_tweets when includeQuotePosts. Default 10, hard cap 25. */
quoteMaxResults?: number
}
export type XGetPostThreadParams = XAccountParams & {
id?: string
postId?: string
url?: string
/** Bounded search-recent page size for conversation replies. Default 20, hard cap 50. */
maxResults?: number
max_results?: number
postFields?: string
expansions?: string
userFields?: string
authMode?: XAuthMode
}
export type XPublicMetrics = {
impression_count?: number
like_count?: number
reply_count?: number
retweet_count?: number
bookmark_count?: number
quote_count?: number
[key: string]: unknown
}
export type XPostMetricsInput = {
id?: string
public_metrics?: XPublicMetrics | JsonRecord | null
[key: string]: unknown
}
export type XSummarizePostMetricsSort =
| 'likesPer1k'
| 'bookmarksPer1k'
| 'repliesPer1k'
| 'quotesPer1k'
| 'engagementPer1k'
| 'impressions'
| 'likes'
| 'replies'
| 'retweets'
| 'bookmarks'
| 'quotes'
export type XSummarizePostMetricsParams = XAccountParams & {
posts?: XPostMetricsInput[]
post?: XPostMetricsInput
ids?: string[]
id?: string
url?: string
sort?: XSummarizePostMetricsSort
/**
* `lowLikeHighImpression`: impressions at/above median AND likesPer1k
* strictly below median (among rows with impressions > 0).
*/
filter?: 'lowLikeHighImpression'
authMode?: XAuthMode
}
export type XCreatePostParams = XAccountParams & {
text: string
/** X API reply object. Prefer this shape. */
reply?: {
in_reply_to_tweet_id: string
exclude_reply_user_ids?: string[]
excludeReplyUserIds?: string[]
}
/** Alias → reply.in_reply_to_tweet_id (mapped; unknown keys still rejected). */
replyTo?: string
/** Alias → reply.in_reply_to_tweet_id */
inReplyTo?: string
/** Alias → reply.in_reply_to_tweet_id */
inReplyToTweetId?: string
/** Alias → reply.exclude_reply_user_ids (omit users from auto reply-chain mentions). */
excludeReplyUserIds?: string[]
/** Alias → reply.exclude_reply_user_ids */
exclude_reply_user_ids?: string[]
quote_tweet_id?: string
quotePostId?: string
media?: JsonRecord
poll?: JsonRecord
direct_message_deep_link?: string
directMessageDeepLink?: string
for_super_followers_only?: boolean
forSuperFollowersOnly?: boolean
dryRun?: boolean
confirm?: boolean
}
export type XDeletePostParams = XAccountParams & {
id: string
dryRun?: boolean
confirm?: boolean
}
export type XPostActionParams = XAccountParams & {
/** Post/status id (X API resource is still a tweet). */
postId?: string
id?: string
userId?: string
dryRun?: boolean
confirm?: boolean
}
export type XUserActionParams = XAccountParams & {
username?: string
userId?: string
targetUserId?: string
id?: string
dryRun?: boolean
confirm?: boolean
}
export type XDmEvent = JsonRecord & {
id?: string
event_type?: string
text?: string
sender_id?: string
created_at?: string
dm_conversation_id?: string
attachments?: JsonRecord
referenced_tweets?: unknown[]
}
/**
* DM target selection: exactly one of `conversationId`, `participantId`,
* `username`, or `participantIds` (group creation).
*/
export type XDmTargetParams = {
conversationId?: string
dm_conversation_id?: string
participantId?: string
participant_id?: string
username?: string
/** Two or more user ids — creates a new group DM conversation. */
participantIds?: string[]
participant_ids?: string[]
}
export type XSendDmParams = XAccountParams &
XDmTargetParams & {
text?: string
/** Shorthand for attachments: [{ media_id }]. */
mediaId?: string
media_id?: string
attachments?: JsonRecord[]
dryRun?: boolean
confirm?: boolean
/**
* Optional stable key for one logical DM. Same `(account, idempotencyKey)`
* within 7 days returns the prior successful send result instead of sending
* again. Different keys are different sends. dryRun / unconfirmed calls ignore this.
*/
idempotencyKey?: string
}
export type XDmReadParams = XAccountParams & {
maxResults?: number
max_results?: number
paginationToken?: string
pagination_token?: string
/** Comma-separated subset of MessageCreate,ParticipantsJoin,ParticipantsLeave. */
eventTypes?: string
event_types?: string
dmEventFields?: string
expansions?: string
userFields?: string
}
export type XListDmEventsParams = XDmReadParams
export type XGetDmConversationParams = XDmReadParams & {
conversationId?: string
dm_conversation_id?: string
participantId?: string
participant_id?: string
username?: string
}
export type XChatSidecarParams = {
/** Override the Fly sidecar origin. Else package storage `xChatSidecarUrl`, else owner-config default. */
sidecarUrl?: string
}
export type XListChatConversationsParams = XAccountParams &
XChatSidecarParams & {
maxResults?: number
max_results?: number
paginationToken?: string
pagination_token?: string
}
export type XGetChatConversationParams = XAccountParams &
XChatSidecarParams & {
conversationId?: string
conversation_id?: string
participantId?: string
participant_id?: string
username?: string
maxResults?: number
max_results?: number
paginationToken?: string
pagination_token?: string
}
export type XSendChatParams = XAccountParams &
XChatSidecarParams & {
conversationId?: string
conversation_id?: string
participantId?: string
participant_id?: string
username?: string
text?: string
dryRun?: boolean
confirm?: boolean
/**
* Optional stable key for one logical Chat message. Same `(account, idempotencyKey)`
* within 7 days returns the prior successful send result instead of sending
* again. Different keys are different sends. dryRun / unconfirmed calls ignore this.
*/
idempotencyKey?: string
}
export type XChatSigningKey = {
user_id: string
public_key_version: string
public_key: string
identity_public_key: string
identity_public_key_signature: string
}
export type XChatPublicKeyRecord = JsonRecord & {
public_key?: string
signing_public_key?: string
identity_public_key?: string
identity_public_key_signature?: string
public_key_version?: string | number
juicebox_config?: JsonRecord | string
}
export type XChatConversation = JsonRecord & {
id?: string
type?: string
participant_ids?: string[]
is_muted?: boolean
}
export type XChatMessage = {
id?: string
type?: string
senderId?: string
createdAt?: string
text?: string | null
conversationId?: string
}
export type XUserSummary = {
id?: string
username?: string
name?: string
}
export type XSmokeTestResult = {
ok: boolean
bearer?: { user: XUserSummary | null }
oauth?: { user: XUserSummary | null }
rateLimited?: boolean
note?: string
status?: number
}