import invariant from "invariant"; import { lowerFirst } from "es-toolkit/compat"; import pluralize from "pluralize"; import ApiKeysStore from "./ApiKeysStore"; import AuthStore from "./AuthStore"; import AuthenticationProvidersStore from "./AuthenticationProvidersStore"; import CollectionsStore from "./CollectionsStore"; import CommentsStore from "./CommentsStore"; import DialogsStore from "./DialogsStore"; import DocumentPresenceStore from "./DocumentPresenceStore"; import DocumentsStore from "./DocumentsStore"; import EventsStore from "./EventsStore"; import EmojisStore from "./EmojiStore"; import FileOperationsStore from "./FileOperationsStore"; import GroupMembershipsStore from "./GroupMembershipsStore"; import GroupUsersStore from "./GroupUsersStore"; import GroupsStore from "./GroupsStore"; import ImportsStore from "./ImportsStore"; import IntegrationsStore from "./IntegrationsStore"; import MembershipsStore from "./MembershipsStore"; import NotificationsStore from "./NotificationsStore"; import OAuthAuthenticationsStore from "./OAuthAuthenticationsStore"; import OAuthClientsStore from "./OAuthClientsStore"; import PinsStore from "./PinsStore"; import PoliciesStore from "./PoliciesStore"; import RevisionsStore from "./RevisionsStore"; import SearchesStore from "./SearchesStore"; import SharesStore from "./SharesStore"; import StarsStore from "./StarsStore"; import SubscriptionsStore from "./SubscriptionsStore"; import TemplatesStore from "./TemplatesStore"; import UiStore from "./UiStore"; import UnfurlsStore from "./UnfurlsStore"; import UserMembershipsStore from "./UserMembershipsStore"; import UsersStore from "./UsersStore"; import ViewsStore from "./ViewsStore"; import WebhookSubscriptionsStore from "./WebhookSubscriptionStore"; import type Store from "./base/Store"; export default class RootStore { apiKeys: ApiKeysStore; auth: AuthStore; authenticationProviders: AuthenticationProvidersStore; collections: CollectionsStore; groupMemberships: GroupMembershipsStore; comments: CommentsStore; dialogs: DialogsStore; documents: DocumentsStore; emojis: EmojisStore; events: EventsStore; groups: GroupsStore; groupUsers: GroupUsersStore; imports: ImportsStore; integrations: IntegrationsStore; memberships: MembershipsStore; notifications: NotificationsStore; oauthAuthentications: OAuthAuthenticationsStore; oauthClients: OAuthClientsStore; presence: DocumentPresenceStore; pins: PinsStore; policies: PoliciesStore; revisions: RevisionsStore; searches: SearchesStore; shares: SharesStore; ui: UiStore; unfurls: UnfurlsStore; stars: StarsStore; subscriptions: SubscriptionsStore; templates: TemplatesStore; users: UsersStore; views: ViewsStore; fileOperations: FileOperationsStore; webhookSubscriptions: WebhookSubscriptionsStore; userMemberships: UserMembershipsStore; constructor() { // Models this.registerStore(ApiKeysStore); this.registerStore(AuthenticationProvidersStore); this.registerStore(CollectionsStore); this.registerStore(GroupMembershipsStore); this.registerStore(CommentsStore); this.registerStore(DocumentsStore); this.registerStore(EmojisStore); this.registerStore(EventsStore); this.registerStore(GroupsStore); this.registerStore(GroupUsersStore); this.registerStore(ImportsStore); this.registerStore(IntegrationsStore); this.registerStore(MembershipsStore); this.registerStore(NotificationsStore); this.registerStore(OAuthAuthenticationsStore, "oauthAuthentications"); this.registerStore(OAuthClientsStore, "oauthClients"); this.registerStore(PinsStore); this.registerStore(PoliciesStore); this.registerStore(RevisionsStore); this.registerStore(SearchesStore); this.registerStore(SharesStore); this.registerStore(StarsStore); this.registerStore(SubscriptionsStore); this.registerStore(TemplatesStore); this.registerStore(UnfurlsStore); this.registerStore(UsersStore); this.registerStore(ViewsStore); this.registerStore(FileOperationsStore); this.registerStore(WebhookSubscriptionsStore); this.registerStore(UserMembershipsStore); // Non-models this.registerStore(DocumentPresenceStore, "presence"); this.registerStore(DialogsStore, "dialogs"); this.registerStore(UiStore, "ui"); // AuthStore must be initialized last as it makes use of the other stores. this.registerStore(AuthStore, "auth"); } /** * Get a store by model name. * * @param modelName */ public getStoreForModelName(modelName: string) { const storeName = this.getStoreNameForModelName(modelName); invariant(storeName, `No store found for model name "${modelName}"`); const store = this[storeName]; return store as RootStore[K]; } /** * Clear all data from the stores except for auth and ui. */ public clear() { Object.getOwnPropertyNames(this) .filter((key) => ["auth", "ui"].includes(key) === false) .forEach((key: keyof RootStore) => { if ("clear" in this[key]) { // @ts-expect-error clear exists on all stores this[key].clear(); } }); } /** * Register a store with the root store. * * @param StoreClass */ private registerStore( StoreClass: T, name?: keyof RootStore ) { // @ts-expect-error TS thinks we are instantiating an abstract class. const store = new StoreClass(this); const storeName = name ?? this.getStoreNameForModelName(store.modelName); invariant(storeName, `No store found for model name "${store.modelName}"`); this[storeName] = store; } private getStoreNameForModelName(modelName: string) { for (const key of Object.keys(this)) { const store = this[key as keyof RootStore]; if (store && "modelName" in store && store.modelName === modelName) { return key as keyof RootStore; } } const storeName = pluralize(lowerFirst(modelName)) as keyof RootStore; if (storeName) { return storeName; } return undefined; } }