Skip to content

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:

zsh
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:

zsh
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.

prisma
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 the schema.prisma file.

To generate the Prisma client, run the following command:

zsh
bun prisma generate

This will generate the client, and our type definitions, when you import the client, you would do so like this:

typescript
// 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:

zsh
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:

ini
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:

typescript
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.

Released under the Apache-2.0 License.