Skip to content

Commit

Permalink
refactor(rest:manager): don't use client for options
Browse files Browse the repository at this point in the history
Signed-off-by: Splatterxl <splatterxl@outlook.ie>
  • Loading branch information
splatterxl committed May 5, 2022
1 parent bd30819 commit 5fd1fe2
Show file tree
Hide file tree
Showing 7 changed files with 110 additions and 43 deletions.
19 changes: 12 additions & 7 deletions packages/fuwa/src/client/Client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,18 +153,12 @@ export class Client extends EventEmitter {
super();

this.options = Object.assign(
{},
DefaultClientOptions,
options,
) as Required<ClientOptions>;
this.options.intents = resolveIntents(this.options.intents!);
this.#token = token;
this.http = new RequestManager(
new RESTClient(
RESTClient.createRESTOptions(this.options, this.#token, 'Bot'),
),
this,
);
this.ws = new GatewayManager(this);

if (!this.options.logger) {
this.logger = new DisabledLogger();
Expand All @@ -176,6 +170,17 @@ export class Client extends EventEmitter {
this.logger = this.options.logger;
}

this.http = new RequestManager(
new RESTClient(
RESTClient.createRESTOptions(this.options, this.#token, 'Bot'),
),
{
timings: this.options.httpTimings,
logger: this.logger,
},
);
this.ws = new GatewayManager(this);

this.guilds = new GuildManager(this);
this.users = new UserManager(this);
this.channels = new ChannelManager(this);
Expand Down
33 changes: 33 additions & 0 deletions packages/rest/__test__/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
const REST = require('..');
const assert = require('assert');

const manager = new REST.default(
new REST.RESTClient(REST.DefaultDiscordOptions),
{
timings: true,
logger: {
debug: console.log,
trace: console.log,
kleur: null
}
}
);

manager.client.setAuth(process.env.DISCORD_TOKEN);

assert.strictEqual(manager.client.getAuth(), process.env.DISCORD_TOKEN);
assert.strictEqual(manager.client.baseURL, REST.DefaultDiscordOptions.baseURL);
assert.strictEqual(
manager.client.options.userAgent,
REST.DefaultDiscordOptions.userAgent,
);
assert.strictEqual(manager.client.version, REST.DefaultDiscordOptions.version);

manager
.queue('/gateway')
.then(res => res.body.json())
.then(json => {
assert.deepStrictEqual(json, {
url: 'wss://gateway.discord.gg',
});
});
13 changes: 5 additions & 8 deletions packages/rest/src/BucketQueueManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,11 @@ export class BucketQueueManager {
}
}

#__log_header() {
return `[${this.manager.__log_header()} -> ${this.id}]`;
}

private debug(...data: any[]) {
this.manager._client?.debug(
`[${this.manager._client?.logger
.kleur()
.blueBright('REST')} => ${this.manager._client?.logger
.kleur()
.green(this.id)}]`,
...data,
);
this.manager.debug(this.#__log_header(), ...data);
}
}
28 changes: 20 additions & 8 deletions packages/rest/src/RESTClient.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import FormData from 'form-data';
import undici from 'undici';
import { ResponseData } from 'undici/types/dispatcher';
import { inspect } from 'util';
import { RequestOptions, ResponseData } from 'undici/types/dispatcher';
import { APIRequest } from './APIRequest';
import { RouteLike } from './RequestManager.js';

Expand Down Expand Up @@ -63,6 +64,9 @@ export class RESTClient {
this.#auth = auth;
return this;
}
public getAuth() {
return this.#auth;
}

public createHeaders(request: APIRequest): Record<string, string> {
const headers: Record<string, string> = request.headers ?? {};
Expand Down Expand Up @@ -173,10 +177,10 @@ export class RESTClient {
public execute(request: APIRequest, tracefunc?: any): Promise<ResponseData> {
request = this.resolveBody(request);

const options: any = {
method: request.method,
const options: RequestOptions = {
method: request.method ?? 'GET',
headers: this.createHeaders(request),
},
} as RequestOptions,
url = this.createURL(request);

if (request.body) options.body = request.body;
Expand All @@ -185,9 +189,14 @@ export class RESTClient {
tracefunc(
options.method,
url,
'\n',
'body:',
prettifyBody(options.headers['content-type'] ?? '', options.body),
options.body
? prettifyBody(
options.headers![
'content-type' as keyof typeof options['headers']
],
options.body! as Buffer,
)
: '',
);
}

Expand All @@ -206,7 +215,10 @@ export interface RESTClientOptions {

function prettifyBody(contentType: string, body: Buffer) {
if (contentType.startsWith('application/json')) {
return JSON.parse(body.toString());
return inspect(JSON.parse(body.toString()), {
depth: null,
colors: false,
});
}

return body?.toString();
Expand Down
43 changes: 27 additions & 16 deletions packages/rest/src/RequestManager.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,18 @@ import {
APIError,
parseErr,
RateLimitedError,
RESTError
RESTError,
} from './RESTError.js';

// Yeah, copied from Discord.js because I can't even think for myself.
export interface RequestManagerOptions {
timings?: boolean;
logger?: {
debug?: (...args: any[]) => void;
trace?: (...args: any[]) => void;
kleur?: any;
};
}

export class RequestManager {
// maybe this'll be of some use someday
// private buckets: Map<string, RateLimit> = new Map();
Expand All @@ -28,12 +36,10 @@ export class RequestManager {
/** When the global rate limit will reset. */
public reset = Date.now() + 1e3;

/** Whether to measure the timing of HTTP requests */
public timings = false;

constructor(public client: RESTClient, public _client?: any) {
if (_client?.options?.httpTimings) this.timings = true;
}
constructor(
public client: RESTClient,
public options: RequestManagerOptions = {},
) {}

public get durUntilReset() {
return this.reset + this.offset - Date.now();
Expand All @@ -60,7 +66,7 @@ export class RequestManager {
bucket: BucketQueueManager,
req: Required<APIRequest>,
): Promise<ResponseData> {
if (this.timings) req.httpStartTime = Date.now();
if (this.options.timings) req.httpStartTime = Date.now();

const res = await this.client.execute(req, this.trace.bind(this)),
now = Date.now();
Expand All @@ -71,7 +77,7 @@ export class RequestManager {
`${req.method.toUpperCase()} ${req.route} -> ${res.statusCode} ${
STATUS_CODES[res.statusCode]
}${
this.timings
this.options.timings
? ` (${now - req.startTime}ms${
now - req.httpStartTime !== now - req.startTime
? ` full; ${now - req.httpStartTime}ms http`
Expand Down Expand Up @@ -99,7 +105,7 @@ export class RequestManager {

if (req.retries < req.allowedRetries) {
req.retries++;
this._client.debug('got ratelimited at', bucket.id, '- retrying');
this.debug('got ratelimited at', bucket.id, '- retrying');

return this.queue(req);
} else {
Expand Down Expand Up @@ -144,7 +150,7 @@ export class RequestManager {
req = resolveRequest({ route: req, ...options });
} else req = resolveRequest(req);

if (this.timings) req.startTime = Date.now();
if (this.options.timings) req.startTime = Date.now();

if (!req.useRateLimits)
return this.makeRequest(
Expand Down Expand Up @@ -172,15 +178,20 @@ export class RequestManager {
}

#__log_header() {
return `[${this._client?.logger.kleur().green('REST')}]`;
return `[${this.options?.logger?.kleur?.().green('REST') ?? 'REST'}]`;
}

/** @ignore */
__log_header() {
return this.#__log_header();
}

private debug(...args: any[]) {
this._client?.logger.debug(this.#__log_header(), ...args);
debug(...args: any[]) {
this.options?.logger?.debug?.(this.#__log_header(), ...args);
}

private trace(...args: any[]) {
this._client?.logger.trace('[REST]', ...args);
this.options?.logger?.trace?.('[REST]', ...args);
}
}

Expand Down
1 change: 1 addition & 0 deletions packages/rest/typings/RESTClient.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export declare class RESTClient {
static createRESTOptions(clientOptions: any, token: string, tokenType: 'Bot' | 'Bearer'): RESTClientOptions;
static getDefaultOptions(token: string): Required<RESTClientOptions>;
setAuth(auth: string): this;
getAuth(): string | undefined;
createHeaders(request: APIRequest): Record<string, string>;
formatRoute(route: RouteLike, versioned?: boolean, useBase?: boolean): string;
resolveBody(req: APIRequest): APIRequest;
Expand Down
16 changes: 12 additions & 4 deletions packages/rest/typings/RequestManager.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,33 @@ import { ResponseData } from 'undici/types/dispatcher';
import { APIRequest } from './APIRequest.js';
import { BucketQueueManager } from './BucketQueueManager.js';
import { RESTClient } from './RESTClient';
export interface RequestManagerOptions {
timings?: boolean;
logger?: {
debug?: (...args: any[]) => void;
trace?: (...args: any[]) => void;
kleur?: any;
};
}
export declare class RequestManager {
#private;
client: RESTClient;
_client?: any;
options: RequestManagerOptions;
limit: number;
offset: number;
buckets: Map<string, BucketQueueManager>;
remaining: number;
reset: number;
timings: boolean;
constructor(client: RESTClient, _client?: any);
constructor(client: RESTClient, options?: RequestManagerOptions);
get durUntilReset(): number;
getBucket(route: RouteLike): string[];
get globalLimited(): boolean;
makeRequest(bucket: BucketQueueManager, req: Required<APIRequest>): Promise<ResponseData>;
queue<T>(route: RouteLike, options?: Omit<APIRequest, 'route'>): Promise<Response<T>>;
queue<T>(req: APIRequest): Promise<Response<T>>;
private updateOffset;
private debug;
__log_header(): string;
debug(...args: any[]): void;
private trace;
}
export declare type RouteLike = `/${string}`;
Expand Down

0 comments on commit 5fd1fe2

Please sign in to comment.