Skip to content

Commit 37ac617

Browse files
committed
docs: better docs for what's done so far
1 parent 06cfb1d commit 37ac617

File tree

5 files changed

+116
-22
lines changed

5 files changed

+116
-22
lines changed

packages/structures/src/Structure.ts

Lines changed: 56 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,23 @@
1+
/* eslint-disable jsdoc/check-param-names */
12
import { kData } from './utils/symbols.js';
23
import type { ReplaceOmittedWithUnknown } from './utils/types.js';
34

45
/**
6+
* Additional options needed to appropriately construct / patch data
7+
*
8+
* @internal
9+
*/
10+
export interface StructureExtraOptions {
11+
/**
12+
* The template used to remove unwanted properties from raw data storage
13+
*/
14+
template?: {};
15+
}
16+
17+
/**
18+
* Represents a data model from the Discord API
19+
*
20+
* @privateRemarks
521
* Explanation of the type complexity surround Structure:
622
*
723
* There are two layers of Omitted generics, one here, which allows omitting things at the library level so we do not accidentally
@@ -12,26 +28,61 @@ import type { ReplaceOmittedWithUnknown } from './utils/types.js';
1228
* In order to safely set and access this data, the constructor and patch take data as "partial" and forcibly assigns it to kData. To acommodate this,
1329
* kData stores properties as `unknown` when it is omitted, which allows accessing the property in getters even when it may not actually be present.
1430
* This is the most technically correct way of represnting the value, especially since there is no way to guarantee runtime matches the "type cast."
15-
*
16-
* @internal
1731
*/
18-
1932
export abstract class Structure<DataType, Omitted extends keyof DataType | '' = ''> {
33+
/**
34+
* The raw data from the API for this struture
35+
*
36+
* @internal
37+
*/
2038
protected [kData]: Readonly<ReplaceOmittedWithUnknown<Omitted, DataType>>;
2139

22-
protected constructor(data: Readonly<Partial<DataType>>, { template }: { template?: {} } = {}) {
40+
/**
41+
* Creates a new structure to represent API data
42+
*
43+
* @param data - the data from the API that this structure will represent
44+
* @param extraOptions - any additional options needed to appropriately construct a structure from the data
45+
* @internal
46+
*/
47+
protected constructor(data: Readonly<Partial<DataType>>, { template }: StructureExtraOptions = {}) {
2348
this[kData] = Object.assign(template ? Object.create(template) : {}, data);
2449
this._optimizeData(data);
2550
}
2651

27-
protected _patch(data: Readonly<Partial<DataType>>, { template }: { template?: {} } = {}): this {
52+
/**
53+
* Patches the raw data of this object in place
54+
*
55+
* @param data - the updated data from the API to patch with
56+
* @param extraOptions - any additional options needed to appropriately patch the data
57+
* @returns this
58+
* @internal
59+
*/
60+
protected _patch(data: Readonly<Partial<DataType>>, { template }: StructureExtraOptions = {}): this {
2861
this[kData] = Object.assign(template ? Object.create(template) : {}, this[kData], data);
2962
this._optimizeData(data);
3063
return this;
3164
}
3265

66+
/**
67+
* Function called to ensure stored raw data is in optimized formats, used in tandem with a data template
68+
*
69+
* @example created_timestamp is an ISO string, this can be stored in optimized form as a number
70+
* @param _data - the raw data received from the API to optimize
71+
* @remarks Implementation to be done in subclasses where needed
72+
* @virtual
73+
* @internal
74+
*/
3375
protected _optimizeData(_data: Partial<DataType>) {}
3476

77+
/**
78+
* Transforms this object to its JSON format with raw API data (or close to it),
79+
* automatically called by `JSON.stringify()` when this structure is stringified
80+
*
81+
* @remarks
82+
* The type of this data is determined by omissions at runtime and is only guaranteed for default omissions
83+
* @privateRemarks
84+
* When omitting properties at the library level, this must be overriden to re-add those properties
85+
*/
3586
public toJSON(): DataType {
3687
// This will be DataType provided nothing is omitted, when omits occur, subclass needs to overwrite this.
3788
return { ...this[kData] } as DataType;

packages/structures/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
1+
export * from './invites/index.js';
12
export * from './users/index.js';
23
export * from './Structure.js';

packages/structures/src/invites/Invite.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,12 @@ import { type APIInvite, type APIExtendedInvite, RouteBases } from 'discord-api-
22
import { Structure } from '../Structure.js';
33
import { kData, kExpiresTimestamp, kCreatedTimestamp } from '../utils/symbols.js';
44

5+
/**
6+
* Represents an invitation to a discord channel
7+
*
8+
* @typeParam Omitted - Specify the propeties that will not be stored in the raw data field as a union, implement via `DataTemplate`
9+
* @typeParam Extended - Whether the invite is a full extended invite
10+
*/
511
export class Invite<
612
Omitted extends keyof APIExtendedInvite | '' = 'created_at' | 'expires_at',
713
Extended extends boolean = false,
@@ -17,16 +23,27 @@ export class Invite<
1723

1824
/**
1925
* The template used for removing data from the raw data stored for each Invite
20-
* <info>This template has defaults, if you want to remove additional data and keep the defaults,
21-
* use `Object.defineProperties`. To override the defaults, set this value directly.</info>
26+
*
27+
* @remarks This template has defaults, if you want to remove additional data and keep the defaults,
28+
* use `Object.defineProperties`. To override the defaults, set this value directly.
2229
*/
2330
public static DataTemplate: Partial<APIExtendedInvite> = {
2431
set created_at(_: string) {},
2532
set expires_at(_: string) {},
2633
};
2734

35+
/**
36+
* Optimized storage of {@link APIExtendedInvite.expires_at}
37+
*
38+
* @internal
39+
*/
2840
protected [kExpiresTimestamp]: number | null = null;
2941

42+
/**
43+
* Optimized storage of {@link APIExtendedInvite.created_at}
44+
*
45+
* @internal
46+
*/
3047
protected [kCreatedTimestamp]: number | null = null;
3148

3249
public constructor(
@@ -38,11 +55,17 @@ export class Invite<
3855
super(data, { template: Invite.DataTemplate });
3956
}
4057

58+
/**
59+
* {@inheritDoc Structure._patch}
60+
*/
4161
public override _patch(data: Partial<APIExtendedInvite>) {
4262
super._patch(data, { template: Invite.DataTemplate });
4363
return this;
4464
}
4565

66+
/**
67+
* {@inheritDoc Structure._optimizeData}
68+
*/
4669
protected override _optimizeData(data: Partial<APIExtendedInvite>) {
4770
this[kExpiresTimestamp] = data.expires_at ? Date.parse(data.expires_at) : this[kExpiresTimestamp] ?? null;
4871
this[kCreatedTimestamp] = data.created_at ? Date.parse(data.created_at) : this[kCreatedTimestamp] ?? null;
@@ -64,15 +87,17 @@ export class Invite<
6487

6588
/**
6689
* The approximate number of online members of the guild this invite is for
67-
* <info>Only available when the invite was fetched from `GET /invites/<code>` with counts</info>
90+
*
91+
* @remarks Only available when the invite was fetched from `GET /invites/<code>` with counts
6892
*/
6993
public get presenceCount() {
7094
return this[kData].approximate_presence_count;
7195
}
7296

7397
/**
7498
* The approximate total number of members of the guild this invite is for
75-
* <info>Only available when the invite was fetched from `GET /invites/<code>` with counts</info>
99+
*
100+
* @remarks Only available when the invite was fetched from `GET /invites/<code>` with counts
76101
*/
77102
public get memberCount() {
78103
return this[kData].approximate_member_count;
@@ -155,6 +180,9 @@ export class Invite<
155180
return this.url;
156181
}
157182

183+
/**
184+
* {@inheritDoc Structure.toJSON}
185+
*/
158186
public override toJSON() {
159187
const clone = super.toJSON();
160188
if (this[kExpiresTimestamp]) {
@@ -168,11 +196,10 @@ export class Invite<
168196
return clone;
169197
}
170198

199+
/**
200+
* {@inheritDoc Object.valueOf}
201+
*/
171202
public override valueOf() {
172203
return this.code ?? super.valueOf();
173204
}
174205
}
175-
176-
const test = new Invite({} as APIExtendedInvite);
177-
if (test.code) {
178-
}
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './Invite.js';

packages/structures/src/users/User.ts

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,8 @@ import { kData } from '../utils/symbols.js';
55

66
/**
77
* Represents any user on Discord.
8+
*
9+
* @typeParam Omitted - Specify the propeties that will not be stored in the raw data field as a union, implement via `DataTemplate`
810
*/
911
export class User<Omitted extends keyof APIUser | '' = ''> extends Structure<APIUser, Omitted> {
1012
/**
@@ -21,6 +23,9 @@ export class User<Omitted extends keyof APIUser | '' = ''> extends Structure<API
2123
super(data, { template: User.DataTemplate });
2224
}
2325

26+
/**
27+
* {@inheritDoc Structure._patch}
28+
*/
2429
public override _patch(data: Partial<APIUser>) {
2530
return super._patch(data, { template: User.DataTemplate });
2631
}
@@ -76,63 +81,71 @@ export class User<Omitted extends keyof APIUser | '' = ''> extends Structure<API
7681

7782
/**
7883
* Whether the user has mfa enabled
79-
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
84+
*
85+
* @remarks This property is only set when the user was fetched with an OAuth2 token and the `identify` scope
8086
*/
8187
public get mfaEnabled() {
8288
return this[kData].mfa_enabled;
8389
}
8490

8591
/**
8692
* The user's banner hash
87-
* <info>This property is only set when the user was manually fetched</info>
93+
*
94+
* @remarks This property is only set when the user was manually fetched
8895
*/
8996
public get banner() {
9097
return this[kData].banner;
9198
}
9299

93100
/**
94101
* The base 10 accent color of the user's banner
95-
* <info>This property is only set when the user was manually fetched</info>
102+
*
103+
* @remarks This property is only set when the user was manually fetched
96104
*/
97105
public get accentColor() {
98106
return this[kData].accent_color;
99107
}
100108

101109
/**
102110
* The user's primary discord language
103-
* <info>This property is only set when the user was fetched with an Oauth2 token and the `identify` scope</info>
111+
*
112+
* @remarks This property is only set when the user was fetched with an Oauth2 token and the `identify` scope
104113
*/
105114
public get locale() {
106115
return this[kData].locale;
107116
}
108117

109118
/**
110119
* Whether the email on the user's account has been verified
111-
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
120+
*
121+
* @remarks This property is only set when the user was fetched with an OAuth2 token and the `email` scope
112122
*/
113123
public get verified() {
114124
return this[kData].verified;
115125
}
116126

117127
/**
118128
* The user's email
119-
* <info>This property is only set when the user was fetched with an OAuth2 token and the `email` scope</info>
129+
*
130+
* @remarks This property is only set when the user was fetched with an OAuth2 token and the `email` scope
120131
*/
121132
public get email() {
122133
return this[kData].email;
123134
}
124135

125136
/**
126137
* The flags on the user's account
127-
* <info> This property is only set when the user was fetched with an OAuth2 token and the `identity` scope</info>
138+
*
139+
* @remarks This property is only set when the user was fetched with an OAuth2 token and the `identity` scope
128140
*/
129141
public get flags() {
130142
return this[kData].flags;
131143
}
132144

133145
/**
134146
* The type of nitro subscription on the user's account
135-
* <info>This property is only set when the user was fetched with an OAuth2 token and the `identify` scope</info>
147+
*
148+
* @remarks This property is only set when the user was fetched with an OAuth2 token and the `identify` scope
136149
*/
137150
public get premiumType() {
138151
return this[kData].premium_type;
@@ -169,7 +182,8 @@ export class User<Omitted extends keyof APIUser | '' = ''> extends Structure<API
169182

170183
/**
171184
* The hexadecimal version of the user accent color, with a leading hash
172-
* <info>This property is only set when the user was manually fetched</info>
185+
*
186+
* @remarks This property is only set when the user was manually fetched
173187
*/
174188
public get hexAccentColor() {
175189
if (typeof this.accentColor !== 'number') return this.accentColor;

0 commit comments

Comments
 (0)