fix: Do not rely on class names in production bundle (#6212)

This commit is contained in:
Tom Moor
2023-11-24 12:59:57 -05:00
committed by GitHub
parent 13a6f89640
commit b9767a9fdc
38 changed files with 202 additions and 86 deletions

View File

@@ -351,6 +351,6 @@ export default class AuthStore extends Store<Team> {
// Tell the host application we logged out, if any allows window cleanup.
void Desktop.bridge?.onLogout?.();
this.rootStore.logout();
this.rootStore.clear();
};
}

View File

@@ -10,8 +10,6 @@ import RootStore from "./RootStore";
import Store from "./base/Store";
export default class CommentsStore extends Store<Comment> {
apiEndpoint = "comments";
constructor(rootStore: RootStore) {
super(rootStore, Comment);
}

View File

@@ -1,3 +1,5 @@
import invariant from "invariant";
import pluralize from "pluralize";
import ApiKeysStore from "./ApiKeysStore";
import AuthStore from "./AuthStore";
import AuthenticationProvidersStore from "./AuthenticationProvidersStore";
@@ -25,6 +27,7 @@ import UiStore from "./UiStore";
import UsersStore from "./UsersStore";
import ViewsStore from "./ViewsStore";
import WebhookSubscriptionsStore from "./WebhookSubscriptionStore";
import Store from "./base/Store";
export default class RootStore {
apiKeys: ApiKeysStore;
@@ -56,42 +59,79 @@ export default class RootStore {
webhookSubscriptions: WebhookSubscriptionsStore;
constructor() {
this.apiKeys = new ApiKeysStore(this);
this.authenticationProviders = new AuthenticationProvidersStore(this);
this.collections = new CollectionsStore(this);
this.collectionGroupMemberships = new CollectionGroupMembershipsStore(this);
this.comments = new CommentsStore(this);
this.dialogs = new DialogsStore();
this.documents = new DocumentsStore(this);
this.events = new EventsStore(this);
this.groups = new GroupsStore(this);
this.groupMemberships = new GroupMembershipsStore(this);
this.integrations = new IntegrationsStore(this);
this.memberships = new MembershipsStore(this);
this.notifications = new NotificationsStore(this);
this.pins = new PinsStore(this);
this.policies = new PoliciesStore(this);
this.presence = new DocumentPresenceStore();
this.revisions = new RevisionsStore(this);
this.searches = new SearchesStore(this);
this.shares = new SharesStore(this);
this.stars = new StarsStore(this);
this.subscriptions = new SubscriptionsStore(this);
this.ui = new UiStore();
this.users = new UsersStore(this);
this.views = new ViewsStore(this);
this.fileOperations = new FileOperationsStore(this);
this.webhookSubscriptions = new WebhookSubscriptionsStore(this);
// Models
this.registerStore(ApiKeysStore);
this.registerStore(AuthenticationProvidersStore);
this.registerStore(CollectionsStore);
this.registerStore(CollectionGroupMembershipsStore);
this.registerStore(CommentsStore);
this.registerStore(DocumentsStore);
this.registerStore(EventsStore);
this.registerStore(GroupsStore);
this.registerStore(GroupMembershipsStore);
this.registerStore(IntegrationsStore);
this.registerStore(MembershipsStore);
this.registerStore(NotificationsStore);
this.registerStore(PinsStore);
this.registerStore(PoliciesStore);
this.registerStore(RevisionsStore);
this.registerStore(SearchesStore);
this.registerStore(SharesStore);
this.registerStore(StarsStore);
this.registerStore(SubscriptionsStore);
this.registerStore(UsersStore);
this.registerStore(ViewsStore);
this.registerStore(FileOperationsStore);
this.registerStore(WebhookSubscriptionsStore);
// 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.auth = new AuthStore(this);
this.registerStore(AuthStore, "auth");
}
logout() {
/**
* Get a store by model name.
*
* @param modelName
*/
public getStoreForModelName<K extends keyof RootStore>(
modelName: string
): RootStore[K] {
const storeName = this.getStoreNameForModelName(modelName);
const store = this[storeName];
invariant(store, `No store found for model name "${modelName}"`);
return store;
}
/**
* 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) => {
this[key]?.clear?.();
});
}
/**
* Register a store with the root store.
*
* @param StoreClass
*/
private registerStore<T = typeof Store>(StoreClass: T, name?: string) {
// @ts-expect-error TS thinks we are instantiating an abstract class.
const store = new StoreClass(this);
const storeName = name ?? this.getStoreNameForModelName(store.modelName);
this[storeName] = store;
}
private getStoreNameForModelName(modelName: string) {
return pluralize(modelName.toLowerCase());
}
}

View File

@@ -7,8 +7,6 @@ import Store, { RPCAction } from "./base/Store";
export default class SearchesStore extends Store<SearchQuery> {
actions = [RPCAction.List, RPCAction.Delete];
apiEndpoint = "searches";
constructor(rootStore: RootStore) {
super(rootStore, SearchQuery);
}

View File

@@ -2,7 +2,7 @@ import invariant from "invariant";
import lowerFirst from "lodash/lowerFirst";
import orderBy from "lodash/orderBy";
import { observable, action, computed, runInAction } from "mobx";
import { Class } from "utility-types";
import pluralize from "pluralize";
import RootStore from "~/stores/RootStore";
import Policy from "~/models/Policy";
import Model from "~/models/base/Model";
@@ -22,8 +22,6 @@ export enum RPCAction {
type FetchPageParams = PaginationParams & Record<string, any>;
export const DEFAULT_PAGINATION_LIMIT = 25;
export const PAGINATION_SYMBOL = Symbol.for("pagination");
export default abstract class Store<T extends Model> {
@@ -39,7 +37,7 @@ export default abstract class Store<T extends Model> {
@observable
isLoaded = false;
model: Class<T>;
model: typeof Model;
modelName: string;
@@ -56,13 +54,13 @@ export default abstract class Store<T extends Model> {
RPCAction.Count,
];
constructor(rootStore: RootStore, model: Class<T>) {
constructor(rootStore: RootStore, model: typeof Model) {
this.rootStore = rootStore;
this.model = model;
this.modelName = lowerFirst(model.name).replace(/\d$/, "");
this.modelName = model.modelName;
if (!this.apiEndpoint) {
this.apiEndpoint = `${this.modelName}s`;
this.apiEndpoint = pluralize(lowerFirst(model.modelName));
}
}
@@ -89,6 +87,7 @@ export default abstract class Store<T extends Model> {
return existingModel;
}
// @ts-expect-error TS thinks that we're instantiating an abstract class here
const newModel = new ModelClass(item, this);
this.data.set(newModel.id, newModel);
return newModel;
@@ -103,20 +102,21 @@ export default abstract class Store<T extends Model> {
const inverseRelations = getInverseRelationsForModelClass(this.model);
inverseRelations.forEach((relation) => {
// TODO: Need a better way to get the store for a given model name.
const store = this.rootStore[`${relation.modelName.toLowerCase()}s`];
const items = store.orderedData.filter(
(item: Model) => item[relation.idKey] === id
);
const store = this.rootStore.getStoreForModelName(relation.modelName);
if ("orderedData" in store) {
const items = (store.orderedData as Model[]).filter(
(item) => item[relation.idKey] === id
);
if (relation.options.onDelete === "cascade") {
items.forEach((item: Model) => store.remove(item.id));
}
if (relation.options.onDelete === "cascade") {
items.forEach((item) => store.remove(item.id));
}
if (relation.options.onDelete === "null") {
items.forEach((item: Model) => {
item[relation.idKey] = null;
});
if (relation.options.onDelete === "null") {
items.forEach((item) => {
item[relation.idKey] = null;
});
}
}
});