Skip to content

Instantly share code, notes, and snippets.

@webdeb
Last active March 31, 2024 14:46
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webdeb/68d5b18f97de5df522503c2b2390adb2 to your computer and use it in GitHub Desktop.
Save webdeb/68d5b18f97de5df522503c2b2390adb2 to your computer and use it in GitHub Desktop.
useCloudDB for TG
import { useCloudStorage } from "@tma.js/sdk-react"
import { useEffect, useState } from "react"
type OP = 'addItem' | 'getAll' | 'purge'
const createKeys = (length: number, idxKey: Function): string[] => Array.from({ length: length }).map((_, idx: number) => idxKey(idx))
export const useCloudDB = (tableName: string, threshold: number) => {
const cs = useCloudStorage()
const [busy, setBusy] = useState(false)
const [threshReached, setThreshReached] = useState(false)
const [opStack, setStack] = useState<[Function, OP, string][]>([])
const nextIdxKey = tableName + '_next_idx';
const idxKey = (idx: number) => tableName + '_' + idx
const getNextIdx = async () => Number(await cs.get(nextIdxKey) || 0)
useEffect(() => {
console.log('cloud storage hook')
if (busy || opStack.length === 0)
return
setBusy(true)
const [[resolve, op, item], ...rest] = opStack
setStack(rest)
setTimeout(async () => {
const nextIndex = await getNextIdx()
if (op === "addItem") {
await Promise.all([
cs.set(idxKey(nextIndex), item),
cs.set(nextIdxKey, (nextIndex + 1).toString()),
])
resolve(nextIndex)
nextIndex === threshold && setThreshReached(true)
} else if (op === "getAll") {
resolve(await cs.get(createKeys(nextIndex, idxKey)))
} else if (op === "purge") {
Promise.all([
cs.delete(createKeys(nextIndex, idxKey)),
cs.set(nextIdxKey, (0).toString())
])
resolve()
}
setBusy(false)
})
}, [opStack, busy])
return {
addItem: async (item: string): Promise<number> => new Promise((resolve: any) =>
setStack(stack => [...stack, [resolve, "addItem", item]])),
getAll: async () => new Promise((resolve: Function) =>
setStack(stack => [...stack, [resolve, "getAll", "ok"]])),
purge: async () => new Promise((resolve: Function) =>
setStack(stack => [...stack, [resolve, "purge", "ok"]])),
threshReached,
}
}
/*
useCloudDB manages ops by stacking them.
Every exported function returns a Promise.
You can react when the threshReached (10) with an useEffect for example.
Use it like this in React:
```ts
const { addItem, getAll, purge, threshReached } = useCloudDB("ListIDakaTable", 10)
```
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment