Skip to content

Instantly share code, notes, and snippets.

@oshibka404
Last active June 10, 2024 16:21
Show Gist options
  • Save oshibka404/391254fc19fb5218e355909af8176cee to your computer and use it in GitHub Desktop.
Save oshibka404/391254fc19fb5218e355909af8176cee to your computer and use it in GitHub Desktop.
interface DemoElement {
id: string,
name: string,
collectionId: string,
}
interface IFakeBackendDemo {
/**
* [GET] /elements/{elementId} -> DatabaseItem
* @param id element id
* @returns element with the given id or throws exception if not found
*/
getElementById(id: string): Promise<DemoElement>
/**
* [POST] /elements/{collectionId} -> DatabaseItem
* HTTP Body {File} file
* @param collectionId id of the collection to which the element belongs
* @returns newly created element
*/
createElement(collectionId: string, file: File): Promise<DemoElement>
/**
* [PATCH] /elements/{elementId} -> DatabaseItem
* HTTP Body {File} file
* @param element updated element data
* @returns updated element with the given id
*/
updateElement(element: DemoElement): Promise<DemoElement>
/**
* [DELETE] /elements/{elementId} -> void
* @param id id of the element to delete
*/
deleteElement(id: string): Promise<void>
/**
* [GET] /elements/?collectionId={collectionId} -> DatabaseItem[]
* @param collectionId id of the collection to which the elements belong
* @returns all elements with the given collectionId
*/
getElementsByCollectionId(collectionId: string): Promise<DemoElement[]>
}
const initialDBUpgrade = (db: IDBDatabase) => {
// version 0 means that the client had no database
const elementStore = db.createObjectStore('elements', {keyPath: 'id'})
// Create indexes for faster querying: we're going to query by name and collectionId
elementStore.createIndex('name', 'name', {unique: false})
elementStore.createIndex('collectionId', 'collectionId', {unique: false})
// Optional step: populate the store with initial set of elements
elementStore.transaction.oncomplete = () => {
const elementObjectStore = db.transaction('elements', 'readwrite').objectStore('elements')
elementObjectStore.add({
id: '1',
name: 'Element 1',
collectionId: '1',
})
}
}
interface FileUploader {
uploadFile(file: File): Promise<{data: {id: string, name: string}}>
}
export class FakeBackendDemo implements IFakeBackendDemo {
private db?: IDBDatabase
constructor(private fileUploader: FileUploader) {
const request = window.indexedDB.open('DIAG-1234-BackendMockDemo', 1)
request.onerror = () => {
throw new Error(`can't connect to indexed db`)
}
request.onsuccess = event => {
this.db = (event.target as IDBRequest<IDBDatabase>).result
}
request.onupgradeneeded = (event: IDBVersionChangeEvent) => {
const db = (event.target as IDBRequest<IDBDatabase>).result
switch(event.oldVersion) { // existing db version
case 0:
initialDBUpgrade(db)
case 1:
// here will go your next database update
default:
throw new Error(`error updating a database: unsupported version of db`)
}
}
}
public async getElementById(id: string): Promise<DemoElement> {
if (!this.db) {
throw new Error('db is not initialized')
}
const transaction = this.db.transaction('elements', 'readonly')
const elementStore = transaction.objectStore('elements')
const request = elementStore.get(id)
return new Promise((resolve, reject) => {
request.onsuccess = () => {
resolve(request.result)
}
request.onerror = () => {
reject(new Error(`element with id ${id} not found`))
}
})
}
async createElement(collectionId: string, file: File): Promise<DemoElement> {
if (!this.db) {
throw new Error('DB not initialized')
}
const {data} = await this.fileUploader.uploadFile(file)
const newElement = {
id: data.id,
name: data.name,
collectionId,
}
const request = this.db.transaction('elements', 'readwrite').objectStore('elements').add(newElement)
return new Promise((resolve, reject) => {
request.onsuccess = () => {
resolve(newElement)
}
request.onerror = () => {
reject(request.error)
}
})
}
async updateElement(element: DemoElement): Promise<DemoElement> {
if (!this.db) {
throw new Error('DB not initialized')
}
const request = this.db.transaction('elements', 'readwrite').objectStore('elements').put(element)
return new Promise((resolve, reject) => {
request.onsuccess = () => {
resolve(element)
}
request.onerror = () => {
reject(request.error)
}
})
}
async deleteElement(id: string): Promise<void> {
if (!this.db) {
throw new Error('DB not initialized')
}
const request = this.db.transaction('elements', 'readwrite').objectStore('elements').delete(id)
return new Promise((resolve, reject) => {
request.onsuccess = () => {
resolve()
}
request.onerror = () => {
reject(request.error)
}
})
}
async getElementsByCollectionId(collectionId: string): Promise<DemoElement[]> {
if (!this.db) {
throw new Error('DB not initialized')
}
const transaction = this.db.transaction('elements', 'readonly')
const elementStore = transaction.objectStore('elements')
const index = elementStore.index('collectionId')
const request = index.getAll(collectionId)
return new Promise((resolve, reject) => {
request.onsuccess = () => {
resolve(request.result)
}
request.onerror = () => {
reject(request.error)
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment