Merge branch 'main' into refactor/setup-props-everything

This commit is contained in:
Fleny
2026-01-17 20:02:38 +01:00
committed by GitHub
47 changed files with 855 additions and 711 deletions

View File

@@ -22,21 +22,13 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-test:e2e-${{ inputs.package }}-${{ github.sha }}
- name: Build dist cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
cache-prefix: turbo-cache-
- name: E2E Test
if: ${{ inputs.event_name != 'pull_request' }}
run: yarn test:e2e --cache-dir=".turbo" --filter=./packages/${{ inputs.package }}
run: yarn test:e2e --filter=./packages/${{ inputs.package }}
timeout-minutes: 5
env:
DISCORD_TOKEN: ${{ secrets.DISCORD_TOKEN }}

View File

@@ -19,20 +19,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-test:integration-${{ inputs.package }}-${{ github.sha }}
- name: Build dist cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Integration Test
run: yarn test:integration --cache-dir=".turbo" --filter=./packages/${{ inputs.package }}
run: yarn test:integration --filter=./packages/${{ inputs.package }}
timeout-minutes: 3
- name: Collect and upload the coverage report
uses: codecov/codecov-action@v5

View File

@@ -6,8 +6,6 @@ on:
push:
branches:
- main
paths-ignore:
- 'website/**'
merge_group:
jobs:
@@ -21,14 +19,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Build Types
run: yarn build:type --cache-dir=".turbo"
run: yarn build:type
build-dist:
name: Build Dist
@@ -40,14 +36,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
- name: Type Test
run: yarn build --cache-dir=".turbo"
cache-prefix: turbo-cache-
- name: Build Dist
run: yarn build
format:
name: Format
@@ -60,13 +54,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Build type cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Build Types
run: yarn build:type --cache-dir=".turbo"
run: yarn build:type
- name: Check Formatting
run: yarn biome ci --reporter=github
@@ -81,20 +74,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-unit-and-integration-test:test-type-${{ github.sha }}
- name: Build type cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Test Type Test
run: yarn test:test-type --cache-dir=".turbo"
run: yarn test:test-type
# Not using matrix because test later on cant needs a specific job
bot-unit-test:

View File

@@ -22,20 +22,12 @@ jobs:
with:
deno-version: 'v2.1.x'
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-test:deno-unit-${{ inputs.package }}-${{ github.sha }}
- name: Build dist cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Deno Unit Test
run: yarn test:deno-unit --cache-dir=".turbo" --filter=./packages/${{ inputs.package }}
run: yarn test:deno-unit --filter=./packages/${{ inputs.package }}
bun-unit-test:
name: Bun Unit Test
runs-on: ubuntu-latest
@@ -49,18 +41,10 @@ jobs:
with:
bun-version: '1.1.42'
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-test:bun-unit-${{ inputs.package }}-${{ github.sha }}
- name: Build dist cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Bun Unit Test
run: yarn test:bun-unit --cache-dir=".turbo" --filter=./packages/${{ inputs.package }}
run: yarn test:bun-unit --filter=./packages/${{ inputs.package }}
timeout-minutes: 1

View File

@@ -4,12 +4,6 @@ permissions:
on:
push:
branches: ['main']
paths:
- 'website/**'
- '.github/workflows/site.yml'
- 'typedoc.json'
- 'package.json'
- 'packages/**'
pull_request:
workflow_dispatch:
@@ -31,10 +25,19 @@ jobs:
website/yarn.lock
- name: yarn install (root)
run: yarn install --immutable
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
cache-prefix: turbo-cache-
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
cache-prefix: turbo-cache-website-
server-port: 41231 # The default is 41230, but we use a different cache key so we need a different port
- name: Build all pkg
run: yarn release-build
- name: Build docs
run: yarn build:doc
run: yarn turbo build:doc --single-package
- run: yarn install --immutable
working-directory: ./website
- name: Restore bundler cache
@@ -45,8 +48,10 @@ jobs:
restore-keys: |
${{ runner.os }}-docusaurus-bundler-
- name: Build website
run: yarn build
run: yarn turbo build
working-directory: ./website
env:
TURBO_API: http://localhost:41231
- name: Upload artifact
uses: actions/upload-pages-artifact@v4
with:
@@ -64,10 +69,14 @@ jobs:
website/yarn.lock
- name: yarn install (root)
run: yarn install --immutable
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
cache-prefix: turbo-cache-
- name: Build all pkg
run: yarn release-build
- name: Build docs
run: yarn build:doc
run: yarn turbo build:doc --single-package
- run: yarn install --immutable
working-directory: ./website
- run: yarn typecheck

View File

@@ -19,26 +19,12 @@ jobs:
node-version: 20
cache: yarn
- run: yarn install --immutable
- name: Turbo Cache
id: turbo-cache
uses: actions/cache@v5
- name: Cache for Turbo
uses: rharkor/caching-for-turbo@v2.3.5
with:
path: .turbo
key: ${{ runner.os }}-turbo-test:unit-${{ inputs.package }}-${{ github.sha }}
- name: Build dist cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build-${{ github.sha }}
- name: Build type cache
if: steps.turbo-cache.outputs.cache-hit != 'true'
uses: actions/cache@v5
with:
path: .turbo
key: ${{ runner.os }}-turbo-build:type-${{ github.sha }}
cache-prefix: turbo-cache-
- name: Unit Test
run: yarn test:unit --cache-dir=".turbo" --filter=./packages/${{ inputs.package }}
run: yarn test:unit --filter=./packages/${{ inputs.package }}
timeout-minutes: 1
- name: Collect and upload the coverage report
uses: codecov/codecov-action@v5

View File

@@ -1,9 +0,0 @@
// This needs to be a different file as this is used for Deno and Bun
module.exports = {
recursive: true,
timeout: 2000,
'watch-extensions': 'ts',
'watch-files': ['src', 'tests'],
parallel: false,
}

View File

