Release history

Changelog

New features, fixes, and deliberate breaking changes in Fluxer.js.

v2.2.0

A large client cache rebuild (LimitedCollection + client.cache), Tenor replaced with Klipy for GIF helpers, and a refreshed OpenAPI snapshot with tighter types. Most other breaking changes are import-path moves and small behavior tweaks; the migration notes below walk through each one.

Breaking Changes

  • Tenor GIF helpers replaced with Klipy

    resolveTenorToImageUrl and related Tenor exports are removed. Use resolveKlipyToImageUrl (and KlipyMediaResult) from @fluxerjs/core or @fluxerjs/util. Fluxer’s unfurler expects Klipy page URLs in message content; see the GIFs guide.

  • Disabling the message cache now uses messages: false, not messages: 0

    To match the rest of the cache options, a numeric 0 (and other documented numeric zeros) now means "unbounded / no limit" instead of "off". If you passed cache: { messages: 0 } to turn message caching off, it will now cache every message. Use cache: { messages: false } to disable it.

  • Deep file imports moved; import from package entrypoints instead

    Internal layout was reorganized (guild/message structures, sdk options modules, util helpers). Paths like @fluxerjs/core/structures/Guild.ts no longer resolve. Import public names from the package root or documented subpaths (@fluxerjs/core, @fluxerjs/core/client, @fluxerjs/core/message, @fluxerjs/core/cluster, @fluxerjs/core/errors).

  • formatEmoji custom output is now name:id (previously :name:id)

    The leading colon was dropped from the custom-emoji form, and unicode emoji are no longer passed through encodeURIComponent. Update any code that parsed or compared the old :name:id shape.

  • Animated emoji identifiers now include the a: prefix (a:name:id)

    GuildEmoji.identifier and MessageReaction.emojiIdentifier return a:name:id for animated emoji so they round-trip correctly through the API. Static emoji are unchanged and still return name:id.

  • message.react() always emits a local messageReactionAdd after the REST call

    Once the reaction request succeeds, the client emits messageReactionAdd with a structured emoji object ({ name, id?, animated? }) instead of putting the raw wire string into emoji.name. Your listeners and collectors now see the same shape whether the reaction came from you or from the gateway.

  • EmbedBuilder.toJSON() always includes description (null when unset)

    The description field was previously omitted when it had no value. If you snapshot or diff embed JSON, expect an explicit description: null to appear.

  • WebSocket identify intents is now optional and defaults to 0

    Fluxer ignores the legacy Discord-style intents value, so you can drop it entirely. If your code required intents: N, pass intents: 0 or simply omit it.

  • Stricter request validation may reject bodies that used to be accepted

    The vendored OpenAPI snapshot was refreshed against live Fluxer, which tightened nullability on some channel and guild request fields. Payloads that were loosely typed before may now be rejected; align them with the refreshed snapshot.

Added

  • LimitedCollection: a bounded cache with FIFO eviction (@fluxerjs/collection)

    A drop-in Collection that enforces a maximum size, evicting the oldest entries first, with an onEvict callback so you can react when items are dropped.

  • client.cache controller for inspecting and clearing caches

    Read cache stats, run manual sweeps, and cascade-teardown related data across guilds, channels, members, messages, roles, emojis, and stickers from one place.

  • Identity-preserving guild snapshots on READY / GUILD_CREATE

    When a guild is re-sent, its nested caches (members, channels, roles, and so on) are retained on the same guild instance instead of being rebuilt, so existing references stay valid.

  • resolveKlipyToImageUrl for embedding Klipy GIFs

    Resolves a klipy.com page URL to a direct media URL (and animated flags) for EmbedBuilder.setImage. Send the page URL as message content when you want the native gifv unfurl instead.

  • ClientEvents payload types exported from @fluxerjs/core

    Every camelCase ClientEvents payload type (including helpers like GuildRoleUpdatePayload) is public, plus ClientEventName and ClientEventListener for typed listeners.

  • ClientUser.fetch() and ClientUser.fetchGuilds({ withCounts }) for refreshing the current user and its guilds
  • client.requestGuildMembers() gateway helper for requesting member chunks
  • CHANNEL_RECIPIENT_ADD / CHANNEL_RECIPIENT_REMOVE handlers and matching client events
  • channels.fetch(id, { force }) and matching force/patch behavior on guilds.fetch
  • GUILD_COUNTS_UPDATE now updates guild.memberCount and guild.onlineCount live
  • New WebSocket identify options: flags, ignoredEvents, and initialGuildId
  • OpenAPI gateway coverage, alignment asserts, and Fluxer compare scripts (pnpm openapi:check / openapi:assert)
  • New cache-bot example and an expanded caching guide

