Files observing

This commit is contained in:
Ludvík Prokopec 2022-12-08 12:39:47 +01:00
parent 016bf32083
commit 0224b1ff8d
3 changed files with 216 additions and 107 deletions

View File

@ -4,107 +4,6 @@ import { Models, Query, RealtimeResponseEvent } from 'appwrite'
import { ID } from 'appwrite'
import type { Writable } from 'svelte/store'
const subscribeUpdate = (databaseId: string, collectionId: string, store: Writable<Models.Document[]>, document: Models.Document) => {
client.subscribe(`databases.${databaseId}.collections.${collectionId}.documents.${document.$id}`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`databases.${databaseId}.collections.${collectionId}.documents.${document.$id}.delete`)) {
store.update(current => {
current.splice(current.indexOf(document), 1)
return current
})
return
}
if (response.events.includes(`databases.${databaseId}.collections.${collectionId}.documents.${document.$id}.update`)) {
store.update(current => {
current[current.indexOf(document)] = response.payload
return current
})
return
}
})
}
const subscribeInsert = (databaseId: string, collectionId: string, store: Writable<Models.Document[]>) => {
client.subscribe(`databases.${databaseId}.collections.${collectionId}.documents`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`databases.${databaseId}.collections.${collectionId}.documents.*.create`)) {
let lastIndex = 0
store.update(current => {
current.push(response.payload)
lastIndex = current.length - 1
return current
})
subscribeUpdate(databaseId, collectionId, store, response.payload)
}
})
}
/**
* Subscribe collection insert
* @param databaseId
* @param collectionId
* @returns
*/
const observe = (databaseId: string, collectionId: string) => {
const dataStore = writable<Models.Document[]>([])
subscribeInsert(databaseId, collectionId, dataStore)
return { subscribe: dataStore.subscribe }
}
/**
* Subscribe collection update, delete
* @param databaseId
* @param collectionId
* @param queries
* @returns
*/
const subscribe = (databaseId: string, collectionId: string, queries: string[]) => {
const loadingStore = writable(true)
const dataStore = writable<Models.Document[]>([])
databases.listDocuments(databaseId, collectionId, queries).then(data => {
data.documents.forEach((document) => subscribeUpdate(databaseId, collectionId, dataStore, document))
dataStore.set(data.documents)
loadingStore.set(false)
})
return [{ subscribe: dataStore.subscribe }, { subscribe: loadingStore.subscribe }] as const
}
/**
* Paginate collection
* @param databaseId
* @param collectionId
* @param limit
* @returns
*/
const paginate = (databaseId: string, collectionId: string, limit: number, queries: string[] = []) => {
const dataStore = writable<Models.Document[]>([])
const loadingStore = writable(true)
let offset = 0
const store = {
subscribe: dataStore.subscribe,
async next() {
await databases.listDocuments(databaseId, collectionId, [...queries, Query.limit(limit), Query.offset(offset)]).then(data => {
data.documents.forEach((document) => subscribeUpdate(databaseId, collectionId, dataStore, document))
dataStore.update(current => [...current, ...data.documents])
offset += limit
})
}
}
store.next().then(() => loadingStore.set(false))
return [store, { subscribe: loadingStore.subscribe }] as const
}
class Collection {
constructor(protected databaseId: string, protected collectionId: string) { }
@ -121,16 +20,105 @@ class Collection {
}
createObserver() {
return observe(this.databaseId, this.collectionId)
const dataStore = writable<Models.Document[]>([])
client.subscribe(`databases.${this.databaseId}.collections.${this.collectionId}.documents`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`databases.${this.databaseId}.collections.${this.collectionId}.documents.*.create`)) {
dataStore.update(current => {
current.push(response.payload)
return current
})
this.subscribeCollectionUpdate(response.payload, dataStore)
}
})
return { subscribe: dataStore.subscribe }
}
createSubscriber(queries: string[] = []) {
return subscribe(this.databaseId, this.collectionId, queries)
const loadingStore = writable(true)
const dataStore = writable<Models.Document[]>([])
databases.listDocuments(this.databaseId, this.collectionId, queries).then(data => {
data.documents.forEach((document) => this.subscribeCollectionUpdate(document, dataStore))
dataStore.set(data.documents)
loadingStore.set(false)
})
return [{ subscribe: dataStore.subscribe }, { subscribe: loadingStore.subscribe }] as const
}
createPaginate(limit: number, queries: string[] = []) {
return paginate(this.databaseId, this.collectionId, limit, queries)
const dataStore = writable<Models.Document[]>([])
const loadingStore = writable(true)
let offset = 0
const store = {
subscribe: dataStore.subscribe,
async next() {
await databases.listDocuments(this.databaseId, this.collectionId, [...queries, Query.limit(limit), Query.offset(offset)]).then(data => {
data.documents.forEach((document) => this.subscribeCollectionUpdate(document, dataStore))
dataStore.update(current => [...current, ...data.documents])
offset += limit
})
}
}
export default Collection
store.next().then(() => loadingStore.set(false))
return [store, { subscribe: loadingStore.subscribe }] as const
}
protected subscribeCollectionUpdate(document: Models.Document, store: Writable<Models.Document[]>) {
client.subscribe(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${document.$id}`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${document.$id}.delete`)) {
store.update(current => {
current.splice(current.indexOf(document), 1)
return current
})
return
}
if (response.events.includes(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${document.$id}.update`)) {
store.update(current => {
current[current.indexOf(document)] = response.payload
return current
})
return
}
})
}
}
class Document {
constructor(protected databaseId: string, protected collectionId: string, protected documentId: string) { }
createSubscriber() {
const dataStore = writable<Models.Document>(null)
const loadingStore = writable(true)
databases.getDocument(this.databaseId, this.collectionId, this.documentId).then(data => {
dataStore.set(data)
loadingStore.set(false)
})
client.subscribe(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${this.documentId}`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${this.documentId}.update`)) {
dataStore.set(response.payload)
return
}
if (response.events.includes(`databases.${this.databaseId}.collections.${this.collectionId}.documents.${this.documentId}.delete`)) {
dataStore.set(null)
return
}
})
return [{ subscribe: dataStore.subscribe }, { subscribe: loadingStore.subscribe }] as const
}
}
export { Collection, Document }

116
src/lib/storage.ts Normal file
View File

@ -0,0 +1,116 @@
import { storage, client } from './stores/appwrite'
import { ID, Models, RealtimeResponseEvent } from 'appwrite'
import { Writable, writable } from 'svelte/store'
class Storage {
constructor(protected bucketId: string) { }
createFile(file, permissions: string[] = []) {
return storage.createFile(this.bucketId, ID.unique(), file, permissions)
}
deleteFile(fileId: string) {
return storage.deleteFile(this.bucketId, fileId)
}
updateFile(fileId: string, permissions: string[] = []) {
return storage.updateFile(this.bucketId, fileId, permissions)
}
createUploadDispatcher(acceptManyFiles = false) {
return (node: HTMLInputElement) => {
const eventListener = (e) => {
const files = acceptManyFiles ? e.target.files : [e.target.files[0]]
files.forEach((file) => this.createFile(file))
}
node.addEventListener('change', eventListener)
return {
destroy() {
node.removeEventListener('change', eventListener)
},
}
}
}
createSubsciber(queries: string[] = [], search = '') {
const filesStore = writable<Models.File[]>([])
const loadingStore = writable(true)
storage.listFiles(this.bucketId, queries, search).then(files => {
for (const file of files.files) {
this.subscribeFileUpdate(file, filesStore)
}
})
return [{ subscribe: filesStore.subscribe }, { subscribe: loadingStore.subscribe }] as const
}
createObserver() {
const dataStore = writable<Models.File[]>([])
client.subscribe(`buckets.${this.bucketId}.files`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`buckets.${this.bucketId}.files.*.create`)) {
dataStore.update(current => {
current.push(response.payload)
return current
})
this.subscribeFileUpdate(response.payload, dataStore)
}
})
return { subscribe: dataStore.subscribe }
}
protected subscribeFileUpdate(file: Models.File, filesStore: Writable<Models.File[]>) {
client.subscribe(`buckets.${this.bucketId}.files.${file.$id}`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`buckets.${this.bucketId}.files.${file.$id}.update`)) {
filesStore.update(current => {
current[current.indexOf(file)] = file
return current
})
return
}
if (response.events.includes(`buckets.${this.bucketId}.files.${file.$id}.delete`)) {
filesStore.update(current => {
current.splice(current.indexOf(file), 1)
return current
})
return
}
})
}
}
class File {
constructor(protected bucketId: string, protected fileId: string) { }
createSubscriber() {
const fileStore = writable<Models.File>(null)
const loadingStore = writable(true)
storage.getFile(this.bucketId, this.fileId).then((result) => {
fileStore.set(result)
loadingStore.set(false)
})
client.subscribe(`buckets.${this.bucketId}.files.${this.fileId}`, (response: RealtimeResponseEvent<any>) => {
if (response.events.includes(`buckets.${this.bucketId}.files.${this.fileId}.update`)) {
fileStore.set(response.payload)
return
}
if (response.events.includes(`buckets.${this.bucketId}.files.${this.fileId}.delete`)) {
fileStore.set(null)
return
}
})
return [{ subscribe: fileStore.subscribe }, { subscribe: loadingStore.subscribe }] as const
}
}
export { Storage, File }

View File

@ -1,8 +1,13 @@
import { Client, Account, Databases } from 'appwrite'
import { Client, Account, Databases, Storage, Teams, Functions, Locale, Avatars } from 'appwrite'
const client = new Client()
const account = new Account(client)
const databases = new Databases(client)
const storage = new Storage(client)
const teams = new Teams(client)
const functions = new Functions(client)
const locale = new Locale(client)
const avatars = new Avatars(client)
const url = {
oauth: {
@ -14,4 +19,4 @@ const url = {
client.setEndpoint('http://localhost/v1').setProject('638871b363904655d784')
export default client
export { client, account, url, databases }
export { client, account, url, databases, storage, teams, functions, locale, avatars }