summaryrefslogtreecommitdiffhomepage
path: root/cloud/web/src/components/context-account.tsx
diff options
context:
space:
mode:
authorFrank <[email protected]>2025-08-08 13:22:54 -0400
committerFrank <[email protected]>2025-08-08 13:24:32 -0400
commit183e0911b76025a1f2a82e979d9834fec2131d0e (patch)
tree9987c1753bd64d1ce1d174ab397f1a8c681f642c /cloud/web/src/components/context-account.tsx
parentc7bb19ad0712469063eab35589aa5d3602b0c5b1 (diff)
downloadopencode-183e0911b76025a1f2a82e979d9834fec2131d0e.tar.gz
opencode-183e0911b76025a1f2a82e979d9834fec2131d0e.zip
wip: gateway
Diffstat (limited to 'cloud/web/src/components/context-account.tsx')
-rw-r--r--cloud/web/src/components/context-account.tsx99
1 files changed, 99 insertions, 0 deletions
diff --git a/cloud/web/src/components/context-account.tsx b/cloud/web/src/components/context-account.tsx
new file mode 100644
index 000000000..e6aabafd3
--- /dev/null
+++ b/cloud/web/src/components/context-account.tsx
@@ -0,0 +1,99 @@
+import { createContext, createEffect, ParentProps, Suspense, useContext } from "solid-js"
+import { makePersisted } from "@solid-primitives/storage"
+import { createStore } from "solid-js/store"
+import { useOpenAuth } from "./context-openauth"
+import { createAsync } from "@solidjs/router"
+import { isServer } from "solid-js/web"
+
+type Storage = {
+ accounts: Record<
+ string,
+ {
+ id: string
+ email: string
+ workspaces: {
+ id: string
+ name: string
+ slug: string
+ }[]
+ }
+ >
+}
+
+const context = createContext<ReturnType<typeof init>>()
+
+function init() {
+ const auth = useOpenAuth()
+ const [store, setStore] = makePersisted(
+ createStore<Storage>({
+ accounts: {},
+ }),
+ {
+ name: "opencontrol.account",
+ },
+ )
+
+ async function refresh(id: string) {
+ return fetch(import.meta.env.VITE_API_URL + "/rest/account", {
+ headers: {
+ authorization: `Bearer ${await auth.access(id)}`,
+ },
+ })
+ .then((val) => val.json())
+ .then((val) => setStore("accounts", id, val as any))
+ }
+
+ createEffect((previous: string[]) => {
+ if (Object.keys(auth.all).length === 0) {
+ return []
+ }
+ for (const item of Object.values(auth.all)) {
+ if (previous.includes(item.id)) continue
+ refresh(item.id)
+ }
+ return Object.keys(auth.all)
+ }, [] as string[])
+
+ const result = {
+ get all() {
+ return Object.keys(auth.all)
+ .map((id) => store.accounts[id])
+ .filter(Boolean)
+ },
+ get current() {
+ if (!auth.subject) return undefined
+ return store.accounts[auth.subject.id]
+ },
+ refresh,
+ get ready() {
+ return Object.keys(auth.all).length === result.all.length
+ },
+ }
+
+ return result
+}
+
+export function AccountProvider(props: ParentProps) {
+ const ctx = init()
+ const resource = createAsync(async () => {
+ await new Promise<void>((resolve) => {
+ if (isServer) return resolve()
+ createEffect(() => {
+ if (ctx.ready) resolve()
+ })
+ })
+ return null
+ })
+ return (
+ <Suspense>
+ {resource()}
+ <context.Provider value={ctx}>{props.children}</context.Provider>
+ </Suspense>
+ )
+}
+
+export function useAccount() {
+ const result = useContext(context)
+ if (!result) throw new Error("no account context")
+ return result
+}