Changed

  • Internal package layout was reorganized; public imports stay on package entrypoints (see Breaking Changes)
  • Managers now run on LimitedCollection with cache limits resolved from your options at construction time
  • Unhandled gateway dispatches now emit Events.Debug

    Dispatches the client does not handle surface as a Debug event so they are visible, except session, user, and call events, which stay intentionally unhandled and quiet.

  • Voice join and move now send explicit mute/deaf/self_* defaults in the state update
  • The vendored OpenAPI snapshot was refreshed against live Fluxer and the types package was aligned to it
  • Gateway guild create/ready snapshot typing uses GatewayGuildSnapshot (nested properties plus top-level count fields)

Fixed

  • Guild memberCount / onlineCount hydrate from GUILD_CREATE and COUNTS_UPDATE

    Fluxer puts member_count / online_count on the guild snapshot root (alongside properties). The client merges those top-level fields, keeps prior counts when a later payload omits them, and applies GUILD_COUNTS_UPDATE live.

  • Synthetic react() events no longer stuff the full wire string into emoji.name
  • ReactionCollector no longer double-counts repeated self/gateway events for the same user and emoji
  • CHANNEL_DELETE now cleans up guild-indexed channels after a global FIFO eviction
  • Channel-create rate_limit_per_user and NSFW/CWL nullability now match the OpenAPI schema
  • Multipart / undici form serialization from the earlier 2.x patch line is carried forward in this release

Migration notes

  • Replace resolveTenorToImageUrl / Tenor imports with resolveKlipyToImageUrl (see /guides/gifs/)
  • Change cache: { messages: 0 } (used to mean "off") to cache: { messages: false }
  • Replace deep structure imports with named imports from the root, e.g. import { Guild, MessageReaction } from "@fluxerjs/core"
  • If you matched reactions on emoji.name === "name:id", switch to emoji.id or emojiIdentifier
  • If you passed ws intents: N, change it to intents: 0 or drop it (Fluxer ignores intents)
  • Re-run your typecheck against @fluxerjs/types@2.2.0 after upgrading

v2.1.0

Changed

  • Require Node.js ≥ 22.13 across all published packages
  • REST no longer sends the configured token to cross-origin absolute URLs unless auth: true is set explicitly
  • Automatic retries now apply only to safe methods (GET/HEAD/OPTIONS) by default; opt mutations in per-request via retryPolicy
  • Client now honors configured cache limits (managers are constructed after resolving DEFAULT_CACHE_LIMITS with your options)

Fixed

  • Reactions with external custom emojis are now allowed when permitted by Fluxer
  • Preserve cached reaction users across gateway events
  • Correct REST rate-limit bucket identification
  • Clean up timed-out voice connections
  • Hydrate and harden normalization of nested gateway guild properties

v2.0.3

Fixed

  • ReactionCollector now handles messageReactionAddMany (gateway-batched reactions), not only messageReactionAdd

v2.0.2

Added

  • REST retryPolicy for per-request retry budgets (e.g. keep retries on GET, disable on writes)
  • Guild.available plus GuildUnavailable / GuildAvailable for temporary gateway outages

Fixed

  • User.prototype.send argument typing
  • Temporary guild unavailability no longer emitted as GuildDelete

Docs

  • Versioned SDK reference and guides for each tagged release (v2.0.0+)
  • Website improvements

v2.0.1

Changed

  • Raised Node.js engine requirement (Node 20 support removed; requires Node ≥ 22.13)
  • Updated undici to v7

Fixed

  • Dependency audit fixes
  • Publishing and CI improvements, including bot-login checks

v2.0.0

Major rewrite (non-voice)

  • ChannelType.GuildLink is 998; createChannel uses ChannelCreateRequest (link requires url)
  • EmbedBuilder: removed setVideo/setAudio; request type RESTPostAPIEmbed separate from APIEmbed
  • Default bounded caches (DEFAULT_CACHE_LIMITS); reply defaults; GUILD_UPDATE preserves caches
  • Reaction events emit full ClientEvents arity; Collection first/last/random allocation fixes
  • Interactions / slash commands removed (not in OpenAPI)
  • See the [Migrating to 2.0](/guides/migration/) guide