FeatherDB is a lightweight TypeScript ORM built for Bun and the web. It is made to allow for custom advanced types in an SQLite database. SQL.js is used for web.
Run bun add github:QuixThe2nd/FeatherDB
Import and start a SQLite database:
import { Database } from 'bun:sqlite'
const db = new Database();
import initSqlJs from 'sql.js'
const db = new (await initSqlJs({ locateFile: file => `https://sql.js.org/dist/${file}` })).Database()
Define an interface for your table with types as strict as you like:
interface UserModal {
id: number,
first_name: string,
last_name: string,
favorite_color: null | 'red' | 'blue' | 'yellow' | 'green' | 'orange' | 'purple'
}
Create a class that will be used to represent fetched rows:
class User implements UserModal {
id!: number
first_name!: string
last_name!: string
favorite_color!: null | 'red' | 'blue' | 'yellow' | 'green' | 'orange' | 'purple'
constructor(modal: UserModal) {
Object.assign(this, modal)
}
// You can optionally add custom properties and methods to this class.
getFullName() {
return `${this.first_name} ${this.last_name}`
}
}
const usersDefinition = {
id: { type: 'INTEGER', primaryKey: true },
first_name: { type: 'TEXT' },
last_name: { type: 'TEXT' },
favorite_color: { type: 'TEXT', nullable: true }
} as const
Initialise a FeatherDB Table class and create the table:
import { Table } from "FeatherDB";
const users = new Table<UserModal, User, typeof usersDefinition>(db, {
name: 'user',
definition: usersDefinition,
child: User
})
users.create()
users.add({
id: 12,
first_name: 'John',
last_name: 'Smith',
favorite_color: 'blue'
})
import { eq } from "FeatherDB";
const user = users.get({ where: [{ column: 'first_name', opt: eq('John') }, { column: 'last_name', opt: eq('Smith') }], limit: 1 })[0]
console.log(`${user.getFullName()} - ${user.id}`)
const count = users.count([{ column: 'first_name', opt: eq('John') }])
console.log(`There are ${count} John's`)
users.update({ first_name: 'Tom' }, { where: [{ column: 'id', opt: eq(id) }] })
users.delete({ where: [{ column: 'id', opt: eq(id) }] })
// BUN:
import { Database } from 'bun:sqlite'
// WEB:
// import initSqlJs from 'sql.js'
import { Table, eq } from "FeatherDB";
interface UserModal {
id: number,
first_name: string,
last_name: string,
favorite_color: null | 'red' | 'blue' | 'yellow' | 'green' | 'orange' | 'purple'
}
class User implements UserModal {
id!: number
first_name!: string
last_name!: string
favorite_color!: null | 'red' | 'blue' | 'yellow' | 'green' | 'orange' | 'purple'
constructor(modal: UserModal) {
Object.assign(this, modal)
}
getFullName() {
return `${this.first_name} ${this.last_name}`
}
}
// BUN:
const db = new Database();
// WEB:
// const db = new (await initSqlJs({ locateFile: file => `https://sql.js.org/dist/${file}` })).Database()
const users = new Table<UserModal, User>(db, {
name: 'user',
definition: {
id: { type: 'INTEGER', primaryKey: true },
first_name: { type: 'TEXT' },
last_name: { type: 'TEXT' },
favorite_color: { type: 'TEXT', nullable: true }
},
child: User
})
users.create()
users.add({
id: 12,
first_name: 'John',
last_name: 'Smith',
favorite_color: 'blue'
})
const user = users.get({ where: [{ column: 'first_name', opt: eq('John') }, { column: 'last_name', opt: eq('Smith') }], limit: 1 })[0]
if (user) {
const id = user.id
console.log(`${user.getFullName()} - ${id}`)
const count = users.count([{ column: 'first_name', opt: eq('John') }])
console.log(`There are ${count} John's`)
users.update({ first_name: 'Tom' }, { where: [{ column: 'id', opt: eq(id) }] })
users.delete({ where: [{ column: 'id', opt: eq(id) }] })
} else console.log('User not found')
Operators are defined like so:
{ where: [{ column: 'first_name', opt: eq('John') }] }
import { eq, ne, gt, lt, ge, le } from "FeatherDB";
=
:eq()
!=
:ne()
>
:gt()
<
:lt()
>=
:ge()
<=
:le()