Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor local database #15

Merged
merged 4 commits into from
Apr 8, 2024
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
268 changes: 175 additions & 93 deletions src/lib/utils/localDB/localDBmanager.ts
Original file line number Diff line number Diff line change
@@ -1,110 +1,192 @@
import { Dexie, type Table } from "dexie";

export default class LocalDBManager extends Dexie {
plugins!: Table<DiscodesPluginDataStore, string>;
users!: Table<User, string>;

constructor() {
super("DiscodesDatabase");

this.version(1).stores({
plugins: "id",
users: "id"
});
}

/**
* Returns the plugin table or returns undefined if the owner or the plugin doesn't exist.
*
* @param {string} id
* @return {*} {(Promise<DiscodesPlugin | undefined>)}
* @memberof LocalDBManager
*/
async getPlugin(id: string): Promise<DiscodesPlugin | undefined> {
const val = await this.plugins.get(id);

if (!val) return undefined;

const ownerId = val.owner;
const owner = await this.users.get(ownerId);

if (!owner) return undefined;

const obj: DiscodesPlugin = {
...val,
owner
};

return obj;
}

async createUser(userData: User) {
await this.users.add(userData, window.crypto.randomUUID());
}
export class UserDataGetter {
id: string

constructor(id: string) {
this.id = id
}

async getData(): Promise<User> {
throw new Error("Method not implemented")
}
}

// SINGLETON CLASS! DO NOT BUILD
class LocalDBManager extends Dexie {
plugins!: Table<DiscodesPlugin, string>
workspaces!: Table<DiscodesWorkspace, string>
examples!: Table<DiscodesWorkspace, string>

constructor() {
super("DiscodesDatabase")

this.version(1).stores({
plugins: "id",
workspaces: "id",
examples: "id",
})
}
}

let dbManager: LocalDBManager

export function getDB() {
if (!dbManager) {
dbManager = new LocalDBManager()
}

return dbManager
}

// SINGLETON CLASS! DO NOT BUILD
class UserStorage {
// Be sure to implement both push and pull methods inside these 3 methods (i.e. Pushing offline created ones to server and pulling online ones from the server)
async syncPlugins(): Promise<DiscodesPlugin> {
throw new Error('Method not implemented')
}

async syncWorkspaces(): Promise<DiscodesWorkspace> {
throw new Error('Method not implemented')
}

async syncExamples(): Promise<DiscodesWorkspace> {
throw new Error('Method not implemented')
}

setUser(user: User) {
localStorage.setItem("userdata", JSON.stringify(user))
}

async refreshFollowers(): Promise<string[]> {
throw new Error("Method not implemented") // TODO: Dynamically fetch followers based on their id/the user id from the database
}

async refreshFollowings(): Promise<string[]> {
throw new Error("Menthod not implemented")
}

async getFollowers() {
await this.refreshFollowers()

const userData = this.getUserData()

return await Promise.all(userData.followers.map(v => new UserDataGetter(v)))
}

async getFollowings() {
await this.refreshFollowings()

const userData = this.getUserData()

return await Promise.all(userData.follows.map(v => new UserDataGetter(v)))
}

async getPublishedExamples() {
const userDataJson = this.getUserData()

const db = getDB()

await this.syncExamples()

const plugins = await Promise.all(userDataJson.publishedExamples.map((str) => db.plugins.get(str)))

return plugins
}

getUserData() {
const userData = localStorage.getItem("userdata")

if (!userData) throw new Error("User has not logged on yet")

const userDataJson = JSON.parse(userData) as User // I don't like using 'as' here but I've got no choice

return userDataJson
}

async getPublishedPlugins() {
const userDataJson = this.getUserData()

const db = getDB()

await this.syncPlugins()

const plugins = await Promise.all(userDataJson.publishedPlugins.map((str) => db.plugins.get(str)))

return plugins
}

async getWorkspaces() {
const userData = this.getUserData()

const db = getDB()

await this.syncWorkspaces()

const workspaces = await Promise.all(userData.workspaces.map((str) => db.workspaces.get(str)))

return workspaces
}
}

let userStore: UserStorage

export function getUserStore() {
if (!userStore) userStore = new UserStorage()

return userStore
}

//TODO Make those interfaces!
//? Some data are for the backend only, if you feel like it doesn't belong in the localDB don't add them! Thx <3
type BlockConfig = unknown;

type DiscodesPluginDataStore = {
id: string;
name: string;
owner: string;
description: string;
downloads: number;
likes: number;
rating: number;
version: number;
blocks: BlockConfig[];
};

type DiscodesPlugin = {
id: string;
owner: User;
name: string;
description: string;
downloads: number;
likes: number;
rating: number;
version: number;
blocks: BlockConfig[];
};
id: string,
owner: User
name: string
description: string
downloads: number
likes: number
rating: number
version: number
blocks: BlockConfig[]
}

type User = {
username: string;
id: string;
follows: User[];
followers: User[];
createdAt: Date;
workspaces: DiscodesWorkspace[];
publishedPlugins: DiscodesPlugin[];
publishedExamples: DiscodesFile[];
};
username: string
id: string
follows: string[]
followers: string[]
createdAt: Date
workspaces: string[]
publishedPlugins: string[]
publishedExamples: string[]
}

type BlocklyWorkspaceSave = {
workspaceSave: object | string;
blockLength: number;
};
workspaceSave: object | string
blockLength: number
}

type DiscodesFile = {
name: string;
createdAt: Date;
lastEditedAt: Date;
blocklyWorkspaceSave: BlocklyWorkspaceSave;
thumbnail: string;
timeWasted: number;
};
name: string
createdAt: Date
lastEditedAt: Date
blocklyWorkspaceSave: BlocklyWorkspaceSave
thumbnail: string
timeWasted: number
}

type DiscodesWorkspace = {
files: DiscodesFile[];
createdAt: Date;
lastEditedAt: Date;
owner: string;
editors: string[];
viewers: string[];
id: string;
name: string;
description: string;
timeWasted: number;
};
files: DiscodesFile[]
createdAt: Date
lastEditedAt: Date
owner: string
editors: string[]
viewers: string[]
id: string
name: string
description: string
timeWasted: number
}
Loading