Install & Setup
This section will cover setting up your project, installing the required dependencies and ensuring we are ready to code.
Installation
To start with go to the parent folder of where you want your project to be created and then run the following command:
bun create @sodacore@alpha
This will prompt you for some information about your project, go ahead and fill this in. Once you get to the plugin selection, ensure you select HTTP, WebSockets, Prisma, Discord and I18n plugins. Then press enter. This will create the folders and initialise the project with some example code you can work from.
Once the project is created, open your project folder in your IDE.
Congrats, you now have a basic project setup, if you were to run bun dev
in your project folder, you will see some logging output and you can then go to your browser and
Database setup
To setup our database, we are going to use Prisma ORM to deal with this, and use the SQLite database for simplicity, of course you can use any database you want, but for this guide we will use SQLite.
To start with, the @sodacore/prisma
plugin has already installed the Prisma CLI for us, so we need to run simply run:
bun prisma init --datasource-provider sqlite
This command defines the preconfigured provider as
sqlite
for us.
This will create a prisma
folder in your project, let's open up the ./prisma/schema.prisma
file and take a look, let's create a simple schema for our to-do application.
generator client {
provider = "prisma-client-js"
output = "./prisma"
}
datasource db {
provider = "sqlite"
url = env("DATABASE_URL")
}
model Todos {
id Int @id @default(autoincrement())
title String
description String?
completed Boolean @default(false)
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
model ChatMessages {
id Int @id @default(autoincrement())
username String
message String
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
}
This will cover our basic todos and chat messages (this makes use of the WebSocket plugin), and yes... we are making a todo with a chat system!
Let's generate the Prisma client, in the latest versions of Prisma, you have to define where the Prisma "client" is generated (originally it went into your node_modules
), by default it is generated in the src/generated/prisma
folder, I personally prefer to keep it within the prisma folder so I have amended it to be ./prisma
.
The
output
is relative to theschema.prisma
file.
To generate the Prisma client, run the following command:
bun prisma generate
This will generate the client, and our type definitions, when you import the client, you would do so like this:
// File: src/x.ts
import { PrismaClient } from '../prisma/prisma/client';
Lastly, we need to create the database file, by default with SQLite, there is no file created, here you can use Migrations but for simplicity and because this structure won't change in this demo, we will just push the database schema to the database, so run the following command:
bun prisma db push
This will create the database file within the prisma
folder, as it's based on the DATABASE_URL
environment variable, which has been set to file:./db.sqlite
in our .env
file (which is also relative to the prisma schema file).
Environment Variables
Next, we need to define some environment variables for our project, because we ran the prisma init command earlier, it has already created a .env
file for us, and tweak like so:
CLI_PASSWORD="YOUR_CLI_PASSWORD"
DATABASE_URL="file:./db.sqlite"
DISCORD_TOKEN="YOUR_DISCORD_BOT_TOKEN"
DISCORD_CLIENT_ID="YOUR_DISCORD_CLIENT_ID"
DISCORD_GUILD_ID="YOUR_DISCORD_GUILD_ID"
HTTP_PORT="3000"
This should cover everything we need for our project, you can change the HTTP_PORT
to whatever you want, but for this guide we will use 3000
.
The reason we have added the
DISCORD_GUILD_ID
is that when you install slash commands globally, they can take up to an hour to propagate, but in development you should use the guild ID to start with, as this will register the commands instantly, so you can test them out within your Discord server, and then install globally once you're happy with them, the Sodacore discord plugin can register to both, please note, the CLI will show the the Guild ID when selecting to register to a guild by default (it uses your config).
Setting up the framework
Now we have our project setup, let's write some code to initialise the framework and load our plugins.
Go to the src/main.ts
file and edit the contents like so:
import { Application } from '@sodacore/core';
import { env } from 'bun';
import { resolve } from 'node:path';
import process from 'node:process';
import HttpPlugin from '@sodacore/http';
import DiscordPlugin from '@sodacore/discord';
import PrismaPlugin from '@sodacore/prisma';
import I18nPlugin from '@sodacore/i18n';
import WsPlugin from '@sodacore/ws';
// Initialise application.
const app = new Application({
name: 'Sodacore Demo',
autowire: true,
enableCli: true,
password: env.CLI_PASSWORD,
basePath: env.SODACORE_ENV === 'prod'
? resolve(process.cwd(), './dist')
: undefined,
});
// Install the HTTP plugin.
app.use(new HttpPlugin({
port: env.HTTP_PORT ? parseInt(env.HTTP_PORT) : 8080,
}));
// Install the Discord plugin.
// Commented out for later.
// app.use(new DiscordPlugin({
// token: env.DISCORD_TOKEN,
// clientId: env.DISCORD_CLIENT_ID,
// guildId: env.DISCORD_GUILD_ID,
// }));
// Install the WebSocket plugin.
app.use(new WsPlugin({
path: '/ws',
}));
// Install the Prisma plugin.
// Note that the Prisma plugin automatically will find the schema file in the
// default location of `./prisma/schema.prisma` and will dynamically find the
// generated client and import it, if you have changed it, then you can pass
// the `schemaFileLocation` setting, which points to your schema file, so the
// plugin can automatically parse and find the generated client.
app.use(new PrismaPlugin());
// Install the I18n plugin.
app.use(new I18nPlugin({
defaultLocale: 'en-GB',
}));
// Start the application.
app.start().catch(console.error);
Next Steps
Now we have done all of this our project should be in a good state to start coding.