Skip to content

Commit

Permalink
feat(APIInteraction): add type-check utilities
Browse files Browse the repository at this point in the history
BREAKING CHANGE: This commit removes the `guild_id` property from `APIDMInteraction`
which allows type-checks to work with the `in` operator.
Because of that, we also provide utility functions that help with those type checks.
Use them in your code by importing the `Utils` object, or by directly importing them.
Check the README for examples
  • Loading branch information
vladfrangu committed Apr 11, 2021
1 parent 9e1a73f commit 3307201
Show file tree
Hide file tree
Showing 15 changed files with 199 additions and 28 deletions.
14 changes: 12 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,19 @@ const { APIUser } = require('discord-api-types/v8');
import { APIUser } from 'discord-api-types/v8';
```

You may also import just certain parts of the module that you need. The possible values are: `globals`, `gateway`, `gateway/v*`, `payloads`, `payloads/v*`, `rest`, `rest/v*`, `rpc`, `voice` and `voice/v*`.
You may also import just certain parts of the module that you need. The possible values are: `globals`, `gateway`, `gateway/v*`, `payloads`, `payloads/v*`, `rest`, `rest/v*`, `rpc`, `utils`, `utils/v*`, `voice` and `voice/v*`.
Below are some examples

> _**Note:** The v\* exports include the appropriate version of `gateway`, `payloads` and `rest` you specified, alongside the `globals` exports_
```js
const { GatewayVersion } = require('discord-api-types/gateway/v8');
```

```ts
// TypeScript/ES Module support
import { GatewayVersion } from 'discord-api-types/gateway/v8';
```

> _**Note:** The `v*` exports (`discord-api-type/v*`) include the appropriate version of `gateway`, `payloads`, `rest` and `utils` you specified, alongside the `globals` exports_
### Deno

Expand Down
14 changes: 12 additions & 2 deletions deno/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,19 @@ const { APIUser } = require('discord-api-types/v8');
import { APIUser } from 'discord-api-types/v8';
```

You may also import just certain parts of the module that you need. The possible values are: `globals`, `gateway`, `gateway/v*`, `payloads`, `payloads/v*`, `rest`, `rest/v*`, `rpc`, `voice` and `voice/v*`.
You may also import just certain parts of the module that you need. The possible values are: `globals`, `gateway`, `gateway/v*`, `payloads`, `payloads/v*`, `rest`, `rest/v*`, `rpc`, `utils`, `utils/v*`, `voice` and `voice/v*`.
Below are some examples

> _**Note:** The v\* exports include the appropriate version of `gateway`, `payloads` and `rest` you specified, alongside the `globals` exports_
```js
const { GatewayVersion } = require('discord-api-types/gateway/v8');
```

```ts
// TypeScript/ES Module support
import { GatewayVersion } from 'discord-api-types/gateway/v8';
```

> _**Note:** The `v*` exports (`discord-api-type/v*`) include the appropriate version of `gateway`, `payloads`, `rest` and `utils` you specified, alongside the `globals` exports_
### Deno

