diff --git a/src/collections/ChannelCollection.ts b/src/collections/ChannelCollection.ts new file mode 100644 index 00000000..5f0d104c --- /dev/null +++ b/src/collections/ChannelCollection.ts @@ -0,0 +1,65 @@ +import { API, Channel } from ".."; +import { HydratedChannel } from "../hydration"; + +import { ClassCollection } from "."; + +export class ChannelCollection extends ClassCollection< + Channel, + HydratedChannel +> { + /** + * Delete an object + * @param id Id + */ + override delete(id: string): void { + let channel = this.get(id); + channel?.server?.channelIds.delete(id); + super.delete(id); + } + + /** + * Fetch channel by ID + * @param id Id + * @returns Channel + */ + async fetch(id: string): Promise { + const channel = this.get(id); + if (channel) return channel; + const data = await this.client.api.get(`/channels/${id as ""}`); + return this.getOrCreate(data._id, data); + } + + /** + * Get or create + * @param id Id + * @param data Data + * @param isNew Whether this object is new + */ + getOrCreate(id: string, data: API.Channel, isNew = false) { + if (this.has(id)) { + return this.get(id)!; + } else { + const instance = new Channel(this, id); + this.create(id, "channel", instance, data); + isNew && this.client.emit("channelCreate", instance); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: string) { + if (this.has(id)) { + return this.get(id)!; + } else if (this.client.options.partials) { + const instance = new Channel(this, id); + this.create(id, "channel", instance, { + id, + partial: true, + }); + return instance; + } + } +} diff --git a/src/collections/EmojiCollection.ts b/src/collections/EmojiCollection.ts new file mode 100644 index 00000000..e1a6f0cd --- /dev/null +++ b/src/collections/EmojiCollection.ts @@ -0,0 +1,51 @@ +import { API, Emoji } from ".."; +import { HydratedEmoji } from "../hydration"; + +import { ClassCollection } from "."; + +export class EmojiCollection extends ClassCollection { + /** + * Fetch emoji by ID + * @param id Id + * @returns Emoji + */ + async fetch(id: string): Promise { + const emoji = this.get(id); + if (emoji) return emoji; + const data = await this.client.api.get(`/custom/emoji/${id as ""}`); + return this.getOrCreate(data._id, data); + } + + /** + * Get or create + * @param id Id + * @param data Data + * @param isNew Whether this object is new + */ + getOrCreate(id: string, data: API.Emoji, isNew = false) { + if (this.has(id)) { + return this.get(id)!; + } else { + const instance = new Emoji(this, id); + this.create(id, "emoji", instance, data); + isNew && this.client.emit("emojiCreate", instance); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: string) { + if (this.has(id)) { + return this.get(id)!; + } else if (this.client.options.partials) { + const instance = new Emoji(this, id); + this.create(id, "emoji", instance, { + id, + }); + return instance; + } + } +} diff --git a/src/collections/MessageCollection.ts b/src/collections/MessageCollection.ts new file mode 100644 index 00000000..bca244dc --- /dev/null +++ b/src/collections/MessageCollection.ts @@ -0,0 +1,60 @@ +import { API, Message } from ".."; +import { HydratedMessage } from "../hydration"; + +import { ClassCollection } from "."; + +export class MessageCollection extends ClassCollection< + Message, + HydratedMessage +> { + /** + * Fetch message by Id + * @param channelId Channel Id + * @param messageId Message Id + * @returns Message + */ + async fetch(channelId: string, messageId: string): Promise { + const message = this.get(messageId); + if (message) return message; + + const data = await this.client.api.get( + `/channels/${channelId as ""}/messages/${messageId as ""}` + ); + + return this.getOrCreate(data._id, data, false); + } + + /** + * Get or create + * @param id Id + * @param data Data + * @param isNew Whether this object is new + */ + getOrCreate(id: string, data: API.Message, isNew = false) { + if (this.has(id)) { + return this.get(id)!; + } else { + const instance = new Message(this, id); + this.create(id, "message", instance, data); + isNew && this.client.emit("messageCreate", instance); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: string) { + if (this.has(id)) { + return this.get(id)!; + } else if (this.client.options.partials) { + const instance = new Message(this, id); + this.create(id, "message", instance, { + id, + partial: true, + }); + return instance; + } + } +} diff --git a/src/collections/ServerCollection.ts b/src/collections/ServerCollection.ts new file mode 100644 index 00000000..701e8835 --- /dev/null +++ b/src/collections/ServerCollection.ts @@ -0,0 +1,52 @@ +import { API, Server } from ".."; +import { HydratedServer } from "../hydration"; + +import { ClassCollection } from "."; + +export class ServerCollection extends ClassCollection { + /** + * Fetch server by ID + * @param id Id + * @returns Server + */ + async fetch(id: string): Promise { + const server = this.get(id); + if (server) return server; + const data = await this.client.api.get(`/servers/${id as ""}`); + return this.getOrCreate(data._id, data); + } + + /** + * Get or create + * @param id Id + * @param data Data + * @param isNew Whether this object is new + */ + getOrCreate(id: string, data: API.Server, isNew = false) { + if (this.has(id)) { + return this.get(id)!; + } else { + const instance = new Server(this, id); + this.create(id, "server", instance, data); + isNew && this.client.emit("serverCreate", instance); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: string) { + if (this.has(id)) { + return this.get(id)!; + } else if (this.client.options.partials) { + const instance = new Server(this, id); + this.create(id, "server", instance, { + id, + partial: true, + }); + return instance; + } + } +} diff --git a/src/collections/ServerMemberCollection.ts b/src/collections/ServerMemberCollection.ts new file mode 100644 index 00000000..259d7872 --- /dev/null +++ b/src/collections/ServerMemberCollection.ts @@ -0,0 +1,76 @@ +import { API, ServerMember } from ".."; +import { HydratedServerMember } from "../hydration"; + +import { ClassCollection } from "."; + +export class ServerMemberCollection extends ClassCollection< + ServerMember, + HydratedServerMember +> { + /** + * Check if member exists by composite key + * @param id Id + * @returns Whether it exists + */ + hasByKey(id: API.MemberCompositeKey) { + return super.has(id.server + id.user); + } + + /** + * Get member by composite key + * @param id Id + * @returns Member + */ + getByKey(id: API.MemberCompositeKey) { + return super.get(id.server + id.user); + } + + /** + * Fetch server member by Id + * @param serverId Server Id + * @param userId User Id + * @returns Message + */ + async fetch(serverId: string, userId: string): Promise { + const member = this.get(userId); + if (member) return member; + + const data = await this.client.api.get( + `/servers/${serverId as ""}/members/${userId as ""}` + ); + + return this.getOrCreate(data._id, data); + } + + /** + * Get or create + * @param id Id + * @param data Data + */ + getOrCreate(id: API.MemberCompositeKey, data: API.Member) { + if (this.hasByKey(id)) { + return this.getByKey(id)!; + } else { + const instance = new ServerMember(this, id); + this.create(id.server + id.user, "serverMember", instance, data); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: API.MemberCompositeKey) { + if (this.hasByKey(id)) { + return this.getByKey(id)!; + } else if (this.client.options.partials) { + const instance = new ServerMember(this, id); + this.create(id.server + id.user, "serverMember", instance, { + id, + partial: true, + }); + return instance; + } + } +} diff --git a/src/collections/UserCollection.ts b/src/collections/UserCollection.ts new file mode 100644 index 00000000..d9dd83fd --- /dev/null +++ b/src/collections/UserCollection.ts @@ -0,0 +1,51 @@ +import { API, User } from ".."; +import { HydratedUser } from "../hydration"; + +import { ClassCollection } from "."; + +export class UserCollection extends ClassCollection { + /** + * Fetch user by ID + * @param id Id + * @returns User + */ + async fetch(id: string): Promise { + const user = this.get(id); + if (user) return user; + const data = await this.client.api.get(`/users/${id as ""}`); + return this.getOrCreate(data._id, data); + } + + /** + * Get or create + * @param id Id + * @param data Data + * @param isNew Whether this object is new + */ + getOrCreate(id: string, data: API.User) { + if (this.has(id)) { + return this.get(id)!; + } else { + const instance = new User(this, id); + this.create(id, "user", instance, data); + return instance; + } + } + + /** + * Get or return partial + * @param id Id + */ + getOrPartial(id: string) { + if (this.has(id)) { + return this.get(id)!; + } else if (this.client.options.partials) { + const instance = new User(this, id); + this.create(id, "user", instance, { + id, + partial: true, + }); + return instance; + } + } +} diff --git a/src/collections/index.ts b/src/collections/index.ts index 2bc8fff2..aa6cddb9 100644 --- a/src/collections/index.ts +++ b/src/collections/index.ts @@ -1,26 +1,11 @@ -import type * as API from "revolt-api"; - import { Client } from ".."; -import { - Channel, - Emoji, - Message, - Server, - ServerMember, - User, -} from "../classes"; -import { - HydratedChannel, - HydratedEmoji, - HydratedMessage, - HydratedServer, - HydratedServerMember, - HydratedUser, -} from "../hydration"; import { StoreCollection } from "./Collection"; -class ClassCollection extends StoreCollection { +/** + * Generic class collection backed by store + */ +export class ClassCollection extends StoreCollection { readonly client: Client; constructor(client: Client) { @@ -29,333 +14,9 @@ class ClassCollection extends StoreCollection { } } -export class ChannelCollection extends ClassCollection< - Channel, - HydratedChannel -> { - /** - * Delete an object - * @param id Id - */ - override delete(id: string): void { - let channel = this.get(id); - channel?.server?.channelIds.delete(id); - super.delete(id); - } - - /** - * Fetch channel by ID - * @param id Id - * @returns Channel - */ - async fetch(id: string): Promise { - const channel = this.get(id); - if (channel) return channel; - const data = await this.client.api.get(`/channels/${id as ""}`); - return this.getOrCreate(data._id, data); - } - - /** - * Get or create - * @param id Id - * @param data Data - * @param isNew Whether this object is new - */ - getOrCreate(id: string, data: API.Channel, isNew = false) { - if (this.has(id)) { - return this.get(id)!; - } else { - const instance = new Channel(this, id); - this.create(id, "channel", instance, data); - isNew && this.client.emit("channelCreate", instance); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: string) { - if (this.has(id)) { - return this.get(id)!; - } else if (this.client.options.partials) { - const instance = new Channel(this, id); - this.create(id, "channel", instance, { - id, - partial: true, - }); - return instance; - } - } -} - -export class EmojiCollection extends ClassCollection { - /** - * Fetch emoji by ID - * @param id Id - * @returns Emoji - */ - async fetch(id: string): Promise { - const emoji = this.get(id); - if (emoji) return emoji; - const data = await this.client.api.get(`/custom/emoji/${id as ""}`); - return this.getOrCreate(data._id, data); - } - - /** - * Get or create - * @param id Id - * @param data Data - * @param isNew Whether this object is new - */ - getOrCreate(id: string, data: API.Emoji, isNew = false) { - if (this.has(id)) { - return this.get(id)!; - } else { - const instance = new Emoji(this, id); - this.create(id, "emoji", instance, data); - isNew && this.client.emit("emojiCreate", instance); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: string) { - if (this.has(id)) { - return this.get(id)!; - } else if (this.client.options.partials) { - const instance = new Emoji(this, id); - this.create(id, "emoji", instance, { - id, - }); - return instance; - } - } -} - -export class MessageCollection extends ClassCollection< - Message, - HydratedMessage -> { - /** - * Fetch message by Id - * @param channelId Channel Id - * @param messageId Message Id - * @returns Message - */ - async fetch(channelId: string, messageId: string): Promise { - const message = this.get(messageId); - if (message) return message; - - const data = await this.client.api.get( - `/channels/${channelId as ""}/messages/${messageId as ""}` - ); - - return this.getOrCreate(data._id, data, false); - } - - /** - * Get or create - * @param id Id - * @param data Data - * @param isNew Whether this object is new - */ - getOrCreate(id: string, data: API.Message, isNew = false) { - if (this.has(id)) { - return this.get(id)!; - } else { - const instance = new Message(this, id); - this.create(id, "message", instance, data); - isNew && this.client.emit("messageCreate", instance); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: string) { - if (this.has(id)) { - return this.get(id)!; - } else if (this.client.options.partials) { - const instance = new Message(this, id); - this.create(id, "message", instance, { - id, - partial: true, - }); - return instance; - } - } -} - -export class ServerCollection extends ClassCollection { - /** - * Fetch server by ID - * @param id Id - * @returns Server - */ - async fetch(id: string): Promise { - const server = this.get(id); - if (server) return server; - const data = await this.client.api.get(`/servers/${id as ""}`); - return this.getOrCreate(data._id, data); - } - - /** - * Get or create - * @param id Id - * @param data Data - * @param isNew Whether this object is new - */ - getOrCreate(id: string, data: API.Server, isNew = false) { - if (this.has(id)) { - return this.get(id)!; - } else { - const instance = new Server(this, id); - this.create(id, "server", instance, data); - isNew && this.client.emit("serverCreate", instance); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: string) { - if (this.has(id)) { - return this.get(id)!; - } else if (this.client.options.partials) { - const instance = new Server(this, id); - this.create(id, "server", instance, { - id, - partial: true, - }); - return instance; - } - } -} - -export class UserCollection extends ClassCollection { - /** - * Fetch user by ID - * @param id Id - * @returns User - */ - async fetch(id: string): Promise { - const user = this.get(id); - if (user) return user; - const data = await this.client.api.get(`/users/${id as ""}`); - return this.getOrCreate(data._id, data); - } - - /** - * Get or create - * @param id Id - * @param data Data - * @param isNew Whether this object is new - */ - getOrCreate(id: string, data: API.User) { - if (this.has(id)) { - return this.get(id)!; - } else { - const instance = new User(this, id); - this.create(id, "user", instance, data); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: string) { - if (this.has(id)) { - return this.get(id)!; - } else if (this.client.options.partials) { - const instance = new User(this, id); - this.create(id, "user", instance, { - id, - partial: true, - }); - return instance; - } - } -} - -export class ServerMemberCollection extends ClassCollection< - ServerMember, - HydratedServerMember -> { - /** - * Check if member exists by composite key - * @param id Id - * @returns Whether it exists - */ - hasByKey(id: API.MemberCompositeKey) { - return super.has(id.server + id.user); - } - - /** - * Get member by composite key - * @param id Id - * @returns Member - */ - getByKey(id: API.MemberCompositeKey) { - return super.get(id.server + id.user); - } - - /** - * Fetch server member by Id - * @param serverId Server Id - * @param userId User Id - * @returns Message - */ - async fetch(serverId: string, userId: string): Promise { - const member = this.get(userId); - if (member) return member; - - const data = await this.client.api.get( - `/servers/${serverId as ""}/members/${userId as ""}` - ); - - return this.getOrCreate(data._id, data); - } - - /** - * Get or create - * @param id Id - * @param data Data - */ - getOrCreate(id: API.MemberCompositeKey, data: API.Member) { - if (this.hasByKey(id)) { - return this.getByKey(id)!; - } else { - const instance = new ServerMember(this, id); - this.create(id.server + id.user, "serverMember", instance, data); - return instance; - } - } - - /** - * Get or return partial - * @param id Id - */ - getOrPartial(id: API.MemberCompositeKey) { - if (this.hasByKey(id)) { - return this.getByKey(id)!; - } else if (this.client.options.partials) { - const instance = new ServerMember(this, id); - this.create(id.server + id.user, "serverMember", instance, { - id, - partial: true, - }); - return instance; - } - } -} +export { ChannelCollection } from "./ChannelCollection"; +export { EmojiCollection } from "./EmojiCollection"; +export { MessageCollection } from "./MessageCollection"; +export { ServerCollection } from "./ServerCollection"; +export { ServerMemberCollection } from "./ServerMemberCollection"; +export { UserCollection } from "./UserCollection";