diff --git a/bun.lockb b/bun.lockb index 0f9d77d20..030944d3a 100755 Binary files a/bun.lockb and b/bun.lockb differ diff --git a/ec.config.mjs b/ec.config.mjs index 624133242..06c611287 100644 --- a/ec.config.mjs +++ b/ec.config.mjs @@ -6,7 +6,7 @@ export default defineEcConfig({ defaultProps: { showLineNumbers: false, overridesByLang: { - 'js,javascript,typescript,ts': { + 'js,javascript,typescript,ts,json': { showLineNumbers: true, }, }, diff --git a/src/components/PackageManagers.astro b/src/components/PackageManagers.astro new file mode 100644 index 000000000..ce9ca31b3 --- /dev/null +++ b/src/components/PackageManagers.astro @@ -0,0 +1,60 @@ +--- +import { Tabs, TabItem, Code } from "@astrojs/starlight/components"; + +type Command = "add" | "update" | "remove"; +type PackageManager = (typeof packageManagers)[number]; + +const packageManagers = ["NPM", "PNPM", "Yarn", "Bun"] as const; + +interface Props { + command: Command; + text: string; +} + +const packageManagerCode = ( + command: Command, + text: string, + manager: PackageManager, +) => { + const commands = { + add: { + NPM: `npm install ${text}`, + Yarn: `yarn add ${text}`, + PNPM: `pnpm add ${text}`, + Bun: `bun add ${text}`, + }, + update: { + NPM: `npm update ${text}`, + Yarn: `yarn upgrade ${text}`, + PNPM: `pnpm update ${text}`, + Bun: `bun update ${text}`, + }, + remove: { + NPM: `npm uninstall ${text}`, + Yarn: `yarn remove ${text}`, + PNPM: `pnpm remove ${text}`, + Bun: `bun remove ${text}`, + }, + create: { + NPM: `npm create ${text}`, + Yarn: `yarn create ${text}`, + PNPM: `pnpm create ${text}`, + Bun: `bun create ${text}`, + } + }; + + return commands[command][manager]; +}; + +const { command, text } = Astro.props; +--- + + + { + packageManagers.map((manager) => ( + + + + )) + } + diff --git a/src/content/docs/blog/2022-09-28.md b/src/content/docs/blog/2022-09-28.mdx similarity index 95% rename from src/content/docs/blog/2022-09-28.md rename to src/content/docs/blog/2022-09-28.mdx index 10d476c90..d5097f20a 100644 --- a/src/content/docs/blog/2022-09-28.md +++ b/src/content/docs/blog/2022-09-28.mdx @@ -11,9 +11,9 @@ date: 2022-09-28 Today we're announcing the ability to create class based modules! To get started, install -``` -npm install @sern/handler@latest -``` +import PackageManagers from '~/components/PackageManagers.astro'; + + Quick List of changes! diff --git a/src/content/docs/blog/2022-09-30.md b/src/content/docs/blog/2022-09-30.mdx similarity index 86% rename from src/content/docs/blog/2022-09-30.md rename to src/content/docs/blog/2022-09-30.mdx index cf9340863..95337a622 100644 --- a/src/content/docs/blog/2022-09-30.md +++ b/src/content/docs/blog/2022-09-30.mdx @@ -16,13 +16,13 @@ Today I'm going to show you how to get started with sern and all its cool featur Install the CLI: -``` -npm i -g @sern/cli -``` +import PackageManagers from '~/components/PackageManagers.astro'; + + and then run -``` +```sh sern init ``` @@ -30,7 +30,7 @@ sern init You can also run `sern init -y` if you want to use the default options. ::: -The CLI is written in Typescript and open-sourced on [Github](https://github.com/sern-handler/cli). (thanks [evo](https://github.com/EvolutionX-10)!) +The CLI is written in TypeScript and open-source on [GitHub](https://github.com/sern-handler/cli). (thanks [evo](https://github.com/EvolutionX-10)!) ### Step 2: Have some way to store secrets. diff --git a/src/content/docs/guide/getting-started/choose-ide.md b/src/content/docs/guide/getting-started/choose-ide.md index 7e2808f09..91439c1af 100644 --- a/src/content/docs/guide/getting-started/choose-ide.md +++ b/src/content/docs/guide/getting-started/choose-ide.md @@ -6,7 +6,7 @@ Choosing an IDE is a matter of personal preference. They make programming easier suggestions for choosing an IDE: - [Visual Studio Code](https://code.visualstudio.com) - - we have an [snippet extension](https://marketplace.visualstudio.com/items?itemName=SrIzan.sern-snippets) to help automate development :) + - We have an [snippet extension](https://marketplace.visualstudio.com/items?itemName=SrIzan.sern-snippets) to help automate development :) - [Sublime Text](https://www.sublimetext.com/) - [NotePad++](https://notepad-plus-plus.org/) - [nvim](https://neovim.io/) (chad) diff --git a/src/content/docs/guide/getting-started/preparing.md b/src/content/docs/guide/getting-started/preparing.md index 8501af058..1af518e1a 100644 --- a/src/content/docs/guide/getting-started/preparing.md +++ b/src/content/docs/guide/getting-started/preparing.md @@ -2,12 +2,10 @@ title: Preparing to Code --- -After installing an IDE, you need to install node. +After installing an IDE, you need to install `node`. Node is necessary to use `sern`, as it's based on `Discord.js`. -[Click to download the LTS version of node right here](https://nodejs.org/en/download/). +You can download Node from the official website [here](https://nodejs.org/en/download/). -After you downloaded node you will need: - -#### [Discord token](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token) +After you've downloaded Node you will need a [Discord token](https://github.com/reactiflux/discord-irc/wiki/Creating-a-discord-bot-&-getting-a-token) CONTINUE 🤓 diff --git a/src/content/docs/guide/walkthrough/autocomplete.md b/src/content/docs/guide/walkthrough/autocomplete.md index 23b5aac19..e617aae88 100644 --- a/src/content/docs/guide/walkthrough/autocomplete.md +++ b/src/content/docs/guide/walkthrough/autocomplete.md @@ -4,12 +4,15 @@ sidebar: order: 9 --- -Autocomplete is a special interaction where it can happen on multiple options on a single command. We've handled this with a simple -tree search algorithm in a nested options tree. +Autocomplete is a special interaction which can happen on multiple options can be suggested for a single command. + +We've implemented this functionality using a simple tree search algorithm within a nested options tree. ## Example -```ts title="src/commands/cheese.ts" {13-21} +In this example, the option `list` will autocomplete with the cheeses `gouda`, `parmesan`, and `harvarti`. + +```ts title="src/commands/cheese.ts" {13-22} export default commandModule({ type: CommandType.Slash, description: "show me cheese", @@ -23,9 +26,10 @@ export default commandModule({ command: { onEvent: [], execute: (ctx) => { + // focus can be used to refine the options const focus = ctx.options.getFocused(); ctx.respond( - ["gouda", "parmesan", "harvati"].map((cheese) => ({ + ["gouda", "parmesan", "harvarti"].map((cheese) => ({ name: cheese, value: cheese, })), @@ -41,4 +45,48 @@ export default commandModule({ }); ``` +## Using Focus + +The `focus` object can be used to refine the options. For example, if the user types `g`, the focus object will be `g`. + +We can filter the cheeses based on the focus object, and return only the cheeses that start with the focus object. + +You can do a lot more with the focus object, such as performing API calls, or implementing a fuzzy search. + +```ts title="src/commands/cheese.ts" {13-23} +export default commandModule({ + type: CommandType.Slash, + description: "show me cheese", + options: [ + { + name: "list", + type: ApplicationCommandOptionType.String, + description: "pick a cheese to show", + required: true, + autocomplete: true, + command: { + onEvent: [], + execute: (ctx) => { + const focus = ctx.options.getFocused(); + ctx.respond( + ["gouda", "parmesan", "harvarti"] + .filter((cheese) => cheese.startsWith(focus)) + .map((cheese) => ({ + name: cheese, + value: cheese, + })), + ); + }, + }, + }, + ], + execute: (ctx, [, args]) => { + const cheese = args.getString("list", true); + ctx.reply("selected cheese"); + }, +}); +``` + +:::tip Sern will handle autocomplete interactions at arbitrary depths and subcommand levels. +::: diff --git a/src/content/docs/guide/walkthrough/cli.md b/src/content/docs/guide/walkthrough/cli.md deleted file mode 100644 index 7a3f8cba6..000000000 --- a/src/content/docs/guide/walkthrough/cli.md +++ /dev/null @@ -1,37 +0,0 @@ ---- -title: CLI -sidebar: - order: 3 ---- - -Setting up the [CLI](https://github.com/sern-handler/cli) is easy. - -The cli is your plug to the sern ecosystem. This will allow you to install plugins with ease, install extra utilities, and much more. -If you haven't yet: - -```sh -npm install -g @sern/cli -``` - -- To install [plugins](plugins.md) maintained by the community [repository](https://github.com/sern-handler/awesome-plugins), - -```sh -sern plugins -``` - -:::caution -Make sure to have a correct [sern.config.json](../good-to-know.md#sernconfigjson) -::: - -This will display a menu selection of all installable plugins. - -**Note**: You must have a [sern.config.json](../good-to-know.md) to use this command. -If you want to view plugins, visit the repository linked above. - -- To install extra utilities into your project - -```sh -sern extra -``` - -We have a more in depth [guide](../../cli/README.md) of the CLI diff --git a/src/content/docs/guide/walkthrough/cli.mdx b/src/content/docs/guide/walkthrough/cli.mdx new file mode 100644 index 000000000..c82f311b2 --- /dev/null +++ b/src/content/docs/guide/walkthrough/cli.mdx @@ -0,0 +1,43 @@ +--- +title: CLI +sidebar: + order: 3 +--- + +Setting up the [CLI](https://github.com/sern-handler/cli) is easy. + +The CLI is your plug to the sern ecosystem. It allows you to install plugins with ease, install extra utilities, and much more. + +## Installing the CLI + +If you haven't already installed the CLI globally, you can do so by running: + +import PackageManagers from '~/components/PackageManagers.astro'; + + + +## Adding Plugins + +:::caution +You must have a [sern.config.json](../good-to-know.md#sernconfigjson) to use this command. +::: + +To install [plugins](../plugins) maintained by the community [repository](https://github.com/sern-handler/awesome-plugins): + +```sh +sern plugins +``` + +This will display a menu selection of all installable plugins. + +If you'd like to view all plugins, check out our [plugins page](../../../plugins). + +## Extra Utilities + +To install extra utilities into your project, run: + +```sh +sern extra +``` + +We have a more in depth [guide](../../../cli/about) on the CLI if you're interested in learning more. diff --git a/src/content/docs/guide/walkthrough/conclusion.md b/src/content/docs/guide/walkthrough/conclusion.md deleted file mode 100644 index fa5ec1a38..000000000 --- a/src/content/docs/guide/walkthrough/conclusion.md +++ /dev/null @@ -1,11 +0,0 @@ ---- -title: Conclusion -sidebar: - order: 12 ---- - -If you reached this far, thank you for reading! We hope you have learned the necessities you need -to create a bot with the sern framework. If you have any other questions, bugs, feature requests, concerns, please join our -[community server](https://sern.dev/discord), and we'll be glad to answer your questions. - -![](/blog/newlogo/paperlogo.png) diff --git a/src/content/docs/guide/walkthrough/conclusion.mdx b/src/content/docs/guide/walkthrough/conclusion.mdx new file mode 100644 index 000000000..9e793090f --- /dev/null +++ b/src/content/docs/guide/walkthrough/conclusion.mdx @@ -0,0 +1,16 @@ +--- +title: Conclusion +sidebar: + order: 12 +--- + +If you reached this far, thank you for reading! + +We hope you have learned the necessities you need to create a bot with the sern framework. + +If you have any other questions, bugs, feature requests, concerns, please join our [community server](https://sern.dev/discord), and we'll be glad to answer your questions! + +import { Image } from 'astro:assets'; +import paperLogo from '~/assets/blog/paper-logo.png'; + +paper logo diff --git a/src/content/docs/guide/walkthrough/dependency-injection.md b/src/content/docs/guide/walkthrough/dependency-injection.md deleted file mode 100644 index ebaf585c4..000000000 --- a/src/content/docs/guide/walkthrough/dependency-injection.md +++ /dev/null @@ -1,113 +0,0 @@ ---- -title: Dependency Injection -sidebar: - order: 10 ---- - -:::caution -This contains version 2 code. Please view [transitioning to v3](./transition) -::: - -Since version 2.0.0, dependency injection, thanks to [iti](https://github.com/molszanski/iti), is a feature to customize your bot's utilities and structures. - -Minimal setup for any project. - -```ts -const client = new Client({ - ...options, -}); -Sern.makeDependencies({ - build: (root) => - root.add({ - "@sern/client": single(() => client), - }), -}); -``` - -For any typescript project, you'll need to add an interface to get intellisense and typings. - -```typescript -interface MyDependencies extends Dependencies { - "@sern/client": Singleton; -} -``` - -Full Dependency Injection setup - -```typescript -const client = new Client({ - ...options, -}); - -interface MyDependencies extends Dependencies { - "@sern/client": Singleton; -} - -export const useContainer = Sern.makeDependencies({ - build: (root) => - root.add({ - "@sern/client": single(() => client), - }), -}); -``` - -Everything else is handled. However, you may want customize things. - -## Adding dependencies to root - -Each sern built dependency must implement its contracts. - -- `@sern/logger`: Log data. [Logging](../../api/interfaces/Logging) -- `@sern/errors`: Handling errors and lifetime. [ErrorHandling](../../api/interfaces/ErrorHandling) -- `@sern/modules`: Managing all command modules. [ModuleManager](../../api/interfaces/ModuleManager) -- `@sern/emitter`: is the key to emit events and occurences in a project. [SernEmitter](../../api/classes/SernEmitter) - -You may also add disposers so that when the application crashes, the targeted dependency calls that function. - -```typescript -export const useContainer = Sern.makeDependencies({ - build: (root) => - root - .add({ - "@sern/client": single(() => client), - }) - .addDisposer({ "@sern/client": (client) => client.destroy() }), -}); -``` - -:::tip -Below is v3 api. -::: - -## Init - -Do you need to perform intializing behavor for a dependency? - -```ts -import { Init } from "@sern/handler"; -class Database implements Init { - init() { - await this.connect(); - console.log("Connected"); - } -} -``` - -Modify you Dependencies interface: - -```ts title="src/dependencies.d.ts" -import type { Initializable } from "@sern/handler"; - -interface Dependencies extends CoreDependencies { - database: Initializable; -} -``` - -Make sure its been added: - -```ts title="src/index.ts" -await makeDependencies({ - build: root => root - .add({ database => new Database() }) -}) -``` diff --git a/src/content/docs/guide/walkthrough/dependency-injection.mdx b/src/content/docs/guide/walkthrough/dependency-injection.mdx new file mode 100644 index 000000000..a0ee5b081 --- /dev/null +++ b/src/content/docs/guide/walkthrough/dependency-injection.mdx @@ -0,0 +1,128 @@ +--- +title: Dependency Injection +sidebar: + order: 10 +--- + +:::danger +This contains version 2 code. Please view [transitioning to v3](../transition) for the `Service` API. +::: + +Since version 2.0.0, dependency injection, thanks to [iti](https://github.com/molszanski/iti), is a feature to customize your bot's utilities and structures. + +For example, a minimal setup for any project might look like this: + +```ts title="src/index.ts" +const client = new Client({ + ...options, +}); + +Sern.makeDependencies({ + build: (root) => + root.add({ + "@sern/client": single(() => client), + }), +}); +``` + +For any TypeScript project, you'll need to add an interface to get intellisense and typings. + +```ts title="src/dependencies.d.ts" +interface MyDependencies extends Dependencies { + "@sern/client": Singleton; +} +``` + +## Full Example + +Your full setup may have the following structure: + +import { FileTree } from '@astrojs/starlight/components'; + + +- src/ + - index.ts **(your main file and client)** + - dependencies.d.ts **(for intellisense)** + + +```ts title="src/index.ts" +const client = new Client({ + ...options, +}); + +interface MyDependencies extends Dependencies { + "@sern/client": Singleton; +} + +export const useContainer = Sern.makeDependencies({ + build: (root) => + root.add({ + "@sern/client": single(() => client), + }), +}); +``` + +Everything else is handled. However, you may want customize things. + +## Adding Dependencies to Root + +Each sern built dependency must implement its contracts: + +- `@sern/logger`: Logging data → [`Logging`](../../../api/interfaces/logging) +- `@sern/errors`: Handling errors and lifetime → [`ErrorHandling`](../../../api/interfaces/errorhandling) +- `@sern/modules`: Managing all command modules → [`ModuleManager`](../../../api/interfaces/modulemanager) +- `@sern/emitter`: The key to emit events and occurences in a project → [`Emitter`](../../../api/interfaces/emitter) + +You may also add disposers so that when the application crashes, the targeted dependency calls that function. + +```ts title="src/index.ts" +export const useContainer = Sern.makeDependencies({ + build: (root) => + root + .add({ + "@sern/client": single(() => client), + }) + .addDisposer({ "@sern/client": (client) => client.destroy() }), +}); +``` + +:::caution +Below is v3 API. +::: + +## Init + +import { Steps } from '@astrojs/starlight/components'; + + +1. Do you need to perform intializing behavor for a dependency? + ```ts title="src/database.ts" + import { Init } from "@sern/handler"; + + class Database implements Init { + init() { + await this.connect(); + console.log("Connected"); + } + } + ``` + +2. Modify your `Dependencies` interface: + ```ts title="src/dependencies.d.ts" {4} + import type { Initializable } from "@sern/handler"; + + interface Dependencies extends CoreDependencies { + database: Initializable; + } + ``` + +3. Make sure its been added: + ```ts title="src/index.ts" {3} + await makeDependencies({ + build: root => root + .add({ database => new Database() }) + }) + ``` + +4. Now, when your bot starts, the `init` method will be called. 🎉 + diff --git a/src/content/docs/guide/walkthrough/first-command.mdx b/src/content/docs/guide/walkthrough/first-command.mdx index c2b9323d4..3614729bc 100644 --- a/src/content/docs/guide/walkthrough/first-command.mdx +++ b/src/content/docs/guide/walkthrough/first-command.mdx @@ -4,19 +4,29 @@ sidebar: order: 5 --- -We will dissect a basic command. -If you installed a new project via the cli, This is the `ping` command located in src/commands folder. - :::tip -TLDR: command modules are discord bot commands. There are many types, and each one will correspond to an event from discord. -For example, CommandType.Slash commands will listen to slash command interactions. +**TLDR:** Command modules are Discord bot commands. There are many types, and each one will correspond to an event from Discord. For example, `CommandType.Slash` commands will listen to slash command interactions. ::: +## Introduction + +In this guide, we'll walk you through creating your first command module. + +If you installed a new project via the CLI, your file should be here: + +import { FileTree } from '@astrojs/starlight/components'; + + +- src/commands/ + - ping.ts **(right here, probably)** +- ... + + import { Tabs, TabItem } from '@astrojs/starlight/components'; - ```js + ```js title="src/commands/ping.js" const { CommandType, commandModule } = require("@sern/handler"); export default commandModule({ @@ -30,8 +40,8 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; }); ``` - - ```ts + + ```ts title="src/commands/ping.ts" import { commandModule, CommandType } from "@sern/handler"; export default commandModule({ @@ -47,22 +57,27 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; -To view what each of these properties mean in depth, visit the [official documentation](https://sern.dev/docs/api/enums/CommandType). +To view what each of these properties mean in depth, visit the docs for [`CommandType`](../../../api/enumerations/commandtype). -### Types of command modules +## Command Module Types -Every command module `type` is part of an enum. This field allows type inference for the rest of a module's fields.
-All the command types can be found in the [official documentation](https://sern.dev/docs/api/enums/CommandType)! +Every command module `type` is part of an enum. This field allows type inference for the rest of a module's fields. -

So, lets say you want to make a command module that listens to modals.

+All the command types can be found in the [`CommandType`](../../../api/enumerations/commandtype) enum! -**Note**: Keep in mind you'll need to send a modal with a custom id `dm-me`. This example below is the response to a modal being sent. -
+## Example Modal Command + +So, lets say you want to make a command module that listens to modals. + +:::tip +Keep in mind, you'll need to send a modal with a custom id of `dm-me`. This example below is the response to a modal being sent. +::: ```javascript const { CommandType, commandModule } = require("@sern/handler"); + exports.default = commandModule({ name: "dm-me", type: CommandType.Modal, @@ -76,9 +91,10 @@ All the command types can be found in the [official documentation](https://sern. }); ``` - + ```typescript import { commandModule, CommandType } from "@sern/handler"; + export default commandModule({ name: "dm-me", type: CommandType.Modal, @@ -94,14 +110,13 @@ All the command types can be found in the [official documentation](https://sern. -Commands are straight forward. Keep in mind, every other property on the commandModule object is -optional **except** the type and execute function. +Commands are straight forward. Keep in mind, the only required fields for command modules are the `type` and `execute` function. -# Context class +## Context Class -The provided Context class helps with modules of `CommandType.Both` (A mixture of slash / legacy commands). +The provided [`Context`](../../../api/classes/context) class helps with modules of `CommandType.Both` (A mixture of slash / legacy commands). -The Context class is passed into modules with type: +The `Context` class is passed into modules with type: - `CommandType.Both` - `CommandType.Slash` diff --git a/src/content/docs/guide/walkthrough/first-event.mdx b/src/content/docs/guide/walkthrough/first-event.mdx index 0c707e905..705c7f410 100644 --- a/src/content/docs/guide/walkthrough/first-event.mdx +++ b/src/content/docs/guide/walkthrough/first-event.mdx @@ -4,17 +4,19 @@ sidebar: order: 6 --- -We will dissect a basic event module.
- :::tip -TLDR: event modules are event listeners. there are three types EventType.Discord, EventType.Sern, EventType.External +**TLDR:** Event modules are event listeners. There are three types: `EventType.Discord`, `EventType.Sern`, and `EventType.External`. ::: +## Introduction + +In this guide, we'll walk you through creating your first event module. + import { Tabs, TabItem } from '@astrojs/starlight/components'; - ```javascript + ```js title="src/events/activate.js" exports.default = eventModule({ type: EventType.Sern, plugins : [], @@ -25,8 +27,8 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; }) ``` - - ```typescript + + ```ts title="src/events/activate.ts" export default eventModule({ type: EventType.Sern, plugins : [], @@ -39,16 +41,15 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; -Like command modules, the `type` property denotes what kind of event it is, which -can be found [here](https://sern.dev/docs/api/enums/EventType). +Similar to command modules, the `type` property denotes what kind of event it is. You can view [`EventType`](../../../api/enumerations/eventtype) for more information. -To view what each of these properties mean in depth, visit the [official documentation](https://sern.dev/docs/api/enums/EventType). +To view what each of these properties mean in depth, visit the docs for [`EventType`](../../../api/enumerations/eventtype). -## External +## External Events -In version 2 & 3, any dependency that you have passed into makeDependencies can be registered here as well. +In versions 2 & 3, any dependency that you have passed into `makeDependencies` can be registered here as well. -```ts title="src/index.ts" +```ts title="src/index.ts" {3} await makeDependencies({ build: root => root.add({ eventlistener: single(() => new EventEmitter()) @@ -56,14 +57,18 @@ await makeDependencies({ }) ``` -```ts title="events/myevent.ts" +In your event module, you can now listen to events from `eventlistener`, which will be emitted from the `EventEmitter`. + +```ts title="src/events/myevent.ts" {3} export default eventModule({ type: EventType.External, emitter: 'eventlistener', execute: (args) => { - console.log('Got event from eventlistener: ', args); + console.log('Got event from eventlistener: ', args); } }) ``` - +:::note +Make sure that the `emitter` property matches the name of the dependency you passed into `makeDependencies`. +::: \ No newline at end of file diff --git a/src/content/docs/guide/walkthrough/goal.md b/src/content/docs/guide/walkthrough/goal.md deleted file mode 100644 index 6dc142a13..000000000 --- a/src/content/docs/guide/walkthrough/goal.md +++ /dev/null @@ -1,52 +0,0 @@ ---- -title: Goal -sidebar: - order: 1 ---- - -This walkthrough will be written in [TypeScript](https://www.typescriptlang.org/) but will have JavaScript snippets throughout. - -# Make robust, modular, bots - -- _Modularity_: sern is built with modularity in mind. You can swap pieces and parts easily. -- _Familiar_: commands and structures are similar to classic v12 handlers and the official discord.js command handler guide, while packing many features -- _Concise_: Too much code is a liability. with sern, write less for more 🤯 - -### Using @sapphire/framework - -```ts title="commands/ping.ts" showLineNumbers -import { Command } from "@sapphire/framework"; -import type { CommandInteraction } from "discord.js"; - -export class PingCommand extends Command { - public constructor(context: Command.Context) { - super(context, { - description: "Pong!", - chatInputCommand: { - register: true, - }, - }); - } - public async chatInputRun(interaction: CommandInteraction) { - await interaction.reply("Pong!"); - } -} -``` - -### Using @sern/handler - -```ts title="commands/ping.ts" showLineNumbers -import { commandModule, CommandType } from "@sern/handler"; -import { publish } from "../plugins"; - -export default commandModule({ - type: CommandType.Both, - plugins: [publish()], - description: "Pong!", - execute: (ctx, args) => { - await ctx.reply("Pong!"); - }, -}); -``` - -Keep in mind the above example acts as both a slash command AND text command diff --git a/src/content/docs/guide/walkthrough/goal.mdx b/src/content/docs/guide/walkthrough/goal.mdx new file mode 100644 index 000000000..6704eec59 --- /dev/null +++ b/src/content/docs/guide/walkthrough/goal.mdx @@ -0,0 +1,57 @@ +--- +title: Goal +sidebar: + order: 1 +--- + +This walkthrough will be written in [TypeScript](https://www.typescriptlang.org/) but will have JavaScript snippets throughout. + +## Make robust, modular, bots + +- **Modularity**: sern is built with modularity in mind. You can swap pieces and parts easily. +- **Familiar**: Commands and structures are similar to classic v12 handlers and the official Discord.js command handler guide, while packing many features! +- **Concise**: Too much code is a liability. With sern, write less for more. 🤯 + +## Why sern? + +import { Tabs, TabItem } from '@astrojs/starlight/components'; + + + + ```ts title="commands/ping.ts" + import { Command } from "@sapphire/framework"; + import type { CommandInteraction } from "discord.js"; + + export class PingCommand extends Command { + public constructor(context: Command.Context) { + super(context, { + description: "Pong!", + chatInputCommand: { + register: true, + }, + }); + } + public async chatInputRun(interaction: CommandInteraction) { + await interaction.reply("Pong!"); + } + } + ``` + + + ```ts title="commands/ping.ts" + import { commandModule, CommandType } from "@sern/handler"; + + export default commandModule({ + type: CommandType.Both, + description: "Pong!", + execute: async (ctx, args) => { + await ctx.reply("Pong!"); + }, + }); + ``` + + + +Keep in mind the sern example acts as both a slash command AND a text command. The Sapphire example is only a slash command, and it's more code than sern. + +## Be smart. Choose sern. diff --git a/src/content/docs/guide/walkthrough/good-to-know.md b/src/content/docs/guide/walkthrough/good-to-know.md index 417c5dabc..207756a99 100644 --- a/src/content/docs/guide/walkthrough/good-to-know.md +++ b/src/content/docs/guide/walkthrough/good-to-know.md @@ -6,15 +6,15 @@ sidebar: ## sern.config.json -

A sern.config.json, although not necessary, allows your project to communicate with our cli.

+A `sern.config.json`, although not necessary, allows your project to communicate with our cli. -For example, when installing typescript plugins, the language property is necessary to install from our -[open source repository](https://github.com/sern-handler/awesome-plugins).
+For example, when installing TypeScript plugins, the language property is necessary to install from our [open source repository](https://github.com/sern-handler/awesome-plugins). + +Using the CLI and running `sern init --sync` on pre-existing projects should install this file in the your project. -Using the cli and running `sern init --sync` on pre-existing projects should install this json file in the root directory given. Or, if this is a brand-new project, `sern init` automatically installs it. -```json +```json title="sern.config.json" { "language": "typescript", "paths": { diff --git a/src/content/docs/guide/walkthrough/new-project.md b/src/content/docs/guide/walkthrough/new-project.md deleted file mode 100644 index 6af40bfa0..000000000 --- a/src/content/docs/guide/walkthrough/new-project.md +++ /dev/null @@ -1,13 +0,0 @@ ---- -title: New Project -sidebar: - order: 2 ---- - -```sh -npm create @sern/bot -``` - -and follow the interactive prompts. - -if somehow you need help, feel free to ask [here](https://sern.dev/discord) diff --git a/src/content/docs/guide/walkthrough/new-project.mdx b/src/content/docs/guide/walkthrough/new-project.mdx new file mode 100644 index 000000000..e43ce7de5 --- /dev/null +++ b/src/content/docs/guide/walkthrough/new-project.mdx @@ -0,0 +1,13 @@ +--- +title: New Project +sidebar: + order: 2 +--- + +import PackageManagers from '~/components/PackageManagers.astro'; + + + +Once you've used this command, follow the interactive prompts to create your new project. + +If you need help, feel free to ask on our [Discord](https://sern.dev/discord). diff --git a/src/content/docs/guide/walkthrough/plugins.mdx b/src/content/docs/guide/walkthrough/plugins.mdx index 2066a9e8b..0ad406117 100644 --- a/src/content/docs/guide/walkthrough/plugins.mdx +++ b/src/content/docs/guide/walkthrough/plugins.mdx @@ -5,25 +5,31 @@ sidebar: --- :::tip -TLDR: Plugins help reduce code repetition and are installable via `sern plugins`. Put them onto the plugins field of a command/event module. +**TLDR:** Plugins help reduce code repetition and are installable via `sern plugins`. Put them into the `plugins` field of a command/event module. ::: -## Installing +## Installation Chances are, you just want your bot to work. Plugins can preprocess and create reusable conditions for modules. -run: +To install plugins, you can use the CLI: ```sh sern plugins ``` -- Install your favorite(s) (or the ones that look the coolest). In my imaginary mind, I installed the ownerOnly plugin. - - This should install in `plugins` directory in `src`. -- Some plugins only work with specific types. Most are targeted towards slash / both modules. -- Add to your module. +:::caution +Some plugins only work with specific command types. Most, however, are targeted towards slash / both modules. +::: -```ts +import { Steps } from '@astrojs/starlight/components'; + + +1. Install your favorite(s) (or the ones that look the coolest). In my imaginary mind, I installed the `ownerOnly` plugin. (This should install to `src/plugins`) +2. Add the plugin to your module in the `plugins` field. + + +```ts title="src/commands/ping.ts" {6} import { commandModule, CommandType } from '@sern/handler' import { ownerOnly } from '../plugins' @@ -39,13 +45,17 @@ export default commandModule({ #### ┗|` O′|┛ perfect, your first plugin! -## Creating your own plugins +## Creating Plugins -The controller determines in plugins whether to continue or fail. +Plugins are essentially functions that use the controller object to determine whether to continue or stop the execution of a command. -### The controller object +### Controller Object -```typescript +The controller object is passed into every plugin. It has two methods: `next` and `stop`. + +Plugins use these methods to control the flow of the command. For example, if a plugin fails, it can call `controller.stop()` to prevent the command from executing. + +```ts export interface Controller { next: () => Ok; stop: () => Err; @@ -55,28 +65,31 @@ export interface Controller { ## Init Plugins Init plugins modify how commands are loaded or do preprocessing. -An instance of the above object is passed into every plugin.
-This controls whether a module is stored into sern.
-```typescript +An instance of `Controller` (as seen above) is passed into every plugin. This controls whether a module is stored into sern. + +```ts title="src/plugins/inDir.ts" {11} {14} import { CommandInitPlugin } from "@sern/handler"; import path from "path"; + export const inDir = (dir: string) => { return CommandInitPlugin(({ module, absPath }) => { if (path.dirname(absPath) !== dir) { console.log( - +new Date(), + Date.now(), `${module.name} is not in the correct directory!`, ); return controller.stop(); } - console.log(+new Date(), `${module.name} is in the correct directory!`); - return controller.next(); //continue + console.log(Date.now(), `${module.name} is in the correct directory!`); + return controller.next(); // continue to next plugin }); }; ``` -Above, this simple plugin logs that the module has been loaded along with a timestamp.
+:::tip +The plugin above simply checks if the module is in the correct directory. If it's not, it logs a message and stops the command from being loaded. +::: ## Event Plugins @@ -85,20 +98,24 @@ import eventPlugins from '~/assets/docs/event-plugins.png'; control plugins -- An event is emitted by discord.js. -- This event is passed to all plugins (**in order!!**), -- If all are successful, + +1. An event is emitted by `discord.js`. +2. This event is passed to all plugins (**in order!!**), +3. If all are successful, the command is executed. + -The command is executed. Calling `controller.stop()` notifies sern that this command should not be run, -and command is ignored. +:::note +Calling `controller.stop()` notifies sern that this command should not be run, and command is ignored. +::: -Can you predict the behavior of this command? +#### Can you predict the behavior of this command? -- Before loading into sern, this command module will check if this module is in the correct directory `other`. -- Before an event occurs, this command module will check if the user has the id `182326315813306368`. + +1. Before loading into sern, this command module will check if this module is in the correct directory: `other`. +2. Before an event occurs, this command module will check if the user has the id `182326315813306368`. +3. If all plugins return `controller.next()`, this command replies `Pong 🏓` + :::tip Event Plugins are good for filtering, preconditions, parsing. -::: - -If all plugins return `controller.next()`, this command replies `Pong 🏓` +::: \ No newline at end of file diff --git a/src/content/docs/guide/walkthrough/sern-emitter.md b/src/content/docs/guide/walkthrough/sern-emitter.md deleted file mode 100644 index f819dc4f8..000000000 --- a/src/content/docs/guide/walkthrough/sern-emitter.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -title: Sern Emitter -sidebar: - order: 11 ---- - -You're shipped with the SernEmitter. This EventEmitter listens to - -- command modules executing and its status, the `module.activate` event -- command modules registered and its status, the `module.register` event -- On default, sern creates a single SernEmitter for your bot process. -- any error that occurs, the `error` event -- `warn` events, where it is possible to throw errors - -You can put these and other event listeners into [event modules](./first-event.md)! -
View all events diff --git a/src/content/docs/guide/walkthrough/sern-emitter.mdx b/src/content/docs/guide/walkthrough/sern-emitter.mdx new file mode 100644 index 000000000..1dc87001e --- /dev/null +++ b/src/content/docs/guide/walkthrough/sern-emitter.mdx @@ -0,0 +1,21 @@ +--- +title: Sern Emitter +sidebar: + order: 11 +--- + +You're shipped with the `SernEmitter` class. This `EventEmitter` listens to + +import { Steps } from '@astrojs/starlight/components'; + + +1. Command modules executing and its status; the `module.activate` event +2. Command modules registered and its status; the `module.register` event +3. On default, sern creates a single SernEmitter for your bot process. +4. Any error that occurs; the `error` event +5. `warn` events, where it is possible to throw errors + + +You can put these and other event listeners into [event modules](../first-event)! + +You can view all events in the [`SernEventsMapping`](../../../api/interfaces/serneventsmapping) interface. \ No newline at end of file diff --git a/src/content/docs/guide/walkthrough/services.mdx b/src/content/docs/guide/walkthrough/services.mdx index 40ca288b6..a94b0607d 100644 --- a/src/content/docs/guide/walkthrough/services.mdx +++ b/src/content/docs/guide/walkthrough/services.mdx @@ -4,16 +4,16 @@ sidebar: order: 8 --- -:::tip +:::danger This is version 3 api only!! ::: :::tip -TLDR: The direct upgrade to useContainer. if you set up a bot with create-bot, check dependencies.d.ts. +**TLDR:** The direct upgrade to `useContainer`. if you set up a bot with `create-bot`, check `dependencies.d.ts`. Dependencies are the types that Services uses. ::: -You need someway to use dependencies in your command module. Services to the rescue! +You need some way to use dependencies in your command module. Services to the rescue! ```ts title="src/dependencies.d.ts" import { CoreDependencies, Singleton } from "@sern/handler"; @@ -24,28 +24,31 @@ interface Dependencies extends CoreDependencies { } ``` -Recall, some keys in Dependencies are special. +## Special Dependencies -> Special key dependency must implement its contracts. -> -> - `@sern/client`: Your discord client. -> [Emitter](../../api/interfaces/Emitter) -> - `@sern/logger`: Log data -> [Logging](../../api/interfaces/Logging) -> - `@sern/errors`: Handling errors and lifetime -> [ErrorHandling](../../api/interfaces/ErrorHandling) -> - `@sern/modules`: Managing all command modules -> [ModuleManager](../../api/interfaces/ModuleManager) -> - `@sern/emitter`: is the key to emit events and occurences in a project -> [Emitter](../../api/interfaces/Emitter) +Some keys in `Dependencies` are special and are used by sern internally: + +- `@sern/client`: Your Discord client. → [`Emitter`](../../../api/interfaces/emitter) +- `@sern/logger`: Logging data → [`Logging`](../../../api/interfaces/logging) +- `@sern/errors`: Handling errors and lifetime → [`ErrorHandling`](../../../api/interfaces/errorhandling) +- `@sern/modules`: Managing all command modules → [`ModuleManager`](../../../api/interfaces/modulemanager) +- `@sern/emitter`: The key to emit events and occurences in a project → [`Emitter`](../../../api/interfaces/emitter) + +## Usage Lets try to access the client you provided. -```ts title="src/commands/ping.ts" +```ts title="src/commands/ping.ts" {8} import { Service } from "@sern/handler"; export default commandModule({ // ... execute: (ctx) => { - //Client! + // Type is inferred from the dependencies file. + // → Dependencies['@sern/client'] const client = Service("@sern/client"); }, - // + // ... }); ``` @@ -53,16 +56,18 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ## Safety -- Services cannot be called in other services while makeDependencies is forming. +Services cannot be called in other services while `makeDependencies` is forming. + +For example, let's pass a logger into our database: + +### Example - Lets pass a logger into our database. - ```ts title="index.ts" await makeDependencies({ build: root => root - //Overriding the default logger provided. + // Overriding the default logger provided. .upsert({ '@sern/logger': single(() => new Logger()) }) // Wiring our logger into the database. @@ -77,7 +82,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; await makeDependencies({ build: (root) => root - //Overriding the default logger provided. + // Overriding the default logger provided. .upsert({ "@sern/logger": single(() => new Logger()) }) // Wiring our logger into the database. @@ -89,7 +94,7 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; ```ts title="index.ts" import { Service, makeDependencies } from "@sern/handler"; - //Calling Service prematurely! + // Calling Service prematurely! const logger = Service("@sern/logger"); class Database { @@ -102,18 +107,12 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; -- Services can only be used after sern has made dependencies. - - Calling a service before will crash your application. -- Services can be safely used outside of commandModules. - - - Be careful to not cause too many side effects. - -- You will need to wire dependencies together. +### Another Example ```ts title="index.ts" - await makeDependencies(...pass your options here) + await makeDependencies(/* ...pass your options here */) ``` ```ts title="commands/ping.ts" @@ -133,12 +132,19 @@ import { Tabs, TabItem } from '@astrojs/starlight/components'; -- Services can only be used after sern has made dependencies. - - Calling a service before will crash your application. -- Services can be safely used outside of commandModules. - - Be careful to not cause too many side effects. +## Important -## Related api +import { Steps } from '@astrojs/starlight/components'; -- use `Service` for single dependency. -- use `Services` for multiple dependencies. + +1. Services can only be used after sern has made dependencies.
→ Calling a service before will crash your application. +2. Services can be safely used outside of a `commandModule`.
→ Be careful to not cause too many side effects. +3. You will need to wire dependencies together.
→ This is a good practice to keep your code clean. +4. Services can only be used after sern has made dependencies.
→ Calling a service before will crash your application. +5. Services can be safely used outside of a `commandModule`.
→ Be careful to not cause too many side effects. +
+ +## Related API + +- Use `Service` for single dependency. +- Use `Services` for multiple dependencies. diff --git a/src/content/docs/guide/walkthrough/transition.mdx b/src/content/docs/guide/walkthrough/transition.mdx index 32bcf33b4..4eaa42b94 100644 --- a/src/content/docs/guide/walkthrough/transition.mdx +++ b/src/content/docs/guide/walkthrough/transition.mdx @@ -9,10 +9,10 @@ sidebar: + await makeDependencies({ build: () => {} }) ``` -v3 comes with the new [Service api](../services). To make sure to enable intellisense -include a dependencies.d.ts file into compilation. [Click here for all new features](../../../blog/3.0.0) +v3 comes with the new [Service API](../services). To make sure to enable intellisense, +include a `dependencies.d.ts` file into compilation. (Check out the [changelog](../../../blog/3.0.0) for all new features) -```ts +```ts title="dependencies.d.ts" /** * This file serves as intellisense for sern projects. * Types are declared here for dependencies to function properly @@ -48,7 +48,7 @@ import { FileTree } from '@astrojs/starlight/components'; - commands/ - events/ - plugins/ - - dependencies.d.ts + - dependencies.d.ts **(add this)** - index.ts - .env - .gitignore