Skip to content

Commit 0e58825

Browse files
committed
refactor: base class, shallow clone, symbols
1 parent 480df0f commit 0e58825

File tree

4 files changed

+65
-29
lines changed

4 files changed

+65
-29
lines changed
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { data as kData } from './utils/symbols';
2+
3+
export abstract class Structure<DataType, Omitted extends keyof DataType | '' = ''> {
4+
protected [kData]: Readonly<Omit<DataType, Omitted>>;
5+
6+
protected constructor(data: Readonly<Omit<DataType, Omitted>>) {
7+
// Do not shallow clone data here as subclasses should do it (also allows them to set the constructor to public)
8+
this[kData] = data;
9+
}
10+
11+
/**
12+
* Update this structure with new data
13+
* @param data - A payload with updated data for this structure
14+
* @returns New structure with patched data
15+
*/
16+
public patch(data: Readonly<Partial<DataType>>): this {
17+
// @ts-expect-error TS cannot identify the type of this.constructor properly because subclasses
18+
return new this.constructor({ ...this.toJSON(), ...data }) as this;
19+
}
20+
21+
public toJSON(): DataType {
22+
// This will be DataType provided nothing is omitted, when omits occur, subclass needs to overwrite this.
23+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
24+
return { ...this[kData] } as DataType;
25+
}
26+
}
Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,76 +1,80 @@
11
import type { APIConnection } from 'discord-api-types/v10';
2+
import { Structure } from '../Structure';
3+
import { data as kData } from '../utils/symbols';
24

35
/**
46
* Represents a user's connection on Discord.
57
*/
6-
export class Connection {
8+
export class Connection extends Structure<APIConnection> {
79
public constructor(
810
/**
911
* The raw data received from the API for the connection
1012
*/
11-
protected raw: APIConnection,
12-
) {}
13+
data: APIConnection,
14+
) {
15+
super({ ...data });
16+
}
1317

1418
/**
1519
* The id of the connection account
1620
*/
1721
public get id() {
18-
return this.raw.id;
22+
return this[kData].id;
1923
}
2024

2125
/**
2226
* The username of the connection account
2327
*/
2428
public get name() {
25-
return this.raw.name;
29+
return this[kData].name;
2630
}
2731

2832
/**
2933
* The type of service this connection is for
3034
*/
3135
public get type() {
32-
return this.raw.type;
36+
return this[kData].type;
3337
}
3438

3539
/**
3640
* Whether the connection is revoked
3741
*/
3842
public get revoked() {
39-
return this.raw.revoked ?? false;
43+
return this[kData].revoked ?? false;
4044
}
4145

4246
/**
4347
* Any integrations associated with this connection
4448
*/
4549
public get integrations() {
46-
return this.raw.integrations ?? null;
50+
return this[kData].integrations ?? null;
4751
}
4852

4953
/**
5054
* Whether the connection is verified
5155
*/
5256
public get verified() {
53-
return this.raw.verified;
57+
return this[kData].verified;
5458
}
5559

5660
/**
5761
* Whether friend sync is enabled for this connection
5862
*/
5963
public get friendSync() {
60-
return this.raw.friend_sync;
64+
return this[kData].friend_sync;
6165
}
6266

6367
/**
6468
* Whether activities related to this connection are shown in the users presence
6569
*/
6670
public get showActivity() {
67-
return this.raw.show_activity;
71+
return this[kData].show_activity;
6872
}
6973

7074
/**
7175
* The visibilty state for this connection
7276
*/
7377
public get visibility() {
74-
return this.raw.visibility;
78+
return this[kData].visibility;
7579
}
7680
}

packages/structures/src/users/User.ts

Lines changed: 22 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,120 +1,125 @@
11
import { DiscordSnowflake } from '@sapphire/snowflake';
22
import type { APIUser, Snowflake } from 'discord-api-types/v10';
3+
import { Structure } from '../Structure';
4+
5+
import { data as kData } from '../utils/symbols';
36

47
/**
58
* Represents any user on Discord.
69
*/
7-
export class User {
10+
export class User extends Structure<APIUser> {
811
public constructor(
912
/**
1013
* The raw data received from the API for the user
1114
*/
12-
protected raw: APIUser,
13-
) {}
15+
data: APIUser,
16+
) {
17+
super({ ...data });
18+
}
1419

1520
/**
1621
* The user's id
1722
*/
1823
public get id(): Snowflake {
19-
return this.raw.id;
24+
return this[kData].id;
2025
}
2126

2227
/**
2328
* The username of the user
2429
*/
2530
public get username() {
26-
return this.raw.username;
31+
return this[kData].username;
2732
}
2833

2934
/**
3035
* The user's 4 digit tag, in combination with the username can uniquely identify the user
3136
*/
3237
public get discriminator() {
33-
return this.raw.discriminator;
38+
return this[kData].discriminator;
3439
}
3540

3641
/**
3742
* The user avatar's hash
3843
*/
3944
public get avatar() {
40-
return this.raw.avatar;
45+
return this[kData].avatar;
4146
}
4247

4348
/**
4449
* Whether the user is a bot
4550
*/
4651
public get bot() {
47-
return this.raw.bot ?? false;
52+
return this[kData].bot ?? false;
4853
}
4954

5055
/**
5156
* Whether the user is an Official Discord System user
5257
*/
5358
public get system() {
54-
return this.raw.system ?? false;
59+
return this[kData].system ?? false;
5560
}
5661

5762
/**
5863
* Whether the user has mfa enabled
5964
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
6065
*/
6166
public get mfaEnabled() {
62-
return this.raw.mfa_enabled;
67+
return this[kData].mfa_enabled;
6368
}
6469

6570
/**
6671
* The user's banner hash
6772
* <info>This property is only set when the user was manually fetched</info>
6873
*/
6974
public get banner() {
70-
return this.raw.banner;
75+
return this[kData].banner;
7176
}
7277

7378
/**
7479
* The base 10 accent color of the user's banner
7580
* <info>This property is only set when the user was manually fetched</info>
7681
*/
7782
public get accentColor() {
78-
return this.raw.accent_color;
83+
return this[kData].accent_color;
7984
}
8085

8186
/**
8287
* The user's primary discord language
8388
* <info>This property is only set when the user was fetched with an Oauth2 token and the `identify` scope</info>
8489
*/
8590
public get locale() {
86-
return this.raw.locale;
91+
return this[kData].locale;
8792
}
8893

8994
/**
9095
* Whether the email on the user's account has been verified
9196
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
9297
*/
9398
public get verified() {
94-
return this.raw.verified;
99+
return this[kData].verified;
95100
}
96101

97102
/**
98103
* The user's email
99104
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
100105
*/
101106
public get email() {
102-
return this.raw.email;
107+
return this[kData].email;
103108
}
104109

105110
/**
106111
* The type of nitro subscription on the user's account
107112
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
108113
*/
109114
public get premiumType() {
110-
return this.raw.premium_type;
115+
return this[kData].premium_type;
111116
}
112117

113118
/**
114119
* The flags for the user
115120
*/
116121
public get flags() {
117-
return this.raw.public_flags;
122+
return this[kData].public_flags;
118123
}
119124

120125
/**
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export const data = Symbol('structure:data');

0 commit comments

Comments
 (0)