How do you register paths for pieces? Also have an additional question when this one is solved.
I have a file structure as outlined below, I am wondering how I can make sapphire recognize this path and register the respective stores for that path. I am running into the issue of even when calling <Store>.registerPath and pointing to my pieces folder it isn't loading the commands I have.
45 Replies
I extend the SapphireClient (as I will be adding my own stuff later) and call registerPath in the constructor so it does so when the client is inited.
It's best if you use absolute paths instead of relative ones, so if you want to use a path from CWD,
path.resolve('src/pieces')
will work just fine.
However, you can debug the piece loader by assigning Store.logger
(static property), which will be called on every loader operation, or define logger: { level: LogLevel.Trace }
in your client options for the same behaviour (source). This will write a lot of lines showing what exactly is the loader loading and where it's crawling in the file system.
If you're getting other errors, please let me know which error, runtime (Node.js, Deno, Bun), runtime version, Sapphire version, and if possible, a link to the Git repository to help investigate.Uhm, wow that is a lot of mess
it seems to be loading from src/pieces and from my root folder
Sapphire does some mess so you don't have to! <:iara_wink_peace:881533315126018128>
Question, did you set
loadDefaultErrorListeners: false
? If you don't have an error listener, the loader may be erroring but with no listener listening to the errors, nothing is printedno I didn't I have a pretty basic implementation right now.
It appears to be loading everything in the place I specify but then trying to load it somewhere else overriding the previous store values
You don't want to load anything at
core
, right? Only at pieces
yes
right now it is loading at
C:\Dev\maid
and C:\Dev\maid\src\pieces
In that case you can use the
baseUserDirectory
Client option to override the default path, baseUserDirectory: path.resolve('src/pieces')
should suffice
Also, we recommend using listeners instead of client.on
, it'll help organise your codeI was going to add listeners but it wasn't registering the commands or listeners so I used client.on temporarily to see if calling registerPath in ready would see
It's not loading my commands
I'll need code then, what's in those commands?
Oh... you're trying to run TypeScript code directly
nope, I am using tsc first
then running the js code
Then you should be running the compiled code, which should ideally be in a folder named
dist
it indeed is
I am running the resulting index.js file which is the project's main file after compiling
Have a look at https://sapphirejs.dev/docs/Guide/additional-information/implementing-a-discordpy-like-cog-system. Although with that you will have to name events to listeners or register the custom name still.
And there's also https://github.com/KBot-discord/plugins/tree/main/packages/modules which basically implements that cog system from the guide page.
GitHub
plugins/packages/modules at main · KBot-discord/plugins
Sapphire plugins for KBot. Contribute to KBot-discord/plugins development by creating an account on GitHub.
I might be confused on how this helps, but I don't see how this has anything to do with it skipping over the command file?
It is clearly already attempting to load the command at the right path, but skipping over it for some reason.
Also no idea what cogs are.
Discord py term. Modules essentially. We get many discord py transitions here
Oh I was just coming from detritus lol
pretty sure dpy references the concept of cogs in a wheel/system
but i never used dpy so idk
In detritus you could register commands in the
options
field it had and it was basically a command of itself. It just made it a subcommand
So I instinctivly did ModGroup cause I was expecting to be able to separate my sub commands into their own files.anyway did you change
src/pieces
to dist/pieces
already?I can right now yea.
You're loading the JS files after all, not the TS ones
yea thats fair. Idk what I was thinking there.
Haven't made a discord bot in 2.5 years
Might I say I've never heard of detritus before but I find it extremely ironic how they first say they are a "pure-TypeScript library" but then proceed to use requirement statements in the top most code sample
lol
they are a dead project now. but it was actually a refreshing library rather than djs
That being said, the file structure you're using doesn't align with what the JS ecosystem typically does, which is why you're going thru some hops to even get it working 😅
In the JS ecosystem we have the piece directories alongside a
lib
directory, which is what your core
folder isYea, I haven't used typescript in a while, I just have never made a bot in rust
Adding to what kyra said, Maybe also have a looksie at some of the bots using sapphire
Discord Bots using @sapphire/framework
v5.x
- Gemboard ᴱ ᴰ
- Skyra ᴱ ᴬ ᴰ
- Dragonite ᴱ ᴰ
- Archangel ᴱ ᴰ
- Official Bot Examples ᴱ ᴰ ᴶˢ
- KBot ᴱ ᴬ ᴰ
v4.x
- Radon ᴱ ᴬ
- Sapphire Application Commands Examples ᴱ
- Zeyr ᴰ ᴬ
- Birthdayy ᴰ
- RTByte ᴱ ᴬ
Legend for the identifiers
ᴱ: Uses ESM (if not specified then uses CJS)
ᴬ: Advanced bot (if not specified it is a simple bot, or not graded)
ᴰ: Uses Docker in production
ᴶˢ: Written in JavaScript. If not specified then the bot is written in TypeScript.
I just realised that there's only 2 (ish) CJS bots there @kyra 🩵🩷🤍🩷🩵
lol, you're right
ESM stay winning
Also as for the other question I had, do i really have to code my subcommands all in one file?
Adding to this, it works just fine without a performance impact because when you're registering a path in the store manager, you're actually registering the path + the store name, so registering
src/pieces
will register src/pieces/commands
in the command store, src/pieces/listeners
in the listener store, and so on. A src/pieces/lib
would never be loaded unless you have a store named lib
. If other loaders you used just loaded the entire root, I can see why you separated the "lib" from the "pieces".What is the point of the lib folder? I looked at some of those other projects and they don't seem to do much with it if they use it at all
No, prefix non-piece utility files with
_
(underscore) to ignore it in the loader. So if you have conf.ts
, you can do _conf-add.ts
, _conf-remove.ts
, and so on, alternatively a _
prefixed directory would also work: _conf/add.ts
, _conf/remove.ts
.Okay, but how do I load those as sub commands ?
You'd export a function in those files which then the command calls in the subcommands
gotcha
so it'd work similar I just have to import that function and use the function name
ish. If you use the subcommands plugin then yes you do need to at least define the subcommands in the same file, but you can implement a class like this (rapid pseudo code!):
Yup, you can use
container
from @sapphire/framework
if you need to access to the Client instance of any other part of your application. In fact, this.container
in pieces is actually a getter returning that object.Well thanks for all the help guys!
I seem to be understanding more of how sapphire works