mirror of
https://github.com/stoatchat/javascript-client-sdk.git
synced 2026-08-26 15:08:03 -04:00
refactor: Add ability to hydrate outside batch() (#186)
* refactor: Add ability to hydrate outside batch() Signed-off-by: Jacob Schlecht <dadadah@echoha.us> * chore: Update javadoc for these new functions to use link Signed-off-by: Jacob Schlecht <dadadah@echoha.us> * chore: Fix this comment Signed-off-by: Jacob Schlecht <dadadah@echoha.us> --------- Signed-off-by: Jacob Schlecht <dadadah@echoha.us>
This commit is contained in:
+33
-64
@@ -22,6 +22,8 @@ import { decodeTime } from "ulid";
|
||||
import type { ServerCollection } from "../collections/ServerCollection.js";
|
||||
import { hydrate } from "../hydration/index.js";
|
||||
import type { ServerFlags } from "../hydration/server.js";
|
||||
import { HydratedServerMember } from "../hydration/serverMember.js";
|
||||
import { HydratedUser } from "../hydration/user.js";
|
||||
import {
|
||||
bitwiseAndEq,
|
||||
calculatePermission,
|
||||
@@ -675,10 +677,7 @@ export class Server {
|
||||
|
||||
#synced: undefined | "partial" | "full";
|
||||
|
||||
async syncMembers(
|
||||
excludeOffline?: boolean,
|
||||
excludeOfflineUserCap?: number,
|
||||
): Promise<void> {
|
||||
async syncMembers(excludeOffline?: boolean): Promise<void> {
|
||||
if (this.#synced && (this.#synced === "full" || excludeOffline)) return;
|
||||
|
||||
const data = await this.#collection.client.api.get(
|
||||
@@ -686,67 +685,37 @@ export class Server {
|
||||
{ exclude_offline: excludeOffline },
|
||||
);
|
||||
|
||||
const newUsers: HydratedUser[] = [];
|
||||
const newServerMembers: HydratedServerMember[] = [];
|
||||
|
||||
for (let i = 0; i < data.users.length; i++) {
|
||||
const user = data.users[i];
|
||||
if (!excludeOffline || user.online) {
|
||||
const newUser = this.#collection.client.users.hydrateIfNotHas(
|
||||
user._id,
|
||||
user,
|
||||
);
|
||||
if (newUser) {
|
||||
newUsers.push(newUser);
|
||||
}
|
||||
const newMember = this.#collection.client.serverMembers.hydrateIfNotHas(
|
||||
data.members[i]._id,
|
||||
data.members[i],
|
||||
);
|
||||
if (newMember) {
|
||||
newServerMembers.push(newMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
batch(() => {
|
||||
if (excludeOffline && excludeOfflineUserCap) {
|
||||
// quick fix to cap users
|
||||
let count = 0;
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < data.users.length && count < excludeOfflineUserCap;
|
||||
i++
|
||||
) {
|
||||
const user = data.users[i];
|
||||
if (user.online && data.members[i].roles?.length) {
|
||||
this.#collection.client.users.getOrCreate(user._id, user);
|
||||
this.#collection.client.serverMembers.getOrCreate(
|
||||
data.members[i]._id,
|
||||
data.members[i],
|
||||
);
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
|
||||
for (
|
||||
let i = 0;
|
||||
i < data.users.length && count < excludeOfflineUserCap;
|
||||
i++
|
||||
) {
|
||||
const user = data.users[i];
|
||||
if (user.online && !data.members[i].roles?.length) {
|
||||
this.#collection.client.users.getOrCreate(user._id, user);
|
||||
this.#collection.client.serverMembers.getOrCreate(
|
||||
data.members[i]._id,
|
||||
data.members[i],
|
||||
);
|
||||
|
||||
count++;
|
||||
}
|
||||
}
|
||||
// end quick fix
|
||||
} else if (excludeOffline) {
|
||||
for (let i = 0; i < data.users.length; i++) {
|
||||
const user = data.users[i];
|
||||
if (user.online) {
|
||||
this.#collection.client.users.getOrCreate(user._id, user);
|
||||
this.#collection.client.serverMembers.getOrCreate(
|
||||
data.members[i]._id,
|
||||
data.members[i],
|
||||
);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (let i = 0; i < data.users.length; i++) {
|
||||
this.#collection.client.users.getOrCreate(
|
||||
data.users[i]._id,
|
||||
data.users[i],
|
||||
);
|
||||
this.#collection.client.serverMembers.getOrCreate(
|
||||
data.members[i]._id,
|
||||
data.members[i],
|
||||
);
|
||||
}
|
||||
for (const newUser of newUsers) {
|
||||
this.#collection.client.users.addHydratedUser(newUser);
|
||||
}
|
||||
for (const newServerMember of newServerMembers) {
|
||||
this.#collection.client.serverMembers.addHydratedServerMember(
|
||||
newServerMember,
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -175,6 +175,29 @@ export abstract class StoreCollection<T, V> extends Collection<T> {
|
||||
this.#objects.set(id, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate a new instance of an object. This function does not add the object to the collection.
|
||||
* @param id Id
|
||||
* @param type Type
|
||||
* @param instance Instance
|
||||
* @param context Context
|
||||
* @param data Data
|
||||
*/
|
||||
protected hydrate(type: keyof Hydrators, context: unknown, data: object): V {
|
||||
return this.#storage.hydrateOnly(type, context, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a previously hydrated object to the collection
|
||||
* @param id Id
|
||||
* @param instance Instance
|
||||
* @param hydrated Hydrated
|
||||
*/
|
||||
protected add(id: string, instance: T, hydrated: V) {
|
||||
this.#storage.add(id, hydrated);
|
||||
this.#objects.set(id, instance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check whether an object is partially defined
|
||||
* @param id Id
|
||||
|
||||
@@ -97,4 +97,36 @@ export class ServerMemberCollection extends ClassCollection<
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate a new server member if it is not in the collection yet. This
|
||||
* function does not add the server member to the store, make sure you call
|
||||
* {@link addHydratedServerMember} afterwards. This function is particularly
|
||||
* useful when adding many server members asynchronously. See
|
||||
* Server.syncMembers for an example of this in use.
|
||||
* @param id The ID of the server member
|
||||
* @param data The API object for a server member
|
||||
* @returns The HydratedServerMember, or undefined if the user is in the collection
|
||||
*/
|
||||
hydrateIfNotHas(
|
||||
id: MemberCompositeKey,
|
||||
data: Member,
|
||||
): HydratedServerMember | undefined {
|
||||
if (this.hasByKey(id) && !this.isPartialByKey(id)) {
|
||||
return;
|
||||
} else {
|
||||
return this.hydrate("serverMember", this.client, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pre-hydrated server member to this collection.
|
||||
* @param user A hydrated server member
|
||||
* @returns The server member instance
|
||||
*/
|
||||
addHydratedServerMember(member: HydratedServerMember): ServerMember {
|
||||
const instance = new ServerMember(this, member.id);
|
||||
this.add(member.id.server + member.id.user, instance, member);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,7 +42,6 @@ export class UserCollection extends ClassCollection<User, HydratedUser> {
|
||||
* Get or create
|
||||
* @param id Id
|
||||
* @param data Data
|
||||
* @param isNew Whether this object is new
|
||||
*/
|
||||
getOrCreate(id: string, data: APIUser): User {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
@@ -70,4 +69,32 @@ export class UserCollection extends ClassCollection<User, HydratedUser> {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate a new user if it is not in the collection yet. This function does
|
||||
* not add the user to the store, make sure you call {@link addHydratedUser}
|
||||
* afterwards. This function is particularly useful when adding many users
|
||||
* asynchronously. See Server.syncMembers for an example of this in use.
|
||||
* @param id The ID of the user
|
||||
* @param data The API object for a user
|
||||
* @returns The HydratedUser, or undefined if the user is in the collection
|
||||
*/
|
||||
hydrateIfNotHas(id: string, data: APIUser): HydratedUser | undefined {
|
||||
if (this.has(id) && !this.isPartial(id)) {
|
||||
return;
|
||||
} else {
|
||||
return this.hydrate("user", this.client, data);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a pre-hydrated user to this collection.
|
||||
* @param user A hydrated user
|
||||
* @returns The user instance
|
||||
*/
|
||||
addHydratedUser(user: HydratedUser): User {
|
||||
const instance = new User(this, user.id);
|
||||
this.add(user.id, instance, user);
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,4 +47,26 @@ export class ObjectStorage<T> {
|
||||
this.set(id, hydrate(type, data as never, context, true) as T);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Hydrate some data without putting it into storage. Call {@link add}
|
||||
* afterwards to add the hydrated value into storage.
|
||||
* @param type Hydration type
|
||||
* @param context Context
|
||||
* @param data Input Data
|
||||
* @returns The hydrated type
|
||||
*/
|
||||
hydrateOnly(type: keyof Hydrators, context: unknown, data: object): T {
|
||||
data = { partial: false, ...data };
|
||||
return hydrate(type, data as never, context, true) as T;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a previously hydrated object to the storage
|
||||
* @param id ID
|
||||
* @param toAdd Hydrated object
|
||||
*/
|
||||
add(id: string, toAdd: T) {
|
||||
this.set(id, toAdd);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user