@@ -1,6 +1,23 @@
module.exports = {
...require('./.mocharc.base.cjs'),
require: 'ts-node/register',
loader: 'ts-node/esm',
'enable-source-maps': true,
// @ts-check
// If we are running in Bun or Deno, they have native TypeScript support with .js imports, node requires .ts imports
const supportsTypescript = 'Bun' in globalThis || 'Deno' in globalThis
/** @type {import("mocha").MochaInstanceOptions & Record<string, unknown>} */
const mochaConfig = {
timeout: 2000,
'watch-extensions': 'ts',
'watch-files': ['src', 'tests'],
}
if (!supportsTypescript) {
mochaConfig.require = ['ts-node/register']
// Node options
mochaConfig.loader = ['ts-node/esm']
// Node will output a ExperimentalWarning about --loader (--experimental-loader) and a DeprecationWarning because ts-node uses fs.Stat
mochaConfig['no-warnings'] = true
mochaConfig['enable-source-maps'] = true
}
module.exports = mochaConfig

View File

@@ -1,5 +1,5 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.10/schema.json",
"$schema": "https://biomejs.dev/schemas/2.3.11/schema.json",
"root": true,
"formatter": {
"enabled": true,

View File

@@ -19,7 +19,7 @@
},
"devDependencies": {
"@favware/cliff-jumper": "^6.0.0",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"dotenv": "^17.2.3",
"typescript": "^5.9.3"
}

View File

@@ -321,12 +321,12 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:^25.0.3":
version: 25.0.3
resolution: "@types/node@npm:25.0.3"
"@types/node@npm:^25.0.6":
version: 25.0.6
resolution: "@types/node@npm:25.0.6"
dependencies:
undici-types: "npm:~7.16.0"
checksum: 10c0/b7568f0d765d9469621615e2bb257c7fd1953d95e9acbdb58dffb6627a2c4150d405a4600aa1ad8a40182a94fe5f903cafd3c0a2f5132814debd0e3bfd61f835
checksum: 10c0/4ee3b6b606bc28f6840c04d58769e1e75dd8085149908956c874c85f8f8c890990701bcbe783fc2d14017817861dc07fcf23de6fc2805fe491f84eae717b5705
languageName: node
linkType: hard
@@ -1133,7 +1133,7 @@ __metadata:
"@fastify/helmet": "npm:^13.0.2"
"@fastify/multipart": "npm:^9.0.3"
"@favware/cliff-jumper": "npm:^6.0.0"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
dotenv: "npm:^17.2.3"
fastify: "npm:^5.5.0"
typescript: "npm:^5.9.3"

View File

@@ -1102,12 +1102,12 @@ __metadata:
languageName: node
linkType: hard
"mkdirp@npm:^3.0.1":
version: 3.0.1
resolution: "mkdirp@npm:3.0.1"
bin:
mkdirp: dist/cjs/src/bin.js
checksum: 10c0/9f2b975e9246351f5e3a40dcfac99fcd0baa31fbfab615fe059fb11e51f10e4803c63de1f384c54d656e4db31d000e4767e9ef076a22e12a641357602e31d57d
"minizlib@npm:^3.1.0":
version: 3.1.0
resolution: "minizlib@npm:3.1.0"
dependencies:
minipass: "npm:^7.1.2"
checksum: 10c0/5aad75ab0090b8266069c9aabe582c021ae53eb33c6c691054a13a45db3b4f91a7fb1bd79151e6b4e9e9a86727b522527c0a06ec7d45206b745d54cd3097bcec
languageName: node
linkType: hard
@@ -1617,16 +1617,15 @@ __metadata:
linkType: hard
"tar@npm:^7.4.3":
version: 7.4.3
resolution: "tar@npm:7.4.3"
version: 7.5.3
resolution: "tar@npm:7.5.3"
dependencies:
"@isaacs/fs-minipass": "npm:^4.0.0"
chownr: "npm:^3.0.0"
minipass: "npm:^7.1.2"
minizlib: "npm:^3.0.1"
mkdirp: "npm:^3.0.1"
minizlib: "npm:^3.1.0"
yallist: "npm:^5.0.0"
checksum: 10c0/d4679609bb2a9b48eeaf84632b6d844128d2412b95b6de07d53d8ee8baf4ca0857c9331dfa510390a0727b550fd543d4d1a10995ad86cdf078423fbb8d99831d
checksum: 10c0/e5e3237bca325fbb33282d92d9807f4c8d81abaf71bf2627efdf93bd5610c146460c78fc7e9767d4ab5ae3c0b18af8197314c964f8cbd23b30b25bf4d42d7cb4
languageName: node
linkType: hard

View File

@@ -10,27 +10,26 @@
"scripts": {
"build": "turbo build",
"build:type": "turbo build:type",
"release-build": "turbo build build:type",
"build:doc": "typedoc --options ./typedoc.jsonc",
"build:watch": "turbo watch build build:type",
"release-build": "turbo build build:type",
"test:unit": "turbo test:unit",
"test:unit-coverage": "turbo test:unit-coverage",
"test:bun-unit": "turbo test:bun-unit",
"test:deno-unit": "turbo test:deno-unit",
"test:bun-unit": "turbo test:bun-unit",
"test:integration": "turbo test:integration",
"test:e2e": "turbo test:e2e",
"test:type": "turbo build:type",
"test:test-type": "turbo test:test-type",
"test:type": "turbo build:type",
"check": "turbo check",
"check:all": "biome check --write",
"postinstall": "husky"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"husky": "^9.1.7",
"lint-staged": "^16.2.7",
"turbo": "^2.7.2",
"typedoc": "^0.28.15",
"turbo": "^2.7.4",
"typedoc": "^0.28.16",
"typedoc-plugin-markdown": "^4.9.0",
"typescript": "^5.9.3"
},

View File

@@ -17,14 +17,12 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/unit/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js discordeno",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/unit/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:e2e": "c8 --r lcov mocha --no-warnings --jobs 1 --t 30000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest",
"test:type": "tsc --noEmit",
"test:test-type": "tsc --project tests/tsconfig.json"
"test:unit": "c8 -r lcov mocha 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js bot",
"test:deno-unit": "deno -A npm:mocha 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/unit/**/*.spec.ts'",
"test:e2e": "c8 -r lcov mocha -t 30000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js bot",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"dependencies": {
"@discordeno/gateway": "workspace:^",
@@ -33,12 +31,12 @@
"@discordeno/utils": "workspace:^"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/chai": "^5.2.3",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"@types/sinon": "^21.0.0",
"c8": "^10.1.3",
"chai": "^6.2.2",

View File

@@ -179,6 +179,9 @@ export function createBotHelpers<TProps extends TransformersDesiredProperties, T
createInvite: async (channelId, options, reason) => {
return await bot.rest.createInvite(channelId, options, reason)
},
getGuildRoleMemberCounts: async (guildId) => {
return await bot.rest.getGuildRoleMemberCounts(guildId)
},
createRole: async (guildId, options, reason) => {
return bot.transformers.role(bot, snakelize(await bot.rest.createRole(guildId, options, reason)), { guildId })
},
@@ -871,6 +874,7 @@ export type BotHelpers<TProps extends TransformersDesiredProperties, TBehavior e
) => Promise<SetupDesiredProps<Sticker, TProps, TBehavior>>
createGuildTemplate: (guildId: BigString, options: CreateTemplate) => Promise<SetupDesiredProps<Template, TProps, TBehavior>>
createInvite: (channelId: BigString, options?: CreateChannelInvite, reason?: string) => Promise<Camelize<DiscordInvite>>
getGuildRoleMemberCounts: (guildId: BigString) => Promise<Record<string, number>>
createRole: (guildId: BigString, options: CreateGuildRole, reason?: string) => Promise<SetupDesiredProps<Role, TProps, TBehavior>>
createScheduledEvent: (
guildId: BigString,

View File

@@ -20,6 +20,7 @@ export function transformAutoModerationRule(bot: Bot, payload: DiscordAutoModera
presets: payload.trigger_metadata.presets,
allowList: payload.trigger_metadata.allow_list,
mentionTotalLimit: payload.trigger_metadata.mention_total_limit,
mentionRaidProtectionEnabled: payload.trigger_metadata.mention_raid_protection_enabled,
}
: undefined,
actions: payload.actions.map((action) => ({

View File

@@ -55,6 +55,7 @@ export function transformRole(bot: Bot, payload: DiscordRole, extra?: { guildId?
if (props.position) role.position = payload.position
if (props.guildId && extra?.guildId) role.guildId = bot.transformers.snowflake(extra?.guildId)
if (props.color && payload.color !== undefined) role.color = payload.color
if (props.colors && payload.colors) role.colors = bot.transformers.roleColors(bot, payload.colors)
if (props.permissions && payload.permissions) role.permissions = new Permissions(payload.permissions)
if (props.icon && payload.icon) role.icon = iconHashToBigInt(payload.icon)
if (props.unicodeEmoji && payload.unicode_emoji) role.unicodeEmoji = payload.unicode_emoji

View File

@@ -358,11 +358,57 @@ export interface AutoModerationRule {
}
export interface AutoModerationRuleTriggerMetadata {
/**
* Substrings which will be searched for in content.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.Keyword} and {@link AutoModerationTriggerTypes.MemberProfile}.
*
* Can have up to 1000 elements in the array and each string can have up to 60 characters.
*/
keywordFilter?: string[]
/**
* Regular expression patterns which will be matched against content.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.Keyword} and {@link AutoModerationTriggerTypes.MemberProfile}.
*
* Only Rust flavored regex is currently supported. Can have up to 10 elements in the array and each string can have up to 260 characters.
*/
regexPatterns?: string[]
/**
* The Discord pre-defined wordsets which will be searched for in content.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.KeywordPreset}.
*/
presets?: DiscordAutoModerationRuleTriggerMetadataPresets[]
/**
* The substrings which should not trigger the rule.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.Keyword}, {@link AutoModerationTriggerTypes.KeywordPreset} and {@link AutoModerationTriggerTypes.MemberProfile}.
*
* When used with {@link AutoModerationTriggerTypes.Keyword} and {@link AutoModerationTriggerTypes.MemberProfile}, there can be up to 100 elements in the array and each string can have up to 60 characters.
* When used with {@link AutoModerationTriggerTypes.KeywordPreset}, there can be up to 1000 elements in the array and each string can have up to 60 characters.
*/
allowList?: string[]
/**
* Total number of unique role and user mentions allowed per message.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.MentionSpam}.
*
* Maximum of 50
*/
mentionTotalLimit?: number
regexPatterns: string[]
/**
* Whether to automatically detect mention raids.
*
* @remarks
* Only present with {@link AutoModerationTriggerTypes.MentionSpam}.
*/
mentionRaidProtectionEnabled?: boolean
}
export interface AvatarDecorationData {
@@ -901,7 +947,7 @@ export interface Interaction {
/** The type of interaction */
type: InteractionTypes
/** Guild that the interaction was sent from */
guild: Guild
guild?: Partial<Guild>
/** The guild it was sent from */
guildId?: bigint
/** The channel it was sent from */

View File

@@ -17,13 +17,11 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js discordeno",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:type": "tsc --noEmit",
"test:test-type": "tsc --project tests/tsconfig.json"
"test:unit": "c8 -r lcov mocha 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js discordeno",
"test:deno-unit": "deno -A npm:mocha 'tests/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/**/*.spec.ts'",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"dependencies": {
"@discordeno/bot": "workspace:^",
@@ -33,12 +31,12 @@
"@discordeno/utils": "workspace:^"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/chai": "^5.2.3",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"c8": "^10.1.3",
"chai": "^6.2.2",
"mocha": "^11.7.5",

View File

@@ -17,30 +17,28 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/unit/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js gateway",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/unit/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:integration": "c8 --r lcov mocha --no-warnings --t 15000 'tests/integration/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js gateway",
"test:type": "tsc --noEmit",
"test:test-type": "tsc --project tests/tsconfig.json"
"test:unit": "c8 -r lcov mocha 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js gateway",
"test:deno-unit": "deno -A npm:mocha 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/unit/**/*.spec.ts'",
"test:integration": "c8 -r lcov mocha -t 15000 'tests/integration/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js gateway",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"dependencies": {
"@discordeno/types": "workspace:^",
"@discordeno/utils": "workspace:^",
"ws": "^8.18.3"
"ws": "^8.19.0"
},
"optionalDependencies": {
"fzstd": "^0.1.1"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/chai": "^5.2.3",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"@types/sinon": "^21.0.0",
"@types/ws": "^8.18.1",
"c8": "^10.1.3",

View File

@@ -730,7 +730,6 @@ export class DiscordenoShard {
break
case 'READY': {
const payload = packet.d as DiscordReady
this.events.ready?.(this)
// Important for future resumes.
this.resumeGatewayUrl = payload.resume_gateway_url
@@ -739,6 +738,7 @@ export class DiscordenoShard {
this.state = ShardState.Connected
this.logger.debug(`[Shard] Shard #${this.id} received READY`)
this.events.ready?.(this)
// Continue the requests which have been queued since the shard went offline.
// Important when this is a re-identify

View File

@@ -17,27 +17,25 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/unit/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/unit/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/unit/**/*.spec.ts'",
"test:e2e": "c8 --r lcov mocha --exit --no-warnings --jobs 1 --t 60000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest",
"test:type": "tsc --noEmit",
"test:test-type": "tsc --project tests/tsconfig.json"
"test:unit": "c8 -r lcov mocha 'tests/unit/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest",
"test:deno-unit": "deno -A npm:mocha 'tests/unit/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/unit/**/*.spec.ts'",
"test:e2e": "c8 -r lcov mocha -t 60000 'tests/e2e/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js rest",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"dependencies": {
"@discordeno/types": "workspace:^",
"@discordeno/utils": "workspace:^"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/chai": "^5.2.3",
"@types/chai-as-promised": "^8.0.2",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"@types/sinon": "^21.0.0",
"c8": "^10.1.3",
"chai": "^6.2.2",

View File

@@ -819,6 +819,10 @@ export function createRestManager(options: CreateRestManagerOptions): RestManage
return await rest.post<DiscordInvite>(rest.routes.channels.invites(channelId), { body, reason })
},
async getGuildRoleMemberCounts(guildId) {
return await rest.get<Record<string, number>>(rest.routes.guilds.roles.memberCounts(guildId))
},
async createRole(guildId, body, reason) {
return await rest.post<DiscordRole>(rest.routes.guilds.roles.all(guildId), { body, reason })
},

View File

@@ -2,29 +2,37 @@ import type { GetMessagesOptions, GetScheduledEventUsers } from '@discordeno/typ
import { isGetMessagesAfter, isGetMessagesAround, isGetMessagesBefore, isGetMessagesLimit } from '@discordeno/utils'
import type { RestRoutes } from './typings/routes.js'
export function createRoutes(): RestRoutes {
/**
* Creates the available discord API routes
*
* @param disableURIEncode Don't encode strings, except where required - Danger: disabling URI encoding may lead to path traversal if unsafe strings are used
* @returns The available discord API routes
*/
export function createRoutes(disableURIEncode: boolean = false): RestRoutes {
const encode: typeof encodeComponent = disableURIEncode ? (x) => x.toString() : encodeComponent
return {
webhooks: {
id: (webhookId) => {
return `/webhooks/${webhookId}`
return `/webhooks/${encode(webhookId)}`
},
message: (webhookId, token, messageId, options) => {
let url = `/webhooks/${webhookId}/${token}/messages/${messageId}?`
let url = `/webhooks/${encode(webhookId)}/${encode(token)}/messages/${encode(messageId)}?`
if (options) {
if (options.threadId) url += `thread_id=${options.threadId}`
if (options.withComponents) url += `&with_components=${options.withComponents}`
if (options.threadId) url += `thread_id=${encode(options.threadId)}`
if (options.withComponents) url += `&with_components=${encode(options.withComponents)}`
}
return url
},
webhook: (webhookId, token, options) => {
let url = `/webhooks/${webhookId}/${token}?`
let url = `/webhooks/${encode(webhookId)}/${encode(token)}?`
if (options) {
if (options?.wait !== undefined) url += `wait=${options.wait.toString()}`
if (options.threadId) url += `&thread_id=${options.threadId}`
if (options.withComponents) url += `&with_components=${options.withComponents}`
if (options?.wait !== undefined) url += `wait=${encode(options.wait)}`
if (options.threadId) url += `&thread_id=${encode(options.threadId)}`
if (options.withComponents) url += `&with_components=${encode(options.withComponents)}`
}
return url
@@ -34,106 +42,104 @@ export function createRoutes(): RestRoutes {
// Channel Endpoints
channels: {
bulk: (channelId) => {
return `/channels/${channelId}/messages/bulk-delete`
return `/channels/${encode(channelId)}/messages/bulk-delete`
},
dm: () => {
return '/users/@me/channels'
},
dmRecipient: (channelId, userId) => {
return `/channels/${channelId}/recipients/${userId}`
return `/channels/${encode(channelId)}/recipients/${encode(userId)}`
},
pin: (channelId, messageId) => {
return `/channels/${channelId}/pins/${messageId}`
return `/channels/${encode(channelId)}/pins/${encode(messageId)}`
},
pins: (channelId) => {
return `/channels/${channelId}/pins`
return `/channels/${encode(channelId)}/pins`
},
messagePins: (channelId, options) => {
let url = `/channels/${channelId}/messages/pins?`
let url = `/channels/${encode(channelId)}/messages/pins?`
if (options) {
if (options.before) url += `before=${options.before}`
if (options.limit) url += `&limit=${options.limit}`
if (options.before) url += `before=${encode(options.before)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
messagePin: (channelId, messageId) => {
return `/channels/${channelId}/messages/pins/${messageId}`
return `/channels/${encode(channelId)}/messages/pins/${encode(messageId)}`
},
reactions: {
bot: (channelId, messageId, emoji) => {
return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/@me`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}/reactions/${encodeURIComponent(emoji)}/@me`
},
user: (channelId, messageId, emoji, userId) => {
return `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}/${userId}`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}/reactions/${encodeURIComponent(emoji)}/${encode(userId)}`
},
all: (channelId, messageId) => {
return `/channels/${channelId}/messages/${messageId}/reactions`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}/reactions`
},
emoji: (channelId, messageId, emoji, options) => {
let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`
let url = `/channels/${encode(channelId)}/messages/${encode(messageId)}/reactions/${encodeURIComponent(emoji)}?`
if (options) {
if (options.type) url += `type=${options.type}`
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
if (options.after) url += `&after=${options.after}`
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
if (options.limit) url += `&limit=${options.limit}`
if (options.type) url += `type=${encode(options.type)}`
if (options.after) url += `&after=${encode(options.after)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
message: (channelId, messageId, emoji, options) => {
let url = `/channels/${channelId}/messages/${messageId}/reactions/${encodeURIComponent(emoji)}?`
let url = `/channels/${encode(channelId)}/messages/${encode(messageId)}/reactions/${encodeURIComponent(emoji)}?`
if (options) {
if (options.after) url += `after=${options.after}`
if (options.limit) url += `&limit=${options.limit}`
if (options.after) url += `after=${encode(options.after)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
},
webhooks: (channelId) => {
return `/channels/${channelId}/webhooks`
return `/channels/${encode(channelId)}/webhooks`
},
channel: (channelId) => {
return `/channels/${channelId}`
return `/channels/${encode(channelId)}`
},
follow: (channelId) => {
return `/channels/${channelId}/followers`
return `/channels/${encode(channelId)}/followers`
},
forum: (channelId) => {
return `/channels/${channelId}/threads`
return `/channels/${encode(channelId)}/threads`
},
invites: (channelId) => {
return `/channels/${channelId}/invites`
return `/channels/${encode(channelId)}/invites`
},
message: (channelId, messageId) => {
return `/channels/${channelId}/messages/${messageId}`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}`
},
messages: (channelId, options?: GetMessagesOptions) => {
let url = `/channels/${channelId}/messages?`
let url = `/channels/${encode(channelId)}/messages?`
if (options) {
if (isGetMessagesAfter(options) && options.after) {
url += `after=${options.after}`
url += `after=${encode(options.after)}`
}
if (isGetMessagesBefore(options) && options.before) {
url += `&before=${options.before}`
url += `&before=${encode(options.before)}`
}
if (isGetMessagesAround(options) && options.around) {
url += `&around=${options.around}`
url += `&around=${encode(options.around)}`
}
if (isGetMessagesLimit(options) && options.limit) {
url += `&limit=${options.limit}`
url += `&limit=${encode(options.limit)}`
}
}
@@ -141,11 +147,11 @@ export function createRoutes(): RestRoutes {
},
overwrite: (channelId, overwriteId) => {
return `/channels/${channelId}/permissions/${overwriteId}`
return `/channels/${encode(channelId)}/permissions/${encode(overwriteId)}`
},
crosspost: (channelId, messageId) => {
return `/channels/${channelId}/messages/${messageId}/crosspost`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}/crosspost`
},
stages: () => {
@@ -153,81 +159,84 @@ export function createRoutes(): RestRoutes {
},
stage: (channelId) => {
return `/stage-instances/${channelId}`
return `/stage-instances/${encode(channelId)}`
},
// Thread Endpoints
threads: {
message: (channelId, messageId) => {
return `/channels/${channelId}/messages/${messageId}/threads`
return `/channels/${encode(channelId)}/messages/${encode(messageId)}/threads`
},
all: (channelId) => {
return `/channels/${channelId}/threads`
return `/channels/${encode(channelId)}/threads`
},
active: (guildId) => {
return `/guilds/${guildId}/threads/active`
return `/guilds/${encode(guildId)}/threads/active`
},
members: (channelId, options) => {
let url = `/channels/${channelId}/thread-members?`
let url = `/channels/${encode(channelId)}/thread-members?`
if (options) {
if (options.withMember) url += `with_member=${options.withMember}`
if (options.limit) url += `&limit=${options.limit}`
if (options.after) url += `&after=${options.after}`
if (options.withMember) url += `with_member=${encode(options.withMember)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
if (options.after) url += `&after=${encode(options.after)}`
}
return url
},
me: (channelId) => {
return `/channels/${channelId}/thread-members/@me`
return `/channels/${encode(channelId)}/thread-members/@me`
},
getUser(channelId, userId, options) {
let url = `/channels/${channelId}/thread-members/${userId}?`
let url = `/channels/${encode(channelId)}/thread-members/${encode(userId)}?`
if (options) {
if (options.withMember) url += `with_member=${options.withMember}`
if (options.withMember) url += `with_member=${encode(options.withMember)}`
}
return url
},
user: (channelId, userId) => {
return `/channels/${channelId}/thread-members/${userId}`
return `/channels/${encode(channelId)}/thread-members/${encode(userId)}`
},
archived: (channelId) => {
return `/channels/${channelId}/threads/archived`
return `/channels/${encode(channelId)}/threads/archived`
},
public: (channelId, options) => {
let url = `/channels/${channelId}/threads/archived/public?`
let url = `/channels/${encode(channelId)}/threads/archived/public?`
if (options) {
if (options.before) {
url += `before=${new Date(options.before).toISOString()}`
const iso = new Date(options.before).toISOString()
url += `before=${encode(iso)}`
}
if (options.limit) url += `&limit=${options.limit}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
private: (channelId, options) => {
let url = `/channels/${channelId}/threads/archived/private?`
let url = `/channels/${encode(channelId)}/threads/archived/private?`
if (options) {
if (options.before) {
url += `before=${new Date(options.before).toISOString()}`
const iso = new Date(options.before).toISOString()
url += `before=${encode(iso)}`
}
if (options.limit) url += `&limit=${options.limit}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
joined: (channelId, options) => {
let url = `/channels/${channelId}/users/@me/threads/archived/private?`
let url = `/channels/${encode(channelId)}/users/@me/threads/archived/private?`
if (options) {
if (options.before) {
url += `before=${new Date(options.before).toISOString()}`
const iso = new Date(options.before).toISOString()
url += `before=${encode(iso)}`
}
if (options.limit) url += `&limit=${options.limit}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
@@ -235,22 +244,22 @@ export function createRoutes(): RestRoutes {
},
typing: (channelId) => {
return `/channels/${channelId}/typing`
return `/channels/${encode(channelId)}/typing`
},
polls: {
votes: (channelId, messageId, answerId, options) => {
let url = `/channels/${channelId}/polls/${messageId}/answers/${answerId}?`
let url = `/channels/${encode(channelId)}/polls/${encode(messageId)}/answers/${encode(answerId)}?`
if (options) {
if (options.after) url += `after=${options.after}`
if (options.limit) url += `&limit=${options.limit}`
if (options.after) url += `after=${encode(options.after)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
},
expire: (channelId, messageId) => {
return `/channels/${channelId}/polls/${messageId}/expire`
return `/channels/${encode(channelId)}/polls/${encode(messageId)}/expire`
},
},
},
@@ -264,167 +273,167 @@ export function createRoutes(): RestRoutes {
let url = '/users/@me/guilds?'
if (options) {
if (options.after) url += `after=${options.after}`
if (options.before) url += `&before=${options.before}`
if (options.limit) url += `&limit=${options.limit}`
if (options.withCounts) url += `&with_counts=${options.withCounts}`
if (options.after) url += `after=${encode(options.after)}`
if (options.before) url += `&before=${encode(options.before)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
if (options.withCounts) url += `&with_counts=${encode(options.withCounts)}`
}
return url
},
auditlogs: (guildId, options) => {
let url = `/guilds/${guildId}/audit-logs?`
let url = `/guilds/${encode(guildId)}/audit-logs?`
if (options) {
if (options.actionType) url += `action_type=${options.actionType}`
if (options.before) url += `&before=${options.before}`
if (options.after) url += `&after=${options.after}`
if (options.limit) url += `&limit=${options.limit}`
if (options.userId) url += `&user_id=${options.userId}`
if (options.actionType) url += `action_type=${encode(options.actionType)}`
if (options.before) url += `&before=${encode(options.before)}`
if (options.after) url += `&after=${encode(options.after)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
if (options.userId) url += `&user_id=${encode(options.userId)}`
}
return url
},
automod: {
rule: (guildId, ruleId) => {
return `/guilds/${guildId}/auto-moderation/rules/${ruleId}`
return `/guilds/${encode(guildId)}/auto-moderation/rules/${encode(ruleId)}`
},
rules: (guildId) => {
return `/guilds/${guildId}/auto-moderation/rules`
return `/guilds/${encode(guildId)}/auto-moderation/rules`
},
},
channels: (guildId) => {
return `/guilds/${guildId}/channels`
return `/guilds/${encode(guildId)}/channels`
},
emoji: (guildId, emojiId) => {
return `/guilds/${guildId}/emojis/${emojiId}`
return `/guilds/${encode(guildId)}/emojis/${encode(emojiId)}`
},
emojis: (guildId) => {
return `/guilds/${guildId}/emojis`
return `/guilds/${encode(guildId)}/emojis`
},
events: {
events: (guildId, withUserCount?: boolean) => {
let url = `/guilds/${guildId}/scheduled-events?`
let url = `/guilds/${encode(guildId)}/scheduled-events?`
if (withUserCount !== undefined) {
url += `with_user_count=${withUserCount.toString()}`
url += `with_user_count=${encode(withUserCount)}`
}
return url
},
event: (guildId, eventId, withUserCount?: boolean) => {
let url = `/guilds/${guildId}/scheduled-events/${eventId}`
let url = `/guilds/${encode(guildId)}/scheduled-events/${encode(eventId)}`
if (withUserCount !== undefined) {
url += `with_user_count=${withUserCount.toString()}`
url += `with_user_count=${encode(withUserCount)}`
}
return url
},
users: (guildId, eventId, options?: GetScheduledEventUsers) => {
let url = `/guilds/${guildId}/scheduled-events/${eventId}/users?`
let url = `/guilds/${encode(guildId)}/scheduled-events/${encode(eventId)}/users?`
if (options) {
if (options.limit !== undefined) url += `limit=${options.limit}`
if (options.limit !== undefined) url += `limit=${encode(options.limit)}`
if (options.withMember !== undefined) {
url += `&with_member=${options.withMember.toString()}`
url += `&with_member=${encode(options.withMember)}`
}
if (options.after !== undefined) url += `&after=${options.after}`
if (options.before !== undefined) url += `&before=${options.before}`
if (options.after !== undefined) url += `&after=${encode(options.after)}`
if (options.before !== undefined) url += `&before=${encode(options.before)}`
}
return url
},
},
guild(guildId, withCounts) {
let url = `/guilds/${guildId}?`
let url = `/guilds/${encode(guildId)}?`
if (withCounts !== undefined) {
url += `with_counts=${withCounts.toString()}`
url += `with_counts=${encode(withCounts)}`
}
return url
},
integration(guildId, integrationId) {
return `/guilds/${guildId}/integrations/${integrationId}`
return `/guilds/${encode(guildId)}/integrations/${encode(integrationId)}`
},
integrations: (guildId) => {
return `/guilds/${guildId}/integrations?include_applications=true`
return `/guilds/${encode(guildId)}/integrations?include_applications=true`
},
invite(inviteCode, options) {
let url = `/invites/${inviteCode}?`
let url = `/invites/${encode(inviteCode)}?`
if (options) {
if (options.withCounts !== undefined) {
url += `with_counts=${options.withCounts.toString()}`
url += `with_counts=${encode(options.withCounts)}`
}
if (options.scheduledEventId) {
url += `&guild_scheduled_event_id=${options.scheduledEventId}`
url += `&guild_scheduled_event_id=${encode(options.scheduledEventId)}`
}
}
return url
},
invites: (guildId) => {
return `/guilds/${guildId}/invites`
return `/guilds/${encode(guildId)}/invites`
},
leave: (guildId) => {
return `/users/@me/guilds/${guildId}`
return `/users/@me/guilds/${encode(guildId)}`
},
members: {
ban: (guildId, userId) => {
return `/guilds/${guildId}/bans/${userId}`
return `/guilds/${encode(guildId)}/bans/${encode(userId)}`
},
bans: (guildId, options) => {
let url = `/guilds/${guildId}/bans?`
let url = `/guilds/${encode(guildId)}/bans?`
if (options) {
if (options.limit) url += `limit=${options.limit}`
if (options.after) url += `&after=${options.after}`
if (options.before) url += `&before=${options.before}`
if (options.limit) url += `limit=${encode(options.limit)}`
if (options.after) url += `&after=${encode(options.after)}`
if (options.before) url += `&before=${encode(options.before)}`
}
return url
},
bulkBan: (guildId) => {
return `/guilds/${guildId}/bulk-ban`
return `/guilds/${encode(guildId)}/bulk-ban`
},
bot: (guildId) => {
return `/guilds/${guildId}/members/@me`
return `/guilds/${encode(guildId)}/members/@me`
},
member: (guildId, userId) => {
return `/guilds/${guildId}/members/${userId}`
return `/guilds/${encode(guildId)}/members/${encode(userId)}`
},
currentMember: (guildId) => {
return `/users/@me/guilds/${guildId}/member`
return `/users/@me/guilds/${encode(guildId)}/member`
},
members: (guildId, options) => {
let url = `/guilds/${guildId}/members?`
let url = `/guilds/${encode(guildId)}/members?`
if (options !== undefined) {
if (options.limit) url += `limit=${options.limit}`
if (options.after) url += `&after=${options.after}`
if (options.limit) url += `limit=${encode(options.limit)}`
if (options.after) url += `&after=${encode(options.after)}`
}
return url
},
search: (guildId, query, options) => {
let url = `/guilds/${guildId}/members/search?query=${encodeURIComponent(query)}`
let url = `/guilds/${encode(guildId)}/members/search?query=${encode(query)}`
if (options) {
if (options.limit !== undefined) url += `&limit=${options.limit}`
if (options.limit !== undefined) url += `&limit=${encode(options.limit)}`
}
return url
},
prune: (guildId, options) => {
let url = `/guilds/${guildId}/prune?`
let url = `/guilds/${encode(guildId)}/prune?`
if (options) {
if (options.days) url += `days=${options.days}`
if (options.days) url += `days=${encode(options.days)}`
if (Array.isArray(options.includeRoles)) {
url += `&include_roles=${options.includeRoles.join(',')}`
url += `&include_roles=${encode(options.includeRoles.join(','))}`
} else if (options.includeRoles) {
url += `&include_roles=${options.includeRoles}`
url += `&include_roles=${encode(options.includeRoles)}`
}
}
@@ -432,17 +441,17 @@ export function createRoutes(): RestRoutes {
},
},
preview: (guildId) => {
return `/guilds/${guildId}/preview`
return `/guilds/${encode(guildId)}/preview`
},
prune: (guildId, options) => {
let url = `/guilds/${guildId}/prune?`
let url = `/guilds/${encode(guildId)}/prune?`
if (options) {
if (options.days) url += `days=${options.days}`
if (options.days) url += `days=${encode(options.days)}`
if (Array.isArray(options.includeRoles)) {
url += `&include_roles=${options.includeRoles.join(',')}`
url += `&include_roles=${encode(options.includeRoles.join(','))}`
} else if (options.includeRoles) {
url += `&include_roles=${options.includeRoles}`
url += `&include_roles=${encode(options.includeRoles)}`
}
}
@@ -450,63 +459,66 @@ export function createRoutes(): RestRoutes {
},
roles: {
one: (guildId, roleId) => {
return `/guilds/${guildId}/roles/${roleId}`
return `/guilds/${encode(guildId)}/roles/${encode(roleId)}`
},
all: (guildId) => {
return `/guilds/${guildId}/roles`
return `/guilds/${encode(guildId)}/roles`
},
member: (guildId, memberId, roleId) => {
return `/guilds/${guildId}/members/${memberId}/roles/${roleId}`
return `/guilds/${encode(guildId)}/members/${encode(memberId)}/roles/${encode(roleId)}`
},
memberCounts: (guildId) => {
return `/guilds/${guildId}/roles/member-counts`
},
},
stickers: (guildId) => {
return `/guilds/${guildId}/stickers`
return `/guilds/${encode(guildId)}/stickers`
},
sticker: (guildId, stickerId) => {
return `/guilds/${guildId}/stickers/${stickerId}`
return `/guilds/${encode(guildId)}/stickers/${encode(stickerId)}`
},
voice: (guildId, userId) => {
return `/guilds/${guildId}/voice-states/${userId ?? '@me'}`
return `/guilds/${encode(guildId)}/voice-states/${encode(userId ?? '@me')}`
},
templates: {
code: (code) => {
return `/guilds/templates/${code}`
return `/guilds/templates/${encode(code)}`
},
guild: (guildId, code) => {
return `/guilds/${guildId}/templates/${code}`
return `/guilds/${encode(guildId)}/templates/${encode(code)}`
},
all: (guildId) => {
return `/guilds/${guildId}/templates`
return `/guilds/${encode(guildId)}/templates`
},
},
vanity: (guildId) => {
return `/guilds/${guildId}/vanity-url`
return `/guilds/${encode(guildId)}/vanity-url`
},
regions: (guildId) => {
return `/guilds/${guildId}/regions`
return `/guilds/${encode(guildId)}/regions`
},
webhooks: (guildId) => {
return `/guilds/${guildId}/webhooks`
return `/guilds/${encode(guildId)}/webhooks`
},
welcome: (guildId) => {
return `/guilds/${guildId}/welcome-screen`
return `/guilds/${encode(guildId)}/welcome-screen`
},
widget: (guildId) => {
return `/guilds/${guildId}/widget`
return `/guilds/${encode(guildId)}/widget`
},
widgetJson: (guildId) => {
return `/guilds/${guildId}/widget.json`
return `/guilds/${encode(guildId)}/widget.json`
},
onboarding: (guildId) => {
return `/guilds/${guildId}/onboarding`
return `/guilds/${encode(guildId)}/onboarding`
},
incidentActions: (guildId) => {
return `/guilds/${guildId}/incident-actions`
return `/guilds/${encode(guildId)}/incident-actions`
},
},
sticker: (stickerId) => {
return `/stickers/${stickerId}`
return `/stickers/${encode(stickerId)}`
},
regions: () => {
@@ -518,10 +530,10 @@ export function createRoutes(): RestRoutes {
commands: {
// Application Endpoints
commands: (applicationId, withLocalizations) => {
let url = `/applications/${applicationId}/commands?`
let url = `/applications/${encode(applicationId)}/commands?`
if (withLocalizations !== undefined) {
url += `with_localizations=${withLocalizations.toString()}`
url += `with_localizations=${encode(withLocalizations)}`
}
return url
@@ -529,30 +541,30 @@ export function createRoutes(): RestRoutes {
guilds: {
all(applicationId, guildId, withLocalizations) {
let url = `/applications/${applicationId}/guilds/${guildId}/commands?`
let url = `/applications/${encode(applicationId)}/guilds/${encode(guildId)}/commands?`
if (withLocalizations !== undefined) {
url += `with_localizations=${withLocalizations.toString()}`
url += `with_localizations=${encode(withLocalizations)}`
}
return url
},
one(applicationId, guildId, commandId) {
return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}`
return `/applications/${encode(applicationId)}/guilds/${encode(guildId)}/commands/${encode(commandId)}`
},
},
permissions: (applicationId, guildId) => {
return `/applications/${applicationId}/guilds/${guildId}/commands/permissions`
return `/applications/${encode(applicationId)}/guilds/${encode(guildId)}/commands/permissions`
},
permission: (applicationId, guildId, commandId) => {
return `/applications/${applicationId}/guilds/${guildId}/commands/${commandId}/permissions`
return `/applications/${encode(applicationId)}/guilds/${encode(guildId)}/commands/${encode(commandId)}/permissions`
},
command: (applicationId, commandId, withLocalizations) => {
let url = `/applications/${applicationId}/commands/${commandId}?`
let url = `/applications/${encode(applicationId)}/commands/${encode(commandId)}?`
if (withLocalizations !== undefined) {
url += `withLocalizations=${withLocalizations.toString()}`
url += `withLocalizations=${encode(withLocalizations)}`
}
return url
@@ -562,13 +574,13 @@ export function createRoutes(): RestRoutes {
responses: {
// Interaction Endpoints
callback: (interactionId, token, options) => {
return `/interactions/${interactionId}/${token}/callback?with_response=${!!options?.withResponse}`
return `/interactions/${encode(interactionId)}/${encode(token)}/callback?with_response=${encode(!!options?.withResponse)}`
},
original: (interactionId, token) => {
return `/webhooks/${interactionId}/${token}/messages/@original`
return `/webhooks/${encode(interactionId)}/${encode(token)}/messages/@original`
},
message: (applicationId, token, messageId) => {
return `/webhooks/${applicationId}/${token}/messages/${messageId}`
return `/webhooks/${encode(applicationId)}/${encode(token)}/messages/${encode(messageId)}`
},
},
},
@@ -591,49 +603,49 @@ export function createRoutes(): RestRoutes {
return '/users/@me/connections'
},
roleConnections: (applicationId) => {
return `/users/@me/applications/${applicationId}/role-connection`
return `/users/@me/applications/${encode(applicationId)}/role-connection`
},
},
monetization: {
entitlements: (applicationId, options) => {
let url = `/applications/${applicationId}/entitlements?`
let url = `/applications/${encode(applicationId)}/entitlements?`
if (options) {
if (options.after) url += `after=${options.after}`
if (options.before) url += `&before=${options.before}`
if (options.excludeEnded) url += `&exclude_ended=${options.excludeEnded}`
if (options.guildId) url += `&guild_id=${options.guildId}`
if (options.limit) url += `&limit=${options.limit}`
if (options.skuIds) url += `&sku_ids=${options.skuIds.join(',')}`
if (options.userId) url += `&user_id=${options.userId}`
if (options.after) url += `after=${encode(options.after)}`
if (options.before) url += `&before=${encode(options.before)}`
if (options.excludeEnded) url += `&exclude_ended=${encode(options.excludeEnded)}`
if (options.guildId) url += `&guild_id=${encode(options.guildId)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
if (options.skuIds) url += `&sku_ids=${encode(options.skuIds.join(','))}`
if (options.userId) url += `&user_id=${encode(options.userId)}`
}
return url
},
entitlement: (applicationId, entitlementId) => {
return `/applications/${applicationId}/entitlements/${entitlementId}`
return `/applications/${encode(applicationId)}/entitlements/${encode(entitlementId)}`
},
consumeEntitlement: (applicationId, entitlementId) => {
return `/applications/${applicationId}/entitlements/${entitlementId}/consume`
return `/applications/${encode(applicationId)}/entitlements/${encode(entitlementId)}/consume`
},
skus: (applicationId) => {
return `/applications/${applicationId}/skus`
return `/applications/${encode(applicationId)}/skus`
},
subscription: (skuId, subscriptionId) => {
return `/skus/${skuId}/subscriptions/${subscriptionId}`
return `/skus/${encode(skuId)}/subscriptions/${encode(subscriptionId)}`
},
subscriptions: (skuId, options) => {
let url = `/skus/${skuId}/subscriptions?`
let url = `/skus/${encode(skuId)}/subscriptions?`
if (options) {
if (options.after) url += `after=${options.after}`
if (options.before) url += `&before=${options.before}`
if (options.userId) url += `&user_id=${options.userId}`
if (options.limit) url += `&limit=${options.limit}`
if (options.after) url += `after=${encode(options.after)}`
if (options.before) url += `&before=${encode(options.before)}`
if (options.userId) url += `&user_id=${encode(options.userId)}`
if (options.limit) url += `&limit=${encode(options.limit)}`
}
return url
@@ -642,16 +654,16 @@ export function createRoutes(): RestRoutes {
soundboard: {
sendSound: (channelId) => {
return `/channels/${channelId}`
return `/channels/${encode(channelId)}`
},
listDefault: () => {
return `/soundboard-default-sounds`
},
guildSounds: (guildId) => {
return `/guilds/${guildId}/soundboard-sounds`
return `/guilds/${encode(guildId)}/soundboard-sounds`
},
guildSound: (guildId, soundId) => {
return `/guilds/${guildId}/soundboard-sounds/${soundId}`
return `/guilds/${encode(guildId)}/soundboard-sounds/${encode(soundId)}`
},
},
@@ -661,37 +673,37 @@ export function createRoutes(): RestRoutes {
},
lobby: (lobbyId) => {
return `/lobbies/${lobbyId}`
return `/lobbies/${encode(lobbyId)}`
},
member: (lobbyId, userId) => {
return `/lobbies/${lobbyId}/members/${userId}`
return `/lobbies/${encode(lobbyId)}/members/${encode(userId)}`
},
leave: (lobbyId) => {
return `/lobbies/${lobbyId}/members/@me`
return `/lobbies/${encode(lobbyId)}/members/@me`
},
link: (lobbyId) => {
return `/lobbies/${lobbyId}/channel-linking`
return `/lobbies/${encode(lobbyId)}/channel-linking`
},
},
applicationEmoji(applicationId, emojiId) {
return `/applications/${applicationId}/emojis/${emojiId}`
return `/applications/${encode(applicationId)}/emojis/${encode(emojiId)}`
},
applicationEmojis(applicationId) {
return `/applications/${applicationId}/emojis`
return `/applications/${encode(applicationId)}/emojis`
},
applicationRoleConnectionMetadata(applicationId) {
return `/applications/${applicationId}/role-connections/metadata`
return `/applications/${encode(applicationId)}/role-connections/metadata`
},
// User endpoints
user(userId) {
return `/users/${userId}`
return `/users/${encode(userId)}`
},
application() {
@@ -699,7 +711,7 @@ export function createRoutes(): RestRoutes {
},
applicationActivityInstance(applicationId, instanceId) {
return `/applications/${applicationId}/activity-instances/${instanceId}`
return `/applications/${encode(applicationId)}/activity-instances/${encode(instanceId)}`
},
currentUser() {
@@ -711,7 +723,7 @@ export function createRoutes(): RestRoutes {
},
stickerPack(stickerPackId) {
return `/sticker-packs/${stickerPackId}`
return `/sticker-packs/${encode(stickerPackId)}`
},
stickerPacks() {
@@ -719,3 +731,10 @@ export function createRoutes(): RestRoutes {
},
}
}
function encodeComponent(uriComponent: string | number | bigint | boolean): string {
if (typeof uriComponent !== 'string') return uriComponent.toString()
if (/^\d+$/.test(uriComponent)) return uriComponent
return encodeURIComponent(uriComponent)
}

View File

@@ -558,6 +558,16 @@ export interface RestManager {
* @see {@link https://discord.com/developers/docs/resources/channel#create-channel-invite}
*/
createInvite: (channelId: BigString, options?: CreateChannelInvite, reason?: string) => Promise<Camelize<DiscordInvite>>
/**
* Get guild role member counts
*
* Returns a map of role IDs to the number of members with the role. Does not include the \@everyone role.
*
* @param guildId - The ID of the guild to get role member counts for.
*
* @see {@link https://discord.com/developers/docs/resources/guild#get-guild-role-member-counts}
*/
getGuildRoleMemberCounts: (guildId: BigString) => Promise<Record<string, number>>
/**
* Creates a role in a guild.
*

View File

@@ -215,6 +215,8 @@ export interface RestRoutes {
all: (guildId: BigString) => string
/** Route for handling a members roles in a guild. */
member: (guildId: BigString, memberId: BigString, roleId: BigString) => string
/** Route for the role member counts */
memberCounts: (guildId: BigString) => string
}
/** Route for handling a specific guild sticker. */
stickers: (guildId: BigString) => string

View File

@@ -1,8 +1,8 @@
import { AutoModerationActionType, AutoModerationEventTypes, AutoModerationTriggerTypes } from '@discordeno/types'
import { expect } from 'chai'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
describe('Automod tests', async () => {
describe('Automod tests', () => {
it('Create a MessageSend rule for Keyword with BlockMessage action.', async () => {
const rule = await rest.createAutomodRule(e2eCache.guild.id, {
name: 'test',
@@ -17,6 +17,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -30,8 +31,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions).to.be.exist
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(AutoModerationActionType.BlockMessage)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
it('Create a MessageSend rule for Keyword with Timeout action.', async () => {
@@ -51,6 +50,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -65,8 +65,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(AutoModerationActionType.Timeout)
expect(fetchedRule.actions[0].metadata?.durationSeconds).to.equal(10)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
it('Create a MessageSend rule for Keyword with BlockMessage & Timeout action.', async () => {
@@ -89,6 +87,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -103,8 +102,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions[0].type).to.equal(AutoModerationActionType.BlockMessage)
expect(fetchedRule.actions[1].type).to.equal(AutoModerationActionType.Timeout)
expect(fetchedRule.actions[1].metadata?.durationSeconds).to.equal(10)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
describe('with a channel', () => {
@@ -125,6 +122,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -139,8 +137,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions[0]).to.be.exist
expect(fetchedRule.actions[0].type).to.equal(AutoModerationActionType.SendAlertMessage)
expect(fetchedRule.actions[0].metadata?.channelId).to.equal(e2eCache.channel.id)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
it('Create a MessageSend rule for Keyword with SendAlertMessage & Timeout action.', async () => {
@@ -166,6 +162,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -182,8 +179,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions[0].metadata?.channelId).to.equal(e2eCache.channel.id)
expect(fetchedRule.actions[1].type).to.equal(AutoModerationActionType.Timeout)
expect(fetchedRule.actions[1].metadata?.durationSeconds).to.equal(10)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
it('Create a MessageSend rule for Keyword with BlockMessage & SendAlertMessage & Timeout action.', async () => {
@@ -212,6 +207,7 @@ describe('Automod tests', async () => {
},
],
})
toDispose.add(async () => await rest.deleteAutomodRule(e2eCache.guild.id, rule.id))
// Get the rule again to make sure it was created correctly
const fetchedRule = await rest.getAutomodRule(e2eCache.guild.id, rule.id)
@@ -232,8 +228,6 @@ describe('Automod tests', async () => {
expect(fetchedRule.actions[0].type).to.equal(AutoModerationActionType.BlockMessage)
expect(fetchedRule.actions[1].type).to.equal(AutoModerationActionType.SendAlertMessage)
expect(fetchedRule.actions[2].type).to.equal(AutoModerationActionType.Timeout)
await rest.deleteAutomodRule(e2eCache.guild.id, rule.id)
})
})
})

View File

@@ -1,9 +1,9 @@
import dotenv from 'dotenv'
dotenv.config({ path: '../../.env' })
dotenv.config({ path: '../../.env', quiet: true })
if (!process.env.DISCORD_TOKEN) throw new Error('Token was not provided.')
export const token = process.env.DISCORD_TOKEN
export const token = process.env.DISCORD_TOKEN!
if (!token) throw new Error('Token was not provided.')
export const E2E_TEST_GUILD_ID = process.env.E2E_TEST_GUILD_ID!
if (!E2E_TEST_GUILD_ID) throw new Error('COMMUNITY guild id was not provided.')

View File

@@ -3,7 +3,7 @@ import { urlToBase64 } from '@discordeno/utils'
import { use as chaiUse, expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe, it } from 'mocha'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
chaiUse(chaiAsPromised)
@@ -15,9 +15,10 @@ describe('Create and delete emojis', () => {
roles: [],
})
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!))
// Assertions
expect(emoji.id).to.be.exist
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
expect(emoji.id).to.exist
})
// delete an emoji without a reason
@@ -27,11 +28,15 @@ describe('Create and delete emojis', () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
const cleanEmoji = async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
toDispose.add(cleanEmoji)
// Assertions
expect(emoji.id).to.be.exist
expect(emoji.id).to.exist
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
// Remove from toDispose since we already deleted it
toDispose.delete(cleanEmoji)
await expect(rest.getEmoji(e2eCache.guild.id, emoji.id!)).to.eventually.rejected
})
@@ -43,11 +48,15 @@ describe('Create and delete emojis', () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
const cleanEmoji = async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
toDispose.add(cleanEmoji)
// Assertions
expect(emoji.id).to.be.exist
expect(emoji.id).to.exist
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!, 'with a reason')
// Remove from toDispose since we already deleted it
toDispose.delete(cleanEmoji)
await expect(rest.getEmoji(e2eCache.guild.id, emoji.id!)).to.eventually.rejected
})
@@ -62,10 +71,8 @@ describe('Edit and get emojis', () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})) as Camelize<DiscordEmoji> & { id: string }
})
afterEach(async () => {
await rest.deleteEmoji(e2eCache.guild.id, emoji.id)
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id))
})
// edit an emoji name
@@ -83,9 +90,8 @@ describe('Edit and get emojis', () => {
const role = await rest.createRole(e2eCache.guild.id, {
name: 'dd-test-emoji',
})
after(async () => {
await rest.deleteRole(e2eCache.guild.id, role.id)
})
toDispose.add(async () => await rest.deleteRole(e2eCache.guild.id, role.id))
await rest.editEmoji(e2eCache.guild.id, emoji.id, {
roles: [role.id],
})
@@ -108,12 +114,12 @@ describe('Edit and get emojis', () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/814955268123000832.png'),
roles: [],
})
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, newEmoji.id!))
const exists = await rest.getEmojis(e2eCache.guild.id)
expect(exists.length).to.greaterThan(1)
expect(exists.find((x) => x.id === newEmoji.id)).to.exist
expect(exists.find((x) => x.id === emoji.id)).to.exist
await rest.deleteEmoji(e2eCache.guild.id, newEmoji.id!)
})
})

View File

@@ -2,11 +2,11 @@ import { ChannelTypes } from '@discordeno/types'
import { use as chaiUse, expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe, it } from 'mocha'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
chaiUse(chaiAsPromised)
describe('Manage Guilds', async () => {
describe('Manage Guilds', () => {
it('Get a guild', async () => {
const exists = await rest.getGuild(e2eCache.guildId)
expect(exists).to.be.exist
@@ -20,14 +20,10 @@ describe('Manage Guilds', async () => {
name: 'e2e-afk-channel',
type: ChannelTypes.GuildVoice,
})
toDispose.add(async () => await rest.deleteChannel(voiceChannel.id))
expect(voiceChannel.id).to.be.exist
after(async () => {
// Clean up the AFK channel created for testing
await rest.deleteChannel(voiceChannel.id)
})
// Set the AFK channel
const edited = await rest.editGuild(e2eCache.guild.id, {
afkChannelId: voiceChannel.id,
@@ -65,7 +61,6 @@ describe('Manage Guilds', async () => {
expect(fetchedBan).to.be.exist
expect(fetchedBan.user.id).to.equal('379643682984296448')
// Assertions
expect(fetchedBans).to.be.exist
expect(fetchedBans.length).to.greaterThanOrEqual(2)

View File

@@ -1,14 +1,18 @@
import { processReactionString, urlToBase64 } from '@discordeno/utils'
import { expect } from 'chai'
import { describe, it } from 'mocha'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
describe('Send a message', () => {
it('With content', async () => {
const message = await rest.sendMessage(e2eCache.channel.id, { content: 'testing rate limit manager' })
expect(message.content).to.be.equal('testing rate limit manager')
const edited = await rest.editMessage(message.channelId, message.id, { content: 'testing rate limit manager edited' })
expect(message.content).to.be.not.equal(edited.content)
await rest.deleteMessage(message.channelId, message.id)
})
@@ -16,40 +20,43 @@ describe('Send a message', () => {
const image = await fetch('https://cdn.discordapp.com/avatars/270010330782892032/d031ea881688526d1ae235fd2843e53c.jpg?size=2048')
.then(async (res) => await res.blob())
.catch(() => undefined)
expect(image).to.not.be.undefined
if (!image) throw new Error('Was not able to fetch the image.')
const message = await rest.sendMessage(e2eCache.channel.id, { files: [{ blob: image, name: 'gamer' }] })
expect(message.attachments.length).to.be.greaterThan(0)
const message = await rest.sendMessage(e2eCache.channel.id, { files: [{ blob: image!, name: 'gamer' }] })
const [attachment] = message.attachments
expect(message.attachments.length).to.be.greaterThan(0)
expect(attachment.filename).to.be.equal('gamer')
})
it('With a file attachment', async () => {
const txtFile = new Blob(['hello world'], { type: 'text/plain' })
const fileMsg = await rest.sendMessage(e2eCache.channel.id, {
content: '222',
files: [
{
name: 'application.txt',
blob: txtFile,
blob: new Blob(['hello world'], { type: 'text/plain' }),
},
],
})
expect(fileMsg.id).not.equals(undefined)
expect(fileMsg.content).equals('222')
expect(fileMsg.attachments.length).equals(1)
expect(fileMsg.attachments.at(0)?.filename).equals('application.txt')
expect(fileMsg.attachments.at(0)?.size).equals(11)
const txtFile2 = new Blob(['hello world edit'], { type: 'text/plain' })
const edited = await rest.editMessage(e2eCache.channel.id, fileMsg.id, {
content: '222 edit',
files: [
{
name: 'application_edit.txt',
blob: txtFile2,
blob: new Blob(['hello world edit'], { type: 'text/plain' }),
},
],
})
expect(edited.id).not.equals(undefined)
expect(edited.content).equals('222 edit')
expect(edited.attachments.length).equals(1)
@@ -58,7 +65,7 @@ describe('Send a message', () => {
})
})
describe('Manage reactions', async () => {
describe('Manage reactions', () => {
it('Add and delete a unicode reaction', async () => {
const message = await rest.sendMessage(e2eCache.channel.id, { content: 'add reaction test' })
await rest.addReaction(message.channelId, message.id, '📙')
@@ -79,11 +86,7 @@ describe('Manage reactions', async () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/785403373817823272.webp?size=96'),
roles: [],
})
after(async () => {
// Clean up the emoji created for testing
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
})
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!))
const emojiCode = `<:${emoji.name!}:${emoji.id!}>`
@@ -109,11 +112,7 @@ describe('Manage reactions', async () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/785403373817823272.webp?size=96'),
roles: [],
})
after(async () => {
// Clean up the emoji created for testing
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
})
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!))
const emojiCode = `<:${emoji.name!}:${emoji.id!}>`
@@ -136,11 +135,7 @@ describe('Manage reactions', async () => {
image: await urlToBase64('https://cdn.discordapp.com/emojis/785403373817823272.webp?size=96'),
roles: [],
})
after(async () => {
// Clean up the emoji created for testing
await rest.deleteEmoji(e2eCache.guild.id, emoji.id!)
})
toDispose.add(async () => await rest.deleteEmoji(e2eCache.guild.id, emoji.id!))
const emojiCode = `<:${emoji.name!}:${emoji.id!}>`
@@ -197,10 +192,7 @@ describe('Rate limit manager testing', () => {
// Create 10 channels and send a message to each
const promises = Array.from({ length: 10 }, async (_, i) => {
const channel = await rest.createChannel(e2eCache.guild.id, { name: `rate-limit-${i}` })
after(async () => {
await rest.deleteChannel(channel.id)
})
toDispose.add(async () => await rest.deleteChannel(channel.id))
const messagePromises = Array.from({ length: 10 }, async (_, j) => {
await rest.sendMessage(channel.id, { content: `testing rate limit manager ${j}` })

View File

@@ -1,13 +1,16 @@
import { use as chaiUse, expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe } from 'mocha'
import { e2eCache, rest } from './utils.js'
chaiUse(chaiAsPromised)
describe('Typings', () => {
it('Trigger Typing Indication', async () => {
await rest.triggerTypingIndicator(e2eCache.channel.id)
})
})
/* TODO: Add this back when bot's name is changed (https://discord.com/channels/785384884197392384/785384884197392387/1142474846811459776)
describe('Commands', () => {
it('Upsert global commands', async () => {
await rest.upsertGlobalApplicationCommands([
@@ -33,7 +36,6 @@ describe('Commands', () => {
await rest.deleteGlobalApplicationCommand(created!.id)
expect(rest.getGlobalApplicationCommand(created!.id)).to.throw
await expect(rest.getGlobalApplicationCommand(created!.id)).to.eventually.be.rejected
})
})
*/

View File

@@ -1,17 +1,13 @@
import { calculateBits } from '@discordeno/utils'
import { expect } from 'chai'
import { describe, it } from 'mocha'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
describe('Role tests', async () => {
describe('Role tests', () => {
// Create a role with a reason
it('Create a role with a reason', async () => {
const role = await rest.createRole(e2eCache.guild?.id, { name: `test role ${Date.now()}` }, 'test reason')
after(async () => {
// Clean up the role created for testing
await rest.deleteRole(e2eCache.guild.id, role.id)
})
toDispose.add(async () => await rest.deleteRole(e2eCache.guild.id, role.id))
expect(role.id).to.exist
})
@@ -21,11 +17,7 @@ describe('Role tests', async () => {
const role = await rest.createRole(e2eCache.guild.id, {
name: `test role ${Date.now()}`,
})
after(async () => {
// Clean up the role created for testing
await rest.deleteRole(e2eCache.guild.id, role.id)
})
toDispose.add(async () => await rest.deleteRole(e2eCache.guild.id, role.id))
expect(role.id).to.exist
})
@@ -47,11 +39,7 @@ describe('Role tests', async () => {
const role = await rest.createRole(e2eCache.guild.id, {
name: `test role ${Date.now()}`,
})
after(async () => {
// Clean up the role created for testing
await rest.deleteRole(e2eCache.guild.id, role.id)
})
toDispose.add(async () => await rest.deleteRole(e2eCache.guild.id, role.id))
const edited = await rest.editRole(e2eCache.guild.id, role.id, {
name: 'test role 4',
@@ -82,11 +70,7 @@ describe('Role tests', async () => {
const role = await rest.createRole(e2eCache.guild.id, {
name: `test role ${Date.now()}`,
})
after(async () => {
// Clean up the role created for testing
await rest.deleteRole(e2eCache.guild.id, role.id)
})
toDispose.add(async () => await rest.deleteRole(e2eCache.guild.id, role.id))
// Assign the role to the user
await rest.addRole(e2eCache.guild.id, rest.applicationId, role.id)

View File

@@ -2,12 +2,12 @@ import { StickerFormatTypes } from '@discordeno/types'
import { use as chaiUse, expect } from 'chai'
import chaiAsPromised from 'chai-as-promised'
import { describe, it } from 'mocha'
import { e2eCache, rest } from './utils.js'
import { e2eCache, rest, toDispose } from './utils.js'
chaiUse(chaiAsPromised)
// waiting for channel
describe('Sticker tests', async () => {
describe('Sticker tests', () => {
it('Can get a sticker', async () => {
const sticker = await rest.getSticker(749054660769218631n)
expect(sticker.name).to.equal('Wave')
@@ -23,6 +23,10 @@ describe('Sticker tests', async () => {
name: 'ddlogo.png',
},
})
const cleanSticker = async () => await rest.deleteGuildSticker(e2eCache.guild.id, sticker.id)
// We may remove this as we also test sticker deletion at the end of the test, so we need a var to reference the function
toDispose.add(cleanSticker)
expect(sticker.name).to.equal('sticker name')
expect(sticker.description).to.equal('sticker description')
@@ -62,15 +66,15 @@ describe('Sticker tests', async () => {
},
})
after(async () => {
// Clean up the sticker created for testing
await rest.deleteGuildSticker(e2eCache.guild.id, sticker2.id)
})
toDispose.add(async () => await rest.deleteGuildSticker(e2eCache.guild.id, sticker2.id))
const stickers = await rest.getGuildStickers(e2eCache.guild.id)
expect(stickers.length).to.greaterThan(1)
await rest.deleteGuildSticker(e2eCache.guild.id, sticker.id)
// Since we have already deleted the sticker, we can remove it from the toDispose set
toDispose.delete(cleanSticker)
await expect(rest.getGuildSticker(e2eCache.guild.id, sticker.id)).to.eventually.rejected
})
})

View File

@@ -3,7 +3,6 @@ import { createRestManager } from '../../src/manager.js'
import { E2E_TEST_GUILD_ID, token } from './constants.js'
// For debugging purposes
// logger.setLevel(LogLevels.Debug)
// logger.setDepth(LogDepth.Full)
export const rest = createRestManager({
token,
@@ -29,3 +28,25 @@ export const e2eCache = {
guild,
channel,
}
// Some resources created during tests need to be disposed of afterwards, as they will persist otherwise (e.g., emojis, roles, automod rules)
export const toDispose = new Set<() => Promise<void>>()
afterEach(async () => {
let aggregateError: AggregateError | null = null
for (const dispose of toDispose) {
try {
await dispose()
} catch (error) {
console.error('Error during cleanup:', error)
aggregateError ??= new AggregateError([], 'Errors occurred during cleanup')
aggregateError.errors.push(error)
}
}
toDispose.clear()
if (aggregateError) throw aggregateError
})

View File

@@ -5,7 +5,7 @@ import { e2eCache, rest } from './utils.js'
chaiUse(chaiAsPromised)
describe('Webhook helpers', async () => {
describe('Webhook helpers', () => {
it('Manage webhooks', async () => {
const webhook = await rest.createWebhook(e2eCache.channel.id, {
name: 'idk',

View File

@@ -17,19 +17,18 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js utils",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:unit": "c8 -r lcov mocha 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js types",
"test:deno-unit": "deno -A npm:mocha 'tests/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/**/*.spec.ts'",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"c8": "^10.1.3",
"mocha": "^11.7.5",
"ts-node": "^10.9.2",

View File

@@ -102,6 +102,8 @@ export const BitwisePermissionFlags = {
USE_EXTERNAL_APPS: 1n << 50n,
/** Allows pinning and unpinning messages */
PIN_MESSAGES: 1n << 51n,
/** Allows bypassing slowmode restrictions */
BYPASS_SLOWMODE: 1n << 52n,
} as const
/** https://discord.com/developers/docs/topics/permissions#permissions-bitwise-permission-flags */

View File

@@ -39,6 +39,8 @@ export interface DiscordEventWebhookEventBody {
| DiscordEventWebhookApplicationAuthorizedBody
| DiscordEventWebhookApplicationDeauthorizedBody
| DiscordEventWebhookEntitlementCreateBody
| DiscordEventWebhookEntitlementUpdateBody
| DiscordEventWebhookEntitlementDeleteBody
| DiscordEventWebhookLobbyMessageCreateBody
| DiscordEventWebhookLobbyMessageUpdateBody
| DiscordEventWebhookLobbyMessageDeleteBody
@@ -55,6 +57,10 @@ export enum DiscordWebhookEventType {
ApplicationDeauthorized = 'APPLICATION_DEAUTHORIZED',
/** Entitlement was created */
EntitlementCreate = 'ENTITLEMENT_CREATE',
/** Entitlement was updated */
EntitlementUpdate = 'ENTITLEMENT_UPDATE',
/** Entitlement was deleted */
EntitlementDelete = 'ENTITLEMENT_DELETE',
/** User was added to a Quest (currently unavailable) */
QuestUserEnrollment = 'QUEST_USER_ENROLLMENT',
/** Sent when a message is created in a lobby */
@@ -92,6 +98,12 @@ export interface DiscordEventWebhookApplicationDeauthorizedBody {
/** https://discord.com/developers/docs/events/webhook-events#entitlement-create-entitlement-create-structure */
export type DiscordEventWebhookEntitlementCreateBody = DiscordEntitlement
/** https://discord.com/developers/docs/events/webhook-events#entitlement-update-entitlement-update-structure */
export type DiscordEventWebhookEntitlementUpdateBody = DiscordEntitlement
/** https://discord.com/developers/docs/events/webhook-events#entitlement-delete-entitlement-delete-structure */
export type DiscordEventWebhookEntitlementDeleteBody = DiscordEntitlement
/** https://discord.com/developers/docs/events/webhook-events#lobby-message-create-lobby-message-create-structure */
export type DiscordEventWebhookLobbyMessageCreateBody = DiscordSocialSDKLobbyMessage

View File

@@ -17,24 +17,22 @@
"build:type": "tsc --declaration --emitDeclarationOnly --declarationDir dist",
"release-build": "yarn build && yarn build:type",
"check": "biome check --write",
"test:unit-coverage": "c8 mocha --no-warnings 'tests/**/*.spec.ts'",
"test:unit": "c8 --r lcov mocha --no-warnings 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js utils",
"test:unit:watch": "mocha --no-warnings --watch --parallel 'tests/**/*.spec.ts'",
"test:deno-unit": "deno -A ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:bun-unit": "bun ../../node_modules/mocha/bin/mocha.js --config ../../.mocharc.base.cjs 'tests/**/*.spec.ts'",
"test:type": "tsc --noEmit",
"test:test-type": "tsc --project tests/tsconfig.json"
"test:unit": "c8 -r lcov mocha 'tests/**/*.spec.ts' && node ../../scripts/coveragePathFixing.js utils",
"test:deno-unit": "deno -A npm:mocha 'tests/**/*.spec.ts'",
"test:bun-unit": "bun --bun mocha 'tests/**/*.spec.ts'",
"test:test-type": "tsc --project tests/tsconfig.json",
"test:type": "tsc --noEmit"
},
"dependencies": {
"@discordeno/types": "workspace:^"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@swc/cli": "^0.7.9",
"@swc/core": "^1.15.7",
"@swc/core": "^1.15.8",
"@types/chai": "^5.2.3",
"@types/mocha": "^10.0.10",
"@types/node": "^25.0.3",
"@types/node": "^25.0.6",
"@types/sinon": "^21.0.0",
"c8": "^10.1.3",
"chai": "^6.2.2",

View File

@@ -2,42 +2,61 @@
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"outputs": ["dist/**/*.js"],
"inputs": ["src/**/*.ts"]
"inputs": ["src/**/*.ts"],
"outputs": ["dist/**/*.js"]
},
"build:type": {
"dependsOn": ["^build:type"],
"inputs": ["src/**/*.ts"],
"outputs": ["dist/**/*.d.ts", "dist/**/*.d.ts.map", "dist/tsconfig.tsbuildinfo"]
},
"test:unit-coverage": {
"dependsOn": ["^build"],
"outputs": ["coverage/**"]
},
"test:unit": {
"dependsOn": ["^build", "build"],
"outputs": ["coverage/**"]
},
"test:integration": {
"dependsOn": ["^build"],
"outputs": ["coverage/**"]
},
"test:test-type": {
"dependsOn": ["^build:type"]
},
"test:deno-unit": {
"dependsOn": ["^build", "build"]
},
"test:bun-unit": {
"dependsOn": ["^build", "build"]
},
"test:e2e": {
"dependsOn": ["^build"],
"outputs": ["coverage/**"],
"env": ["DISCORD_TOKEN", "E2E_TEST_GUILD_ID"]
},
"check": {
"dependsOn": ["build:type"],
"cache": false
},
"test:unit": {
"dependsOn": ["^build", "build"],
// We need to exclude e2e and integration test manually since when there aren't e2e or integration we don't have a unit folder
"inputs": ["src/**/*.ts", "tests/**/*.spec.ts", "!tests/e2e/**/*.spec.ts", "!tests/integration**/*.spec.ts"],
"outputs": ["coverage/**"]
},
"test:deno-unit": {
"dependsOn": ["^build", "build"],
// We need to exclude e2e and integration test manually since when there aren't e2e or integration we don't have a unit folder
"inputs": ["src/**/*.ts", "tests/**/*.spec.ts", "!tests/e2e/**/*.spec.ts", "!tests/integration**/*.spec.ts"]
},
"test:bun-unit": {
"dependsOn": ["^build", "build"],
// We need to exclude e2e and integration test manually since when there aren't e2e or integration we don't have a unit folder
"inputs": ["src/**/*.ts", "tests/**/*.spec.ts", "!tests/e2e/**/*.spec.ts", "!tests/integration**/*.spec.ts"]
},
"test:integration": {
"dependsOn": ["^build"],
"inputs": ["src/**/*.ts", "tests/integration**/*.spec.ts"],
"outputs": ["coverage/**"]
},
"test:e2e": {
"dependsOn": ["^build"],
"inputs": ["src/**/*.ts", "tests/e2e**/*.spec.ts"],
"outputs": ["coverage/**"],
"env": ["DISCORD_TOKEN", "E2E_TEST_GUILD_ID"]
},
"test:test-type": {
"dependsOn": ["^build:type"],
"inputs": ["src/**/*.ts", "tests/**/*.ts"]
},
"test:type": {
"dependsOn": ["^build:type"],
"inputs": ["src/**/*.ts"]
},
"check": {
"dependsOn": ["build:type"],
"cache": false
},
"build:doc": {
// NOTE: This task can only be run with "--singe-package" in the flags to turbo, as it is defined only in the root package.json
"inputs": ["packages/**/src/**/*.ts"],
"outputs": ["website/api_reference/generated/**/*"]
}
}
}

View File

@@ -124,7 +124,7 @@ export const influxDB =
: undefined
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET)
let savingAnalyticsId: NodeJS.Interval | undefined = undefined
let saveAnalyticsId: NodeJS.Interval | undefined = undefined
if (!saveAnalyticsId) {
setInterval(() => {
console.log(`[Influx - REST] Saving events...`)

View File

@@ -426,7 +426,7 @@ export const influxDB =
: undefined
export const Influx = influxDB?.getWriteApi(INFLUX_ORG, INFLUX_BUCKET)
let savingAnalyticsId: NodeJS.Interval | undefined = undefined
let saveAnalyticsId: NodeJS.Interval | undefined = undefined
if (!saveAnalyticsId) {
setInterval(() => {
console.log(`[Influx - Gateway] Saving events...`)

View File

@@ -1,6 +1,7 @@
{
"name": "website",
"version": "0.0.0",
"packageManager": "yarn@4.12.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
@@ -30,11 +31,12 @@
"react-dom": "^19.2.3"
},
"devDependencies": {
"@biomejs/biome": "2.3.10",
"@biomejs/biome": "2.3.11",
"@docusaurus/module-type-aliases": "^3.9.2",
"@docusaurus/tsconfig": "^3.9.2",
"@docusaurus/types": "^3.9.2",
"@types/react": "^19.2.7",
"@types/react": "^19.2.8",
"turbo": "^2.7.4",
"typescript": "5.9.3",
"webpack": "5.104.1"
},

9
website/turbo.json Normal file
View File

@@ -0,0 +1,9 @@
{
"$schema": "https://turbo.build/schema.json",
"tasks": {
"build": {
"outputs": ["build/**"],
"inputs": ["src/**/*", "static/**/*", "blog/**/*", "docs/**/*", "api_reference/**/*", "docusaurus.config.ts", "sidebars.ts"]
}
}
}

View File

@@ -5361,18 +5361,18 @@ __metadata:
languageName: node
linkType: hard
"@biomejs/biome@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/biome@npm:2.3.10"
"@biomejs/biome@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/biome@npm:2.3.11"
dependencies:
"@biomejs/cli-darwin-arm64": "npm:2.3.10"
"@biomejs/cli-darwin-x64": "npm:2.3.10"
"@biomejs/cli-linux-arm64": "npm:2.3.10"
"@biomejs/cli-linux-arm64-musl": "npm:2.3.10"
"@biomejs/cli-linux-x64": "npm:2.3.10"
"@biomejs/cli-linux-x64-musl": "npm:2.3.10"
"@biomejs/cli-win32-arm64": "npm:2.3.10"
"@biomejs/cli-win32-x64": "npm:2.3.10"
"@biomejs/cli-darwin-arm64": "npm:2.3.11"
"@biomejs/cli-darwin-x64": "npm:2.3.11"
"@biomejs/cli-linux-arm64": "npm:2.3.11"
"@biomejs/cli-linux-arm64-musl": "npm:2.3.11"
"@biomejs/cli-linux-x64": "npm:2.3.11"
"@biomejs/cli-linux-x64-musl": "npm:2.3.11"
"@biomejs/cli-win32-arm64": "npm:2.3.11"
"@biomejs/cli-win32-x64": "npm:2.3.11"
dependenciesMeta:
"@biomejs/cli-darwin-arm64":
optional: true
@@ -5392,62 +5392,62 @@ __metadata:
optional: true
bin:
biome: bin/biome
checksum: 10c0/317bf8f8051f4030dc52855159bbd058db5cf2c9d5e7b212271f3d91842e0fc5bbc05495e47943676481325d4081cd41cf25dfa18a437d2b6e27f72dacfd41b4
checksum: 10c0/b9764070c3d1583466a8861d37dc480c18103f7bb52115db0f265a38e6343d69792c9beea094e0b3db0905cb365b9a82ad2a0f3f05b7f04873a8f9b444263140
languageName: node
linkType: hard
"@biomejs/cli-darwin-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-darwin-arm64@npm:2.3.10"
"@biomejs/cli-darwin-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-darwin-arm64@npm:2.3.11"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@biomejs/cli-darwin-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-darwin-x64@npm:2.3.10"
"@biomejs/cli-darwin-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-darwin-x64@npm:2.3.11"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@biomejs/cli-linux-arm64-musl@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.10"
"@biomejs/cli-linux-arm64-musl@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.11"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@biomejs/cli-linux-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-arm64@npm:2.3.10"
"@biomejs/cli-linux-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-arm64@npm:2.3.11"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@biomejs/cli-linux-x64-musl@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.10"
"@biomejs/cli-linux-x64-musl@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.11"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@biomejs/cli-linux-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-x64@npm:2.3.10"
"@biomejs/cli-linux-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-x64@npm:2.3.11"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@biomejs/cli-win32-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-win32-arm64@npm:2.3.10"
"@biomejs/cli-win32-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-win32-arm64@npm:2.3.11"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@biomejs/cli-win32-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-win32-x64@npm:2.3.10"
"@biomejs/cli-win32-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-win32-x64@npm:2.3.11"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
@@ -19935,6 +19935,77 @@ __metadata:
languageName: node
linkType: hard
"turbo-darwin-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-darwin-64@npm:2.7.4"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"turbo-darwin-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-darwin-arm64@npm:2.7.4"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"turbo-linux-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-linux-64@npm:2.7.4"
conditions: os=linux & cpu=x64
languageName: node
linkType: hard
"turbo-linux-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-linux-arm64@npm:2.7.4"
conditions: os=linux & cpu=arm64
languageName: node
linkType: hard
"turbo-windows-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-windows-64@npm:2.7.4"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"turbo-windows-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-windows-arm64@npm:2.7.4"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"turbo@npm:^2.7.4":
version: 2.7.4
resolution: "turbo@npm:2.7.4"
dependencies:
turbo-darwin-64: "npm:2.7.4"
turbo-darwin-arm64: "npm:2.7.4"
turbo-linux-64: "npm:2.7.4"
turbo-linux-arm64: "npm:2.7.4"
turbo-windows-64: "npm:2.7.4"
turbo-windows-arm64: "npm:2.7.4"
dependenciesMeta:
turbo-darwin-64:
optional: true
turbo-darwin-arm64:
optional: true
turbo-linux-64:
optional: true
turbo-linux-arm64:
optional: true
turbo-windows-64:
optional: true
turbo-windows-arm64:
optional: true
bin:
turbo: bin/turbo
checksum: 10c0/506a59df8d898833efb7d41b552a3a448a26fb2ebd5d545d37bf1e4854bdab0a0b847d8d82f962f499ba5340b7dc123abb5d4ceb9dae12b32ec6c46d1f5fe6fc
languageName: node
linkType: hard
"type-fest@npm:^0.21.3":
version: 0.21.3
resolution: "type-fest@npm:0.21.3"
@@ -19996,9 +20067,9 @@ __metadata:
linkType: hard
"undici@npm:^6.19.5":
version: 6.21.3
resolution: "undici@npm:6.21.3"
checksum: 10c0/294da109853fad7a6ef5a172ad0ca3fb3f1f60cf34703d062a5ec967daf69ad8c03b52e6d536c5cba3bb65615769bf08e5b30798915cbccdddaca01045173dda
version: 6.23.0
resolution: "undici@npm:6.23.0"
checksum: 10c0/d846b3fdfd05aa6081ba1eab5db6bbc21b283042c7a43722b86d1ee2bf749d7c990ceac0c809f9a07ffd88b1b0f4c0f548a8362c035088cb1997d63abdda499c
languageName: node
linkType: hard
@@ -20786,7 +20857,7 @@ __metadata:
version: 0.0.0-use.local
resolution: "website@workspace:."
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@docusaurus/core": "npm:^3.9.2"
"@docusaurus/faster": "npm:^3.9.2"
"@docusaurus/module-type-aliases": "npm:^3.9.2"
@@ -20798,11 +20869,12 @@ __metadata:
"@docusaurus/types": "npm:^3.9.2"
"@easyops-cn/docusaurus-search-local": "npm:^0.52.1"
"@mdx-js/react": "npm:^3.1.1"
"@types/react": "npm:^19.2.7"
"@types/react": "npm:^19.2.8"
"@xyflow/react": "npm:^12.10.0"
prism-react-renderer: "npm:^2.4.1"
react: "npm:^19.2.3"
react-dom: "npm:^19.2.3"
turbo: "npm:^2.7.4"
typescript: "npm:5.9.3"
webpack: "npm:5.104.1"
languageName: unknown

284
yarn.lock
View File

@@ -12,18 +12,18 @@ __metadata:
languageName: node
linkType: hard
"@biomejs/biome@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/biome@npm:2.3.10"
"@biomejs/biome@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/biome@npm:2.3.11"
dependencies:
"@biomejs/cli-darwin-arm64": "npm:2.3.10"
"@biomejs/cli-darwin-x64": "npm:2.3.10"
"@biomejs/cli-linux-arm64": "npm:2.3.10"
"@biomejs/cli-linux-arm64-musl": "npm:2.3.10"
"@biomejs/cli-linux-x64": "npm:2.3.10"
"@biomejs/cli-linux-x64-musl": "npm:2.3.10"
"@biomejs/cli-win32-arm64": "npm:2.3.10"
"@biomejs/cli-win32-x64": "npm:2.3.10"
"@biomejs/cli-darwin-arm64": "npm:2.3.11"
"@biomejs/cli-darwin-x64": "npm:2.3.11"
"@biomejs/cli-linux-arm64": "npm:2.3.11"
"@biomejs/cli-linux-arm64-musl": "npm:2.3.11"
"@biomejs/cli-linux-x64": "npm:2.3.11"
"@biomejs/cli-linux-x64-musl": "npm:2.3.11"
"@biomejs/cli-win32-arm64": "npm:2.3.11"
"@biomejs/cli-win32-x64": "npm:2.3.11"
dependenciesMeta:
"@biomejs/cli-darwin-arm64":
optional: true
@@ -43,62 +43,62 @@ __metadata:
optional: true
bin:
biome: bin/biome
checksum: 10c0/317bf8f8051f4030dc52855159bbd058db5cf2c9d5e7b212271f3d91842e0fc5bbc05495e47943676481325d4081cd41cf25dfa18a437d2b6e27f72dacfd41b4
checksum: 10c0/b9764070c3d1583466a8861d37dc480c18103f7bb52115db0f265a38e6343d69792c9beea094e0b3db0905cb365b9a82ad2a0f3f05b7f04873a8f9b444263140
languageName: node
linkType: hard
"@biomejs/cli-darwin-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-darwin-arm64@npm:2.3.10"
"@biomejs/cli-darwin-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-darwin-arm64@npm:2.3.11"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@biomejs/cli-darwin-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-darwin-x64@npm:2.3.10"
"@biomejs/cli-darwin-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-darwin-x64@npm:2.3.11"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@biomejs/cli-linux-arm64-musl@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.10"
"@biomejs/cli-linux-arm64-musl@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-arm64-musl@npm:2.3.11"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@biomejs/cli-linux-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-arm64@npm:2.3.10"
"@biomejs/cli-linux-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-arm64@npm:2.3.11"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@biomejs/cli-linux-x64-musl@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.10"
"@biomejs/cli-linux-x64-musl@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-x64-musl@npm:2.3.11"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@biomejs/cli-linux-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-linux-x64@npm:2.3.10"
"@biomejs/cli-linux-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-linux-x64@npm:2.3.11"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@biomejs/cli-win32-arm64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-win32-arm64@npm:2.3.10"
"@biomejs/cli-win32-arm64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-win32-arm64@npm:2.3.11"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@biomejs/cli-win32-x64@npm:2.3.10":
version: 2.3.10
resolution: "@biomejs/cli-win32-x64@npm:2.3.10"
"@biomejs/cli-win32-x64@npm:2.3.11":
version: 2.3.11
resolution: "@biomejs/cli-win32-x64@npm:2.3.11"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
@@ -116,16 +116,16 @@ __metadata:
version: 0.0.0-use.local
resolution: "@discordeno/bot@workspace:packages/bot"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@discordeno/gateway": "workspace:^"
"@discordeno/rest": "workspace:^"
"@discordeno/types": "workspace:^"
"@discordeno/utils": "workspace:^"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/chai": "npm:^5.2.3"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
"@types/sinon": "npm:^21.0.0"
c8: "npm:^10.1.3"
chai: "npm:^6.2.2"
@@ -141,14 +141,14 @@ __metadata:
version: 0.0.0-use.local
resolution: "@discordeno/gateway@workspace:packages/gateway"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@discordeno/types": "workspace:^"
"@discordeno/utils": "workspace:^"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/chai": "npm:^5.2.3"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
"@types/sinon": "npm:^21.0.0"
"@types/ws": "npm:^8.18.1"
c8: "npm:^10.1.3"
@@ -159,7 +159,7 @@ __metadata:
ts-node: "npm:^10.9.2"
tsconfig: "npm:*"
typescript: "npm:^5.9.3"
ws: "npm:^8.18.3"
ws: "npm:^8.19.0"
dependenciesMeta:
fzstd:
optional: true
@@ -170,15 +170,15 @@ __metadata:
version: 0.0.0-use.local
resolution: "@discordeno/rest@workspace:packages/rest"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@discordeno/types": "workspace:^"
"@discordeno/utils": "workspace:^"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/chai": "npm:^5.2.3"
"@types/chai-as-promised": "npm:^8.0.2"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
"@types/sinon": "npm:^21.0.0"
c8: "npm:^10.1.3"
chai: "npm:^6.2.2"
@@ -196,11 +196,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "@discordeno/types@workspace:packages/types"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
c8: "npm:^10.1.3"
mocha: "npm:^11.7.5"
ts-node: "npm:^10.9.2"
@@ -213,13 +213,13 @@ __metadata:
version: 0.0.0-use.local
resolution: "@discordeno/utils@workspace:packages/utils"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@discordeno/types": "workspace:^"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/chai": "npm:^5.2.3"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
"@types/sinon": "npm:^21.0.0"
c8: "npm:^10.1.3"
chai: "npm:^6.2.2"
@@ -589,90 +589,90 @@ __metadata:
languageName: node
linkType: hard
"@swc/core-darwin-arm64@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-darwin-arm64@npm:1.15.7"
"@swc/core-darwin-arm64@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-darwin-arm64@npm:1.15.8"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"@swc/core-darwin-x64@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-darwin-x64@npm:1.15.7"
"@swc/core-darwin-x64@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-darwin-x64@npm:1.15.8"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"@swc/core-linux-arm-gnueabihf@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.7"
"@swc/core-linux-arm-gnueabihf@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-linux-arm-gnueabihf@npm:1.15.8"
conditions: os=linux & cpu=arm
languageName: node
linkType: hard
"@swc/core-linux-arm64-gnu@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-linux-arm64-gnu@npm:1.15.7"
"@swc/core-linux-arm64-gnu@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-linux-arm64-gnu@npm:1.15.8"
conditions: os=linux & cpu=arm64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-arm64-musl@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-linux-arm64-musl@npm:1.15.7"
"@swc/core-linux-arm64-musl@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-linux-arm64-musl@npm:1.15.8"
conditions: os=linux & cpu=arm64 & libc=musl
languageName: node
linkType: hard
"@swc/core-linux-x64-gnu@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-linux-x64-gnu@npm:1.15.7"
"@swc/core-linux-x64-gnu@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-linux-x64-gnu@npm:1.15.8"
conditions: os=linux & cpu=x64 & libc=glibc
languageName: node
linkType: hard
"@swc/core-linux-x64-musl@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-linux-x64-musl@npm:1.15.7"
"@swc/core-linux-x64-musl@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-linux-x64-musl@npm:1.15.8"
conditions: os=linux & cpu=x64 & libc=musl
languageName: node
linkType: hard
"@swc/core-win32-arm64-msvc@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-win32-arm64-msvc@npm:1.15.7"
"@swc/core-win32-arm64-msvc@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-win32-arm64-msvc@npm:1.15.8"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"@swc/core-win32-ia32-msvc@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-win32-ia32-msvc@npm:1.15.7"
"@swc/core-win32-ia32-msvc@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-win32-ia32-msvc@npm:1.15.8"
conditions: os=win32 & cpu=ia32
languageName: node
linkType: hard
"@swc/core-win32-x64-msvc@npm:1.15.7":
version: 1.15.7
resolution: "@swc/core-win32-x64-msvc@npm:1.15.7"
"@swc/core-win32-x64-msvc@npm:1.15.8":
version: 1.15.8
resolution: "@swc/core-win32-x64-msvc@npm:1.15.8"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"@swc/core@npm:^1.15.7":
version: 1.15.7
resolution: "@swc/core@npm:1.15.7"
"@swc/core@npm:^1.15.8":
version: 1.15.8
resolution: "@swc/core@npm:1.15.8"
dependencies:
"@swc/core-darwin-arm64": "npm:1.15.7"
"@swc/core-darwin-x64": "npm:1.15.7"
"@swc/core-linux-arm-gnueabihf": "npm:1.15.7"
"@swc/core-linux-arm64-gnu": "npm:1.15.7"
"@swc/core-linux-arm64-musl": "npm:1.15.7"
"@swc/core-linux-x64-gnu": "npm:1.15.7"
"@swc/core-linux-x64-musl": "npm:1.15.7"
"@swc/core-win32-arm64-msvc": "npm:1.15.7"
"@swc/core-win32-ia32-msvc": "npm:1.15.7"
"@swc/core-win32-x64-msvc": "npm:1.15.7"
"@swc/core-darwin-arm64": "npm:1.15.8"
"@swc/core-darwin-x64": "npm:1.15.8"
"@swc/core-linux-arm-gnueabihf": "npm:1.15.8"
"@swc/core-linux-arm64-gnu": "npm:1.15.8"
"@swc/core-linux-arm64-musl": "npm:1.15.8"
"@swc/core-linux-x64-gnu": "npm:1.15.8"
"@swc/core-linux-x64-musl": "npm:1.15.8"
"@swc/core-win32-arm64-msvc": "npm:1.15.8"
"@swc/core-win32-ia32-msvc": "npm:1.15.8"
"@swc/core-win32-x64-msvc": "npm:1.15.8"
"@swc/counter": "npm:^0.1.3"
"@swc/types": "npm:^0.1.25"
peerDependencies:
@@ -701,7 +701,7 @@ __metadata:
peerDependenciesMeta:
"@swc/helpers":
optional: true
checksum: 10c0/ae1d20db777bfe0404f2c840d8fa66da0664bca1f88ac8727cbe4c0cb04ee28505009b55caf345f1e790b96410f9bcf66d0178372e9c6505a9da76e7562a06bf
checksum: 10c0/929f334a224776fdb3c4a8aaba68f07666ff56fae7502a9459bc9666cb73d94e65f042ce8c4ef4e6746a8bb3f8255cbe8599bef6e3181269caf761c8e55513cf
languageName: node
linkType: hard
@@ -835,12 +835,12 @@ __metadata:
languageName: node
linkType: hard
"@types/node@npm:^25.0.3":
version: 25.0.3
resolution: "@types/node@npm:25.0.3"
"@types/node@npm:^25.0.6":
version: 25.0.6
resolution: "@types/node@npm:25.0.6"
dependencies:
undici-types: "npm:~7.16.0"
checksum: 10c0/b7568f0d765d9469621615e2bb257c7fd1953d95e9acbdb58dffb6627a2c4150d405a4600aa1ad8a40182a94fe5f903cafd3c0a2f5132814debd0e3bfd61f835
checksum: 10c0/4ee3b6b606bc28f6840c04d58769e1e75dd8085149908956c874c85f8f8c890990701bcbe783fc2d14017817861dc07fcf23de6fc2805fe491f84eae717b5705
languageName: node
linkType: hard
@@ -1442,11 +1442,11 @@ __metadata:
version: 0.0.0-use.local
resolution: "discordeno-monorepo@workspace:."
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
husky: "npm:^9.1.7"
lint-staged: "npm:^16.2.7"
turbo: "npm:^2.7.2"
typedoc: "npm:^0.28.15"
turbo: "npm:^2.7.4"
typedoc: "npm:^0.28.16"
typedoc-plugin-markdown: "npm:^4.9.0"
typescript: "npm:^5.9.3"
languageName: unknown
@@ -1456,17 +1456,17 @@ __metadata:
version: 0.0.0-use.local
resolution: "discordeno@workspace:packages/discordeno"
dependencies:
"@biomejs/biome": "npm:2.3.10"
"@biomejs/biome": "npm:2.3.11"
"@discordeno/bot": "workspace:^"
"@discordeno/gateway": "workspace:^"
"@discordeno/rest": "workspace:^"
"@discordeno/types": "workspace:^"
"@discordeno/utils": "workspace:^"
"@swc/cli": "npm:^0.7.9"
"@swc/core": "npm:^1.15.7"
"@swc/core": "npm:^1.15.8"
"@types/chai": "npm:^5.2.3"
"@types/mocha": "npm:^10.0.10"
"@types/node": "npm:^25.0.3"
"@types/node": "npm:^25.0.6"
c8: "npm:^10.1.3"
chai: "npm:^6.2.2"
mocha: "npm:^11.7.5"
@@ -2917,58 +2917,58 @@ __metadata:
languageName: unknown
linkType: soft
"turbo-darwin-64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-darwin-64@npm:2.7.2"
"turbo-darwin-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-darwin-64@npm:2.7.4"
conditions: os=darwin & cpu=x64
languageName: node
linkType: hard
"turbo-darwin-arm64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-darwin-arm64@npm:2.7.2"
"turbo-darwin-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-darwin-arm64@npm:2.7.4"
conditions: os=darwin & cpu=arm64
languageName: node
linkType: hard
"turbo-linux-64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-linux-64@npm:2.7.2"
"turbo-linux-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-linux-64@npm:2.7.4"
conditions: os=linux & cpu=x64
languageName: node
linkType: hard
"turbo-linux-arm64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-linux-arm64@npm:2.7.2"
"turbo-linux-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-linux-arm64@npm:2.7.4"
conditions: os=linux & cpu=arm64
languageName: node
linkType: hard
"turbo-windows-64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-windows-64@npm:2.7.2"
"turbo-windows-64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-windows-64@npm:2.7.4"
conditions: os=win32 & cpu=x64
languageName: node
linkType: hard
"turbo-windows-arm64@npm:2.7.2":
version: 2.7.2
resolution: "turbo-windows-arm64@npm:2.7.2"
"turbo-windows-arm64@npm:2.7.4":
version: 2.7.4
resolution: "turbo-windows-arm64@npm:2.7.4"
conditions: os=win32 & cpu=arm64
languageName: node
linkType: hard
"turbo@npm:^2.7.2":
version: 2.7.2
resolution: "turbo@npm:2.7.2"
"turbo@npm:^2.7.4":
version: 2.7.4
resolution: "turbo@npm:2.7.4"
dependencies:
turbo-darwin-64: "npm:2.7.2"
turbo-darwin-arm64: "npm:2.7.2"
turbo-linux-64: "npm:2.7.2"
turbo-linux-arm64: "npm:2.7.2"
turbo-windows-64: "npm:2.7.2"
turbo-windows-arm64: "npm:2.7.2"
turbo-darwin-64: "npm:2.7.4"
turbo-darwin-arm64: "npm:2.7.4"
turbo-linux-64: "npm:2.7.4"
turbo-linux-arm64: "npm:2.7.4"
turbo-windows-64: "npm:2.7.4"
turbo-windows-arm64: "npm:2.7.4"
dependenciesMeta:
turbo-darwin-64:
optional: true
@@ -2984,7 +2984,7 @@ __metadata:
optional: true
bin:
turbo: bin/turbo
checksum: 10c0/390937a32070ac52120af56705006e831de2edf8e22a2b0146006d07740cd413b3a36335339e7617b57cf74b008f4b15931cf56e1c7c0c03808f028ed937c4de
checksum: 10c0/506a59df8d898833efb7d41b552a3a448a26fb2ebd5d545d37bf1e4854bdab0a0b847d8d82f962f499ba5340b7dc123abb5d4ceb9dae12b32ec6c46d1f5fe6fc
languageName: node
linkType: hard
@@ -3011,9 +3011,9 @@ __metadata:
languageName: node
linkType: hard
"typedoc@npm:^0.28.15":
version: 0.28.15
resolution: "typedoc@npm:0.28.15"
"typedoc@npm:^0.28.16":
version: 0.28.16
resolution: "typedoc@npm:0.28.16"
dependencies:
"@gerrit0/mini-shiki": "npm:^3.17.0"
lunr: "npm:^2.3.9"
@@ -3024,7 +3024,7 @@ __metadata:
typescript: 5.0.x || 5.1.x || 5.2.x || 5.3.x || 5.4.x || 5.5.x || 5.6.x || 5.7.x || 5.8.x || 5.9.x
bin:
typedoc: bin/typedoc
checksum: 10c0/b5988ebebb367fed44f110bbd37baee85fe95fe10c8d5a511c33d787eb1e924e66ba54cb0763d63ed2c406adbd32fcb87bcbc3fd61b0bc8ab6f3a6c06f2de978
checksum: 10c0/ae444913068088e88be6319a017a3a18f69cbd91dbb5b959fbdd0cf87d1a2a07f3a0d4ab29c957a83dd72808ff35bdd6ceec3ad1803fa412ddceffb78fa60ebb
languageName: node
linkType: hard
@@ -3148,9 +3148,9 @@ __metadata:
languageName: node
linkType: hard
"ws@npm:^8.18.3":
version: 8.18.3
resolution: "ws@npm:8.18.3"
"ws@npm:^8.19.0":
version: 8.19.0
resolution: "ws@npm:8.19.0"
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: ">=5.0.2"
@@ -3159,7 +3159,7 @@ __metadata:
optional: true
utf-8-validate:
optional: true
checksum: 10c0/eac918213de265ef7cb3d4ca348b891a51a520d839aa51cdb8ca93d4fa7ff9f6ccb339ccee89e4075324097f0a55157c89fa3f7147bde9d8d7e90335dc087b53
checksum: 10c0/4741d9b9bc3f9c791880882414f96e36b8b254e34d4b503279d6400d9a4b87a033834856dbdd94ee4b637944df17ea8afc4bce0ff4a1560d2166be8855da5b04
languageName: node
linkType: hard