From c79454efd149596521ce9fa0500a08365331670d Mon Sep 17 00:00:00 2001 From: Retro Date: Sun, 7 Apr 2024 14:11:32 +0630 Subject: [PATCH 1/3] =?UTF-8?q?=F0=9F=93=9D=20Clean=20up=20code=20and=20up?= =?UTF-8?q?date=20localDB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/utils/localDB/localDBmanager.ts | 157 +++++++++++++++++++----- 1 file changed, 125 insertions(+), 32 deletions(-) diff --git a/src/lib/utils/localDB/localDBmanager.ts b/src/lib/utils/localDB/localDBmanager.ts index e0f3ecf..bc771a0 100644 --- a/src/lib/utils/localDB/localDBmanager.ts +++ b/src/lib/utils/localDB/localDBmanager.ts @@ -1,34 +1,139 @@ import { Dexie, type Table } from "dexie"; -export default class LocalDBManager extends Dexie { - plugins!: Table - users!: Table +let dbManager: LocalDBManager + +export function getDB() { + if (!dbManager) { + dbManager = new LocalDBManager() + } + + return dbManager +} + +// SINGLETON CLASS! DO NOT BUILD +class LocalDBManager extends Dexie { + plugins!: Table + workspaces!: Table + examples!: Table constructor() { super("DiscodesDatabase") this.version(1).stores({ plugins: "id", - users: "id" + workspaces: "id", + examples: "id", }) } +} + +let userStore: UserStorage + +export function getUserStore() { + if (!userStore) userStore = new UserStorage() + + return userStore +} + +// 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 { + throw new Error('Method not implemented') + } + + async syncWorkspaces(): Promise { + throw new Error('Method not implemented') + } + + async syncExamples(): Promise { + throw new Error('Method not implemented') + } + + setUser(user: User) { + localStorage.setItem("userdata", JSON.stringify(user)) + } + + async refreshFollowers(): Promise { + throw new Error("Method not implemented") // TODO: Dynamically fetch followers based on their id/the user id from the database + } + + async refreshFollowings(): Promise { + 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() - async getPlugin(id: string) { - const val = await this.plugins.get(id) + const db = getDB() - if(!val) return undefined + await this.syncWorkspaces() - const ownerId = val.owner - const owner = await this.users.get(ownerId) + const workspaces = await Promise.all(userData.workspaces.map((str) => db.workspaces.get(str))) - if(!owner) return undefined + return workspaces + } +} + +export class UserDataGetter { + id: string - const obj: DiscodesPlugin = { - ...val, - owner - } + constructor(id: string) { + this.id = id + } - return obj + async getData(): Promise { + throw new Error("Method not implemented") } } @@ -36,18 +141,6 @@ export default class LocalDBManager extends Dexie { //? 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 @@ -63,12 +156,12 @@ type DiscodesPlugin = { type User = { username: string id: string - follows: User[] - followers: User[] + follows: string[] + followers: string[] createdAt: Date - workspaces: DiscodesWorkspace[] - publishedPlugins: DiscodesPlugin[] - publishedExamples: DiscodesFile[] + workspaces: string[] + publishedPlugins: string[] + publishedExamples: string[] } type BlocklyWorkspaceSave = { From fb80762648bad81a569064cf70f324efa3db32cb Mon Sep 17 00:00:00 2001 From: Retro Date: Sun, 7 Apr 2024 14:13:29 +0630 Subject: [PATCH 2/3] Complete local db --- src/lib/utils/localDB/localDBmanager.ts | 207 +++++++++++++++++------- 1 file changed, 150 insertions(+), 57 deletions(-) diff --git a/src/lib/utils/localDB/localDBmanager.ts b/src/lib/utils/localDB/localDBmanager.ts index a485a58..bc771a0 100644 --- a/src/lib/utils/localDB/localDBmanager.ts +++ b/src/lib/utils/localDB/localDBmanager.ts @@ -1,34 +1,139 @@ import { Dexie, type Table } from "dexie"; -export default class LocalDBManager extends Dexie { - plugins!: Table - users!: Table +let dbManager: LocalDBManager - constructor() { - super("DiscodesDatabase"); +export function getDB() { + if (!dbManager) { + dbManager = new LocalDBManager() + } + + return dbManager +} + +// SINGLETON CLASS! DO NOT BUILD +class LocalDBManager extends Dexie { + plugins!: Table + workspaces!: Table + examples!: Table + + constructor() { + super("DiscodesDatabase") this.version(1).stores({ plugins: "id", - users: "id" + workspaces: "id", + examples: "id", }) } +} + +let userStore: UserStorage + +export function getUserStore() { + if (!userStore) userStore = new UserStorage() + + return userStore +} + +// 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 { + throw new Error('Method not implemented') + } + + async syncWorkspaces(): Promise { + throw new Error('Method not implemented') + } + + async syncExamples(): Promise { + throw new Error('Method not implemented') + } + + setUser(user: User) { + localStorage.setItem("userdata", JSON.stringify(user)) + } + + async refreshFollowers(): Promise { + throw new Error("Method not implemented") // TODO: Dynamically fetch followers based on their id/the user id from the database + } + + async refreshFollowings(): Promise { + 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 getPlugin(id: string) { - const val = await this.plugins.get(id) + async getFollowings() { + await this.refreshFollowings() - if(!val) return undefined + 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 + } - const ownerId = val.owner - const owner = await this.users.get(ownerId) + getUserData() { + const userData = localStorage.getItem("userdata") - if(!owner) return undefined + if (!userData) throw new Error("User has not logged on yet") - const obj: DiscodesPlugin = { - ...val, - owner - } + const userDataJson = JSON.parse(userData) as User // I don't like using 'as' here but I've got no choice - return obj + 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 + } +} + +export class UserDataGetter { + id: string + + constructor(id: string) { + this.id = id + } + + async getData(): Promise { + throw new Error("Method not implemented") } } @@ -36,10 +141,10 @@ export default class LocalDBManager extends Dexie { //? 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 = { +type DiscodesPlugin = { id: string, + owner: User name: string - owner: string description: string downloads: number likes: number @@ -48,52 +153,40 @@ type DiscodesPluginDataStore = { blocks: BlockConfig[] } -type DiscodesPlugin = { - 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[] + follows: string[] + followers: string[] createdAt: Date - workspaces: DiscodesWorkspace[] - publishedPlugins: DiscodesPlugin[] - publishedExamples: DiscodesFile[] + 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 +} From b4529cac1e3989b7a0acb2ee4dd1256e8b236ea2 Mon Sep 17 00:00:00 2001 From: Retro Date: Sun, 7 Apr 2024 14:16:17 +0630 Subject: [PATCH 3/3] Reconfigure code for eslint --- src/lib/utils/localDB/localDBmanager.ts | 34 ++++++++++++------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/src/lib/utils/localDB/localDBmanager.ts b/src/lib/utils/localDB/localDBmanager.ts index bc771a0..3eea6de 100644 --- a/src/lib/utils/localDB/localDBmanager.ts +++ b/src/lib/utils/localDB/localDBmanager.ts @@ -1,13 +1,15 @@ import { Dexie, type Table } from "dexie"; -let dbManager: LocalDBManager +export class UserDataGetter { + id: string -export function getDB() { - if (!dbManager) { - dbManager = new LocalDBManager() + constructor(id: string) { + this.id = id } - return dbManager + async getData(): Promise { + throw new Error("Method not implemented") + } } // SINGLETON CLASS! DO NOT BUILD @@ -27,12 +29,14 @@ class LocalDBManager extends Dexie { } } -let userStore: UserStorage +let dbManager: LocalDBManager -export function getUserStore() { - if (!userStore) userStore = new UserStorage() +export function getDB() { + if (!dbManager) { + dbManager = new LocalDBManager() + } - return userStore + return dbManager } // SINGLETON CLASS! DO NOT BUILD @@ -125,16 +129,12 @@ class UserStorage { } } -export class UserDataGetter { - id: string +let userStore: UserStorage - constructor(id: string) { - this.id = id - } +export function getUserStore() { + if (!userStore) userStore = new UserStorage() - async getData(): Promise { - throw new Error("Method not implemented") - } + return userStore } //TODO Make those interfaces!