Expand Down
31 changes: 24 additions & 7 deletions deno/payloads/v8/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ export interface APIBaseInteraction {
* https://discord.com/developers/docs/interactions/slash-commands#interaction
*/
export interface APIGuildInteraction extends APIBaseInteraction {
/**
* The guild it was sent from
*
* In the case of an `APIDMInteraction`, this will not be present
*/
guild_id: Snowflake;
/**
* Guild member data for the invoking user, including permissions
Expand All @@ -147,12 +152,6 @@ export interface APIGuildInteraction extends APIBaseInteraction {
* https://discord.com/developers/docs/interactions/slash-commands#interaction
*/
export interface APIDMInteraction extends APIBaseInteraction {
/**
* The guild it was sent from
*
* In the case of an `APIDMInteraction`, this will not be present
*/
guild_id?: never;
/**
* User object for the invoking user, if invoked in a DM
*/
Expand All @@ -165,10 +164,28 @@ export interface APIDMInteraction extends APIBaseInteraction {
*/
export type APIInteraction = APIGuildInteraction | APIDMInteraction;

/**
* Like APIGuildInteraction, only with the `data` property always present
*
* @see APIGuildInteraction
*/
export type APIApplicationCommandGuildInteraction = Required<APIGuildInteraction>;

/**
* Like APIDMInteraction, only with the `data` property always present
*
* @see APIDMInteraction
*/
export type APIApplicationCommandDMInteraction = Required<APIDMInteraction>;

/**
* Like APIInteraction, only with the `data` property always present
*
* @see APIInteraction
*/
export type APIApplicationCommandInteraction = Required<APIInteraction>;
export type APIApplicationCommandInteraction =
| APIApplicationCommandGuildInteraction
| APIApplicationCommandDMInteraction;

/**
* https://discord.com/developers/docs/interactions/slash-commands#interaction-interactiontype
Expand Down
1 change: 1 addition & 0 deletions deno/shortcuts/v8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from '../globals.ts';
export * from '../gateway/v8.ts';
export * from '../payloads/v8/mod.ts';
export * from '../rest/v8/mod.ts';
export * as Utils from '../utils/v8.ts';
4 changes: 4 additions & 0 deletions deno/utils/mod.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file exports all the utility functions available in the recommended API / Gateway version
// Thereby, things MAY break in the future. Try sticking to imports from a specific version

export * from './v8.ts';
48 changes: 48 additions & 0 deletions deno/utils/v8.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
APIApplicationCommandDMInteraction,
APIApplicationCommandGuildInteraction,
APIApplicationCommandInteraction,
APIDMInteraction,
APIGuildInteraction,
APIInteraction,
} from '../payloads.ts';

/**
* A type-guard check for guild interactions.
* @param interaction The interaction to check against the
* @returns A boolean that indicates if the interaction was received from a guild
*/
export function isGuildInteraction(interaction: APIInteraction): interaction is APIGuildInteraction {
return Reflect.has(interaction, 'guild_id');
}

/**
* A type-guard check for DM interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the interaction was received from a direct message
*/
export function isDMInteraction(interaction: APIInteraction): interaction is APIDMInteraction {
return !isGuildInteraction(interaction);
}

/**
* A type-guard check for guild application command interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the command interaction was received from a guild
*/
export function isApplicationCommandGuildInteraction(
interaction: APIApplicationCommandInteraction,
): interaction is APIApplicationCommandGuildInteraction {
return isGuildInteraction(interaction);
}

/**
* A type-guard check for direct message application command interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the command interaction was received from a direct message
*/
export function isApplicationCommandDMInteraction(
interaction: APIApplicationCommandInteraction,
): interaction is APIApplicationCommandDMInteraction {
return !isGuildInteraction(interaction);
}
19 changes: 14 additions & 5 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,22 @@
"./voice/v*": {
"require": "./voice/v*.js",
"import": "./voice/v*.mjs"
},
"./utils": {
"require": "./utils/index.js",
"import": "./utils/index.mjs"
},
"./utils/v*": {
"require": "./utils/v*.js",
"import": "./utils/v*.mjs"
}
},
"scripts": {
"build:ci": "tsc --noEmit --incremental false",
"build:deno": "node ./scripts/deno.mjs",
"build:node": "tsc && run-p esm:*",
"clean:deno": "rimraf deno/",
"clean:node": "rimraf {gateway,payloads,rest,rpc,voice,shortcuts}/**/*.{js,mjs,d.ts,map} globals.{js,mjs,d.ts,*map}",
"clean:node": "rimraf {gateway,payloads,rest,rpc,voice,shortcuts,utils}/**/*.{js,mjs,d.ts,map} globals.{js,mjs,d.ts,*map}",
"clean": "run-p clean:*",
"esm:globals": "gen-esm-wrapper ./globals.js ./globals.mjs",
"esm:gateway": "gen-esm-wrapper ./gateway/index.js ./gateway/index.mjs",
Expand All @@ -69,10 +77,11 @@
"esm:rpc": "gen-esm-wrapper ./rpc/index.js ./rpc/index.mjs",
"esm:v6": "gen-esm-wrapper ./shortcuts/v6.js ./shortcuts/v6.mjs",
"esm:v8": "gen-esm-wrapper ./shortcuts/v8.js ./shortcuts/v8.mjs",
"esm:utils": "gen-esm-wrapper ./utils/index.js ./utils/index.mjs",
"esm:voice": "gen-esm-wrapper ./voice/index.js ./voice/index.mjs",
"esm:versions": "node ./scripts/versions.mjs",
"lint": "eslint --fix --ext mjs,ts {gateway,payloads,rest,rpc,voice,shortcuts}/** globals.ts",
"test:lint": "eslint --ext mjs,ts {gateway,payloads,rest,rpc,voice,shortcuts}/** globals.ts",
"lint": "eslint --fix --ext mjs,ts {gateway,payloads,rest,rpc,voice,shortcuts,utils}/** globals.ts",
"test:lint": "eslint --ext mjs,ts {gateway,payloads,rest,rpc,voice,shortcuts,utils}/** globals.ts",
"prepublishOnly": "run-s clean test:lint build:node",
"postpublish": "run-s clean:node build:deno",
"version": "conventional-changelog -p angular -i CHANGELOG.md -s && git add CHANGELOG.md"
Expand All @@ -86,7 +95,7 @@
"author": "Vlad Frangu <kingdgrizzle@gmail.com>",
"license": "MIT",
"files": [
"{gateway,payloads,rest,rpc,voice,shortcuts}/**/*.{js,js.map,d.ts,d.ts.map,mjs}",
"{gateway,payloads,rest,rpc,voice,shortcuts,utils}/**/*.{js,js.map,d.ts,d.ts.map,mjs}",
"globals.{js,js.map,d.ts,d.ts.map,mjs}"
],
"engines": {
Expand Down Expand Up @@ -145,7 +154,7 @@
}
},
"lint-staged": {
"{gateway,rest,rpc,voice,shortcuts}/**/*.{mjs,js,ts}": "eslint --fix --ext mjs,js,ts",
"{gateway,payloads,rest,rpc,voice,shortcuts,utils}/**/*.{mjs,js,ts}": "eslint --fix --ext mjs,js,ts",
"globals.ts": "eslint --fix --ext mjs,js,ts"
},
"commitlint": {
Expand Down
31 changes: 24 additions & 7 deletions payloads/v8/interactions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,11 @@ export interface APIBaseInteraction {
* https://discord.com/developers/docs/interactions/slash-commands#interaction
*/
export interface APIGuildInteraction extends APIBaseInteraction {
/**
* The guild it was sent from
*
* In the case of an `APIDMInteraction`, this will not be present
*/
guild_id: Snowflake;
/**
* Guild member data for the invoking user, including permissions
Expand All @@ -147,12 +152,6 @@ export interface APIGuildInteraction extends APIBaseInteraction {
* https://discord.com/developers/docs/interactions/slash-commands#interaction
*/
export interface APIDMInteraction extends APIBaseInteraction {
/**
* The guild it was sent from
*
* In the case of an `APIDMInteraction`, this will not be present
*/
guild_id?: never;
/**
* User object for the invoking user, if invoked in a DM
*/
Expand All @@ -165,10 +164,28 @@ export interface APIDMInteraction extends APIBaseInteraction {
*/
export type APIInteraction = APIGuildInteraction | APIDMInteraction;

/**
* Like APIGuildInteraction, only with the `data` property always present
*
* @see APIGuildInteraction
*/
export type APIApplicationCommandGuildInteraction = Required<APIGuildInteraction>;

/**
* Like APIDMInteraction, only with the `data` property always present
*
* @see APIDMInteraction
*/
export type APIApplicationCommandDMInteraction = Required<APIDMInteraction>;

/**
* Like APIInteraction, only with the `data` property always present
*
* @see APIInteraction
*/
export type APIApplicationCommandInteraction = Required<APIInteraction>;
export type APIApplicationCommandInteraction =
| APIApplicationCommandGuildInteraction
| APIApplicationCommandDMInteraction;

/**
* https://discord.com/developers/docs/interactions/slash-commands#interaction-interactiontype
Expand Down
7 changes: 2 additions & 5 deletions scripts/deno.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,11 @@ await Promise.all(
'rest/',
'rpc/',
'shortcuts/',
'utils/',
'voice/',
].map((item) => adaptFolderToDeno(item)),
);

await Promise.all(
[
'LICENSE', //
'README.md',
'globals.ts',
].map((item) => copyFile(new URL(item, baseDirectory), new URL(item, denoPath))),
['LICENSE', 'README.md', 'globals.ts'].map((item) => copyFile(new URL(item, baseDirectory), new URL(item, denoPath))),
);
3 changes: 3 additions & 0 deletions scripts/versions.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ Promise.allSettled(

// Voice
fileToESMWrapperCall('voice', version),

// Utils
fileToESMWrapperCall('utils', version),
])
.flat(),
);
1 change: 1 addition & 0 deletions shortcuts/v8.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,3 +2,4 @@ export * from '../globals';
export * from '../gateway/v8';
export * from '../payloads/v8/index';
export * from '../rest/v8/index';
export * as Utils from '../utils/v8';
1 change: 1 addition & 0 deletions tsconfig.eslint.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"rest/**/*.ts",
"rpc/**/*.ts",
"shortcuts/**/*.ts",
"utils/**/*.ts",
"voice/**/*.ts",
"scripts",
"deno"
Expand Down
1 change: 1 addition & 0 deletions tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
"rest/**/*.ts",
"rpc/**/*.ts",
"shortcuts/**/*.ts",
"utils/**/*.ts",
"voice/**/*.ts"
]
}
4 changes: 4 additions & 0 deletions utils/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
// This file exports all the utility functions available in the recommended API / Gateway version
// Thereby, things MAY break in the future. Try sticking to imports from a specific version

export * from './v8';
48 changes: 48 additions & 0 deletions utils/v8.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
import {
APIApplicationCommandDMInteraction,
APIApplicationCommandGuildInteraction,
APIApplicationCommandInteraction,
APIDMInteraction,
APIGuildInteraction,
APIInteraction,
} from '../payloads';

/**
* A type-guard check for guild interactions.
* @param interaction The interaction to check against the
* @returns A boolean that indicates if the interaction was received from a guild
*/
export function isGuildInteraction(interaction: APIInteraction): interaction is APIGuildInteraction {
return Reflect.has(interaction, 'guild_id');
}

/**
* A type-guard check for DM interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the interaction was received from a direct message
*/
export function isDMInteraction(interaction: APIInteraction): interaction is APIDMInteraction {
return !isGuildInteraction(interaction);
}

/**
* A type-guard check for guild application command interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the command interaction was received from a guild
*/
export function isApplicationCommandGuildInteraction(
interaction: APIApplicationCommandInteraction,
): interaction is APIApplicationCommandGuildInteraction {
return isGuildInteraction(interaction);
}

/**
* A type-guard check for direct message application command interactions.
* @param interaction The interaction to check against
* @returns A boolean that indicates if the command interaction was received from a direct message
*/
export function isApplicationCommandDMInteraction(
interaction: APIApplicationCommandInteraction,
): interaction is APIApplicationCommandDMInteraction {
return !isGuildInteraction(interaction);
}

0 comments on commit 3307201

Please sign in to comment.