expo-sqlite-wrapper
This is a wrapper for expo-sqlite
as it make it very easy to create,update and work with the database file
Installations
npm install expo-sqlite
npm install expo-sqlite-wrapper
Installation for expo-sqlite
read https://docs.expo.dev/versions/latest/sdk/sqlite/
Usage
SetupModules
import { IBaseModule, TableStructor, ColumnType, IQueryResultItem } from 'expo-sqlite-wrapper'
export type TableNames = "Parents" | "Childrens";
export class Parent extends IBaseModule<TableNames>{
name: string;
email: string;
children: IQueryResultItem<Child,TableNames>[];
constructor(name:string, email: string ){
super("Parents");
this.name = name;
this.email = email;
this.children = [];
}
static GetTableStructor() {
return new TableStructor(
"Parents",
[
{ columnName: "id", columnType: ColumnType.Number, nullable: false, isPrimary: true, autoIncrement: true },
{ columnName: "name", columnType: ColumnType.String },
{ columnName: "email", columnType: ColumnType.String, isUique: true }
]
)
}
}
export class Child extends IBaseModule<TableNames>{
someFiel: string;
parentId?: number;
constructor(someFiel:string, parentId?: number ){
super("Childrens");
this.someFiel = someFiel;
this.parentId = parentId;
}
static GetTableStructor() {
return new TableStructor(
"Childrens",
[
{ columnName: "id", columnType: ColumnType.Number, nullable: false, isPrimary: true, autoIncrement: true },
{ columnName: "name", columnType: ColumnType.String },
{ columnName: "parentId", columnType: ColumnType.Number, nullable: true },
],
[
{ contraintTableName: "Parents", contraintColumnName: "id", columnName: "parentId" }
]
)
}
}
Setup dbContexts
import createDbContext, { IDatabase, IQueryResultItem, IBaseModule } from 'expo-sqlite-wrapper'
import * as SQLite from 'expo-sqlite';
const tables = [Parent.GetTableStructor(), Child.GetTableStructor()]
export default class DbContext {
databaseName: string = "mydatabase.db";
database: IDatabase<TableNames>;
constructor() {
this.database = createDbContext<TableNames>(tables, async () => SQLite.openDatabase(this.databaseName));
}
}
Using the dbContexts
const dbContext = new DbContext();
const App=()=> {
React.useEffect(()=> {
const firstRun= async()=> {
await dbContext.database.setUpDataBase();
}
firstRun();
},[]);
const addItem= async ()=> {
var item = await dbContext.database.save(new Parent("testName", "test@gmail.com"));
var child = await dbContext.database.save(new Child("testName",item.id));
var item = await dbContext.database.where<Parent>("Parents", { name: "testName"})
var item = await dbContext.database.query<Parent>("Parents").Column(x=> x.name).EqualTo("testName").firstOrDefault();
item.name= "test"
item.saveChanges();
var item = await dbContext.database.query<Parent>("Parents")
.Start().Column(x=> x.name).IN(["name", "testName"]).End()
.OR()
.Start().Column(x=> x.email).Contains("test@").End()
.LoadChildren("Childrens", x=> x.id)
.With<Child>(x=> x.parentId)
.AssignTo(x=> x.children).toList();
var item= (await dbContext.database.find("Select * from Parents where (name in (?,?)) OR (email like %?%)", ["name", "testName","test@" ])) as Parent[];
useEffect(()=> {
var watcher = dbContext.database.watch<Parent>("Parents");
watcher.onSave = async (item)=> {
console.log(item);
}
watcher.onDelete = async (item)=> {
console.log(item);
}
return ()=> watcher.removeWatch();
},[])
}
}
IQuery
interface IQuery<T, D extends string> {
Column: <B>(item: (x: T) => B) => IQuery<T, D>;
EqualTo: <B>(value: ((x: T) => B) | SingleValue) => IQuery<T, D>;
Contains: <B>(value: ((x: T) => B) | SingleValue) => IQuery<T, D>;
NotEqualTo: <B>(value: ((x: T) => B) | SingleValue) => IQuery<T, D>;
EqualAndGreaterThen: <B>(value: ((x: T) => B) | NumberValue) => IQuery<T, D>;
EqualAndLessThen: <B>(value: ((x: T) => B) | NumberValue) => IQuery<T, D>;
Start: () => IQuery<T, D>;
End: () => IQuery<T, D>;
OR: () => IQuery<T, D>;
AND: () => IQuery<T, D>;
GreaterThan: <B>(value: ((x: T) => B) | NumberValue) => IQuery<T, D>;
LessThan: <B>(value: ((x: T) => B) | NumberValue) => IQuery<T, D>;
IN: <B>(value: ((x: T) => B) | ArrayValue) => IQuery<T, D>;
NotIn: () => IQuery<T, D>;
Null: () => IQuery<T, D>;
LoadChildren: <B>(childTableName: D, parentProperty: (x: T) => B) => IChildQueryLoader<B, T, D>;
LoadChild: <B>(childTableName: D, parentProperty: (x: T) => B) => IChildQueryLoader<B, T, D>
firstOrDefault: () => Promise<IQueryResultItem<T, D> | undefined>;
findOrSave: (item: IBaseModule<D>) => Promise<IQueryResultItem<T, D>>;
toList: () => Promise<IQueryResultItem<T, D>[]>;
getQueryResult: () => IQuaryResult<D>;
}
IDatabase
export interface IDatabase<D extends string> {
allowedKeys: (tableName: D) => Promise<string[]>;
asQueryable: <T>(item: IBaseModule<D>, tableName?: D) => Promise<IQueryResultItem<T, D>>
watch: <T>(tableName: D) => IWatcher<T, D>;
query: <T>(tableName: D) => IQuery<T, D>;
find: (query: string, args?: any[], tableName?: D) => Promise<IBaseModule<D>[]>
save: <T>(item?: IBaseModule<D> | (IBaseModule<D>[]), insertOnly?: Boolean, tableName?: D) => Promise<T[]>;
where: <T>(tableName: D, query?: any | T) => Promise<T[]>;
delete: (item: IBaseModule<D> | (IBaseModule<D>[]), tableName?: D) => Promise<void>;
execute: (query: string, args?: any[]) => Promise<boolean>;
dropTables: () => Promise<void>;
setUpDataBase: (forceCheck?: boolean) => Promise<void>;
tableHasChanges: (item: TablaStructor<D>) => Promise<boolean>;
}
This Library is new and I am using it for my project and decided too put it on npm, so there may be some issues discovered later.
Please report those so I could make sure to fix them.