feat(lib/storage): add Storage#subscribe

This commit is contained in:
PalmDevs 2025-08-11 16:39:23 +07:00
parent 53e5f918da
commit dcfe40c1d7
No known key found for this signature in database
GPG key ID: 6FAE8F8677ACA8BA
3 changed files with 14 additions and 18 deletions

View file

@ -1,6 +0,0 @@
import type { Storage, StorageSubscription } from '.'
export const instanceToSubscriptions = new WeakMap<
Storage<any>,
Set<StorageSubscription<any>>
>()

View file

@ -3,7 +3,6 @@
import { FileModule } from '@revenge-mod/discord/native'
import { getErrorStack } from '@revenge-mod/utils/error'
import { mergeDeep } from '@revenge-mod/utils/object'
import { instanceToSubscriptions } from './_internal'
import type { AnyObject, DeepPartial } from '@revenge-mod/utils/types'
export type StorageSubscription<T extends AnyObject = AnyObject> = (
@ -22,7 +21,6 @@ export function Storage<T extends AnyObject>(
const fullPath = `${dirPath}/${path}`
const subscriptions = new Set<StorageSubscription<T>>()
instanceToSubscriptions.set(this, subscriptions)
this.loaded = false
this.cache = options?.default
@ -30,6 +28,11 @@ export function Storage<T extends AnyObject>(
this.exists = () => FileModule.fileExists(fullPath)
this.delete = () => FileModule.removeFile(directory, path)
this.subscribe = callback => {
subscriptions.add(callback)
return () => subscriptions.delete(callback)
}
this.get = async function () {
if (!(await this.exists())) {
this.cache = options?.default ?? {}
@ -73,7 +76,7 @@ export function Storage<T extends AnyObject>(
}
// React is only initialized right before the init stage, so this is a dummy method
// See init.ts for the actual implementation
// See define-storage-use.ts in api.storage plugin for the actual implementation
Storage.prototype.use = () => {
throw new Error('Storage#use can only be called after the init stage!')
}
@ -153,8 +156,13 @@ export interface Storage<T extends AnyObject> {
* // ...
* }
*/
use(filter?: UseStorageFilter<T>): T | undefined
/**
* Subscribe to storage updates. The callback will be called with what was called in `Storage#set`.
* @param callback The callback to call when the storage is updated.
* @returns A function to unsubscribe.
*/
subscribe(callback: StorageSubscription<T>): () => void
/**
* Get the storage.
*/

View file

@ -1,7 +1,6 @@
import { Storage } from '@revenge-mod/storage'
import { useReRender } from '@revenge-mod/utils/react'
import { useEffect } from 'react'
import { instanceToSubscriptions } from '../../../../lib/storage/src/_internal'
import type { StorageSubscription } from '@revenge-mod/storage'
// Actual implementation of Storage#use
@ -10,7 +9,6 @@ SP.use = function (filter) {
if (!this.cache) this.get()
const reRender = useReRender()
const subscriptions = instanceToSubscriptions.get(this)!
useEffect(() => {
const sub: StorageSubscription = filter
@ -19,12 +17,8 @@ SP.use = function (filter) {
}
: reRender
subscriptions.add(sub)
return () => {
subscriptions.delete(sub)
}
}, [filter, reRender, subscriptions.add, subscriptions.delete])
return this.subscribe(sub)
}, [filter, reRender])
return this.cache
}