Skip to content

Commit

Permalink
feat: handle cases of unknown component types better
Browse files Browse the repository at this point in the history
  • Loading branch information
suneettipirneni committed Mar 6, 2022
1 parent f202d9a commit 2d9d1d5
Show file tree
Hide file tree
Showing 4 changed files with 33 additions and 7 deletions.
4 changes: 0 additions & 4 deletions packages/builders/__tests__/components/actionRow.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -81,8 +81,6 @@ describe('Action Row Components', () => {
expect(new ActionRowBuilder(actionRowData).toJSON()).toEqual(actionRowData);
expect(new ActionRowBuilder().toJSON()).toEqual({ type: ComponentType.ActionRow, components: [] });
expect(() => createComponentBuilder({ type: ComponentType.ActionRow, components: [] })).not.toThrowError();
// @ts-expect-error
expect(() => createComponentBuilder({ type: 42, components: [] })).toThrowError();
});
test('GIVEN valid builder options THEN valid JSON output is given', () => {
const rowWithButtonData: APIActionRowComponent<APIMessageActionRowComponent> = {
Expand Down Expand Up @@ -123,8 +121,6 @@ describe('Action Row Components', () => {
expect(new ActionRowBuilder(rowWithSelectMenuData).toJSON()).toEqual(rowWithSelectMenuData);
expect(new ActionRowBuilder().toJSON()).toEqual({ type: ComponentType.ActionRow, components: [] });
expect(() => createComponentBuilder({ type: ComponentType.ActionRow, components: [] })).not.toThrowError();
// @ts-expect-error
expect(() => createComponentBuilder({ type: 42, components: [] })).toThrowError();
});
test('GIVEN valid builder options THEN valid JSON output is given', () => {
const button = new ButtonBuilder().setLabel('test').setStyle(ButtonStyle.Primary).setCustomId('123');
Expand Down
8 changes: 6 additions & 2 deletions packages/builders/src/components/Components.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { APIBaseComponent, APIMessageComponent, APIModalComponent, ComponentType } from 'discord-api-types/v9';
import { APIMessageComponent, APIModalComponent, ComponentType } from 'discord-api-types/v9';
import { ActionRowBuilder, ButtonBuilder, ComponentBuilder, SelectMenuBuilder, TextInputBuilder } from '../index';
import type { MessageComponentBuilder, ModalComponentBuilder } from './ActionRow';
import { UnknownComponentBuilder } from './UnknownComponent';

export interface MappedComponentTypes {
[ComponentType.ActionRow]: ActionRowBuilder;
Expand Down Expand Up @@ -34,6 +35,9 @@ export function createComponentBuilder(
case ComponentType.TextInput:
return new TextInputBuilder(data);
default:
throw new Error(`Cannot serialize component type: ${(data as APIBaseComponent<ComponentType>).type}`);
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
console.warn(`Cannot properly serialize component type: ${data.type}`);
return new UnknownComponentBuilder(data);
}
}
23 changes: 23 additions & 0 deletions packages/builders/src/components/UnknownComponent.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
import type {
APIActionRowComponent,
APIMessageActionRowComponent,
APITextInputComponent,
APIActionRowComponentTypes,
} from 'discord-api-types/v9';
import { ComponentBuilder } from './Component';

/**
* This class is simply a class provided to match any future components that
* may not be implemented in builders. This future-proofs by not throwing an error anytime an unknown
* component type is encountered.
*/
export class UnknownComponentBuilder extends ComponentBuilder {
public toJSON():
| APIActionRowComponent<APIMessageActionRowComponent | APITextInputComponent>
| APIActionRowComponentTypes {
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
return { ...this.data } as
| APIActionRowComponent<APIMessageActionRowComponent | APITextInputComponent>
| APIActionRowComponentTypes;
}
}
5 changes: 4 additions & 1 deletion packages/discord.js/src/util/Components.js
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,10 @@ class Components extends null {
case ComponentType.SelectMenu:
return new SelectMenuComponent(data);
default:
throw new Error(`Found unknown component type: ${data.type}`);
// This is done for future-proofing purposes to prevent
// crashes when unknown component types are found.
console.warn(`Found unknown component type: ${data.type}`);
return new Component(data);
}
}
}
Expand Down

0 comments on commit 2d9d1d5

Please sign in to comment.