spearkit 0.3.1 → 0.4.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/llms.txt CHANGED
@@ -6,6 +6,85 @@ spearkit re-exports the entire discord.js surface (so it is a drop-in replacemen
6
6
 
7
7
  Core rules an agent should follow: use `SpearClient` (not `Client`); define commands with `command()`/`commandGroup()` and options with `option.*`; define components with `button`/`stringSelect`/`modal`/… and let spearkit route them by custom-id — never write an `interactionCreate` switch; register with `client.register(...)`; `await client.start(token)` then `await client.deployCommands({ guildId })` (deploy only after start); the ready event is `clientReady`, not `ready`.
8
8
 
9
+ ## Use cases — reach for
10
+
11
+ **Bot setup & lifecycle**
12
+
13
+ | Want to… | Reach for |
14
+ | --- | --- |
15
+ | Start a bot and connect | `new SpearClient({ intents })` + `await client.start(token)` |
16
+ | Choose gateway intents | `Intents.none / default / guilds / messages / all` |
17
+ | Wire up handlers | `client.register(...)`; one file per handler → `client.load(dir)` |
18
+ | Push commands to Discord | `client.deployCommands({ guildId })`; slash + context menus, safe CI → `client.deployAllCommands({ strategy: "diff", dryRun })` |
19
+ | Package a reusable feature | `definePlugin(...)` + `client.use(...)` |
20
+ | Migrate an existing discord.js bot | import from `"spearkit"`, swap `Client` → `SpearClient` |
21
+
22
+ **Commands & input**
23
+
24
+ | Want to… | Reach for |
25
+ | --- | --- |
26
+ | A slash command | `command({ name, description, run })` |
27
+ | Typed inputs to a command | `options: { x: option.string/integer/number/boolean/user/channel/role/mentionable/attachment(...) }` |
28
+ | Group many commands under one name | `commandGroup` + `subcommand` / `subcommandGroup` |
29
+ | Suggest values while the user types | `option.string({ autocomplete })` |
30
+ | A right-click "Apps" action on a user/message | `userCommand` / `messageCommand` |
31
+ | A classic `!text` command | `prefixCommand(...)` + `new SpearClient({ prefix })` |
32
+ | Parse `!cmd` arguments into typed values | `args: (a) => a.snowflake().duration().rest()` → `ctx.options` |
33
+ | Avoid `Unknown interaction` (10062) on slow work | `command({ autoDefer: true })` / `new SpearClient({ autoDefer: true })` |
34
+
35
+ **Interactivity (components)**
36
+
37
+ | Want to… | Reach for |
38
+ | --- | --- |
39
+ | A clickable button | `button({ id, run })` → `row(btn.build(...))` |
40
+ | A URL button (no handler) | `linkButton` |
41
+ | A dropdown of fixed options | `stringSelect` |
42
+ | Pick users / roles / channels / mentionables | `userSelect` / `roleSelect` / `channelSelect` / `mentionableSelect` |
43
+ | A form with text fields | `modal` + `textInput` |
44
+ | Carry data through a component | custom-id params `id: "x:{id}"` → `ctx.params.id` |
45
+ | A paged list with next/prev | `paginate(...)` |
46
+ | An "Are you sure?" yes/no gate | `confirm(...)` |
47
+
48
+ **Replies & UX**
49
+
50
+ | Want to… | Reach for |
51
+ | --- | --- |
52
+ | Reply, public or hidden | `ctx.reply(...)` / `ctx.replyEphemeral(...)` |
53
+ | Work that takes >3s | `ctx.defer()` then `ctx.editReply(...)` |
54
+ | A styled success/error/info/warn embed | `ctx.success/error/info/warn(...)` |
55
+ | "Reply, edit, or follow-up — whichever fits" | `ctx.send(...)` |
56
+
57
+ **Cross-cutting concerns**
58
+
59
+ | Want to… | Reach for |
60
+ | --- | --- |
61
+ | React to gateway events | `event(name, run)`; once on startup → `event("clientReady", ...)` |
62
+ | Rate-limit a command/handler | `cooldown` (per-command or client-wide) |
63
+ | Restrict by role / permission / owner / guild | guards: `requireAnyRole` / `requireUserPermissions` / `requireOwner` / `guildOnly` |
64
+ | Run jobs on cron or interval | `task({ cron \| interval })` / `client.schedule(...)` |
65
+ | Delay once / staged follow-ups / recover on restart | `client.scheduler.delay` / `followUp` / `reconcile` |
66
+ | Structured logs to file/webhook | `client.logger` + `consoleSink` / `jsonlSink` / `webhookSink` |
67
+ | Track who used what | `new SpearClient({ usage })` + `MemoryUsageStore` / `JsonFileUsageStore` |
68
+ | Read typed env / load `.env` | `env.string/number/boolean/require` (auto-loaded on `start()`) |
69
+ | Shut down cleanly on SIGINT/SIGTERM | `client.enableGracefulShutdown({ onShutdown })` |
70
+ | Permission / role-hierarchy preflight | `moderationCheck(...)`, `missingPermissions(...)`, `canActOn(...)`, `ctx.botMissing(...)` |
71
+ | Wait for a reply / click / modal submission | `ctx.awaitMessageFrom(...)` / `ctx.awaitModal(...)` / `awaitComponent(...)` |
72
+ | Branch on a Discord API error | `isDiscordError(err, DiscordErrorCode.X)` / `explainDiscordError(err)` |
73
+ | Per-guild prefix from a store | `prefix: { dynamic: (message) => ... }` |
74
+
75
+ **Utilities (primitives)**
76
+
77
+ | Want to… | Reach for |
78
+ | --- | --- |
79
+ | Stop concurrent runs per key (e.g. per user) | `KeyedLock` |
80
+ | Fetch that returns `null` instead of throwing | `safeFetch.{member,channel,message,user,guild,role}` |
81
+ | Format/parse `"1h30m"` durations | `formatDuration` / `parseDuration` |
82
+ | Render `<t:…>` Discord timestamps | `discordTimestamp` / `relativeTimestamp` |
83
+ | In-memory cache / counters / rate-limit window | `MemoryCache` |
84
+ | Load JSON/JSON5/YAML config | `loadConfig` |
85
+ | Persist key-value data / per-guild settings | `MemoryStore` / `JsonStore` + `createSettings({ store, defaults })` |
86
+ | Split text to Discord's 2000-char limit | `chunkMessage(text)` / `truncate(text, max)` |
87
+
9
88
  ## Documentation
10
89
 
11
90
  - [Getting started](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/getting-started.md): spearkit is discord.js++: it re-exports the entire discord.js surface and adds a fully type-safe layer for events, slash commands and interactive components. This page takes you from an empty folder…
@@ -17,16 +96,25 @@ Core rules an agent should follow: use `SpearClient` (not `Client`); define comm
17
96
  - [Commands](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/commands.md): Slash commands in spearkit are defined as a single object: the metadata, the typed options, and the handler all live together. spearkit serialises them for discord and routes incoming interactions to…
18
97
  - [Options](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/options.md): Slash command options are declared as a map of name → builder. spearkit infers the exact value type each option resolves to, so your handler's ctx.options is fully typed — no casts, no any, no manual…
19
98
  - [Components](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/components.md): Buttons, select menus and modals in spearkit follow one pattern: define the appearance, the custom-id pattern, and the handler in one place; register it; then build() the discord.js component to put…
99
+ - [Context-menu commands](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/context-menus.md): Context-menu commands are the right-click "Apps" actions Discord shows on a user or a message. spearkit makes them first-class: define one with userCommand or messageCommand, register it like…
20
100
  - [Events](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/events.md): event() defines a reusable, loadable discord.js event listener with a fully-typed handler. The handler's arguments are inferred from discord.js' ClientEvents, so you never annotate them by hand…
21
101
  - [Contexts](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/context.md): Every spearkit handler — command, button, select, modal — receives a context object. They all share BaseContext, which smooths over discord.js' reply/defer/edit/follow-up state machine and exposes…
22
- - [Cooldowns](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/cooldown.md): Rate-limit commands per user, per role, per guild, per channel or globally. Cooldowns are enforced automatically by command dispatch: when an actor is still on cooldown, spearkit replies
102
+ - [Guards](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/guards.md): Guards are declarative preconditions that run before a handler. They work uniformly across slash commands, components (buttons, selects, modals), prefix commands and context-menu commands and can
103
+ - [Permissions & hierarchy](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/permissions.md): Moderation commands fail in two predictable ways: the bot lacks a permission in the channel (Missing Permissions, 50013), or the target sits above the bot (or the moderator) in the role list. Both…
104
+ - [Auto-defer](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/auto-defer.md): The single most common discord.js error is DiscordAPIError[10062]: Unknown interaction. An interaction token is valid for only 3 seconds before your first response; any handler that awaits a database…
105
+ - [Cooldowns](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/cooldown.md): Rate-limit commands per user, per guild, per channel, or globally — with per-role and per-user exemptions and overrides. Cooldowns are enforced automatically by command dispatch: when an actor is…
23
106
  - [Scheduled tasks](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/scheduler.md): Run work on a cron schedule or a fixed interval. The client starts the scheduler when it becomes ready and stops it on destroy(), so timers never outlive your bot.
24
107
  - [Prefix commands](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/prefix.md): Alongside slash commands, spearkit can dispatch classic text/prefix commands like !ping. You define them with prefixCommand, enable them with the client's prefix option, and spearkit parses each…
25
108
  - [Logging](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/logging.md): spearkit ships a small, dependency-free structured logger. Every client owns one at client.logger, and spearkit routes its own command, component, event, and gateway errors through it. You can use…
26
- - [Usage tracking](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/usage.md): Usage tracking records who used what: every successful command, component, and prefix-command invocation becomes a UsageEvent that spearkit can persist to a store and/or mirror into a Discord
109
+ - [Discord API errors](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/errors.md): discord.js reports REST failures as DiscordAPIError with a numeric code (10008 "Unknown Message", 50013 "Missing Permissions", 50007 "Cannot send DMs to this user", …). Catching everything turns
110
+ - [Usage tracking](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/usage.md): Usage tracking records who used what: every command, component, context-menu and prefix-command invocation — successful or errored — becomes a UsageEvent that spearkit can persist to a store and/or…
27
111
  - [Environment & dotenv](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/env.md): spearkit includes a tiny, dependency-free .env loader and a typed reader over process.env, so a bot needs no extra dotenv dependency. The client auto-loads .env on start(), and the same helpers are…
28
112
  - [Plugins](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/plugins.md): A plugin is a named, reusable bundle of commands, events and components. It lets you package a feature once and install it into any SpearClient with a single call — useful for sharing functionality…
29
- - [File-based loading](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/loading.md): Instead of importing and registering every handler by hand, you can keep one command, event or component per file and let spearkit discover them. The loader imports a directory, inspects each
113
+ - [Collectors](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/collectors.md): discord.js collectors are powerful but fiddly: you wire an event emitter, set a time, write a filter, remember that dismissed modals need their own timeout, and translate the "timed out" rejection
114
+ - [Key-value store & settings](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/store.md): Almost every community bot needs to remember something per guild — a custom prefix, a mod-log channel, a welcome message — and reaches for a database on day one. spearkit ships a dependency-free…
115
+ - [Messages & limits](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/messages.md): Discord caps a message's content at 2000 characters. Long output — a log dump, a list, an AI response — silently fails or throws unless you split it. spearkit ships two helpers (in addition to the…
116
+ - [Graceful shutdown](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/shutdown.md): A Ctrl-C or a container stop sends your process a signal. If you don't handle it, the process dies mid-flight — the gateway connection, scheduler timers, and any open database handles are reaped…
117
+ - [File-based loading](https://raw.githubusercontent.com/byigitt/spearkit/main/docs/loading.md): Instead of importing and registering every handler by hand, you can keep one handler per file and let spearkit discover them. The loader imports a directory, inspects each module's exports, and…
30
118
 
31
119
  ## Reference
32
120
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "spearkit",
3
- "version": "0.3.1",
3
+ "version": "0.4.0",
4
4
  "description": "discord.js++ — a developer-experience-first Discord library. Drop-in compatible with discord.js, with ergonomic events, slash commands, and interactive components.",
5
5
  "type": "module",
6
6
  "license": "PolyForm-Noncommercial-1.0.0",