From 02a541339d22c836adf7ed27a51d000817dfc149 Mon Sep 17 00:00:00 2001 From: Jersey Date: Fri, 14 Mar 2025 16:35:57 -0400 Subject: [PATCH 1/4] BREAKING CHANGE: remove solid.js dependency and redo collection interface --- .eslintrc.json | 3 +- .vscode/settings.json | 5 +- package.json | 5 +- src/Client.ts | 41 ++-- src/classes/Channel.ts | 33 ++- src/classes/ChannelWebhook.ts | 2 +- src/classes/MFA.ts | 30 ++- src/classes/PublicInvite.ts | 22 +- src/classes/Server.ts | 92 ++++---- src/classes/Session.ts | 2 +- src/classes/User.ts | 2 +- src/collections/BotCollection.ts | 14 +- src/collections/ChannelCollection.ts | 7 +- src/collections/ChannelUnreadCollection.ts | 20 +- src/collections/ChannelWebhookCollection.ts | 4 +- src/collections/Collection.ts | 225 ++++++++------------ src/collections/EmojiCollection.ts | 4 +- src/collections/MessageCollection.ts | 7 +- src/collections/ServerCollection.ts | 28 +-- src/collections/ServerMemberCollection.ts | 4 +- src/collections/SessionCollection.ts | 13 +- src/collections/UserCollection.ts | 4 +- src/events/EventClient.ts | 29 +-- src/events/v1.ts | 189 ++++++++-------- src/hydration/channel.ts | 13 +- src/hydration/channelUnread.ts | 8 +- src/hydration/message.ts | 11 +- src/hydration/server.ts | 16 +- src/storage/ObjectStorage.ts | 44 ---- 29 files changed, 348 insertions(+), 529 deletions(-) delete mode 100644 src/storage/ObjectStorage.ts diff --git a/.eslintrc.json b/.eslintrc.json index 589d74e4..77ffa33a 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,10 +1,9 @@ { "root": true, "parser": "@typescript-eslint/parser", - "plugins": ["solid", "spellcheck"], + "plugins": ["spellcheck"], "extends": [ "eslint:recommended", - "plugin:solid/typescript", "plugin:@typescript-eslint/recommended", "prettier" ], diff --git a/.vscode/settings.json b/.vscode/settings.json index 9bf4d12b..c4aecfc3 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -1,4 +1,7 @@ { "editor.defaultFormatter": "esbenp.prettier-vscode", - "editor.formatOnSave": true + "editor.formatOnSave": true, + "[typescript]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" + } } diff --git a/package.json b/package.json index 1bb75f60..8b692830 100644 --- a/package.json +++ b/package.json @@ -26,8 +26,6 @@ "description": "Library for interacting with the Revolt API.", "packageManager": "pnpm@9.4.0", "dependencies": { - "@solid-primitives/map": "^0.4.11", - "@solid-primitives/set": "^0.4.11", "eventemitter3": "^5.0.1", "isomorphic-ws": "^5.0.0", "long": "^5.2.3", @@ -46,7 +44,6 @@ "dotenv": "^16.4.5", "eslint": "^8.57.0", "eslint-config-prettier": "^8.10.0", - "eslint-plugin-solid": "^0.12.1", "eslint-plugin-spellcheck": "^0.0.20", "prettier": "^2.8.8", "tsc-watch": "^6.0.4", @@ -54,4 +51,4 @@ "typedoc": "^0.25.1", "typescript": "^5.4.2" } -} \ No newline at end of file +} diff --git a/src/Client.ts b/src/Client.ts index 994bdad1..b5d050b9 100644 --- a/src/Client.ts +++ b/src/Client.ts @@ -1,7 +1,5 @@ -import { Accessor, Setter, batch, createSignal } from "solid-js"; - import EventEmitter from "eventemitter3"; -import type { DataLogin, Error, RevoltConfig } from "revolt-api"; +import type { DataLogin, RevoltConfig } from "revolt-api"; import { API, Role } from "revolt-api"; import { @@ -180,11 +178,9 @@ export class Client extends EventEmitter { #session: Session | undefined; user: User | undefined; - readonly ready: Accessor; - #setReady: Setter; + ready = false; + connectionFailureCount = 0; - readonly connectionFailureCount: Accessor; - #setConnectionFailureCount: Setter; #reconnectTimeout: number | undefined; /** @@ -225,14 +221,6 @@ export class Client extends EventEmitter { baseURL: this.options.baseURL, }); - const [ready, setReady] = createSignal(false); - this.ready = ready; - this.#setReady = setReady; - - const [connectionFailureCount, setConnectionFailureCount] = createSignal(0); - this.connectionFailureCount = connectionFailureCount; - this.#setConnectionFailureCount = setConnectionFailureCount; - this.account = new AccountCollection(this); this.bots = new BotCollection(this); this.channels = new ChannelCollection(this); @@ -250,11 +238,9 @@ export class Client extends EventEmitter { this.events.on("state", (state) => { switch (state) { case ConnectionState.Connected: - batch(() => { - this.servers.forEach((server) => server.resetSyncStatus()); - this.#setConnectionFailureCount(0); - this.emit("connected"); - }); + this.servers.forEach((server) => server.resetSyncStatus()); + this.connectionFailureCount = 0; + this.emit("connected"); break; case ConnectionState.Connecting: this.emit("connecting"); @@ -264,18 +250,23 @@ export class Client extends EventEmitter { if (this.options.autoReconnect) { this.#reconnectTimeout = setTimeout( () => this.connect(), - this.options.retryDelayFunction(this.connectionFailureCount()) * - 1e3 + this.options.retryDelayFunction(this.connectionFailureCount) * 1e3 ) as never; - this.#setConnectionFailureCount((count) => count + 1); + this.connectionFailureCount += 1; } break; } }); this.events.on("event", (event) => - handleEventV1(this, event, this.#setReady) + handleEventV1( + this, + event, + ((value: boolean) => { + this.ready = value; + }).bind(this) + ) ); } @@ -301,7 +292,7 @@ export class Client extends EventEmitter { connect() { clearTimeout(this.#reconnectTimeout); this.events.disconnect(); - this.#setReady(false); + this.ready = false; this.events.connect( this.configuration?.ws ?? "wss://ws.revolt.chat", typeof this.#session === "string" ? this.#session : this.#session!.token diff --git a/src/classes/Channel.ts b/src/classes/Channel.ts index 02220ccc..2ddd8769 100644 --- a/src/classes/Channel.ts +++ b/src/classes/Channel.ts @@ -1,5 +1,3 @@ -import { batch } from "solid-js"; - import type { Member as ApiMember, Message as ApiMessage, @@ -381,10 +379,8 @@ export class Channel { `/channels/${this.id as ""}/members` ); - return batch(() => - members.map((user) => - this.#collection.client.users.getOrCreate(user._id, user) - ) + return members.map((user) => + this.#collection.client.users.getOrCreate(user._id, user) ); } @@ -398,10 +394,8 @@ export class Channel { `/channels/${this.id as ""}/webhooks` ); - return batch(() => - webhooks.map((webhook) => - this.#collection.client.channelWebhooks.getOrCreate(webhook.id, webhook) - ) + return webhooks.map((webhook) => + this.#collection.client.channelWebhooks.getOrCreate(webhook.id, webhook) ); } @@ -424,7 +418,7 @@ export class Channel { }); if (this.type === "DirectMessage") { - this.#collection.updateUnderlyingObject(this.id, "active", false); + this.#collection.setUnderlyingKey(this.id, "active", false); return; } @@ -549,7 +543,7 @@ export class Channel { { ...params, include_users: true } )) as { messages: ApiMessage[]; users: ApiUser[]; members?: ApiMember[] }; - return batch(() => ({ + return { messages: data.messages.map((message) => this.#collection.client.messages.getOrCreate(message._id, message) ), @@ -559,7 +553,7 @@ export class Channel { members: data.members?.map((member) => this.#collection.client.serverMembers.getOrCreate(member._id, member) ), - })); + }; } /** @@ -574,10 +568,8 @@ export class Channel { params )) as ApiMessage[]; - return batch(() => - messages.map((message) => - this.#collection.client.messages.getOrCreate(message._id, message) - ) + return messages.map((message) => + this.#collection.client.messages.getOrCreate(message._id, message) ); } @@ -596,7 +588,7 @@ export class Channel { } )) as { messages: ApiMessage[]; users: ApiUser[]; members?: ApiMember[] }; - return batch(() => ({ + return { messages: data.messages.map((message) => this.#collection.client.messages.getOrCreate(message._id, message) ), @@ -606,7 +598,7 @@ export class Channel { members: data.members?.map((member) => this.#collection.client.serverMembers.getOrCreate(member._id, member) ), - })); + }; } /** @@ -669,7 +661,8 @@ export class Channel { const unreads = this.#collection.client.channelUnreads; const channelUnread = unreads.get(this.id); if (channelUnread) { - unreads.updateUnderlyingObject(this.id, { + unreads.setUnderlyingObject(this.id, { + ...unreads.getUnderlyingObject(this.id), lastMessageId, }); diff --git a/src/classes/ChannelWebhook.ts b/src/classes/ChannelWebhook.ts index aa73fcf9..07b35a77 100644 --- a/src/classes/ChannelWebhook.ts +++ b/src/classes/ChannelWebhook.ts @@ -82,7 +82,7 @@ export class ChannelWebhook { data ); - this.#collection.updateUnderlyingObject( + this.#collection.setUnderlyingObject( this.id, // @ts-expect-error not in prod hydrate("channelWebhook", webhook, this.#collection.client) diff --git a/src/classes/MFA.ts b/src/classes/MFA.ts index 739c1e86..577e75c1 100644 --- a/src/classes/MFA.ts +++ b/src/classes/MFA.ts @@ -1,5 +1,3 @@ -import { SetStoreFunction, createStore } from "solid-js/store"; - import { MFAMethod, MFAResponse, @@ -14,7 +12,7 @@ import { Client } from "../index.js"; */ export class MFA { #client: Client; - #store: [MultiFactorStatus, SetStoreFunction]; + #store: MultiFactorStatus; /** * Construct MFA helper @@ -23,21 +21,30 @@ export class MFA { */ constructor(client: Client, state: MultiFactorStatus) { this.#client = client; - this.#store = createStore(state); + this.#store = state; + } + + /** + * Mutate the store + * @param key Key + * @param value Value + */ + #mutateStore(key: keyof MultiFactorStatus, value: boolean) { + this.#store[key] = value; } /** * Whether authenticator app is enabled */ get authenticatorEnabled() { - return this.#store[0].totp_mfa; + return this.#store.totp_mfa; } /** * Whether recovery codes are enabled */ get recoveryEnabled() { - return this.#store[0].recovery_active; + return this.#store.recovery_active; } /** @@ -59,7 +66,10 @@ export class MFA { createTicket(params: MFAResponse) { return this.#client.api .put("/auth/mfa/ticket", params) - .then((ticket) => new MFATicket(this.#client, ticket, this.#store[1])); + .then( + (ticket) => + new MFATicket(this.#client, ticket, this.#mutateStore.bind(this)) + ); } /** @@ -68,7 +78,7 @@ export class MFA { */ async enableAuthenticator(token: string) { await this.#client.api.put("/auth/mfa/totp", { totp_code: token }); - this.#store[1]("totp_mfa", true); + this.#mutateStore("totp_mfa", true); } } @@ -78,7 +88,7 @@ export class MFA { export class MFATicket { #client: Client; #ticket: TicketType; - #mutate: SetStoreFunction; + #mutate: (key: keyof MultiFactorStatus, value: boolean) => void; #used = false; /** @@ -90,7 +100,7 @@ export class MFATicket { constructor( client: Client, ticket: TicketType, - mutate: SetStoreFunction + mutate: (key: keyof MultiFactorStatus, value: boolean) => void ) { this.#client = client; this.#ticket = ticket; diff --git a/src/classes/PublicInvite.ts b/src/classes/PublicInvite.ts index 68444d87..cfbda196 100644 --- a/src/classes/PublicInvite.ts +++ b/src/classes/PublicInvite.ts @@ -1,5 +1,3 @@ -import { batch } from "solid-js"; - import { ServerFlags } from "../hydration/server.js"; import { API, Client, File } from "../index.js"; @@ -100,17 +98,15 @@ export class ServerPublicInvite extends PublicChannelInvite { const invite = await this.client!.api.post(`/invites/${this.code as ""}`); if (invite.type === "Server") { - return batch(() => { - for (const channel of invite.channels) { - this.client!.channels.getOrCreate(channel._id, channel); - } - - return this.client!.servers.getOrCreate( - invite.server._id, - invite.server, - true - ); - }); + for (const channel of invite.channels) { + this.client!.channels.getOrCreate(channel._id, channel); + } + + return this.client!.servers.getOrCreate( + invite.server._id, + invite.server, + true + ); } else { throw "unreachable"; } diff --git a/src/classes/Server.ts b/src/classes/Server.ts index 38f58a81..a17f6568 100644 --- a/src/classes/Server.ts +++ b/src/classes/Server.ts @@ -1,5 +1,3 @@ -import { batch } from "solid-js"; - import type { AllMemberResponse, BannedUser, @@ -375,7 +373,7 @@ export class Server { * @param data Changes */ async edit(data: DataEditServer) { - this.#collection.updateUnderlyingObject( + this.#collection.setUnderlyingObject( this.id, hydrate( "server", @@ -394,26 +392,22 @@ export class Server { * @param leaveEvent Whether we are leaving */ $delete(leaveEvent?: boolean) { - batch(() => { - const server = this.#collection.client.servers.getUnderlyingObject( - this.id - ); - - // Avoid race conditions - if (server.id) { - this.#collection.client.emit( - leaveEvent ? "serverLeave" : "serverDelete", - server - ); + const server = this.#collection.client.servers.getUnderlyingObject(this.id); - for (const channel of this.channelIds) { - this.#collection.client.channels.delete(channel); - } + // Avoid race conditions + if (server.id) { + this.#collection.client.emit( + leaveEvent ? "serverLeave" : "serverDelete", + server + ); - this.#collection.delete(this.id); + for (const channel of this.channelIds) { + this.#collection.client.channels.delete(channel); } - // TODO: delete members, emoji, etc - }); + + this.#collection.delete(this.id); + } + // TODO: delete members, emoji, etc } /** @@ -432,11 +426,9 @@ export class Server { * Mark a server as read */ async ack() { - batch(() => { - for (const channel of this.channels) { - channel.ack(undefined, false, true); - } - }); + for (const channel of this.channels) { + channel.ack(undefined, false, true); + } await this.#collection.client.api.put(`/servers/${this.id}/ack`); } @@ -603,31 +595,29 @@ export class Server { { exclude_offline: excludeOffline } ); - batch(() => { - 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] - ); + 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] + ); + } + } } /** @@ -647,14 +637,14 @@ export class Server { `/servers/${this.id as ""}/members` )) as AllMemberResponse; - return batch(() => ({ + return { members: data.members.map((member) => this.#collection.client.serverMembers.getOrCreate(member._id, member) ), users: data.users.map((user) => this.#collection.client.users.getOrCreate(user._id, user) ), - })); + }; } /** @@ -671,14 +661,14 @@ export class Server { )}` as never )) as AllMemberResponse; - return batch(() => ({ + return { members: data.members.map((member) => this.#collection.client.serverMembers.getOrCreate(member._id, member) ), users: data.users.map((user) => this.#collection.client.users.getOrCreate(user._id, user) ), - })); + }; } /** @@ -713,10 +703,8 @@ export class Server { `/servers/${this.id as ""}/emojis` ); - return batch(() => - emojis.map((emoji) => - this.#collection.client.emojis.getOrCreate(emoji._id, emoji) - ) + return emojis.map((emoji) => + this.#collection.client.emojis.getOrCreate(emoji._id, emoji) ); } diff --git a/src/classes/Session.ts b/src/classes/Session.ts index d0952ba1..6640fbe1 100644 --- a/src/classes/Session.ts +++ b/src/classes/Session.ts @@ -64,7 +64,7 @@ export class Session { friendly_name: name, }); - this.#collection.updateUnderlyingObject(this.id, "name", name); + this.#collection.setUnderlyingKey(this.id, "name", name); } /** diff --git a/src/classes/User.ts b/src/classes/User.ts index b664c910..6b17d3ca 100644 --- a/src/classes/User.ts +++ b/src/classes/User.ts @@ -249,7 +249,7 @@ export class User { if (dm) { if (!dm.active) { - this.#collection.client.channels.updateUnderlyingObject( + this.#collection.client.channels.setUnderlyingKey( dm.id, "active", true diff --git a/src/collections/BotCollection.ts b/src/collections/BotCollection.ts index 03296b18..b4eb4f2e 100644 --- a/src/collections/BotCollection.ts +++ b/src/collections/BotCollection.ts @@ -1,16 +1,14 @@ -import { batch } from "solid-js"; - import { OwnedBotsResponse } from "revolt-api"; import { HydratedBot } from "../hydration/bot.js"; import { API, Bot, PublicBot } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Bots */ -export class BotCollection extends ClassCollection { +export class BotCollection extends Collection { /** * Fetch bot by ID * @param id Id @@ -30,12 +28,8 @@ export class BotCollection extends ClassCollection { */ async fetchOwned(): Promise { const data = (await this.client.api.get("/bots/@me")) as OwnedBotsResponse; - return batch(() => { - data.users.forEach((user) => - this.client.users.getOrCreate(user._id, user) - ); - return data.bots.map((bot) => this.getOrCreate(bot._id, bot)); - }); + data.users.forEach((user) => this.client.users.getOrCreate(user._id, user)); + return data.bots.map((bot) => this.getOrCreate(bot._id, bot)); } /** diff --git a/src/collections/ChannelCollection.ts b/src/collections/ChannelCollection.ts index 9d4c6d57..ad0dc9dd 100644 --- a/src/collections/ChannelCollection.ts +++ b/src/collections/ChannelCollection.ts @@ -1,15 +1,12 @@ import { HydratedChannel } from "../hydration/index.js"; import { API, Channel, User } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Channels */ -export class ChannelCollection extends ClassCollection< - Channel, - HydratedChannel -> { +export class ChannelCollection extends Collection { /** * Delete an object * @param id Id diff --git a/src/collections/ChannelUnreadCollection.ts b/src/collections/ChannelUnreadCollection.ts index 7615b65d..5a9b4664 100644 --- a/src/collections/ChannelUnreadCollection.ts +++ b/src/collections/ChannelUnreadCollection.ts @@ -1,15 +1,13 @@ -import { batch } from "solid-js"; - import { ChannelUnread } from "../classes/ChannelUnread.js"; import { HydratedChannelUnread } from "../hydration/index.js"; import { API } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Channel Unreads */ -export class ChannelUnreadCollection extends ClassCollection< +export class ChannelUnreadCollection extends Collection< ChannelUnread, HydratedChannelUnread > { @@ -18,19 +16,19 @@ export class ChannelUnreadCollection extends ClassCollection< */ async sync() { const unreads = await this.client.api.get("/sync/unreads"); - batch(() => { - this.reset(); - for (const unread of unreads) { - this.getOrCreate(unread._id.channel, unread); - } - }); + this.reset(); + for (const unread of unreads) { + this.getOrCreate(unread._id.channel, unread); + } } /** * Clear all unread data */ reset() { - this.updateUnderlyingObject({}); + for (const key of this.keys()) { + this.setUnderlyingObject(key, {} as never); + } } /** diff --git a/src/collections/ChannelWebhookCollection.ts b/src/collections/ChannelWebhookCollection.ts index 2c49ee7f..112bd75b 100644 --- a/src/collections/ChannelWebhookCollection.ts +++ b/src/collections/ChannelWebhookCollection.ts @@ -2,12 +2,12 @@ import { ChannelWebhook } from "../classes/ChannelWebhook.js"; import { HydratedChannelWebhook } from "../hydration/channelWebhook.js"; import { API } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Channel Webhooks */ -export class ChannelWebhookCollection extends ClassCollection< +export class ChannelWebhookCollection extends Collection< ChannelWebhook, HydratedChannelWebhook > { diff --git a/src/collections/Collection.ts b/src/collections/Collection.ts index 83808f4e..2e60cd06 100644 --- a/src/collections/Collection.ts +++ b/src/collections/Collection.ts @@ -1,150 +1,66 @@ -import { SetStoreFunction } from "solid-js/store"; - -import { ReactiveMap } from "@solid-primitives/map"; - -import { Hydrators } from "../hydration/index.js"; -import { Client } from "../index.js"; -import { ObjectStorage } from "../storage/ObjectStorage.js"; +import { Client } from "../Client.js"; +import { Hydrators, hydrate } from "../hydration/index.js"; /** - * Abstract Collection type + * Collection backed by a store */ -export abstract class Collection { - /** - * Get an existing object - * @param id Id - * @returns Object - */ - abstract get(id: string): T | undefined; +export class Collection { + #storage = new Map(); + #objects = new Map(); /** - * Check whether an id exists in the Collection - * @param id Id - * @returns Whether it exists + * Construct store backed collection */ - abstract has(id: string): boolean; + constructor(public readonly client: Client) {} /** - * Delete an object + * Get an existing object * @param id Id */ - abstract delete(id: string): void; - - /** - * Number of stored objects - * @returns Size - */ - abstract size(): number; - - /** - * Iterable of keys in the map - * @returns Iterable - */ - abstract keys(): IterableIterator; - - /** - * Iterable of values in the map - * @returns Iterable - */ - abstract values(): IterableIterator; - - /** - * Iterable of key, value pairs in the map - * @returns Iterable - */ - abstract entries(): IterableIterator<[string, T]>; - - /** - * Execute a provided function over each key, value pair in the map - * @param cb Callback for each pair - */ - abstract forEach( - cb: (value: T, key: string, map: ReactiveMap) => void - ): void; - - /** - * List of values in the map - * @returns List - */ - toList() { - return [...this.values()]; + get(id: string): T | undefined { + return this.#objects.get(id); } /** - * Filter the collection by a given predicate - * @param predicate Predicate to satisfy + * Get an underlying object */ - filter(predicate: (value: T, key: string) => boolean): T[] { - const list: T[] = []; - for (const [key, value] of this.entries()) { - if (predicate(value, key)) { - list.push(value); - } - } - - return list; + getUnderlyingObject(id: string): V { + return this.#storage.get(id) ?? ({} as V); } /** - * Map the collection using a given callback - * @param cb Callback + * Set a key of an underlying object */ - map(cb: (value: T, key: string) => O): O[] { - const list: O[] = []; - for (const [key, value] of this.entries()) { - list.push(cb(value, key)); - } - - return list; + setUnderlyingKey(id: string, key: K, value: V[K]) { + this.#storage.set(id, { + [key]: value, + ...((this.#storage.get(id) ?? {}) as V), + }); } /** - * Find some value based on a predicate - * @param predicate Predicate to satisfy + * Set an underlying object */ - find(predicate: (value: T, key: string) => boolean): T | undefined { - for (const [key, value] of this.entries()) { - if (predicate(value, key)) { - return value; - } - } + setUnderlyingObject(id: string, value: V) { + this.#storage.set(id, value); } -} - -/** - * Collection backed by a Solid.js Store - */ -export abstract class StoreCollection extends Collection { - #storage = new ObjectStorage(); - #objects = new ReactiveMap(); - readonly getUnderlyingObject: (id: string) => V; - readonly updateUnderlyingObject: SetStoreFunction>; /** - * Construct store backed collection - */ - constructor() { - super(); - this.getUnderlyingObject = (key) => this.#storage.get(key) ?? ({} as V); - this.updateUnderlyingObject = this.#storage.set; - } - - /** - * Get an existing object + * Check whether an id exists in the Collection * @param id Id - * @returns Object + * @returns Whether it exists */ - get(id: string): T | undefined { - return this.#objects.get(id); + has(id: string): boolean { + return this.#objects.has(id); } /** - * Check whether an id exists in the Collection + * Check whether the underlying id exists * @param id Id * @returns Whether it exists */ - has(id: string) { - return this.#objects.has(id); + hasUnderlying(id: string): boolean { + return !!((this.#storage.get(id) as { id: string }) ?? { id: false }).id; } /** @@ -153,7 +69,7 @@ export abstract class StoreCollection extends Collection { */ delete(id: string): void { this.#objects.delete(id); - this.updateUnderlyingObject(id, undefined as never); + this.#storage.delete(id); } /** @@ -170,8 +86,13 @@ export abstract class StoreCollection extends Collection { instance: T, context: unknown, data?: unknown - ) { - this.#storage.hydrate(id, type, context, data); + ): void { + if (data) { + this.#storage.set( + id, + hydrate(type, { partial: false, ...data } as never, context, true) as V + ); + } this.#objects.set(id, instance); } @@ -181,14 +102,16 @@ export abstract class StoreCollection extends Collection { * @returns Whether it is a partial */ isPartial(id: string): boolean { - return !!(this.getUnderlyingObject(id) as { partial: boolean }).partial; + return !!( + (this.#storage.get(id) ?? { partial: true }) as { partial: boolean } + ).partial; } /** * Number of stored objects * @returns Size */ - size() { + size(): number { return this.#objects.size; } @@ -196,7 +119,7 @@ export abstract class StoreCollection extends Collection { * Iterable of keys in the map * @returns Iterable */ - keys() { + keys(): MapIterator { return this.#objects.keys(); } @@ -204,7 +127,7 @@ export abstract class StoreCollection extends Collection { * Iterable of values in the map * @returns Iterable */ - values() { + values(): MapIterator { return this.#objects.values(); } @@ -212,32 +135,64 @@ export abstract class StoreCollection extends Collection { * Iterable of key, value pairs in the map * @returns Iterable */ - entries() { + entries(): MapIterator<[string, T]> { return this.#objects.entries(); } /** * Execute a provided function over each key, value pair in the map * @param cb Callback for each pair - * @returns Iterable */ - forEach(cb: (value: T, key: string, map: ReactiveMap) => void) { + forEach(cb: (value: T, key: string, map: Map) => void): void { return this.#objects.forEach(cb); } -} -/** - * Generic class collection backed by store - */ -export class ClassCollection extends StoreCollection { - readonly client: Client; + /** + * List of values in the map + * @returns List + */ + toList(): T[] { + return [...this.values()]; + } + + /** + * Filter the collection by a given predicate + * @param predicate Predicate to satisfy + */ + filter(predicate: (value: T, key: string) => boolean): T[] { + const list: T[] = []; + for (const [key, value] of this.entries()) { + if (predicate(value, key)) { + list.push(value); + } + } + + return list; + } + + /** + * Map the collection using a given callback + * @param cb Callback + */ + map(cb: (value: T, key: string) => O): O[] { + const list: O[] = []; + for (const [key, value] of this.entries()) { + list.push(cb(value, key)); + } + + return list; + } /** - * Create generic class collection - * @param client Client + * Find some value based on a predicate + * @param predicate Predicate to satisfy */ - constructor(client: Client) { - super(); - this.client = client; + find(predicate: (value: T, key: string) => boolean): T | undefined { + for (const [key, value] of this.entries()) { + if (predicate(value, key)) { + return value; + } + } + return undefined; } } diff --git a/src/collections/EmojiCollection.ts b/src/collections/EmojiCollection.ts index 86f6efbb..b75329a5 100644 --- a/src/collections/EmojiCollection.ts +++ b/src/collections/EmojiCollection.ts @@ -1,12 +1,12 @@ import { HydratedEmoji } from "../hydration/index.js"; import { API, Emoji } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Emoji */ -export class EmojiCollection extends ClassCollection { +export class EmojiCollection extends Collection { /** * Fetch emoji by ID * @param id Id diff --git a/src/collections/MessageCollection.ts b/src/collections/MessageCollection.ts index 7bb9975c..ecab168e 100644 --- a/src/collections/MessageCollection.ts +++ b/src/collections/MessageCollection.ts @@ -1,15 +1,12 @@ import { HydratedMessage } from "../hydration"; import { API, Message } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Messages */ -export class MessageCollection extends ClassCollection< - Message, - HydratedMessage -> { +export class MessageCollection extends Collection { /** * Fetch message by Id * @param channelId Channel Id diff --git a/src/collections/ServerCollection.ts b/src/collections/ServerCollection.ts index 1496902c..52c2d9a8 100644 --- a/src/collections/ServerCollection.ts +++ b/src/collections/ServerCollection.ts @@ -1,16 +1,14 @@ -import { batch } from "solid-js"; - import { DataCreateServer } from "revolt-api"; import { HydratedServer } from "../hydration/index.js"; import { API, Server } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Servers */ -export class ServerCollection extends ClassCollection { +export class ServerCollection extends Collection { /** * Fetch server by ID * @@ -25,15 +23,13 @@ export class ServerCollection extends ClassCollection { include_channels: true, }); - return batch(() => { - for (const channel of data.channels as unknown as API.Channel[]) { - if (typeof channel !== "string") { - this.client.channels.getOrCreate(channel._id, channel); - } + for (const channel of data.channels as unknown as API.Channel[]) { + if (typeof channel !== "string") { + this.client.channels.getOrCreate(channel._id, channel); } + } - return this.getOrCreate(data._id, data); - }); + return this.getOrCreate(data._id, data); } /** @@ -81,12 +77,10 @@ export class ServerCollection extends ClassCollection { data ); - return batch(() => { - for (const channel of channels) { - this.client.channels.getOrCreate(channel._id, channel); - } + for (const channel of channels) { + this.client.channels.getOrCreate(channel._id, channel); + } - return this.getOrCreate(server._id, server, true); - }); + return this.getOrCreate(server._id, server, true); } } diff --git a/src/collections/ServerMemberCollection.ts b/src/collections/ServerMemberCollection.ts index 7461d15e..4db064c1 100644 --- a/src/collections/ServerMemberCollection.ts +++ b/src/collections/ServerMemberCollection.ts @@ -1,12 +1,12 @@ import { HydratedServerMember } from "../hydration/index.js"; import { API, ServerMember } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Server Members */ -export class ServerMemberCollection extends ClassCollection< +export class ServerMemberCollection extends Collection< ServerMember, HydratedServerMember > { diff --git a/src/collections/SessionCollection.ts b/src/collections/SessionCollection.ts index 60e04b91..71a4a327 100644 --- a/src/collections/SessionCollection.ts +++ b/src/collections/SessionCollection.ts @@ -1,27 +1,20 @@ -import { batch } from "solid-js"; - import { Session } from "../classes/index.js"; import { HydratedSession } from "../hydration/session.js"; import { API } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Sessions */ -export class SessionCollection extends ClassCollection< - Session, - HydratedSession -> { +export class SessionCollection extends Collection { /** * Fetch active sessions * @returns List of sessions */ async fetch(): Promise { const data = await this.client.api.get("/auth/session/all"); - return batch(() => - data.map((session) => this.getOrCreate(session._id, session)) - ); + return data.map((session) => this.getOrCreate(session._id, session)); } /** diff --git a/src/collections/UserCollection.ts b/src/collections/UserCollection.ts index a052eab2..1f0e10f6 100644 --- a/src/collections/UserCollection.ts +++ b/src/collections/UserCollection.ts @@ -1,12 +1,12 @@ import { HydratedUser } from "../hydration/index.js"; import { API, Client, User } from "../index.js"; -import { ClassCollection } from "./index.js"; +import { Collection } from "./index.js"; /** * Collection of Users */ -export class UserCollection extends ClassCollection { +export class UserCollection extends Collection { /** * Construct User collection */ diff --git a/src/events/EventClient.ts b/src/events/EventClient.ts index f3cbb887..5bb583c1 100644 --- a/src/events/EventClient.ts +++ b/src/events/EventClient.ts @@ -1,5 +1,3 @@ -import { Accessor, Setter, createSignal } from "solid-js"; - import EventEmitter from "eventemitter3"; import WebSocket from "isomorphic-ws"; import { Error } from "revolt-api"; @@ -65,11 +63,8 @@ export class EventClient extends EventEmitter< #protocolVersion: T; #transportFormat: "json" | "msgpack"; - readonly ping: Accessor; - #setPing: Setter; - - readonly state: Accessor; - #setStateSetter: Setter; + ping = -1; + state = ConnectionState.Idle; #socket: WebSocket | undefined; #heartbeatIntervalReference: number | undefined; @@ -103,14 +98,6 @@ export class EventClient extends EventEmitter< ...options, }; - const [state, setState] = createSignal(ConnectionState.Idle); - this.state = state; - this.#setStateSetter = setState; - - const [ping, setPing] = createSignal(-1); - this.ping = ping; - this.#setPing = setPing; - this.disconnect = this.disconnect.bind(this); } @@ -119,7 +106,7 @@ export class EventClient extends EventEmitter< * @param state state */ private setState(state: ConnectionState) { - this.#setStateSetter(state); + this.state = state; this.emit("state", state); } @@ -217,8 +204,8 @@ export class EventClient extends EventEmitter< return; case "Pong": clearTimeout(this.#pongTimeoutReference); - this.#setPing(+new Date() - event.data); - this.options.debug && console.debug(`[ping] ${this.ping()}ms`); + this.ping = +new Date() - event.data; + this.options.debug && console.debug(`[ping] ${this.ping}ms`); return; case "Error": this.#lastError = { @@ -230,7 +217,7 @@ export class EventClient extends EventEmitter< return; } - switch (this.state()) { + switch (this.state) { case ConnectionState.Connecting: if (event.type === "Authenticated") { // no-op @@ -249,9 +236,7 @@ export class EventClient extends EventEmitter< } break; default: - throw `Unreachable code. Received ${ - event.type - } in state ${this.state()}.`; + throw `Unreachable code. Received ${event.type} in state ${this.state}.`; } } diff --git a/src/events/v1.ts b/src/events/v1.ts index c0eb3e46..17a5925b 100644 --- a/src/events/v1.ts +++ b/src/events/v1.ts @@ -1,6 +1,3 @@ -import { Setter, batch } from "solid-js"; - -import { ReactiveSet } from "@solid-primitives/set"; import type { Channel, Emoji, @@ -188,7 +185,7 @@ type ReadyData = { export async function handleEvent( client: Client, event: ServerMessage, - setReady: Setter + setReady: (value: boolean) => void ) { if (client.options.debug) { console.debug("[S->C]", event); @@ -202,31 +199,29 @@ export async function handleEvent( break; } case "Ready": { - batch(() => { - for (const user of event.users) { - const u = client.users.getOrCreate(user._id, user); + for (const user of event.users) { + const u = client.users.getOrCreate(user._id, user); - if (u.relationship === "User") { - client.user = u; - } + if (u.relationship === "User") { + client.user = u; } + } - for (const server of event.servers) { - client.servers.getOrCreate(server._id, server); - } + for (const server of event.servers) { + client.servers.getOrCreate(server._id, server); + } - for (const member of event.members) { - client.serverMembers.getOrCreate(member._id, member); - } + for (const member of event.members) { + client.serverMembers.getOrCreate(member._id, member); + } - for (const channel of event.channels) { - client.channels.getOrCreate(channel._id, channel); - } + for (const channel of event.channels) { + client.channels.getOrCreate(channel._id, channel); + } - for (const emoji of event.emojis) { - client.emojis.getOrCreate(emoji._id, emoji); - } - }); + for (const emoji of event.emojis) { + client.emojis.getOrCreate(emoji._id, emoji); + } if (client.options.syncUnreads) { await client.channelUnreads.sync(); @@ -239,25 +234,23 @@ export async function handleEvent( } case "Message": { if (!client.messages.has(event._id)) { - batch(() => { - if (event.member) { - client.serverMembers.getOrCreate(event.member._id, event.member); - } + if (event.member) { + client.serverMembers.getOrCreate(event.member._id, event.member); + } - if (event.user) { - client.users.getOrCreate(event.user._id, event.user); - } + if (event.user) { + client.users.getOrCreate(event.user._id, event.user); + } - delete event.member; - delete event.user; + delete event.member; + delete event.user; - client.messages.getOrCreate(event._id, event, true); - client.channels.updateUnderlyingObject( - event.channel, - "lastMessageId", - event._id - ); - }); + client.messages.getOrCreate(event._id, event, true); + client.channels.setUnderlyingKey( + event.channel, + "lastMessageId", + event._id + ); } break; } @@ -269,7 +262,7 @@ export async function handleEvent( channelId: event.channel, }; - client.messages.updateUnderlyingObject(event.id, { + client.messages.setUnderlyingObject(event.id, { ...hydrate( "message", { ...event.data, channel: event.channel }, @@ -291,18 +284,14 @@ export async function handleEvent( channelId: event.channel, }; - client.messages.updateUnderlyingObject(event.id, "embeds", (embeds) => [ - ...(embeds ?? []), + client.messages.setUnderlyingKey(event.id, "embeds", [ + ...(previousMessage.embeds ?? []), ...(event.append.embeds?.map((embed) => MessageEmbed.from(client, embed) ) ?? []), ]); - client.messages.updateUnderlyingObject( - event.id, - "channelId", - event.channel - ); + client.messages.setUnderlyingKey(event.id, "channelId", event.channel); client.emit("messageUpdate", message, previousMessage); } @@ -317,22 +306,20 @@ export async function handleEvent( break; } case "BulkMessageDelete": { - batch(() => - client.emit( - "messageDeleteBulk", - event.ids - .map((id) => { - if (client.messages.has(id)) { - const message = client.messages.getUnderlyingObject(id); - client.messages.delete(id); - return message!; - } - - return undefined!; - }) - .filter((x) => x), - client.channels.get(event.channel) - ) + client.emit( + "messageDeleteBulk", + event.ids + .map((id) => { + if (client.messages.has(id)) { + const message = client.messages.getUnderlyingObject(id); + client.messages.delete(id); + return message!; + } + + return undefined!; + }) + .filter((x) => x), + client.channels.get(event.channel) ); break; } @@ -345,7 +332,7 @@ export async function handleEvent( if (set.has(event.user_id)) return; set.add(event.user_id); } else { - reactions.set(event.emoji_id, new ReactiveSet([event.user_id])); + reactions.set(event.emoji_id, new Set([event.user_id])); } client.emit( @@ -421,7 +408,7 @@ export async function handleEvent( } } - client.channels.updateUnderlyingObject(event.id, changes); + client.channels.setUnderlyingObject(event.id, changes); client.emit("channelUpdate", channel, previousChannel); } break; @@ -511,13 +498,11 @@ export async function handleEvent( } case "ServerCreate": { if (!client.servers.has(event.server._id)) { - batch(() => { - for (const channel of event.channels) { - client.channels.getOrCreate(channel._id, channel); - } + for (const channel of event.channels) { + client.channels.getOrCreate(channel._id, channel); + } - client.servers.getOrCreate(event.server._id, event.server, true); - }); + client.servers.getOrCreate(event.server._id, event.server, true); } break; } @@ -552,7 +537,7 @@ export async function handleEvent( } } - client.servers.updateUnderlyingObject(event.id, changes); + client.servers.setUnderlyingObject(event.id, changes); client.emit("serverUpdate", server, previousServer); } break; @@ -647,7 +632,7 @@ export async function handleEvent( } } - client.serverMembers.updateUnderlyingObject( + client.serverMembers.setUnderlyingObject( event.id.server + event.id.user, changes as never ); @@ -718,7 +703,7 @@ export async function handleEvent( } } - client.users.updateUnderlyingObject(event.id, changes as never); + client.users.setUnderlyingObject(event.id, changes as never); client.emit("userUpdate", user, previousUser); } break; @@ -756,37 +741,35 @@ export async function handleEvent( break; } case "UserPlatformWipe": { - batch(() => { - handleEvent( - client, - { - type: "BulkMessageDelete", - channel: "0", - ids: client.messages - .toList() - .filter((message) => message.authorId === event.user_id) - .map((message) => message.id), - }, - setReady - ); + handleEvent( + client, + { + type: "BulkMessageDelete", + channel: "0", + ids: client.messages + .toList() + .filter((message) => message.authorId === event.user_id) + .map((message) => message.id), + }, + setReady + ); - handleEvent( - client, - { - type: "UserUpdate", - id: event.user_id, - data: { - username: `Deleted User`, - online: false, - flags: event.flags, - badges: 0, - relationship: "None", - }, - clear: ["Avatar", "StatusPresence", "StatusText"], + handleEvent( + client, + { + type: "UserUpdate", + id: event.user_id, + data: { + username: `Deleted User`, + online: false, + flags: event.flags, + badges: 0, + relationship: "None", }, - setReady - ); - }); + clear: ["Avatar", "StatusPresence", "StatusText"], + }, + setReady + ); break; } diff --git a/src/hydration/channel.ts b/src/hydration/channel.ts index aef59c30..9528e324 100644 --- a/src/hydration/channel.ts +++ b/src/hydration/channel.ts @@ -1,4 +1,3 @@ -import { ReactiveSet } from "@solid-primitives/set"; import { Channel as ApiChannel, OverrideField } from "revolt-api"; import { Client, File } from "../index.js"; @@ -15,8 +14,8 @@ export type HydratedChannel = { icon?: File; active: boolean; - typingIds: ReactiveSet; - recipientIds: ReactiveSet; + typingIds: Set; + recipientIds: Set; userId?: string; ownerId?: string; @@ -49,8 +48,8 @@ export const channelHydration: Hydrate, HydratedChannel> = { description: (channel) => channel.description!, icon: (channel, ctx) => new File(ctx as Client, channel.icon!), active: (channel) => channel.active || false, - typingIds: () => new ReactiveSet(), - recipientIds: (channel) => new ReactiveSet(channel.recipients), + typingIds: () => new Set(), + recipientIds: (channel) => new Set(channel.recipients), userId: (channel) => channel.user, ownerId: (channel) => channel.owner, serverId: (channel) => channel.server, @@ -61,7 +60,7 @@ export const channelHydration: Hydrate, HydratedChannel> = { lastMessageId: (channel) => channel.last_message_id!, }, initialHydration: () => ({ - typingIds: new ReactiveSet(), - recipientIds: new ReactiveSet(), + typingIds: new Set(), + recipientIds: new Set(), }), }; diff --git a/src/hydration/channelUnread.ts b/src/hydration/channelUnread.ts index f293327e..1705d9eb 100644 --- a/src/hydration/channelUnread.ts +++ b/src/hydration/channelUnread.ts @@ -1,5 +1,3 @@ -import { ReactiveSet } from "@solid-primitives/set"; - import { API } from "../index.js"; import type { Merge } from "../lib/merge.js"; @@ -8,7 +6,7 @@ import { Hydrate } from "./index.js"; export type HydratedChannelUnread = { id: string; lastMessageId?: string; - messageMentionIds: ReactiveSet; + messageMentionIds: Set; }; export const channelUnreadHydration: Hydrate< @@ -23,9 +21,9 @@ export const channelUnreadHydration: Hydrate< functions: { id: (unread) => unread._id.channel, lastMessageId: (unread) => unread.last_id!, - messageMentionIds: (unread) => new ReactiveSet(unread.mentions!), + messageMentionIds: (unread) => new Set(unread.mentions!), }, initialHydration: () => ({ - messageMentionIds: new ReactiveSet(), + messageMentionIds: new Set(), }), }; diff --git a/src/hydration/message.ts b/src/hydration/message.ts index a75ed487..cb1e8c02 100644 --- a/src/hydration/message.ts +++ b/src/hydration/message.ts @@ -1,6 +1,3 @@ -import { ReactiveMap } from "@solid-primitives/map"; -import { ReactiveSet } from "@solid-primitives/set"; - import { API, Client, @@ -26,7 +23,7 @@ export type HydratedMessage = { embeds?: MessageEmbed[]; mentionIds?: string[]; replyIds?: string[]; - reactions: ReactiveMap>; + reactions: Map>; interactions?: API.Interactions; masquerade?: API.Masquerade; flags?: number; @@ -62,10 +59,10 @@ export const messageHydration: Hydrate, HydratedMessage> = { mentionIds: (message) => message.mentions!, replyIds: (message) => message.replies!, reactions: (message) => { - const map = new ReactiveMap>(); + const map = new Map>(); if (message.reactions) { for (const reaction of Object.keys(message.reactions)) { - map.set(reaction, new ReactiveSet(message.reactions![reaction])); + map.set(reaction, new Set(message.reactions![reaction])); } } return map; @@ -75,6 +72,6 @@ export const messageHydration: Hydrate, HydratedMessage> = { flags: (message) => message.flags!, }, initialHydration: () => ({ - reactions: new ReactiveMap(), + reactions: new Map(), }), }; diff --git a/src/hydration/server.ts b/src/hydration/server.ts index f47e0be9..cdb6f811 100644 --- a/src/hydration/server.ts +++ b/src/hydration/server.ts @@ -1,5 +1,3 @@ -import { ReactiveMap } from "@solid-primitives/map"; -import { ReactiveSet } from "@solid-primitives/set"; import { Server as ApiServer, Category, @@ -21,11 +19,11 @@ export type HydratedServer = { icon?: File; banner?: File; - channelIds: ReactiveSet; + channelIds: Set; categories?: Category[]; systemMessages?: SystemMessageChannels; - roles: ReactiveMap; + roles: Map; defaultPermissions: number; flags: ServerFlags; @@ -47,13 +45,11 @@ export const serverHydration: Hydrate = { ownerId: (server) => server.owner, name: (server) => server.name, description: (server) => server.description!, - channelIds: (server) => new ReactiveSet(server.channels), + channelIds: (server) => new Set(server.channels), categories: (server) => server.categories ?? [], systemMessages: (server) => server.system_messages ?? {}, roles: (server) => - new ReactiveMap( - Object.keys(server.roles!).map((id) => [id, server.roles![id]]) - ), + new Map(Object.keys(server.roles!).map((id) => [id, server.roles![id]])), defaultPermissions: (server) => server.default_permissions, icon: (server, ctx) => new File(ctx as Client, server.icon!), banner: (server, ctx) => new File(ctx as Client, server.banner!), @@ -63,8 +59,8 @@ export const serverHydration: Hydrate = { nsfw: (server) => server.nsfw || false, }, initialHydration: () => ({ - channelIds: new ReactiveSet(), - roles: new ReactiveMap(), + channelIds: new Set(), + roles: new Map(), }), }; diff --git a/src/storage/ObjectStorage.ts b/src/storage/ObjectStorage.ts deleted file mode 100644 index 458b50c3..00000000 --- a/src/storage/ObjectStorage.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { SetStoreFunction, createStore } from "solid-js/store"; - -import { Hydrators, hydrate } from "../hydration/index.js"; - -/** - * Wrapper around Solid.js store - */ -export class ObjectStorage { - private store: Record; - readonly set: SetStoreFunction>; - - /** - * Create new object storage - */ - constructor() { - const [store, setStore] = createStore({}); - this.store = store as never; - this.set = setStore; - this.get = this.get.bind(this); - } - - /** - * Get object by ID - * @param id ID - * @returns Object - */ - get(id: string) { - return this.store[id]; - } - - /** - * Hydrate some data into storage - * @param id ID - * @param type Hydration type - * @param context Context - * @param data Input Data - */ - hydrate(id: string, type: keyof Hydrators, context: unknown, data?: unknown) { - if (data) { - data = { partial: false, ...data }; - this.set(id, hydrate(type, data as never, context, true) as T); - } - } -} From 78e736795e2fb5441db5a7fdaf5c7acb793c8326 Mon Sep 17 00:00:00 2001 From: William Horning Date: Fri, 14 Mar 2025 16:44:14 -0400 Subject: [PATCH 2/4] remove solid.js from package.json --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index 8b692830..92688fa7 100644 --- a/package.json +++ b/package.json @@ -30,7 +30,6 @@ "isomorphic-ws": "^5.0.0", "long": "^5.2.3", "revolt-api": "0.8.3", - "solid-js": "^1.8.15", "ulid": "^2.3.0", "ws": "^8.16.0" }, From 6738be5d9a95fa5532ce7cf40224c5de4c005ca8 Mon Sep 17 00:00:00 2001 From: Jersey Date: Sun, 23 Mar 2025 16:03:31 -0400 Subject: [PATCH 3/4] fix lockfile --- pnpm-lock.yaml | 137 ------------------------------------------------- 1 file changed, 137 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b56ebcad..6ad0f638 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,21 +8,12 @@ importers: .: dependencies: - '@solid-primitives/map': - specifier: ^0.6.0 - version: 0.6.0(solid-js@1.9.5) - '@solid-primitives/set': - specifier: ^0.6.0 - version: 0.6.0(solid-js@1.9.5) '@vladfrangu/async_event_emitter': specifier: ^2.4.6 version: 2.4.6 revolt-api: specifier: 0.8.3 version: 0.8.3 - solid-js: - specifier: ^1.9.5 - version: 1.9.5 ulid: specifier: ^2.3.0 version: 2.3.0 @@ -42,9 +33,6 @@ importers: eslint-plugin-prettier: specifier: ^5.2.3 version: 5.2.3(eslint-config-prettier@8.10.0(eslint@9.22.0))(eslint@9.22.0)(prettier@3.5.3) - eslint-plugin-solid: - specifier: ^0.14.5 - version: 0.14.5(eslint@9.22.0)(typescript@5.8.2) prettier: specifier: ^3.5.3 version: 3.5.3 @@ -203,26 +191,6 @@ packages: '@shikijs/vscode-textmate@10.0.2': resolution: {integrity: sha512-83yeghZ2xxin3Nj8z1NMd/NCuca+gsYXswywDy5bHvwlWL8tpTQmzGeUuHd9FC3E/SBEMvzJRwWEOz5gGes9Qg==} - '@solid-primitives/map@0.6.0': - resolution: {integrity: sha512-h8uCJNxUTvzNK/aTW9vJCd/PQeBkUL8i7AyLPvTFqMgcMnJ1I5GzAi5JODzxpxQwffxoqJyQtOE1vBqFzDv0Vw==} - peerDependencies: - solid-js: ^1.6.12 - - '@solid-primitives/set@0.6.0': - resolution: {integrity: sha512-P1Tp001m8ib5XCi/LEJHh2QsoS2uPO86HewtbrSxr2axt5te9EGc0UOwNKTPxNvNSLNHteUw5IrzDsEklW4m3g==} - peerDependencies: - solid-js: ^1.6.12 - - '@solid-primitives/trigger@1.2.0': - resolution: {integrity: sha512-sW4/3cDXSjYQampn8CIFZ11BlxgNf2li8r2fXnb3b3YWE6RdZZCl8PhvpPF38Gzl0CnryrbTPJWM7OIkseCDgQ==} - peerDependencies: - solid-js: ^1.6.12 - - '@solid-primitives/utils@6.3.0': - resolution: {integrity: sha512-e7hTlJ1Ywh2+g/Qug+n4L1mpfxsikoIS4/sHE2EK9WatQt8UJqop/vE6bsLnXlU1xuhb/jo94Ah5Y27rd4wP7A==} - peerDependencies: - solid-js: ^1.6.12 - '@trivago/prettier-plugin-sort-imports@5.2.2': resolution: {integrity: sha512-fYDQA9e6yTNmA13TLVSA+WMQRc5Bn/c0EUBditUHNfMMxN7M82c38b1kEggVE3pLpZ0FwkwJkUEKMiOi52JXFA==} engines: {node: '>18.12'} @@ -363,9 +331,6 @@ packages: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} - csstype@3.1.3: - resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - debug@4.4.0: resolution: {integrity: sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==} engines: {node: '>=6.0'} @@ -406,13 +371,6 @@ packages: eslint-config-prettier: optional: true - eslint-plugin-solid@0.14.5: - resolution: {integrity: sha512-nfuYK09ah5aJG/oEN6P1qziy1zLgW4PDWe75VNPi4CEFYk1x2AEqwFeQfEPR7gNn0F2jOeqKhx2E+5oNCOBYWQ==} - engines: {node: '>=18.0.0'} - peerDependencies: - eslint: ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 - typescript: '>=4.8.4' - eslint-scope@8.3.0: resolution: {integrity: sha512-pUNxi75F8MJ/GdeKtVLSbYg4ZI34J6C0C7sbL4YOp2exGwen7ZsuBqKzUhXd0qMQ362yET3z+uPwKeg/0C2XCQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -525,10 +483,6 @@ packages: resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} engines: {node: '>=8'} - html-tags@3.3.1: - resolution: {integrity: sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==} - engines: {node: '>=8'} - ignore@5.3.2: resolution: {integrity: sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==} engines: {node: '>= 4'} @@ -541,9 +495,6 @@ packages: resolution: {integrity: sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==} engines: {node: '>=0.8.19'} - inline-style-parser@0.2.4: - resolution: {integrity: sha512-0aO8FkhNZlj/ZIbNi7Lxxr12obT7cL1moPfE4tg1LkX7LlLfC6DeX4l2ZEud1ukP9jNQyNnfzQVqwbwmAATY4Q==} - is-extglob@2.1.1: resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} engines: {node: '>=0.10.0'} @@ -552,10 +503,6 @@ packages: resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} engines: {node: '>=0.10.0'} - is-html@2.0.0: - resolution: {integrity: sha512-S+OpgB5i7wzIue/YSE5hg0e5ZYfG3hhpNh9KGl6ayJ38p7ED6wxQLd1TV91xHpcTvw90KMJ9EwN3F/iNflHBVg==} - engines: {node: '>=8'} - is-number@7.0.0: resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} engines: {node: '>=0.12.0'} @@ -587,15 +534,9 @@ packages: json-stable-stringify-without-jsonify@1.0.1: resolution: {integrity: sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==} - kebab-case@1.0.2: - resolution: {integrity: sha512-7n6wXq4gNgBELfDCpzKc+mRrZFs7D+wgfF5WRFLNAr4DA/qtr9Js8uOAVAfHhuLMfAcQ0pRKqbpjx+TcJVdE1Q==} - keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} - known-css-properties@0.30.0: - resolution: {integrity: sha512-VSWXYUnsPu9+WYKkfmJyLKtIvaRJi1kXUqVmBACORXZQxT5oZDsoZ2vQP+bQFDnWtpI/4eq3MLoRMjI2fnLzTQ==} - levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -721,16 +662,6 @@ packages: engines: {node: '>=10'} hasBin: true - seroval-plugins@1.2.1: - resolution: {integrity: sha512-H5vs53+39+x4Udwp4J5rNZfgFuA+Lt+uU+09w1gYBVWomtAl98B+E9w7yC05Xc81/HgLvJdlyqJbU0fJCKCmdw==} - engines: {node: '>=10'} - peerDependencies: - seroval: ^1.0 - - seroval@1.2.1: - resolution: {integrity: sha512-yBxFFs3zmkvKNmR0pFSU//rIsYjuX418TnlDmc2weaq5XFDqDIV/NOMPBoLrbxjLH42p4UzRuXHryXh9dYcKcw==} - engines: {node: '>=10'} - shebang-command@2.0.0: resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} engines: {node: '>=8'} @@ -739,16 +670,10 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} - solid-js@1.9.5: - resolution: {integrity: sha512-ogI3DaFcyn6UhYhrgcyRAMbu/buBJitYQASZz5WzfQVPP10RD2AbCoRZ517psnezrasyCbWzIxZ6kVqet768xw==} - strip-json-comments@3.1.1: resolution: {integrity: sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==} engines: {node: '>=8'} - style-to-object@1.0.8: - resolution: {integrity: sha512-xT47I/Eo0rwJmaXC4oilDGDWLohVhR6o/xAQcPQN8q6QBuZVL8qMYL85kLmST5cPjAorwvqIA4qXTRQoYHaL6g==} - supports-color@7.2.0: resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} engines: {node: '>=8'} @@ -981,25 +906,6 @@ snapshots: '@shikijs/vscode-textmate@10.0.2': {} - '@solid-primitives/map@0.6.0(solid-js@1.9.5)': - dependencies: - '@solid-primitives/trigger': 1.2.0(solid-js@1.9.5) - solid-js: 1.9.5 - - '@solid-primitives/set@0.6.0(solid-js@1.9.5)': - dependencies: - '@solid-primitives/trigger': 1.2.0(solid-js@1.9.5) - solid-js: 1.9.5 - - '@solid-primitives/trigger@1.2.0(solid-js@1.9.5)': - dependencies: - '@solid-primitives/utils': 6.3.0(solid-js@1.9.5) - solid-js: 1.9.5 - - '@solid-primitives/utils@6.3.0(solid-js@1.9.5)': - dependencies: - solid-js: 1.9.5 - '@trivago/prettier-plugin-sort-imports@5.2.2(prettier@3.5.3)': dependencies: '@babel/generator': 7.26.10 @@ -1166,8 +1072,6 @@ snapshots: shebang-command: 2.0.0 which: 2.0.2 - csstype@3.1.3: {} - debug@4.4.0: dependencies: ms: 2.1.3 @@ -1192,19 +1096,6 @@ snapshots: optionalDependencies: eslint-config-prettier: 8.10.0(eslint@9.22.0) - eslint-plugin-solid@0.14.5(eslint@9.22.0)(typescript@5.8.2): - dependencies: - '@typescript-eslint/utils': 8.26.1(eslint@9.22.0)(typescript@5.8.2) - eslint: 9.22.0 - estraverse: 5.3.0 - is-html: 2.0.0 - kebab-case: 1.0.2 - known-css-properties: 0.30.0 - style-to-object: 1.0.8 - typescript: 5.8.2 - transitivePeerDependencies: - - supports-color - eslint-scope@8.3.0: dependencies: esrecurse: 4.3.0 @@ -1330,8 +1221,6 @@ snapshots: has-flag@4.0.0: {} - html-tags@3.3.1: {} - ignore@5.3.2: {} import-fresh@3.3.1: @@ -1341,18 +1230,12 @@ snapshots: imurmurhash@0.1.4: {} - inline-style-parser@0.2.4: {} - is-extglob@2.1.1: {} is-glob@4.0.3: dependencies: is-extglob: 2.1.1 - is-html@2.0.0: - dependencies: - html-tags: 3.3.1 - is-number@7.0.0: {} isexe@2.0.0: {} @@ -1373,14 +1256,10 @@ snapshots: json-stable-stringify-without-jsonify@1.0.1: {} - kebab-case@1.0.2: {} - keyv@4.5.4: dependencies: json-buffer: 3.0.1 - known-css-properties@0.30.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -1492,30 +1371,14 @@ snapshots: semver@7.7.1: {} - seroval-plugins@1.2.1(seroval@1.2.1): - dependencies: - seroval: 1.2.1 - - seroval@1.2.1: {} - shebang-command@2.0.0: dependencies: shebang-regex: 3.0.0 shebang-regex@3.0.0: {} - solid-js@1.9.5: - dependencies: - csstype: 3.1.3 - seroval: 1.2.1 - seroval-plugins: 1.2.1(seroval@1.2.1) - strip-json-comments@3.1.1: {} - style-to-object@1.0.8: - dependencies: - inline-style-parser: 0.2.4 - supports-color@7.2.0: dependencies: has-flag: 4.0.0 From a3540711f4c0bfce544e418862bb36d16f69a40c Mon Sep 17 00:00:00 2001 From: Jersey Date: Sun, 23 Mar 2025 19:11:23 -0400 Subject: [PATCH 4/4] quick little fix --- src/events/v1.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/events/v1.ts b/src/events/v1.ts index f3aba55b..86eed30c 100644 --- a/src/events/v1.ts +++ b/src/events/v1.ts @@ -266,7 +266,11 @@ export async function handleEvent( client.messages.setUnderlyingObject(event.id, { ...hydrate( "message", - { ...event.data, channel: event.channel }, + { + ...previousMessage, + ...event.data, + channel: event.channel, + } as typeof event.data, client, false, ),