Browse Source

add: database abstraction

pull/1330/head
tetuaoro 8 months ago
parent
commit
7f13a51283
  1. 54
      src/server/databases/database.ts
  2. 10
      src/server/databases/entities/system.ts
  3. 19
      src/server/databases/entities/user.ts
  4. 54
      src/server/databases/providers/inmemory.ts

54
src/server/databases/database.ts

@ -0,0 +1,54 @@
import type System from './entities/system';
import type User from './entities/user';
type Undefined = null | undefined | 0 | '';
/**
* `id` of T or T.
*
* @template T - The specific type that can be used in place of id string.
*/
type Identity<T> = string | T;
export { Undefined, Identity };
/**
* Abstract class for database operations.
* Provides methods to connect, disconnect, and interact with system and user data.
*
* **Note:** This class does not handle errors directly. Error handling should be implemented in the API methods
* that use this class. The methods here should not throw errors themselves but should rely on the consuming code
* to manage any exceptions or failures.
*/
export default abstract class DatabaseProvider {
/**
* Connects to the database.
*/
abstract connect(): Promise<void>;
/**
* Disconnects from the database.
*/
abstract disconnect(): Promise<void>;
/**
* Retrieves system data from the database.
* @returns {Promise<System | Undefined>} The system data or null if not found.
*/
abstract getSystem(): Promise<System | Undefined>;
/**
* Retrieves a user by their ID or by User structure from the database.
* @param {Identity<User>} id - The ID of the user or a user.
* @returns {Promise<User | Undefined>} The user data or null if not found.
*/
abstract getUser(id: Identity<User>): Promise<User | Undefined>;
/**
* Creates or Updates a user in the database.
* @param {User} user - The user to be saved.
*
* **Note:** If the user already exists, this method will update their details.
* If the user does not exist, it will create a new user entry.
*/
abstract saveUser(user: User): Promise<void>;
}

10
src/server/databases/entities/system.ts

@ -0,0 +1,10 @@
/**
* Representing the WireGuard network configuration data structure of a computer interface system.
*/
type System = {
privateKey: string;
publicKey: string;
address: string;
};
export default System;

19
src/server/databases/entities/user.ts

@ -0,0 +1,19 @@
export type ROLE = 'ADMIN';
/**
* Representing a user data structure.
*/
type User = {
id: string;
roles: Array<ROLE>;
name: string;
address: string;
privateKey: string;
publicKey: string;
preSharedKey: string;
createdAt: string;
updatedAt: string;
enabled: boolean;
};
export default User;

54
src/server/databases/providers/inmemory.ts

@ -0,0 +1,54 @@
import DatabaseProvider, { type Identity } from '../database';
import type System from '../entities/system';
import type User from '../entities/user';
import debug from 'debug';
const INMDP_DEBUG = debug('InMemoryDP');
// Represent in-memory data structure
type InMemoryData = {
system?: System;
users: Array<User>;
};
// In-Memory Database Provider
export class InMemoryDP extends DatabaseProvider {
private data: InMemoryData = { users: [] };
async connect() {
// No connection needed for in-memory
}
async disconnect() {
// No disconnection needed for in-memory
}
async getSystem() {
INMDP_DEBUG('Get System');
return this.data.system || null;
}
async saveSystem(system: System) {
INMDP_DEBUG('Save System');
this.data.system = system;
}
async getUser(id: Identity<User>) {
INMDP_DEBUG('Get User');
if (typeof id === 'string') {
return this.data.users.find((user) => user.id === id);
}
return this.data.users.find((user) => user.id === id.id);
}
async saveUser(user: User) {
let _user = await this.getUser(user);
if (_user) {
INMDP_DEBUG('Update User');
_user = user;
} else {
INMDP_DEBUG('New User');
this.data.users.push(user);
}
}
}
Loading…
Cancel
Save