Skip to main content

Database CRUD

This page covers create, read, update, and delete operations across all supported databases. The API is nearly identical for SQLite, PostgreSQL, MySQL, and MongoDB — the main difference is the import path and connection setup.

Setup

First connect to your database and create the table. See Getting Started for connection details.

For SQL databases, define your DataClass using createField from your database module:

// SQLite
const { SQLiteDatabase, createField, types } = require("@lol44lol/classo/databases/sqlite3")

// PostgreSQL
const { PostgresDatabase, createField, types } = require("@lol44lol/classo/databases/postgresql")

// MySQL
const { MySqlDatabase, createField, types } = require("@lol44lol/classo/databases/mysql")

// MongoDB
const { MongoDBDatabase, createField, types } = require("@lol44lol/classo/databases/mongodb")

Here is the DataClass we will use throughout this page. Swap the import for your database:

const { DataClass, DataClassFactory } = require("@lol44lol/classo/dataclasses/base")
const { createField, types } = require("@lol44lol/classo/databases/sqlite3") // change to your database
const { is_required, minLength } = require("@lol44lol/classo/dataclasses/validators")

class UserDataClass extends DataClass {

username = createField(types.TEXT, false, false, [
is_required("Username is required"),
minLength(4, "Username must be at least 4 characters")
])

password = createField(types.TEXT, false, false, [
is_required("Password is required"),
minLength(8, "Password must be at least 8 characters")
])

getName() { return "users" }
}
MySQL VARCHAR

For MySQL, fields you want to be unique must use types.VARCHAR instead of types.TEXT. Pass a max value in metaData:

username = createField(types.VARCHAR, true, false, [...validators], null, null, { max: 250 })

Create

Use DataClassFactory to validate and save data:

const { DATABASE_TYPES } = require("@lol44lol/classo/databases")

const db = new SQLiteDatabase("mydb.db")
await db.connect()
await db.createTable(UserDataClass)

const userFactory = new DataClassFactory(UserDataClass, { DATABASE: DATABASE_TYPES.SQLITE })

const payload = { username: "johndoe", password: "securepassword123" }

// create a DataClass instance for validation
const userInstance = userFactory.createObject(payload)
const result = await userInstance.validate()

if (result.data.okay) {
// transform data (runs afterValidation like password hashing)
const dataToSave = await userInstance.transformValidateDataToBeSaved(payload)
// save to database
const newUser = await userFactory.createModelObject(dataToSave)
console.log(newUser)
} else {
console.log("Validation failed:", result.data.error, "on field:", result.field)
}

createModelObject saves the record and returns the created object including the auto-generated _id, createdAt, and updatedAt fields.

DATABASE_TYPES

DatabaseConstant
SQLiteDATABASE_TYPES.SQLITE
PostgreSQLDATABASE_TYPES.POSTGRES
MySQLDATABASE_TYPES.MYSQL
MongoDBDATABASE_TYPES.MONGODB

Read

Get all records

// limit=10, skip=0 by default
const users = await db.find(UserDataClass, null, true, 10, 0)
console.log(users)

Get with filter

Pass a filter object to find matching records:

const user = await db.find(UserDataClass, { username: "johndoe" }, true)
console.log(user)

Get by ID

const user = await db.findById(UserDataClass, "some-uuid-here")
console.log(user)

find() parameters

ParameterTypeDescription
dataClassDataClassYour DataClass
queryObject or nullFilter conditions e.g. { username: "john" }
getObjBooleanSet to true
limitNumberMax records to return (default 10)
skipNumberRecords to skip for pagination (default 0)

Update

Use updateModelObject on the factory — pass a query to filter records and a payload with the new values:

const userFactory = new DataClassFactory(UserDataClass, { DATABASE: DATABASE_TYPES.SQLITE })

// find user with username "johndoe" and change it to "janedoe"
await userFactory.updateModelObject(
{ username: "johndoe" }, // query - which records to update
{ username: "janedoe" } // payload - what to change
)

This updates all records matching the query.


Delete

Use deleteModels on the factory — pass a query to filter which records to delete:

const userFactory = new DataClassFactory(UserDataClass, { DATABASE: DATABASE_TYPES.SQLITE })

// delete by id
const deleted = await userFactory.deleteModels({ _id: "some-uuid-here" })

// delete by field value
const deleted = await userFactory.deleteModels({ username: "johndoe" })

console.log(deleted) // returns the deleted records

deleteModels returns the deleted records before removing them so you can log or process them if needed.


Database Differences

Most operations work identically across all four databases. The only differences are:

FeatureSQLitePostgreSQLMySQLMongoDB
Table creationcreateTable / createTablescreateTable / createTablescreateTable / createTablesNot needed
Unique fieldstypes.TEXTtypes.TEXTtypes.VARCHARtypes.TEXT
Close connectiondb.close()db.disconnect()db.connection.destroy()db.disconnect()

What's Next

  • Relations — define one-to-many, one-to-one, and many-to-many relations
  • Query Builder — advanced filtering, sorting, and preloading related data
  • Migration — update your database schema as your DataClass changes