diff --git a/packages/core/src/index.ts b/packages/core/src/index.ts index 4dc3aa1e..d7e304af 100644 --- a/packages/core/src/index.ts +++ b/packages/core/src/index.ts @@ -6,9 +6,11 @@ import { Client, create as createW3UPClient } from '@web3-storage/w3up-client' import { Account } from '@web3-storage/w3up-client/account' import { Space } from '@web3-storage/w3up-client/space' import { createServiceConf } from './service' +import { Driver } from '@web3-storage/access/drivers/types' export * from '@web3-storage/w3up-client/types' export { Client, Account, Space, ServiceConfig } +export type Store = Driver const DB_NAME = '@w3ui' const DB_STORE_NAME = 'core' @@ -29,7 +31,12 @@ export interface ContextState { } // eslint-disable-next-line @typescript-eslint/no-empty-interface -export interface ContextActions {} +export interface ContextActions { + /** + * Reset local store (deleting existing agent), logging the user out. + */ + logout: () => Promise +} export interface CreateClientOptions extends ServiceConfig { events?: EventTarget @@ -59,11 +66,11 @@ class IndexedDBEventDispatcherStore extends StoreIndexedDB { */ export async function createClient ( options?: CreateClientOptions -): Promise<{ client: Client, events: EventTarget }> { +): Promise<{ client: Client, events: EventTarget, store: Store }> { const dbName = `${DB_NAME}${options?.servicePrincipal != null ? '@' + options?.servicePrincipal.did() : ''}` const events = options?.events ?? new EventTarget() const store = new IndexedDBEventDispatcherStore(dbName, events) const serviceConf = createServiceConf(options) const client = await createW3UPClient({ store, serviceConf }) - return { client, events } + return { client, events, store } } diff --git a/packages/react/src/providers/Provider.tsx b/packages/react/src/providers/Provider.tsx index 8b91ab91..0aaa8cf5 100644 --- a/packages/react/src/providers/Provider.tsx +++ b/packages/react/src/providers/Provider.tsx @@ -4,7 +4,8 @@ import type { ContextActions, ServiceConfig, Space, - Account + Account, + Store } from '@w3ui/core' import React, { createContext, useState, useContext, useEffect, ReactNode } from 'react' @@ -46,6 +47,7 @@ export function Provider ({ const [events, setEvents] = useState() const [accounts, setAccounts] = useState([]) const [spaces, setSpaces] = useState([]) + const [store, setStore] = useState() useEffect(() => { if ((client === undefined) || (events === undefined)) return @@ -61,22 +63,33 @@ export function Provider ({ } }, [client, events]) - const getClient = async (): Promise => { - if (client == null) { - const { client, events } = await createClient({ servicePrincipal, connection }) - setClient(client) - setEvents(events) - setAccounts(Object.values(client.accounts())) - setSpaces(client.spaces()) - return client + const setupClient = async (): Promise => { + const { client, events, store } = await createClient({ servicePrincipal, connection }) + setClient(client) + setEvents(events) + setAccounts(Object.values(client.accounts())) + setSpaces(client.spaces()) + setStore(store) + } + + const logout = async (): Promise => { + if (store) { + await store.reset() + // set state back to defaults + setClient(undefined) + setEvents(undefined) + setAccounts([]) + setSpaces([]) + setStore(undefined) + // try to set state up again + await setupClient() } - return client } - useEffect(() => { void getClient() }, []) // load client - once. + useEffect(() => { setupClient() }, []) // load client - once. return ( - + {children} )