Skip to content

Commit

Permalink
Initial refactoring
Browse files Browse the repository at this point in the history
  • Loading branch information
mateusabelli committed Nov 10, 2023
1 parent 83f7f18 commit 413cbc7
Show file tree
Hide file tree
Showing 7 changed files with 214 additions and 194 deletions.
141 changes: 112 additions & 29 deletions src/Provider.ts
Original file line number Diff line number Diff line change
@@ -1,45 +1,128 @@
import { CreateParams, DeleteOneParams, GetListParams, GetManyParams, GetOneParams, UpdateParams } from "./interfaces/MethodParams";
import { CreateParams, UpdateParams } from "./interfaces/MethodParams";
import Database from "./utils/Database";

import GetOne from "./methods/GetOne";
import Create from "./methods/Create";
import DeleteOne from "./methods/DeleteOne";
import GetMany from "./methods/GetMany";
import Update from "./methods/Update";
import GetList from "./methods/GetList";
import { Database as SQLiteDatabase } from "sql.js"

class Provider {
private dbPath: string;
private dbArgs: string
private type: 'local' | 'inMemory'

constructor(dbPath: string) {
this.dbPath = dbPath;
}
constructor(type: 'local' | 'inMemory', dbArgs: string) {
this.dbArgs = dbArgs;
this.type = type;
}

create(params: CreateParams) {
return Create.build(this.dbPath, params)
private async dbConnect(): Promise<SQLiteDatabase | void> {
try {
return await Database.init(this.dbArgs);
} catch (error) {
console.error("Error in dbConnect()", error);
}
}

update(params: UpdateParams) {
return Update.build(this.dbPath, params)
}
public async create(params: CreateParams) {
const database = await this.dbConnect();
const { resource, variables } = params;

deleteOne(params: DeleteOneParams) {
return DeleteOne.build(this.dbPath, params);
}
try {
if (!database)
throw new Error("Database connection not available.");

getOne(params: GetOneParams) {
return GetOne.build(this.dbPath, params);
}
const columns = Object.keys(variables).join(", ")
const values = Object.values(variables).map((value) => `'${value}'`).join(", ")

getMany(params: GetManyParams) {
return GetMany.build(this.dbPath, params);
let insertSql = `INSERT INTO ${resource} (${columns}) VALUES (${values})`;
let selectSql = `SELECT * FROM ${resource} WHERE (${columns}) = (${values})`;

database.run(insertSql);
const data = database.exec(selectSql)
const dataColumns = data[0].columns
const dataValues = data[0].values[0]

if (data) {
return {
data: Object.fromEntries(
dataColumns.map((col, index) => [col, dataValues[index]]),
)
}
} else {
throw new Error(`Could not create data in ${resource}`);
}
} catch (error) {
console.error("Error in create()", error);
return {
data: {}
}
} finally {
database?.close()
}
}

public async update(params: UpdateParams) {
const database = await this.dbConnect();
const { resource, id, variables } = params;

try {
if (!database)
throw new Error("Database connection not available.");

getList(params: GetListParams) {
return GetList.build(this.dbPath, params);
const columns = Object.keys(variables || {});
const values = Object.values(variables || {});

let updateQuery = "";

columns.forEach((column, index) => {
updateQuery += `${column} = '${values[index]}', `;
});

// Slices the last comma
updateQuery = updateQuery.slice(0, -2);

const updateSql = `UPDATE ${resource} SET ${updateQuery} WHERE id = ${id}`;
const selectSql = `SELECT * FROM ${resource} WHERE id = ${id}`;

database.run(updateSql);
const data = database.exec(selectSql)
const dataColumns = data[0].columns
const dataValues = data[0].values[0]

if (data) {
return {
data: Object.fromEntries(
dataColumns.map((col, index) => [col, dataValues[index]]),
)
}
} else {
throw new Error(`Could not update data in ${resource}`);
}
} catch (error) {
console.error("Error in update()", error);
return {
data: {}
}
} finally {
database?.close()
}
}

// deleteOne(params: DeleteOneParams) {
// return DeleteOne.build(this.dbPath, params);
// }
//
// getOne(params: GetOneParams) {
// return GetOne.build(this.dbPath, params);
// }
//
// getMany(params: GetManyParams) {
// return GetMany.build(this.dbPath, params);
// }
//
// getList(params: GetListParams) {
// return GetList.build(this.dbPath, params);
// }
}

export const dataProvider = (dbPath: string) => {
return new Provider(dbPath);
};
export const dataProvider = (type: 'local' | 'inMemory', dbArgs: string) => {
return new Provider(type, dbArgs);
}

40 changes: 2 additions & 38 deletions src/methods/Create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,46 +5,10 @@ import sqlite3 from "sqlite3";
import Database from "../utils/Database";

class Create {
private static dbInstance: Database;
private db: sqlite3.Database | null = null;
private constructor() { }

private constructor(dbPath: string) {
Create.dbInstance = Database.getInstance(dbPath);
this.db = Create.dbInstance.getDatabase();
}

static async build(dbPath: string, params: CreateParams): Promise<CreateResponse> {
const init = new Create(dbPath);
const { resource, variables } = params;

try {
if (!init.db)
throw new Error("Database connection not available.");

const columns = Object.keys(variables).join(", ")
const values = Object.values(variables).map((value) => `'${value}'`).join(", ")

let insertSql = `INSERT INTO ${resource} (${columns}) VALUES (${values})`;
let selectSql = `SELECT * FROM ${resource} WHERE (${columns}) = (${values})`;

const dbRun = promisify(init.db.run.bind(init.db));
await dbRun(insertSql);

const dbGet = promisify(init.db.get.bind(init.db));
const data = await dbGet(selectSql) as any;
static async build(params: CreateParams, dbPath?: string, ): Promise<CreateResponse> {

Check failure on line 10 in src/methods/Create.ts

View workflow job for this annotation

GitHub Actions / build (14.x)

A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.

Check failure on line 10 in src/methods/Create.ts

View workflow job for this annotation

GitHub Actions / build (16.x)

A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.

Check failure on line 10 in src/methods/Create.ts

View workflow job for this annotation

GitHub Actions / build (18.x)

A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value.

if (data)
return { data }
else
throw new Error(`Could not create data in ${resource}`);
} catch (error) {
console.error("Error in create()", error);
return {
data: {}
}
} finally {
this.dbInstance.closeDatabase();
}
}
}

Expand Down
40 changes: 0 additions & 40 deletions src/methods/Update.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,46 +14,6 @@ class Update {
}

static async build(dbPath: string, params: UpdateParams): Promise<UpdateResponse> {
const init = new Update(dbPath);
const { resource, id, variables } = params;

try {
if (!init.db)
throw new Error("Database connection not available.");

const columns = Object.keys(variables || {});
const values = Object.values(variables || {});

let updateQuery = "";

columns.forEach((column, index) => {
updateQuery += `${column} = '${values[index]}', `;
});

// Slices the last comma
updateQuery = updateQuery.slice(0, -2);

const updateSql = `UPDATE ${resource} SET ${updateQuery} WHERE id = ${id}`;
const selectSql = `SELECT * FROM ${resource} WHERE id = ${id}`;

const dbRun = promisify(init.db.run.bind(init.db));
await dbRun(updateSql);

const dbGet = promisify(init.db.get.bind(init.db));
const data = await dbGet(selectSql) as any;

if (data)
return { data };
else
throw new Error(`Could not update data in ${resource}`);
} catch (error) {
console.error("Error in update()", error);
return {
data: {}
}
} finally {
this.dbInstance.closeDatabase()
}
}
}

Expand Down
74 changes: 44 additions & 30 deletions src/utils/Database.ts
Original file line number Diff line number Diff line change
@@ -1,38 +1,52 @@
import sqlite3 from "sqlite3";
import initSqlJs, {Database as SQLiteDatabase} from "sql.js"
import fetch from "cross-fetch"

class Database {
private static instance: Database | null = null;
private db: sqlite3.Database | null = null;
private constructor() { }

private constructor(dbPath: string) {
this.db = new sqlite3.Database(dbPath);
}

public static getInstance(dbPath: string) {
if (this.instance === null) {
this.instance = new Database(dbPath);
}
return this.instance;
}
public static async init(dbPath: string): Promise<SQLiteDatabase> {
const SQL = await initSqlJs({
locateFile: () => "node_modules/sql.js/dist/sql-wasm.wasm"
});

public getDatabase() {
if (this.db === null) {
throw new Error("Database connection is not established");
}
return this.db;
}

public closeDatabase() {
if (this.db !== null) {
this.db.close((error) => {
if (error) {
throw new Error(error.message);
}
});
this.db = null;
Database.instance = null;
}
const dbFile = await fetch(dbPath).then(res => res.arrayBuffer());
return new SQL.Database(new Uint8Array(dbFile))
}
}

// class Database {
// private static instance: Database | null = null;
// private db: sqlite3.Database | null = null;
//
// private constructor(dbPath: string) {
// this.db = new sqlite3.Database(dbPath);
// }
//
// public static getInstance(dbPath: string) {
// if (this.instance === null) {
// this.instance = new Database(dbPath);
// }
// return this.instance;
// }
//
// public getDatabase() {
// if (this.db === null) {
// throw new Error("Database connection is not established");
// }
// return this.db;
// }
//
// public closeDatabase() {
// if (this.db !== null) {
// this.db.close((error) => {
// if (error) {
// throw new Error(error.message);
// }
// });
// this.db = null;
// Database.instance = null;
// }
// }
// }

export default Database;
Loading

0 comments on commit 413cbc7

Please sign in to comment.