Skip to main content

๐Ÿ“€ Models

If you're familiar with object-oriented, this is nothing more or less than a system of linking to the database in the form of objects.

Otherwise, imagine you can create a user, an animal or something else that we will call object and save it into the database. In classic SQL system you have to send hard requests to insert, select, update, drop, etc in your database. Here we have Models, an easy way to manipulate data from database, thank's to objects saved in your variables.

Let's create a User object in ./sources/modules/<module_name>/models/ with username, email and created_at as fields (dont forget to replace <module_name> by your module's name).

import { AModel } from "clappybot";

export default class User extends AModel
{
static table = 'users';
static fields = {
username: 'string',
email: 'string',
created_at: 'datetime'
};
}

๐Ÿ†• Create new Modelโ€‹

By convention, you should create your models inside the models folder of the module : ./sources/modules/<module_name>/models/ (dont forget to replace <module_name> by your module's name). Like this :

import { AModel } from "clappybot";

export default class User extends AModel
{
static table = 'users';
static fields = {
username: 'string',
email: 'string',
created_at: 'datetime'
};
}

At first, import the abstract class ' AModels ' which our model will inherit

import { AModel } from "clappybot";

Create your model as follows (replace <ModelName> by the name of your model) and don't forget to use export default so you can import it from other files:

export default class <ModelName> extends AModel

Set a table name (replace <table_name> with the name you want for your table):

static table = '<table_name>';

Define fields (you will see below the possible kinds of fields):

static fields = {
example: "text"
}

๐Ÿ“ Fieldsโ€‹

โŽฏ โ„น๏ธ Field type โ†’ SQL Type

integer โ†’ INT DEFAULT 0 a classic number (INT32), that can be a negative.

size โ†’ UNSIGNED INT โš ๏ธ only supported by mariadb/mysql, it's a number (INT32) but that can't be negative.

bigint โ†’ UNSIGNED BIGINT โš ๏ธ only supported by mariadb/mysql, it's a very big int (INT64) and that can't be negative.

datetime โ†’ DATETIME DEFAULT CURRENT_TIMESTAMP you can store date, it will be set at the creation date with hours (e.g: 2025-12-06 20:09:35) if you don't speficic one when you create a new instance.

string โ†’ VARCHAR(255) this is a tiny text field of up to 256 characters.

text โ†’ TEXT a large text (the maximum size depends on whether you are using PostgeSQL, MySQL/Mariadb or SQLite).

boolean โ†’ BOOLEAN simple true / false element.

timestamp โ†’ VARCHAR(20) used as timestamp (useful for database migrations)

โŽฏ ๐Ÿฅท And a secret field

You don't have to set it (and don't do it!) but there is a secret and default field inside every Model: id. This allows you to have a unique identifier for each instance of a Model. For example, each time you will create a user, it will come with a unique identifier id, so you can find easily the user from its id.

const user = await User.create({username: "Goya"});
console.log(user.id)
// Print "1" if it's the first user

const user_by_id = await User.firstBy({id: user.id})
console.log(user.username == user_by_id.username)
// True

๐Ÿ› ๏ธ Methodsโ€‹

This methods are inherited from AModel.

โŽฏ ๐Ÿงฑ Constructor

Declaration:

/**
* Create an instance of the model
* with the fields provided
* @param {{}} fields
*/
constructor(fields)

Example:

// Create a new instance (you must use user.save())
// if you want to save it in the database
const user = new User({username: "Goya", email: "[email protected]"});

โŽฏ ๐Ÿ’พ To define database

Declaration:

/**
* Defines database to be used
* @param {ADriver} db
*/
static use(db)

Example:

// Define the database to be used by your model, the framework
// will set clappybot.database by default so use this method
// only if you want to use an other database
User.use(clappybot.database);

โŽฏ โš™๏ธ To initialise database

Declaration:

/**
* Initialise the model's table,
* you should
*/
static async init()

Example:

// Initialise the table (the framework do it for you but
// if for some reason you need it, it's available)
await User.init()

โŽฏ โœ… To save instance to the database

Declaration:

/**
* Save current instance in database
*/
async save()

Example:

// Create a new instance (not saved)
const user = new User({username: "Goya", email: "[email protected]"});
// Save it to the database
await user.save();

โŽฏ โ™ป๏ธ Create and save at the same time

Declaration:

/**
* Create new instance of this model
* and save it in the database
* @param {{}} data
* @returns {Promise<AModel>}
*/
static async create(data = {})

Example:

// The "create" method creates the new element and saves it directly
const user = await User.create({username: "LeWeeky", email: "[email protected]"});

โŽฏ ๐Ÿ—‘๏ธ Delete instance

Declaration:

/**
* Delete current instance from database
*/
async delete()

Example:

// The "create" method creates the new element and saves it directly
const user = await User.create({username: "LeWeeky", email: "[email protected]"});
// Delete user thank's to the instance
await user.delete();

โŽฏ ๐Ÿงน Delete by fields

Declaration:

/**
* Deletes all elements that corresponding
* to the requested fields
* @param {{}} fields
*/
static async deleteBy(fields)

Example:

// All user with "LeWeeky" as their username AND "[email protected]" as
// their email will be deleted
await User.deleteBy({username: "LeWeeky", email: "[email protected]"});

โŽฏ ๐Ÿ—ƒ๏ธ Get all instances

Declaration:

/**
* Returns all elements of this table
* as new instances
*/
static async all()

Example:

// Get all users
const users = await User.all()
// Print all users in the console
for (let i = 0; i < users.length; i++)
{
const user = users[i];
console.log(user.username, user)
}

โŽฏ ๐Ÿ”Ž Get all instances by fields

Declaration:

/**
* Returns all elements that corresponding
* to the requested fields as new instances
* @param {{}} fields
* @param {number} limit
* @returns {Promise<new() AModel[] | never[]>}
*/
static async findBy(fields, limit = 0)

Example:

// Get all users with "LeWeeky" as their username
const some_users = await User.findBy({username: "LeWeeky"});
// Get 5 firsts users with "LeWeeky" as their username
const some_users_with_limit = await User.findBy({username: "LeWeeky"}, 5);

โŽฏ ๐Ÿ”Ž Get first instance by fields

Declaration:

/**
* Returns first element that corresponding
* to the requested fields as new instance
* @param {{}} fields
* @returns {Promise<AModel | null>}
*/
static async firstBy(fields)

Example:

// Get the first user from users with one or more specific fields
const leweeky = await User.firstBy({username: "LeWeeky"});

โŽฏ ๐Ÿช„ First or Create

Declaration:

/**
* Returns first element that corresponding
* to the requested fields as new instance
* or create a new one if not found
* @param {{}} fields
* @returns {Promise<AModel>}
*/
static async firstByOrCreate(fields)

Example:

// Get the first user corresponding
// or create one if there are none
const leweeky = await User.firstBy({username: "LeWeeky"});

โŽฏ ๐Ÿฅ‡ First

Declaration:

/**
* Returns first element as new instance
* @returns {Promise<AModel | null>}
*/
static async first()

Example:

// Get the first user
const user = await User.first();

๐Ÿ†™ Update instance fieldsโ€‹

Maybe you want to change username of a specific user, you can do so as follow:

const user = await User.firstBy({id: 1});

user.username = "New username";
// Dont forget to save if you want to update it
// in your database
await user.save();