40 symbols from @neontechspace/fluxerly
Functions#
createClient #
Create a bot client from a token, initially Disconnected
createClient<
F extends MessageFields | undefined = undefined
>(options: ClientOptions<F>): Client<SelectedMessage<F>>createClient<
F extends
| MessageFields | undefined
= undefined
>(
options: ClientOptions<F>
): Client<SelectedMessage<F>>Use run or connect to receive gateway events. HTTP requests work without connecting.
Always finish with shutdown unless an accepted run already manages the client's full lifetime
Parameters
options-
ClientOptions<F>
- Returns
Client<SelectedMessage<F>>
Creation and configuration
Creation validates configuration synchronously without authenticating the token or opening sockets. No timers or process signal handlers are started. Invalid options throw ConfigurationError without the rejected value. An unsupported option key, such as a misspelled logging, throws with a hint naming the closest supported key
A missing or blank token, such as an unset environment variable, throws ConfigurationError with a hint naming that likely cause. Unexpected creation failures throw SdkDefect. An option getter that throws produces code application.defect with the thrown value as the cause
Instance and caching
Hosted Fluxer is selected by default.
For a self-hosted instance, pass its root and let the SDK discover API, gateway and URL endpoints when first needed.
HTTPS and WSS are required unless that explicit instance enables allowInsecure for HTTP and WS
Caching is disabled by default.
Cache settings are copied and validated without calling retention policies or reporters.
Unknown cache or message-cache keys fail validation.
The messageFields option selects received message fields once for this client's lifetime
Connection and sharding
Gateway startup defaults to 30,000 ms, plus one second for each additional local shard when the SDK spaces Identify commands. Automatic sharding first counts communities under a separate deadline of the same length. Each assigned shard allows up to three startup attempts within that budget
An explicit sharding plan fixes this client's assigned IDs for its lifetime, while automatic sharding and a client without sharding settings may move to a larger plan when Fluxer asks for more shards. Shard zero receives direct-message gateway traffic. Request and cache limits still apply across the whole client, not separately to each shard
import { createClient } from "@neontechspace/fluxerly"
export function shardingExample(token) {
return createClient({ token, sharding: { totalShards: 4, shardIds: [0, 2] } })
}
import { createClient } from "@neontechspace/fluxerly"
export function shardingExample(token: string) {
return createClient({ token, sharding: { totalShards: 4, shardIds: [0, 2] } })
}
defineBot #
Define a bot's runBot options without its token, so a module can export them for both runBot and createTestBot from the testing entry point
Returns the same object unchanged, without copying, reading or validating it. runBot and createTestBot check the options when they are called, as they do for an inline object. The function exists for type inference: Command arguments keep their declared types, such as a text argument's value as a string, which an object annotated with BotOptions loses. TypeScript rejects a token here, so the program passes it to runBot, usually from an environment variable
defineBot<
F extends MessageFields | undefined = undefined,
S extends Readonly<Record<string, unknown>>
= Readonly<
Record<
string,
| Readonly<
Record<string, CommandArgumentDescriptor>
>
| undefined
>
>
>(
options: Omit<BotOptions<F, S>, "token">
): Omit<BotOptions<F, S>, "token">defineBot<
F extends
| MessageFields | undefined
= undefined,
S extends Readonly<
Record<string, unknown>
>
= Readonly<
Record<
string,
| Readonly<
Record<
string,
CommandArgumentDescriptor
>
>
| undefined
>
>
>(
options:
Omit<BotOptions<F, S>, "token">
): Omit<BotOptions<F, S>, "token">Parameters
options-
Omit<BotOptions<F, S>, "token">
- Returns
Omit<BotOptions<F, S>, "token">
import { defineBot, runBot } from "@neontechspace/fluxerly"
// A test imports bot and passes it to createTestBot from @neontechspace/fluxerly/testing
export const bot = defineBot({
commands: {
prefix: "!",
commands: {
greet: {
arguments: { name: { type: "text", rest: true } },
execute: ({ reply, values }) => reply(`Hello, ${values.name}!`),
},
},
},
})
// Running this file starts the bot, while importing it from a test does not
if (import.meta.main)
await runBot({ token: process.env.FLUXER_BOT_TOKEN, ...bot })
import { defineBot, runBot } from "@neontechspace/fluxerly"
// A test imports bot and passes it to createTestBot from @neontechspace/fluxerly/testing
export const bot = defineBot({
commands: {
prefix: "!",
commands: {
greet: {
arguments: { name: { type: "text", rest: true } },
execute: ({ reply, values }) => reply(`Hello, ${values.name}!`),
},
},
},
})
// Running this file starts the bot, while importing it from a test does not
if (import.meta.main) await runBot({ token: process.env.FLUXER_BOT_TOKEN, ...bot })
runBot #
Start a bot from event handlers and prefix commands, and watch its connection and subscriptions
The client is created and every handler and command is registered synchronously, before this function returns and before the gateway connects, so no event is missed and no handler runs before registration and setup complete
Invalid options, such as a misspelled option key, an unknown event name, invalid delivery settings or an invalid command, throw ConfigurationError at once. Every option is checked before any client, signal listener or request exists, even when the signal is already aborted, so misuse leaves nothing to clean up
A missing or empty token, usually from an unset environment variable, is reported like a failed run instead: Once every other option is valid, runBot returns an Err ConfigurationError with field token before any client exists. The returned ResultAsync then runs the bot until it stops. Handler contexts expose the full client
Message-create contexts also expose message and a cancellation-aware reply. Handler and command failures are reported to onError, or logged in full, without restarting them or stopping the bot. By default, SIGINT and SIGTERM request a normal stop and messages written by bots skip the events handlers and prefix commands
Set processSignals or ignoreBots to false to opt out. Stopping waits for SDK cleanup, not unrelated application Promises. Expected runner failures return Err, including ApplicationError when the setup callback or a commands register callback fails and ConfigurationError for a missing token, and SDK defects reject with SdkDefect
By default a failed run is also logged once, with code lifecycle.botFailed unless the client already logged that error, and sets process.exitCode to 1, so await runBot({...}) needs no further handling. Set reportFailure to false when the application handles the returned failure and exit status itself
A missing token or a commands-registration failure reported before client creation uses the configured logging settings, prints no stack for the missing token and masks the token after removing surrounding whitespace and one pair of matching quotes. Unusable logging settings are misuse
An option getter that throws while the options are checked throws SdkDefect with code application.defect and the thrown value as the cause, before any client exists. Other misuse and option-getter failures throw synchronously without a runner report or exit-status change, regardless of reportFailure
runBot<
F extends MessageFields | undefined = undefined,
S extends Readonly<Record<string, unknown>>
= Readonly<
Record<
string,
| Readonly<
Record<string, CommandArgumentDescriptor>
>
| undefined
>
>
>(options: BotOptions<F, S>): ResultAsync<
void,
| ConfigurationError | CriticalWorkerStoppedError
| CancelledError | ApplicationError | ConnectError
>runBot<
F extends
| MessageFields | undefined
= undefined,
S extends Readonly<
Record<string, unknown>
>
= Readonly<
Record<
string,
| Readonly<
Record<
string,
CommandArgumentDescriptor
>
>
| undefined
>
>
>(
options: BotOptions<F, S>
): ResultAsync<
void,
| ConfigurationError
| CriticalWorkerStoppedError
| CancelledError
| ApplicationError | ConnectError
>Parameters
options-
BotOptions<F, S>
- Returns
ResultAsync< void, | ConfigurationError | CriticalWorkerStoppedError | CancelledError | ApplicationError | ConnectError >ResultAsync< void, | ConfigurationError | CriticalWorkerStoppedError | CancelledError | ApplicationError | ConnectError >
Aborting the optional signal requests a normal stop, not a cancellation Err. A requested stop first stops accepting events and lets running handlers, scheduled tasks and their requests finish for up to drainMs, default 5,000 ms. Success means the client has stopped and cleanup has finished
The runner always shuts down its client, including after a failure. If an event or command subscription closes while the bot is still running, the result fails with Critical. That includes a handler or command router set to overflow "stop" whose queue overflows
The overflow is still reported to onError or logged, and the error names the event and the exceeded capacity, with the EventOverflowError as its cause. Process signal listeners are removed when the run finishes, and the runner never exits the process
import { runBot } from "@neontechspace/fluxerly"
export function pingBot(token) {
return runBot({
token,
commands: {
prefix: "!",
commands: {
ping: { execute: ({ reply }) => reply("Pong!") },
roll: {
arguments: { sides: { type: "integer", min: 2, max: 100, default: 6 } },
execute: ({ reply, values }) => reply(`${1 + Math.floor(Math.random() * values.sides)}`),
},
},
},
})
}
import { runBot } from "@neontechspace/fluxerly"
export function pingBot(token: string | undefined) {
return runBot({
token,
commands: {
prefix: "!",
commands: {
ping: { execute: ({ reply }) => reply("Pong!") },
roll: {
arguments: { sides: { type: "integer", min: 2, max: 100, default: 6 } },
execute: ({ reply, values }) => reply(`${1 + Math.floor(Math.random() * values.sides)}`),
},
},
},
})
}
Interfaces#
BotApplication #
Application details returned by application.fetch for this client's bot token
Use id to build an installation link. The bot flags show the current installation settings, and ownerId identifies the account that owns the application. The SDK freezes this result but does not cache it. Of the owner it keeps only the user ID, and it contains no redirect URIs, verification keys, client secrets or nested bot account
interface BotApplicationbot#Public -
Whether Fluxer currently permits non-owners to install this bot
boolean bot#Require Code Grant -
Whether Fluxer currently requires its OAuth2 code-grant flow for this bot
boolean description#-
Provider's application description, sourced from the bot bio and null when absent
string | null icon#-
Provider's application icon hash, null when the bot has no avatar
string | null id#-
Decimal application ID, suitable for
links.installationstring name#-
Provider application name
string owner#Id -
Decimal user ID of the account that owns the application, the ID that
guards.ownerOnly()allows when called without IDsstring
BotEventOptions #
A runBot event handler with its own delivery settings
Omitted settings use the runBot defaults: Overflow dropOldest, concurrency 8 for messageCreate or a partitioned handler and 1 otherwise, and the client.on queue limits
interface BotEventOptions<
K extends EventName,
M extends MessageCore = Message
>
extends HandlerOptions<EventMap<M>[K]>interface BotEventOptions<
K extends EventName,
M extends MessageCore = Message
>
extends HandlerOptions<
EventMap<M>[K]
>handler#-
Called for each event
BotEventHandler<K, M> onoptional#Error -
(report: FailureReport) => unknown partitionoptional#Ready -
Hold the events of a partition key until its own setup is done, as the
client.onoptionpartitionReadydoesValid only together with partition, otherwise
runBotthrowsConfigurationErrorbefore any client exists(key: string, signal: AbortSignal) => unknown(key: string, signal: AbortSignal) => unknown
Inherited from Handler: concurrency, max, max, overflow, partition
BotOptions #
Configure a bot: Client settings, event handlers, prefix commands, optional startup work and stop signals
A missing token or a commands-registration failure reported before client creation uses the configured logging settings and masks the normalized token, including a token enclosed in matching quotes. Other misuse and option-getter failures instead throw synchronously without a runner report or exit-status change
interface BotOptions<
F extends MessageFields | undefined = undefined,
S extends Readonly<Record<string, unknown>>
= Readonly<
Record<string, CommandArgumentSchema | undefined>
>
>
extends ClientOptions<F>, RunBotOptionsinterface BotOptions<
F extends
| MessageFields | undefined
= undefined,
S extends Readonly<
Record<string, unknown>
>
= Readonly<
Record<
string,
| CommandArgumentSchema
| undefined
>
>
>
extends ClientOptions<
F
>, RunBotOptionscommandsoptional#-
Prefix commands registered and attached before connecting
BotCommandsOptions<SelectedMessage<F>, S>BotCommandsOptions< SelectedMessage<F>, S > eventsoptional#-
Handlers registered before connecting and closed when the bot stops
Own enumerable entries are read once when
runBotis called. Undefined handlers are skipped. Pass a function, or an object with a handler and its own delivery settings. By defaultmessageCreateand partitioned handlers run up to 8 callbacks at a time and other events 1By default, when a queue fills, the oldest waiting event is dropped with a Warn record, and the bot keeps running. With a partition, the overflow option's rule decides which event is dropped. Bot-authored
messageCreateandmessageUpdateevents skip these handlers unlessignoreBotsis falseBotEvents<SelectedMessage<F>> ignoreoptional#Bots -
Skip
messageCreateandmessageUpdateevents whose author is a bot, including this bot's own messages, before they reach the events handlers or prefix commandsDefaults to true, so a reply cannot trigger its own handler. Set false for a bridge or logging bot that handles every message, and check
message.author.isBotwhere needed. Prefix commands follow the same setting unlesscommands.ignoreBotssets its own. A value other than a boolean throwsConfigurationErrorboolean setupoptional#-
Startup work after events and commands are registered and before the gateway connects, such as extra subscriptions, cache warm-up or scheduled tasks
The bot connects only after a returned promise settles, so no handler runs before setup finishes. Start timers and background work with
client.schedule, whose tasks belong to the bot: A requested stop lets their running work finish withindrainMs, every stop cancels the rest, and a failure reachesonErroror the logThe signal aborts when the bot begins stopping for any reason, including a requested stop before its drain, a failure and a stop while setup is still running. Pass it to SDK operations, or listen for its abort event to end other work started here, which the runner does not track or await
A throw, rejection or returned or resolved Err result stops the bot before connecting, and
runBotreturns an ErrApplicationErrorwhose source is "runBotsetup" and whose cause is the original value, such as theGuildOperationErrorof a failed read. A thrownSdkDefectremains a defect and rejects withSdkDefectThe Effect API runs setup in the bot's Scope instead, so its finalizers and scoped fibers end with the bot
( client: Client<SelectedMessage<F>>, context: { readonly signal: AbortSignal } ) => unknown( client: Client<SelectedMessage<F>>, context: { readonly signal: AbortSignal } ) => unknown
Inherited from Client: cache, connection, gateway, instance, logging, message, observe, on, rest, sharding, token, transport, uploads
Inherited from Run: drain, process, report, signal
CurrentBotApplication #
Read the authenticated bot's application identity, its owner's user ID and selected public settings
No gateway connection, application management or authorization-page navigation is performed. The GET uses shared request limits, the client's default deadline (rest, 30,000 ms unless configured) and at most two transient read retries. The frozen result is not cached
Of the owner only the user ID is kept, and redirect URIs, verification keys, client secrets and nested bot fields are excluded. Fluxer decides application visibility and installability. Input, HTTP and malformed-response failures return Bot. Closure returns ClientClosedError. Abort waits for cleanup and returns CancelledError. Unexpected failures reject with SdkDefect
interface CurrentBotApplicationimport { links } from "@neontechspace/fluxerly"
export async function applicationExample(client) {
const application = await client.application.fetch()
return application.isErr() ? application : links.installation(application.value.id, { permissions: 0n })
}
import { links, type Client } from "@neontechspace/fluxerly"
export async function applicationExample(client: Client) {
const application = await client.application.fetch()
return application.isErr() ? application : links.installation(application.value.id, { permissions: 0n })
}
fetch#
Fetch this bot token's application data from /oauth2/
Only the documented fields are returned, frozen, without cache storage, gateway events, owner profile lookup or follow-up requests. The timeoutMs option bounds this read only and does not change the gateway startup deadline. Cancelling it affects only this read and never changes the application
fetch(options?: RequestOptions): ResultAsync<
BotApplication,
| ConfigurationError | BotApplicationOperationFailure
| CancelledError
>fetch(
options?: RequestOptions
): ResultAsync<
BotApplication,
| ConfigurationError
| BotApplicationOperationFailure
| CancelledError
>Parameters
optionsoptional-
RequestOptions
- Returns
ResultAsync< BotApplication, | ConfigurationError | BotApplicationOperationFailure | CancelledError >ResultAsync< BotApplication, | ConfigurationError | BotApplicationOperationFailure | CancelledError >
CustomStatusInput #
Text, emoji and optional expiration for the bot's custom status
Fluxer makes the final checks for emoji availability, Unicode emoji semantics and whether expiration is still in the future
interface CustomStatusInputemojioptional#-
An explicit custom-emoji ID or one Unicode emoji
CustomStatusEmoji expiresoptional#At -
Future ISO-8601 expiration time
Impossible calendar dates are rejected before retaining the update. Fluxer rejects an expiry that passes before it receives the update
string textoptional#-
Status text, from 1 through 128 UTF-16 code units
string
GatewayCommands #
Send gateway commands that have no SDK method, on this client's ready shards
This is an advanced escape hatch: The SDK validates the frame locally but does not know the command's meaning, and Fluxer closes the connection, ending the client, for commands it rejects. Observe dispatch replies to these commands through the raw event, subscribing before sending. The raw event receives only opcode 0 dispatches. An opcode 12 Gateway Error reply needs a custom transport.webSocket that observes incoming frames
interface GatewayCommandssend#
Send one command frame { op, d } on a Connected local shard
The data is copied through JSON encoding when the operation starts, so later changes to it have no effect, and the encoded frame must be at most 16,384 UTF-8 bytes. Fluxer instances older than October 2026 allow 4,096 bytes and close the connection for a larger frame with 4002, which stops the shard
Undefined data is invalid. Pass null instead. Data JSON cannot encode, such as a cycle or a BigInt, fails with reason input. Heartbeat, Identify, Resume, reserved and server-only opcodes fail with reason reserved
Commands share the shard's outbound pacing with presence and request commands: At most 500 paced commands per rolling 60 seconds per session, sent in call order. The send history is kept across a Resume in the same running client and cleared for a fresh Identify
A session loaded from a SessionStore after a restart starts with an empty history. Heartbeats, Identify and Resume are never delayed. At most 500 gateway.send commands may wait per shard, and further submissions fail with reason busy until transmission or cancellation releases queue capacity
Completion means the frame was handed to the connection, not that Fluxer received or accepted it. A sent Request Guild Members command, opcode 8, counts toward the 12 member requests that members allows this client in any 11 seconds, or the children of one supervisor together, but this method never refuses one for that limit
Fluxer answers an opcode it does not define, missing data or invalid command fields with close code 4001 or 4002. The SDK treats both as permanent, so the client ends. Data must match Fluxer's command schema exactly. Observe dispatch replies through the raw event, which receives every opcode 0 dispatch the session accepts
Other replies, such as an opcode 12 Gateway Error, never reach it. Observe those through a custom transport.webSocket, without logging credentials or complete payloads. A shard that loses its connection before sending fails a waiting command with reason notReady, and the SDK never replays it after reconnecting
Each sent command is logged at Debug with code gateway.commandSent
send(
shardId: number,
op: number,
d: unknown,
options?: OperationOptions
): ResultAsync<
void,
ConfigurationError | CancelledError | GatewaySendFailure
>send(
shardId: number,
op: number,
d: unknown,
options?: OperationOptions
): ResultAsync<
void,
| ConfigurationError
| CancelledError
| GatewaySendFailure
>Parameters
shardId -
number op-
number d-
unknown optionsoptional-
OperationOptions
- Returns
ResultAsync< void, ConfigurationError | CancelledError | GatewaySendFailure >ResultAsync< void, | ConfigurationError | CancelledError | GatewaySendFailure >
Cancellation through options.signal withdraws a command that is still waiting for the pacing budget and returns
CancelledError. Withdrawal immediately releases its local queue capacity.
A command already handed to the connection cannot be withdrawn.
A malformed signal returns ConfigurationError before anything is queued. A throw from the data's own getters or
toJSON rejects with SdkDefect code application.defect and the thrown value as its cause.
Other unexpected failures reject with SdkDefect
// Commands with an SDK method, such as community counts through client.guilds.fetchCounts, use that method instead
export async function sendCustomCommand(client, command, onReply) {
// Subscribe before sending so the raw reply cannot be missed
const replies = client.on("raw", (dispatch) => {
if (dispatch.t === command.replyType)
onReply(dispatch)
})
try {
const result = await client.gateway.send(0, command.op, command.data)
if (result.isErr())
replies.close()
// Close the returned subscription once the reply has arrived
return result.map(() => replies)
}
catch (error) {
replies.close()
throw error
}
}
import type { Client, RawDispatch } from "@neontechspace/fluxerly"
// Commands with an SDK method, such as community counts through client.guilds.fetchCounts, use that method instead
export async function sendCustomCommand(
client: Client,
command: { op: number; data: unknown; replyType: string },
onReply: (reply: RawDispatch) => void,
) {
// Subscribe before sending so the raw reply cannot be missed
const replies = client.on("raw", (dispatch) => {
if (dispatch.t === command.replyType) onReply(dispatch)
})
try {
const result = await client.gateway.send(0, command.op, command.data)
if (result.isErr()) replies.close()
// Close the returned subscription once the reply has arrived
return result.map(() => replies)
} catch (error) {
replies.close()
throw error
}
}
Instance#
Find the selected Fluxer instance's endpoints and build links and asset URLs for it
The resolve method fetches the unauthenticated well-known document only when needed. Concurrent callers share that request. A successful frozen result is retained until client shutdown, without background refresh. Cancelling one caller leaves other callers using the request. The last departing caller waits for discovery cleanup
interface Instanceexport async function instanceExample(client) {
const resolved = await client.instance.resolve({ timeoutMs: 10_000 })
if (resolved.isErr())
return resolved
const channel = resolved.value.links.channel({ id: "1750000000000000000" })
return { api: resolved.value.endpoints.apiPublic, channel }
}
import type { Client } from "@neontechspace/fluxerly"
export async function instanceExample(client: Client) {
const resolved = await client.instance.resolve({ timeoutMs: 10_000 })
if (resolved.isErr()) return resolved
const channel = resolved.value.links.channel({ id: "1750000000000000000" })
return { api: resolved.value.endpoints.apiPublic, channel }
}
fetchBadges #
Read the custom badges that communities on this instance can show, by ID or one page at a time, such as the names and images for a Guild's badgeIds
It uses the client's REST slots and queue limits, and read failures retry like other reads. Nothing is cached, so keep the page and reuse it while its version is unchanged. Expected failures are GuildOperationError with operation instance.fetchBadges, or ClientClosedError
fetchBadges(
query?: InstanceBadgeQuery,
options?: RequestOptions
): ResultAsync<
InstanceBadgePage,
ConfigurationError | GuildOperationFailure | CancelledError
>fetchBadges(
query?: InstanceBadgeQuery,
options?: RequestOptions
): ResultAsync<
InstanceBadgePage,
| ConfigurationError
| GuildOperationFailure
| CancelledError
>Parameters
queryoptional-
InstanceBadgeQuery optionsoptional-
RequestOptions
- Returns
ResultAsync< InstanceBadgePage, ConfigurationError | GuildOperationFailure | CancelledError >ResultAsync< InstanceBadgePage, | ConfigurationError | GuildOperationFailure | CancelledError >
resolve#
Resolve this client's instance endpoints and its pure link and asset URL helpers
The unauthenticated discovery request is shared with other resolves, REST work or gateway startup. The timeoutMs option defaults to 30,000 for this wait only. Cancellation releases only this wait, while other users can keep the shared discovery read alive. Document, rate-limit, timeout, closure and invalid timeout-option failures are expected failures
resolve(options?: RequestOptions): ResultAsync<
ResolvedInstance,
InstanceResolveError | CancelledError
>resolve(
options?: RequestOptions
): ResultAsync<
ResolvedInstance,
| InstanceResolveError
| CancelledError
>Parameters
optionsoptional-
RequestOptions
- Returns
ResultAsync<ResolvedInstance, InstanceResolveError | CancelledError>ResultAsync< ResolvedInstance, | InstanceResolveError | CancelledError >- Fails with
Unexpected cleanup failures reject with SdkDefect, retaining safe details of any accompanying failure or interruption
InstanceBadge #
One custom badge that communities on the instance can show
The badge is frozen
interface InstanceBadgeasset#Url -
URL of the badge image
string description#-
Text shown under the name, null when the badge has none
string | null href#-
URL the badge links to, null when it links nowhere
string | null id#-
Decimal badge ID, as listed in
Guild.badgeIdsstring name#-
Badge name
string position#-
Display position as a decimal string
Badges are shown in ascending order of this value
string
InstanceBadgeLookup #
Look up specific community badges by ID
interface InstanceBadgeLookupInstanceBadgePage #
One frozen page of community badges from client
interface InstanceBadgePagebadges#-
The badges in display order
readonly InstanceBadge[] next#After -
Pass as after to read the next page
Null on the last page and for a lookup by ids
string | null version#-
Version of the instance's badge list
It changes whenever a badge is created, edited, deleted or moved, so badges kept under the same version are still current
string
InstanceBadgePageQuery #
Read one page of every community badge on the instance, in display order
interface InstanceBadgePageQueryInstanceDomainMigration #
A web domain migration announced by instance discovery, such as hosted Fluxer moving its web app to a new domain
A bot client records an enabled migration at Info when it first resolves the instance. Webhook and OAuth clients do not log it. It changes no endpoint itself
interface InstanceDomainMigrationanonymous#Rollout Basis Points -
Share of signed-out web visitors moved to the new domain, in basis points from 0 through 10,000, or null when not supplied
number | null enabled#-
Whether the instance switched the migration on
boolean standalone#Forwarding -
Whether standalone app installs are forwarded to the new domain, or null when not supplied
boolean | null
InstanceEndpoints #
Where the selected Fluxer instance hosts its services, validated from its discovery document
Services may use different origins, which selecting that instance trusts
interface InstanceEndpointsapi#Public -
Public HTTP API base
The SDK appends its documented
/v1route once, preserving any advertised prefixstring gateway#-
Gateway WebSocket base
The SDK adds its required protocol query without deriving another host
string invite#-
Invite base for instance-specific invite and vanity URLs
string media#-
Public media base for instance-specific generated asset URLs
string static#Cdn -
Static CDN base for instance-specific generated default-asset URLs
string webapp#-
Web application base for instance-specific generated navigation and installation links
string
Presence#
Set the bot's displayed status or request updates for selected community members
Outgoing status is sent to live shards assigned to this client, at least four seconds apart per shard. Member selections use separate bounded gateway requests. Neither operation has a provider acknowledgement or recipient-delivery guarantee. The SDK does not fetch membership or filter out self. Fluxer decides access and which updates are visible
interface Presenceset#
Set the bot's requested status and optional custom status, including before connecting
The input is validated and frozen when the call runs. Omitted customStatus keeps the previous request, and null clears it. Expired custom statuses are not restored after reconnect. Each shard retains at most one unsent status update, replacing it with the latest intent even while gateway pacing waits
The four-second interval starts when an update reaches the socket, not when it is queued. Success means the request was accepted locally and scheduled for each shard, not acknowledged by Fluxer. Shutdown releases this intent and its timer
set(input: PresenceInput): Result<void, PresenceFailure>set(
input: PresenceInput
): Result<void, PresenceFailure>Parameters
input-
PresenceInput
- Returns
Result<void, PresenceFailure>- Fails with
Returns a Result synchronously.
A throwing input getter throws SdkDefect with code application.defect and the thrown value as its cause, and other
unexpected failures throw SdkDefect with code sdk.defect
import { MemberMentionPreferences } from "@neontechspace/fluxerly"
export async function botProfileExample(client, guildId) {
const presence = client.presence.set({ status: "online", customStatus: { text: "Ready", emoji: { name: "🌱" } } })
if (presence.isErr())
return presence
return client.members.editSelf(guildId, { nickname: "Support", mentionFlags: MemberMentionPreferences.PreferNoMention })
}
import { MemberMentionPreferences, type Client } from "@neontechspace/fluxerly"
export async function botProfileExample(client: Client, guildId: string) {
const presence = client.presence.set({ status: "online", customStatus: { text: "Ready", emoji: { name: "🌱" } } })
if (presence.isErr()) return presence
return client.members.editSelf(guildId, { nickname: "Support", mentionFlags: MemberMentionPreferences.PreferNoMention })
}
setMembers #
Request presence updates for selected members in one community
Register a presenceUpdate listener, then pass accessible non-self member IDs. Pass [] to clear the selection. Closing the listener does not clear it. No full-member subscription, member lookup or presence cache is created, and Fluxer remains authoritative for access and filtering. The community must belong to a shard assigned to this client, or the call fails with PresenceError reason input
setMembers(
guildId: string,
memberIds: readonly string[]
): Result<void, PresenceFailure>setMembers(
guildId: string,
memberIds: readonly string[]
): Result<void, PresenceFailure>Inputs are copied and retained when the call runs. Up to 1,000 distinct decimal IDs are accepted, but the full UTF-8 gateway frame must fit 16,384 bytes. Long IDs therefore reduce the effective per-community maximum: A frame holds about 740 members with 19-digit IDs
Fluxer instances older than October 2026 allow 4,096 bytes, about 180 such members, and stop the shard for a larger frame. The client retains selections for at most 100 communities and 10,000 IDs. Clearing an unsent selection withdraws its queued command and releases its slot immediately
Changes to a selection that has not reached the socket replace that unsent request. Clearing a selection already sent keeps one bounded session slot until fresh Identify or confirmed community leave, because a local socket write cannot confirm that Fluxer applied a clear
After READY or RESUMED, the latest selection or clear is combined and sent at most once per 125 ms per shard. This interval starts at actual socket transmission, and at most one member-selection command waits per shard. Sending the same list again deliberately requests a refresh
A matching guild creation also retries the latest selection or a previously sent clear. None of these attempts guarantees an event or proves provider acceptance. Initial state and transitions can be missed during recovery. Loss of shared channel visibility can remove the provider subscription, so resend the selection after access returns
Clear explicitly or shut down the client to release local intent. Input or limit failures fail with PresenceError, and closing clients fail with ClientClosedError. The community and member IDs must be positive decimal strings without leading zeros, no greater than 9223372036854775807. The member IDs are copied once, and that copy is validated and subscribed
Parameters
guildId -
string memberIds -
readonly string[]
- Returns
Result<void, PresenceFailure>- Fails with
Returns a Result synchronously.
A throwing ID getter throws SdkDefect with code application.defect and the thrown value as its cause, and other
unexpected failures throw SdkDefect with code sdk.defect
export function watchSelectedMember(client, guildId, memberId) {
const subscription = client.on("presenceUpdate", (presence) => {
if (presence.guildId === guildId && presence.userId === memberId)
void presence.status
})
const selected = client.presence.setMembers(guildId, [memberId])
if (selected.isErr())
subscription.close()
return selected.map(() => subscription)
}
import type { Client } from "@neontechspace/fluxerly"
export function watchSelectedMember(client: Client, guildId: string, memberId: string) {
const subscription = client.on("presenceUpdate", (presence) => {
if (presence.guildId === guildId && presence.userId === memberId) void presence.status
})
const selected = client.presence.setMembers(guildId, [memberId])
if (selected.isErr()) subscription.close()
return selected.map(() => subscription)
}
PresenceInput #
Set the status this bot should publish on its gateway connections
Use customStatus: null to request clearing the custom status. Omission preserves this client's latest custom-status request, or leaves the provider value unchanged if there is no retained request. The client copies the latest accepted settings and retains at most one unsent update per local shard, replacing its payload with the latest intent
Status updates are at least four seconds apart, measured from each actual socket transmission, not queue admission. It publishes those settings on ready local shards and restores them after READY or RESUMED. A successful call means the client accepted the settings
It does not mean every shard published them at once or that another user can see them. Shutdown clears the saved settings and pending local timers
interface PresenceInputcustomoptional#Status -
New custom status, null to clear it, or omission to retain the latest custom-status request made by this client
CustomStatusInput | null status#-
Visible status to publish on the bot's live gateway connections
PresenceStatus
ResolvedInstance #
The selected server's service addresses and matching URL helpers
This frozen result is retained for one client, not refreshed on each later resolve. Use assets and links to build URLs for this instance rather than the hosted default. These helpers make no requests, inspect no credentials and do not refresh discovery or change caches
Built-in badge images and hidden badge kinds from discovery are not kept, because few bots draw community badges. For discovery fields not included here, read /.well-known/fluxer from the selected instance's root with fetch and no Authorization header. This address is outside /v1, so client.rest.request from the raw-request guide cannot read it
Check the response before using it, keep a copy and honor Retry-After
interface ResolvedInstanceapi#Code Version -
Provider code-version indicator from discovery
It is not an API path version
number assets#-
Pure asset URL helpers bound to this instance's media and static-CDN bases
They follow the assets namespace's input-field and fallback rules, return URLs directly and throw
AssetUrlErrorfor invalid inputAssetHelpers discovery#Enabled -
Whether this instance has community directory discovery switched on
True when discovery omits the flag, as Fluxer documents. A present value that is not a boolean makes the discovery document invalid. When false, the discovery namespace's search, apply, edit and withdraw operations fail with reason rejected, HTTP
400andapiError.codediscoveryDisabled(Fluxer code DISCOVERY_DISABLED), whilefetchStatusandfetchCategoriesstill answer. The value is a snapshot from when the client resolved the instance, so an operator's later change appears only in a new clientboolean domain#Migration -
The web domain migration that discovery announced, or null when the instance announced none
Links and OAuth URLs always use the discovered web application base in endpoints, so they follow a migrated domain
InstanceDomainMigration | null endpoints#-
Exact validated service bases from discovery
InstanceEndpoints links#-
Pure application-link helpers bound to this instance's web application base
They return URLs directly, throw
HelperErrorfor invalid input and perform no navigation or access checkLinkHelpers presigned#Attachment Uploads -
Whether this instance advertises temporary upload URLs for attachment transfers
boolean
RestRequest #
One request to a Fluxer API route that the SDK does not wrap, sent with the client's bot credential through the same queue, rate-limit learning, 429 waits, deadline, logging and cancellation as wrapped operations
Invalid input fails before dispatch with RestRequestError reason input. A GET that fails with a network error or HTTP 500, 502, 503 or 504 is retried at most twice. Another method is sent again only after Fluxer confirms a rate limit with HTTP 429, so a write with an unknown outcome is never repeated automatically. Message and resource caches are neither read nor updated, and Fluxer's rate limits and permissions still apply
interface RestRequest extends OperationOptionsinterface RestRequest
extends OperationOptionsAborting the signal stops waiting and cancels the HTTP exchange, but cannot undo a request Fluxer already received
export async function currentUserName(client) {
const result = await client.rest.request({ method: "GET", path: "/users/@me" })
return result.isOk() ? result.value.body.username : undefined
}
import type { Client } from "@neontechspace/fluxerly"
export async function currentUserName(client: Client): Promise<string | undefined> {
const result = await client.rest.request<{ username: string }>({ method: "GET", path: "/users/@me" })
return result.isOk() ? result.value.body.username : undefined
}
auditoptional#Reason -
Audit-log reason sent as the X-Audit-Log-Reason header, 1 through 512 UTF-16 code units after trimming
Any language works, because the header carries its UTF-8 bytes. Control characters, line separators and lone surrogates fail before dispatch. Omission sends no header. Never included in errors, logs or diagnostics
string bodyoptional#-
JSON body, serialized when the request starts
A value JSON cannot represent fails with reason input. Its size counts against the client's queued JSON budget while the request waits. Not allowed with GET
unknown filesoptional#-
Files sent inline as multipart/form-data, with the JSON body as payload_json and each file as files[n] in order
Accepts the same byte, file and stream inputs as message attachments, with the same size, filename and upload-budget rules. The body must then be omitted or a JSON object
The SDK sends
body.attachmentsas Fluxer's message routes expect: The body's entries for existing attachments first, which an edit must list to keep them, then each file's metadata with id n. A body entry whose id is a file's index may add that file's title or description and repeat its filename or flagsA value that differs from the file's own, two entries for one file or another key there fail with reason input. A request whose file source cannot be read again fails with reason
rateLimitinstead of waiting out a 429. Not allowed with GETreadonly AttachmentInput[] method#-
HTTP method
Only POST, PUT, PATCH and DELETE may carry a body or files
"GET" | "POST" | "PUT" | "PATCH" | "DELETE"| "GET" | "POST" | "PUT" | "PATCH" | "DELETE" path#-
API path after /v1, such as /users/@me, of at most 2,048 characters
It must start with one slash and contain only URL path characters with valid percent escapes, without empty, dot or dot-dot segments, a query or a fragment. The /v1 prefix and token-authenticated webhook routes (/
webhooks/{id}/{token}) are rejected, including percent-encoded unreserved characters in those route names. These checks are case-sensitive and do not decode reserved characters. Logs, metrics and spans name the route with numeric IDs and other non-word segments replaced by placeholders string queryoptional#-
Query parameters appended to the path in insertion order
Undefined values are omitted, numbers must be finite, and booleans are sent as true or false. An array sends its name once per item in order, such as
{ tag: ["1", "2"] }fortag=1&tag=2, and an empty array sends nothing. The encoded query may contain at most 8,192 charactersReadonly< Record< string, | string | number | boolean | readonly (string | number | boolean)[] | undefined > >Readonly< Record< string, | string | number | boolean | readonly ( | string | number | boolean)[] | undefined > > timeoutoptional#Ms -
Total milliseconds across local queueing, rate-limit waits, retries and HTTP
An integer from 1 through 2,147,483,647, defaulting to the client's
rest(30,000 unless configured). Owned cleanup is awaited afterward, so completion can take longer.default Timeout Ms number
Inherited from Operation: signal
RestRequests #
Send requests to Fluxer API routes that the SDK does not wrap, with the client's bot credential and its REST scheduler
Calls start immediately, need no gateway connection and default to the client's rest deadline. Abort waits for cleanup and returns CancelledError. Unexpected failures reject with SdkDefect
interface RestRequestscall#
Send one request to a route of Fluxer's API description, checked at compile time: The route is its method and path template, such as POST /, and params, query and body take Fluxer's official field names
The response body has the route's type. These types come from Fluxer's API description at the commit this release pins, so they do not cover later routes or fields, and the response is not checked at runtime
Each path parameter is percent-encoded as one segment, and a missing, extra or empty one fails with RestRequestError reason input before any request. Only the compiler checks that a route is listed, and at runtime any route is sent whose filled path request accepts
The request then follows every rule of request, through the same queue, rate limits, retries, deadline, logging and RestRequestError failures, with operation rest.request
call<R extends keyof RestRoutes>(
route: R,
...input: RestCallArguments<R, RestCallInput<R>>
): ResultAsync<
RestResponse<RestRouteResponse<R>>,
ConfigurationError | RestRequestFailure | CancelledError
>call<R extends keyof RestRoutes>(
route: R,
...input: RestCallArguments<
R, RestCallInput<R>
>
): ResultAsync<
RestResponse<
RestRouteResponse<R>
>,
| ConfigurationError
| RestRequestFailure
| CancelledError
>Parameters
route-
R ...input-
RestCallArguments<R, RestCallInput<R>>
- Returns
ResultAsync< RestResponse<RestRouteResponse<R>>, ConfigurationError | RestRequestFailure | CancelledError >ResultAsync< RestResponse<RestRouteResponse<R>>, | ConfigurationError | RestRequestFailure | CancelledError >
export async function recentContents(client, channelId) {
const result = await client.rest.call("GET /channels/{channel_id}/messages", {
params: { channel_id: channelId },
query: { limit: 10 },
})
return result.map((response) => response.body.map((message) => message.content))
}
import type { Client } from "@neontechspace/fluxerly"
export async function recentContents(client: Client, channelId: string) {
const result = await client.rest.call("GET /channels/{channel_id}/messages", {
params: { channel_id: channelId },
query: { limit: 10 },
})
return result.map((response) => response.body.map((message) => message.content))
}
request#
Send one request to a route under /v1 and resolve with its status, lower-case headers and parsed JSON body
The request waits in the client's queue and learned rate-limit windows like wrapped operations, and fails at once with reason rateLimit and the remaining wait as retryAfterMs when a window outlasts the deadline. A 429 is waited out and sent again while the deadline allows
A GET is also retried at most twice after a network error, including a connection lost while the response body arrives, or HTTP 500, 502, 503 or 504. Another method is never sent again after an uncertain outcome. The body is sent as given, including a lone surrogate, which Fluxer answers with HTTP 503
Invalid input fails with RestRequestError reason input before any request, a non-2xx status fails with its status and sanitized apiError, and closure fails with ClientClosedError. Message and resource caches are not updated. Percent-encoded unreserved letters cannot bypass the reserved /v1 prefix or token-webhook route checks, which remain case-sensitive
Network causes retain sanitized transport facts, not raw errors. Unknown uppercase provider codes remain in details.providerCode, including on HTTP 429 when its wait exceeds the deadline. Logs, metrics and spans name only the route template, never the query
They leave out the body and response too, unless logging.unsafe prints payloads for the rest category, which logs masked request and response bodies
request<T = unknown>(input: RestRequest): ResultAsync<
RestResponse<T>,
ConfigurationError | RestRequestFailure | CancelledError
>request<T = unknown>(
input: RestRequest
): ResultAsync<
RestResponse<T>,
| ConfigurationError
| RestRequestFailure
| CancelledError
>Parameters
input-
RestRequest
- Returns
ResultAsync< RestResponse<T>, ConfigurationError | RestRequestFailure | CancelledError >ResultAsync< RestResponse<T>, | ConfigurationError | RestRequestFailure | CancelledError >
RestResponse #
A successful response from client.rest.request, for any 2xx status
interface RestResponse<T = unknown>body#-
The parsed JSON body, or undefined when the response has no body
The type parameter is not checked at runtime, so decode the value before trusting its shape. A body over 16 MiB or one that is not valid JSON fails the request with reason response
T headers#-
Response headers with lower-case names
Repeated headers are joined with a comma and space as fetch does
Readonly<Record<string, string>> status#-
HTTP status from 200 through 299
number
RestRouteOptions #
Options every client.rest.call accepts beside its route-specific fields, with the same rules as client.rest.request
interface RestRouteOptionsauditoptional#Reason -
Audit-log reason sent as the X-Audit-Log-Reason header, 1 through 512 UTF-16 code units after trimming
Control characters, line separators and lone surrogates fail before dispatch. Omission sends no header. Never included in errors, logs or diagnostics
string timeoutoptional#Ms -
Total milliseconds across local queueing, rate-limit waits, retries and HTTP
An integer from 1 through 2,147,483,647, defaulting to the client's
rest(30,000 unless configured).default Timeout Ms number
ScheduleOptions #
Choose when client.schedule runs a task, in both entry points
Without options the task runs once, as soon as possible
interface ScheduleOptionsdelayoptional#Ms -
Milliseconds before the first run, an integer from 0 through 2,147,483,647
A repeating task waits
intervalMsby default, like an interval timer, and a task that runs once waits 0number intervaloptional#Ms -
Repeat the task, waiting this many milliseconds after each run ends before the next one starts, an integer from 1 through 2,147,483,647
Runs therefore never overlap. Without it the task runs once
number nameoptional#-
Name of the task, 1 through 100 characters without control characters
A failed run's
lifecycle.taskFailedrecord names it in its message andfields.task, and itsFailureReportintaskName, so failures of different tasks stay apart. Without it a failed run is reported as an unnamed taskstring
ScheduledTask #
A task started with client.schedule
It ends by itself after its only run, or when the client shuts down
interface ScheduledTaskclose#
Cancel every later run
A run in progress continues, and a draining shutdown still waits for it. The task can close itself from its own run. Repeated calls do nothing
close(): voidShutdownOptions #
Choose how shutdown treats work that is still running, in both entry points
interface ShutdownOptionsdrainoptional#Ms -
Milliseconds to let running work finish before shutdown cancels it, an integer from 0 through 2,147,483,647
The default 0 cancels running handlers at once. The
runBotfunction drains for 5,000 ms by default when asked to stopnumberDuring the drain the client accepts no new events. New subscriptions and event waits start closed, as after shutdown. Running handlers and commands continue, events already waiting in on handler queues still run, and REST requests continue, including new ones that handlers send
Scheduled task runs in progress continue, while tasks start no new run and new tasks are refused. The connection state stays as it was until the drain ends
The drain ends as soon as no handler or scheduled task is running, no event is waiting and no REST request is in progress, logging
lifecycle.drained, or when the time runs outThen shutdown continues as usual and cancels what is left, logging how many handlers, events, tasks and requests it cut off as a
lifecycleWarn record. Collectors and subscribe subscriptions receive no events during the drain and end with the shutdown. A shutdown call while another is in progress shares that shutdown and its drain.drain Timed Out A default API handler or scheduled task that awaits a draining shutdown of its own client keeps the drain waiting until the time runs out, so start the shutdown without awaiting it there. A native handler, collector callback or scheduled task that calls shutdown ends at once, and the drain continues for the other work. An invalid value throws
ConfigurationErrorin the default API and dies with it in the Effect API, before shutdown starts
StateObserver #
Stop receiving connection-state updates from client.observeState
Use using to close the observer when the enclosing block ends
interface StateObserver[dispose]#
Close this observer, as using does at the end of a block
[dispose](): voidclose#
Stop delivering states and drop a pending one
Listener code already running is not cancelled. Repeated calls do nothing
close(): voidType Aliases#
BotEventContext #
type BotEventContext<
K extends EventName,
M extends MessageCore = Message
> =
& {
readonly client: Client<M>
readonly context: EventContext<K, M>
readonly event: EventMap<M>[K]
readonly signal: AbortSignal
}
& (K extends "messageCreate"
? {
readonly message: M
readonly reply: (
input: ReplyInput | string,
options?: Omit<RequestOptions, "signal">
) => ReturnType<Client<M>["messages"]["reply"]>
}
: { … })type BotEventContext<
K extends EventName,
M extends MessageCore = Message
> =
& {
readonly client: Client<M>
readonly context:
EventContext<K, M>
readonly event:
EventMap<M>[K]
readonly signal: AbortSignal
}
& (K extends "messageCreate"
? {
readonly message: M
readonly reply: (
input:
| ReplyInput
| string,
options?: Omit<
RequestOptions,
"signal"
>
) => ReturnType<
Client<M>["messages"][
"reply"
]
>
}
: { … })BotEventHandler #
A returned or resolved Err result is reported like a thrown error, and other return values are ignored
type BotEventHandler<
K extends EventName,
M extends MessageCore = Message
> = (context: BotEventContext<K, M>) => unknowntype BotEventHandler<
K extends EventName,
M extends MessageCore = Message
> = (
context: BotEventContext<K, M>
) => unknownBotEvents #
One optional handler per event, as a function or an object with a handler and delivery settings
By default, a full queue drops the oldest waiting events, logs a Warn record and counts the drop, and the bot keeps running. With a partition, the overflow option's rule decides which event is dropped. Set overflow to "dropNewest" to drop the arriving event instead, or to "stop" to stop the bot with Critical
By default, messageCreate and partitioned handlers run up to eight callbacks at a time, so they can finish out of order, and other handlers run one at a time. A failed handler is reported with its original error to onError, or logged in full, without stopping the bot or retrying that handler
type BotEvents<M extends MessageCore = Message> = {
readonly [K in EventName]?:
BotEventHandler<K, M> | BotEventOptions<K, M>
}type BotEvents<
M extends MessageCore = Message
> = {
readonly [K in EventName]?:
| BotEventHandler<K, M>
| BotEventOptions<K, M>
}ConnectionState #
The client's current gateway connection state, not a history of events
Disconnected permits startup. Connecting includes startup retries until every shard owned by this client is ready at the same time. Connected means every local shard is ready. Recovering means an established shard lost readiness and lasts until all shards owned by this client are ready again. Other ready shards can continue work during Recovering. Closing means permanent cleanup is underway, and Closed requires a new client to connect again
type ConnectionState =
| "Disconnected" | "Connecting" | "Connected" | "Recovering"
| "Closing" | "Closed"type ConnectionState =
| "Disconnected" | "Connecting"
| "Connected" | "Recovering"
| "Closing" | "Closed"CustomStatusEmoji #
One custom-status emoji
The variants cannot be combined
type CustomStatusEmoji =
{ readonly id: string } | { readonly name: string }type CustomStatusEmoji =
| { readonly id: string }
| { readonly name: string }InstanceBadgeQuery #
Select community badges for client: Either up to 100 badge IDs, such as a Guild's badgeIds, or one page of every community badge on the instance
Unknown keys and invalid values fail locally. The query accepts only ids, after and limit. To send the catalog's version field, use client.rest.request with GET /instance/badges and query.version
type InstanceBadgeQuery =
InstanceBadgeLookup | InstanceBadgePageQuerytype InstanceBadgeQuery =
| InstanceBadgeLookup
| InstanceBadgePageQueryPresenceStatus #
The bot's visible status while connected, with dnd meaning do not disturb
Use invisible to hide online status, not to disconnect the client. The status offline is excluded because Fluxer normalizes it to invisible on a connected session
type PresenceStatus = "online" | "idle" | "dnd" | "invisible"type PresenceStatus =
| "online" | "idle" | "dnd"
| "invisible"RestCallArguments #
The arguments after the route in client.rest.call
The input may be left out when the route requires no field
type RestCallArguments<R extends RestRoute, I> =
{ … } extends RestRouteInput<R> ? [input?: I] : [input: I]type RestCallArguments<
R extends RestRoute, I
> = { … } extends RestRouteInput<R>
? [input?: I]
: [input: I]RestCallInput #
The second argument of client.rest.call: The route's fields, the shared options and an optional abort signal
type RestCallInput<R extends RestRoute> =
RestRouteInput<R> & RestRouteOptions & OperationOptionstype RestCallInput<
R extends RestRoute
> =
& RestRouteInput<R>
& RestRouteOptions
& OperationOptionsRestRoute #
A route that client.rest.call accepts, written as its method and path template the way Fluxer's documentation writes them, such as GET /
The routes are those of Fluxer's API description at the commit this release pins that accept a bot token, which RestRoutes lists
type RestRoute = keyof RestRoutesRestRouteInput #
The route-specific fields of a client.rest.call for one route, with Fluxer's official names: params for the path parameters, query for the query parameters, body for the JSON body and files where the route accepts message-style attachments
Each is present only when the route has it, and required only when Fluxer requires it
type RestRouteInput<R extends RestRoute> = RestRoutes[R]["input"]type RestRouteInput<
R extends RestRoute
> = RestRoutes[R]["input"]RestRouteResponse #
The type of the parsed JSON body of a successful client.rest.call for one route, or undefined for a route Fluxer answers without a body
It comes from Fluxer's API description and is not checked at runtime
type RestRouteResponse<R extends RestRoute> =
RestRoutes[R]["response"]type RestRouteResponse<
R extends RestRoute
> = RestRoutes[R]["response"]