Every method and type of the SDK, by entry point
JavaScript & TypeScript#
Build a Fluxer bot with JavaScript or TypeScript.
Import from @neontechspace/ and call its methods directly
import { runBot } from "@neontechspace/fluxerly"
// A failed run is logged and sets process.exitCode, and Ctrl+C stops the bot cleanly, so the returned Result needs
// no further handling here
await runBot({
token: process.env.FLUXER_BOT_TOKEN,
commands: { prefix: "!", commands: { ping: { execute: ({ reply }) => reply("Pong!") } } },
})
import { runBot } from "@neontechspace/fluxerly"
// A failed run is logged and sets process.exitCode, and Ctrl+C stops the bot cleanly, so the returned Result needs
// no further handling here
await runBot({
token: process.env.FLUXER_BOT_TOKEN,
commands: { prefix: "!", commands: { ping: { execute: ({ reply }) => reply("Pong!") } } },
})
Effect API#
Import from @neontechspace/
Build Fluxer bots, send webhook messages and use OAuth with Effect. Use this entry point in applications that already use Effect
import { Effect } from "effect"
import { createClient } from "@neontechspace/fluxerly/effect"
export function sendOnce(token: string, channelId: string) {
const program = Effect.scoped(
Effect.gen(function* () {
const client = yield* createClient({ token })
return yield* client.messages.send(channelId, "Hello")
}),
)
return Effect.runPromise(program)
}
This example sends through HTTP without connecting the gateway. The returned Promise settles after the scoped client finishes cleanup
Coding agents: read node_ before writing code with this package
Testing#
Test Fluxer bots built with the default API without a network, a token or a Fluxer account.
Import from @neontechspace/ in application tests
import assert from "node:assert/strict"
import { createTestClient } from "@neontechspace/fluxerly/testing"
await using test = createTestClient()
const replies = test.rest.respond("POST /channels/:id/messages", { body: test.fixtures.message({ content: "Pong!" }) })
test.client.on("messageCreate", (message) => message.content === "!ping" ? test.client.messages.reply(message, { content: "Pong!" }) : undefined)
await test.ready()
test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "!ping" }))
// Handlers run after emit returns, so wait for the reply before asserting on it
const request = await replies.next()
assert.equal(request.body.content, "Pong!")
// A message the bot ignores sends nothing, which idle confirms without a fixed sleep
test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "hello" }))
await test.idle()
assert.equal(replies.requests().length, 1)
import assert from "node:assert/strict"
import { createTestClient } from "@neontechspace/fluxerly/testing"
await using test = createTestClient()
const replies = test.rest.respond("POST /channels/:id/messages", { body: test.fixtures.message({ content: "Pong!" }) })
test.client.on("messageCreate", (message) =>
message.content === "!ping" ? test.client.messages.reply(message, { content: "Pong!" }) : undefined,
)
await test.ready()
test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "!ping" }))
// Handlers run after emit returns, so wait for the reply before asserting on it
const request = await replies.next()
assert.equal((request.body as { content?: unknown }).content, "Pong!")
// A message the bot ignores sends nothing, which idle confirms without a fixed sleep
test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "hello" }))
await test.idle()
assert.equal(replies.requests().length, 1)
Effect Testing#
Test Fluxer bots built with the Effect API without a network, a token or a Fluxer account.
Import from @neontechspace/ in application tests
import { Effect } from "effect"
import { createTestClient } from "@neontechspace/fluxerly/effect/testing"
export const pingTest = Effect.scoped(
Effect.gen(function* () {
const test = yield* createTestClient()
const replies = test.rest.respond("POST /channels/:id/messages", {
body: test.fixtures.message({ content: "Pong!" }),
})
yield* test.client.on("messageCreate", (message) =>
message.content === "!ping" ? test.client.messages.reply(message, { content: "Pong!" }) : Effect.void,
)
yield* test.ready()
yield* test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "!ping" }))
// Handlers run after emit returns, so wait for the reply before the Scope closes the client
const reply = yield* replies.next()
// A message the bot ignores sends nothing, which idle confirms without a fixed sleep
yield* test.emit("MESSAGE_CREATE", test.fixtures.message({ content: "hello" }))
yield* test.idle()
return { reply, requests: replies.requests().length }
}),
)
Find a Method by Task#
Each client method, listed by what it does, with the first sentence of its documentation
Fluxer Endpoints#
Each Fluxer HTTP route a bot can use, with the Fluxerly method that calls it and a link to Fluxer's own docs for it
Error and Log Codes#
Every error and log record carries a stable code. Look one up to learn what it means and what to do