Compare commits

..

74 Commits

Author SHA1 Message Date
iCrawl
ce7d6b47b7 chore(brokers): release @discordjs/brokers@0.2.0 2023-04-02 01:49:13 +02:00
Noel
11e682cfe3 feat(core): http-only wrapper (#9281) 2023-04-02 01:44:19 +02:00
Vlad Frangu
9d69bba47c fix(core): include data for defer (#9284) 2023-04-02 01:38:33 +02:00
Jaw0r3k
2792e48119 docs: describe private properties (#8879)
* feat: describe private properties

* Update packages/discord.js/src/structures/GuildMember.js

Co-authored-by: MrMythicalYT <91077061+MrMythicalYT@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: MrMythicalYT <91077061+MrMythicalYT@users.noreply.github.com>

* Apply suggestions from code review

---------

Co-authored-by: MrMythicalYT <91077061+MrMythicalYT@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 23:21:53 +00:00
Jaw0r3k
384b4d10e8 docs: differ User#send (#9251)
* docs: differate user#send

* chore: format

* chore: remove some examples

* docs: add GuildMember#send example

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 23:17:54 +00:00
Jaw0r3k
d16114c526 docs: fix compare position example (#9272)
Update Role.js

Co-authored-by: space <spaceeec@yahoo.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 22:37:18 +00:00
pkdev08
de1aac674a fix: add support for new guild feature GUILD_WEB_PAGE_VANITY_URL (#9219)
Co-authored-by: space <spaceeec@yahoo.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 22:34:07 +00:00
Jaw0r3k
79875658cf fix: resolving string bitfield (#9262)
fix: resolving bitfield

Co-authored-by: space <spaceeec@yahoo.com>
2023-04-01 22:30:51 +00:00
Jiralite
ab3328a0e2 chore: Include discord.js in the user agent string (#9267)
* chore: apply user agent string

* fix: enforce even in custom option

* fix: tests

* refactor: simpler way

* docs: add type

* Update packages/discord.js/src/client/BaseClient.js

Co-authored-by: Aura Román <kyradiscord@gmail.com>

* fix: prioritise `option` type check

* types: `static`

* feat: add runtime check

* docs: update default

* refactor: remove Bun

* Update packages/discord.js/src/client/BaseClient.js

Co-authored-by: Almeida <almeidx@pm.me>

* fix: extra whitespace issues

* refactor: `trimEnd()`

---------

Co-authored-by: Aura Román <kyradiscord@gmail.com>
Co-authored-by: Almeida <almeidx@pm.me>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 22:26:44 +00:00
Jiralite
1864d37d36 fix(AutocompleteInteraction): Send name_localizations correctly (#9238)
fix(AutocompleteInteraction): send locale correctly

Co-authored-by: space <spaceeec@yahoo.com>
2023-04-01 22:19:23 +00:00
Tetie
f340f3b1fd refactor: call GuildBanManager#create() directly (#9263)
refactor: call bans.create directly

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-04-01 22:09:01 +00:00
Suneet Tipirneni
907eb1b470 feat(core): Add AbortSignal support. (#9042)
* feat: add abort signal to guilds api

* feat: add to application commands, channels, and users classes

* chore: finish up

* chore: centralize types

* chore: make requested changes

* chore: make requested changes

* refactor: consistently use empty objects

* Update packages/core/src/api/webhook.ts

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* chore: make requested changes

* refactor: update `setVoiceState` after rebase

* chore: requested changes

* refactor: use -types interface for query

---------

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
2023-04-01 21:11:37 +00:00
iCrawl
e2f39ccc32 fix(website): migration from old website 2023-04-01 15:50:47 +02:00
Tetie
74a6d59ae9 chore: overhaul readmes (#9277)
Co-authored-by: Souji <timoqueezle@gmail.com>
Co-authored-by: Noel <buechler.noel@outlook.com>
2023-04-01 13:45:15 +02:00
iCrawl
a5b0d97224 fix(website): redirect for logo 2023-04-01 13:32:10 +02:00
iCrawl
52c6ea2fdb feat(website): add static logo 2023-04-01 13:15:27 +02:00
iCrawl
cfa48cedc3 fix(website): update url 2023-04-01 13:12:18 +02:00
iCrawl
cf23149d17 fix(website): make sure to use proper revalidate and per request caching 2023-04-01 03:12:12 +02:00
iCrawl
311cab2d3f build(website): build site from db data 2023-04-01 02:50:24 +02:00
Jiralite
34bc36ac4b feat(Guild): Add max_stage_video_channel_users (#8422)
feat(Guild): add `max_stage_video_channel_users`
2023-03-31 22:30:25 +00:00
ckohen
db8df104c5 fix(handlers): create burst handler for interaction callbacks (#8996)
* fix(handlers): create burst handler for interaction callbacks

* docs: use remarks instead of info block

Co-Authored-By: Almeida <almeidx@pm.me>

* refactor: move code duplication to shared handler

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

* Update packages/rest/src/lib/handlers/BurstHandler.ts

---------

Co-authored-by: Almeida <almeidx@pm.me>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: Aura Román <kyradiscord@gmail.com>
2023-03-30 17:22:04 +00:00
Jiralite
984bd55b43 fix: Keep symbols in actions manager (#9293)
fix: keep symbols in actions manager
2023-03-29 17:27:23 +00:00
iCrawl
3cf4f4b317 ci: fix linting astro files 2023-03-28 23:10:41 +02:00
iCrawl
fd008f0144 ci: run specific version of node 2023-03-28 23:02:25 +02:00
iCrawl
8deef3e93f ci: fix docker image build 2023-03-28 22:55:28 +02:00
iCrawl
89235f32b0 ci: docker image build for proxy 2023-03-28 22:47:48 +02:00
Noel
47da24ff5c refactor(website): redesign (#9286) 2023-03-28 19:02:36 +02:00
iCrawl
d1ebe4a52c fix(website): right sidebar height 2023-03-27 20:50:35 +02:00
iCrawl
5cdd5d76ed fix(website): page height to hide footer without scrolling 2023-03-27 20:43:34 +02:00
iCrawl
b8b852ee1e feat(guide): light theme for syntax 2023-03-25 23:46:42 +01:00
iCrawl
ba93bc8141 chore: fixup root package.json 2023-03-25 22:55:53 +01:00
iCrawl
fbd599d586 refactor(guide): next 13 2023-03-25 22:52:47 +01:00
iCrawl
d9a9500b40 feat(website): optimize svg and priority load svg 2023-03-25 18:56:57 +01:00
iCrawl
51de9668e5 feat(website): feature flag package and version selection 2023-03-25 16:33:13 +01:00
iCrawl
b097b25116 fix(website): package / version select spacing 2023-03-25 14:55:15 +01:00
iCrawl
1d2c152320 fix(website): keys 2023-03-25 14:42:53 +01:00
iCrawl
d8d5f31d39 fix(scripts): accessing tsComment 2023-03-25 14:02:40 +01:00
Jiralite
abd6ae9fc8 fix(ClientUser): No mutation on edit (#9259)
fix(ClientUser): no mutation on edit

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-25 12:59:22 +00:00
iCrawl
44ef2d9485 fix(website): wrong bg color for buttons in pkg/version select 2023-03-25 13:52:51 +01:00
DD
519825a651 fix(WebSocketShard): don't await #destroy in error bubbling logic (#9276)
* fix(WebSocketShard): don't await #destroy in error bubbling logic

* fix: properly throw abort errors

* chore: vlad's nit

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-25 12:49:35 +00:00
iCrawl
ad31edc7aa refactor(website): font loading and reduce cls 2023-03-25 13:44:35 +01:00
Almeida
d6f4e60efd refactor(collection): fix/silence linter warnings (#9266)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-25 09:32:52 +00:00
iCrawl
5fcd0e48a8 fix(website): nav / member provider 2023-03-24 06:24:47 +01:00
iCrawl
52f8e0670c feat(website): color scheme / dark and light mode improvements 2023-03-24 06:02:00 +01:00
iCrawl
1c4af93898 feat(website): enhance lazy loading 2023-03-24 04:27:21 +01:00
iCrawl
3bd76078e1 feat(website): sneaky sneaky 2 2023-03-24 01:54:21 +01:00
iCrawl
71eba0e1b2 chore(website): sneaky sneaky 2023-03-24 00:30:14 +01:00
iCrawl
d284b8c64b chore: fix lockfile 2023-03-23 23:49:06 +01:00
iCrawl
795e6c363d fix(website): footer spacing 2023-03-23 23:46:37 +01:00
iCrawl
d6cd3fd7ed chore: deps 2023-03-23 23:24:27 +01:00
iCrawl
d144a78813 ci: add lighthouse for prod 2023-03-23 23:11:13 +01:00
iCrawl
645e2d3d6b ci: lighthouse score 2023-03-23 22:48:27 +01:00
iCrawl
5b745a49d8 chore(website): fix metadata 2023-03-23 22:37:50 +01:00
Suneet Tipirneni
ee5169e0aa feat(website): render syntax and mdx on the server (#9086) 2023-03-23 22:17:41 +01:00
Jiralite
bc641fa936 docs(Role): Fix example for comparePositionTo() (#9270)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-23 20:50:58 +00:00
Suneet Tipirneni
c8c02f957d fix(website): remove layout shift (#9062)
Co-authored-by: Noel <buechler.noel@outlook.com>
2023-03-23 20:44:04 +01:00
Suneet Tipirneni
091824abc5 fix(website): show headers for type aliases (#9054) 2023-03-23 20:42:29 +01:00
Suneet Tipirneni
03f5f1e3b6 refactor(website): use new metadata api instead of head.tsx (#9269) 2023-03-23 20:41:29 +01:00
iCrawl
852fae557e chore: deps 2023-03-23 14:28:58 +01:00
Rodry
5f93dcce46 feat: add GuildBasedTextChannelTypes (#9234)
* feat: add GuildBasedTextChannelTypes

* docs(GuildTextBasedChannels): distinguish from non other

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>

* fix: spread correct array

Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>

---------

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
2023-03-22 22:03:44 +00:00
Erwan
22e880aaa0 fix(Message#editable): update editable check in threads locked (#9216)
* fix(Message#editable): update editable check in threads locked

* fix(Message#editable): add check in archived threads

* fix: check manage threads permission only if thread is locked

* fix: adding a full stop at the end of a sentence

Co-authored-by: Jaworek <jaworekwiadomosci@gmail.com>

---------

Co-authored-by: Jaworek <jaworekwiadomosci@gmail.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
2023-03-22 21:38:32 +00:00
Jiralite
e9a8eb323f fix(ThreadManager): add members and conditionally include hasMore (#9164)
* fix(ThreadManager): conditionally include `hasMore`

* types: fix tests

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:24:09 +00:00
Jiralite
cc57563e73 fix(ThreadManager): Respect cache and force in fetching (#9239)
* fix(ThreadManager): Respect `cache` and `force` in fetching

* refactor: remove defaults

These are already defaulted down the line.

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:20:52 +00:00
Jiralite
519e163f8a refactor(FetchThreadsOptions): Remove active (#9241)
* refactor(FetchThreadsOptions): remove `active`

* docs(FetchThreadsOptions): update description

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:17:47 +00:00
DD
eb81dc982c chore(ws): correct order for debug logs when identifying (#9248)
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:13:56 +00:00
Tetie
bf507ab265 docs: add more examples (#9252)
* docs: add more examples

* fix: fix grammar and syntax

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>

* chore: fine-tune examples

* chore: replace double quotes with singles

* fix: remove redundant example tag

* fix: fix timeout logging

* Update packages/discord.js/src/structures/GuildMember.js

Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>

---------

Co-authored-by: Jaw0r3k <jaworekwiadomosci@gmail.com>
Co-authored-by: Vlad Frangu <kingdgrizzle@gmail.com>
Co-authored-by: Jiralite <33201955+Jiralite@users.noreply.github.com>
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:09:41 +00:00
Jiralite
178c8dcfee docs(FetchArchivedThreadOptions): before respects archive_timestamp, not creation timestamp (#9240)
docs(FetchArchivedThreadOptions): correct `before` description

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 19:01:17 +00:00
Jiralite
56cf138e02 docs: Update APISelectMenuComponent (#9235)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-22 18:57:23 +00:00
Jiralite
950fc47234 ci: Lock ancient issues (#9257)
ci: use dessant/lock-threads@v4
2023-03-20 19:35:58 +00:00
DD
c76b17d3b3 fix(WebSocketShard): don't close in #destroy when status is connecting (#9254) 2023-03-20 19:20:48 +00:00
Jeroen Claassens
229ad077ff fix(rest): remove const enums in favour of regular enums (#9243)
* fix(rest): remove `const enum`s in favour of regular enums

The motivation is that `const enum` produces ambient const enums when
compiling which in turn causes issues with TypeScript 5.x when `verbatimModuleSyntax`
is enabled.

Furthermore, the generally accepted best practice is to avoid `const enum`s
when writing libraries. Can back this up with statements from TS maintainers
if needed, I know they made them, I just can't be bothered to find the GitHub
links lmao. @vladfrangu will probably be able to find those links much easier
than me as it was also the motivation to remove `const enum`'s from discord-api-types

* refactor(rest): restore `const enum` for internal enum

---------

Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
2023-03-19 14:35:27 +00:00
Jeroen Claassens
2e8e95031c build: resolve issue with esbuild-plugin-version-injector not working (#9246)
The issue was two-fold.
First of all, tsup starts using swc when `emitDecoratorMetadata` and `@swc/core` is installed.
`@swc/core` is installed transiently, which still causes the problem.
Okay, sure, so we move the `emitDecoratorMetadata` option to just
`packages/builders/tsconfig.json` seeing as the other packages don't use decorators anyway.
But that still leaves solving the issue for builders. @vladfrangu ended
up finding out that there was a bug in how esbuild handles plugins causing
the esbuild-plugin-version-injector plugin to not get loaded. This is solved
in v1.1.0 where the content is also replaced using the `onEnd` hook, if it
wasn't replaced by `onLoad` yet.
2023-03-19 14:28:06 +00:00
DD
98420826bc fix(WebSocketShard): cancel initial heartbeat in destroy (#9244)
* fix(WebSocketShard): cancel initial heartbeat in destroy

* refactor: use try/catch/finally

* chore: add debug log
2023-03-18 19:32:50 +00:00
n1ck_pro
51edba78bc fix(TextBasedChannelTypes): add GuildStageVoice (#9232)
fix(TextBasedChannelTypes): add GuildStageVoice
2023-03-15 17:32:29 +00:00
277 changed files with 8661 additions and 7165 deletions

View File

@@ -40,7 +40,7 @@ For example, to automatically recompile the `@discordjs/rest` project when chang
If you'd like to create another package under the `@discordjs` organization run the following command:
```bash
```sh
yarn create-package <package-name> [package-description]
```

View File

@@ -143,6 +143,15 @@ jobs:
mv docs/${PACKAGE}/docs/docs.api.json out/${PACKAGE}/${SEMVER}.api.json
fi
- name: Upload documentation to database
if: ${{ github.ref_type == 'tag' && matrix.package == steps.extract-tag.outputs.package }}
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
uses: ./packages/actions/src/uploadDocumentation
with:
package: ${{ steps.extract-tag.outputs.package }}
version: ${{ steps.extract-tag.outputs.semver }}
- name: Move docs to correct directory
if: ${{ github.ref_type == 'branch' }}
env:
@@ -156,6 +165,14 @@ jobs:
mv docs/${PACKAGE}/docs/docs.api.json out/${PACKAGE}/${GITHUB_REF_NAME}.api.json
fi
- name: Upload documentation to database
if: ${{ github.ref_type == 'branch' }}
env:
DATABASE_URL: ${{ secrets.DATABASE_URL }}
uses: ./packages/actions/src/uploadDocumentation
with:
package: ${{ matrix.package }}
- name: Commit and push
run: |
cd out

View File

@@ -2,7 +2,6 @@ name: 'Issue Labeler'
on:
issues:
types: [opened]
jobs:
issue-triage:
runs-on: ubuntu-latest

20
.github/workflows/lighthouse-main.yml vendored Normal file
View File

@@ -0,0 +1,20 @@
name: 'Lighthouse Audit (main)'
on:
workflow_dispatch:
jobs:
lighthouse_audit_main:
name: 'Lighthouse Audit (main)'
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v3
- name: Audit production URLs with Lighthouse
id: lighthouse_audit
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
https://discordjs.dev
https://guide.discordjs.dev
uploadArtifacts: true
temporaryPublicStorage: true

88
.github/workflows/lighthouse.yml vendored Normal file
View File

@@ -0,0 +1,88 @@
name: 'Lighthouse Audit'
on:
issue_comment:
types: [created, edited]
jobs:
lighthouse_audit:
name: 'Lighthouse Audit'
if: ${{ github.event.issue.pull_request }}
runs-on: ubuntu-latest
steps:
- name: Get Vercel preview URL
id: get_preview_url
uses: actions/github-script@v3
with:
script: |
const comment = context.payload.comment;
const regex = /https:\/\/[a-z0-9-]+\.vercel\.app/g;
const matches = comment.body.match(regex);
let previewUrl = "";
if (matches && matches.length) {
previewUrl = matches[0];
console.log('Preview url found:', previewUrl);
}
console.log("No preview url found.");
core.setOutput('vercel_preview_url', previewUrl);
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add comment to PR
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: loading_comment_to_pr
uses: marocchino/sticky-pull-request-comment@v2
with:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
number: ${{ github.event.issue.number }}
header: lighthouse
message: |
Running Lighthouse audit...
- name: Checkout repository
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
uses: actions/checkout@v3
- name: Audit preview URL with Lighthouse
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: lighthouse_audit
uses: treosh/lighthouse-ci-action@v9
with:
urls: |
${{ steps.get_preview_url.outputs.vercel_preview_url }}
uploadArtifacts: true
temporaryPublicStorage: true
- name: Format lighthouse score
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: format_lighthouse_score
uses: actions/github-script@v3
with:
script: |
const result = ${{ steps.lighthouse_audit.outputs.manifest }}[0].summary
const links = ${{ steps.lighthouse_audit.outputs.links }}
const formatResult = (res) => Math.round((res * 100))
Object.keys(result).forEach(key => result[key] = formatResult(result[key]))
const score = res => res >= 90 ? '🟢' : res >= 50 ? '🟠' : '🔴'
const comment = [
`⚡️ [Lighthouse report](${Object.values(links)[0]}) for the changes in this PR:`,
'| Category | Score |',
'| --- | --- |',
`| ${score(result.performance)} Performance | ${result.performance} |`,
`| ${score(result.accessibility)} Accessibility | ${result.accessibility} |`,
`| ${score(result['best-practices'])} Best practices | ${result['best-practices']} |`,
`| ${score(result.seo)} SEO | ${result.seo} |`,
`| ${score(result.pwa)} PWA | ${result.pwa} |`,
' ',
`*Lighthouse ran on [${Object.keys(links)[0]}](${Object.keys(links)[0]})*`
].join('\n')
core.setOutput("comment", comment);
github-token: ${{ secrets.GITHUB_TOKEN }}
- name: Add comment to PR
if: ${{ steps.get_preview_url.outputs.vercel_preview_url != '' }}
id: comment_to_pr
uses: marocchino/sticky-pull-request-comment@v2
with:
number: ${{ github.event.issue.number }}
header: lighthouse
message: |
${{ steps.format_lighthouse_score.outputs.comment }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

19
.github/workflows/lock.yml vendored Normal file
View File

@@ -0,0 +1,19 @@
name: Lock Ancient Issues
on:
schedule:
- cron: '0 16 * * *'
workflow_dispatch:
permissions:
issues: write
concurrency:
group: lock
jobs:
action:
runs-on: ubuntu-latest
steps:
- uses: dessant/lock-threads@v4
with:
github-token: ${{ secrets.GITHUB_TOKEN }}
issue-inactive-days: 365
issue-lock-reason: resolved
process-only: issues

View File

@@ -12,6 +12,17 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install node.js v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
uses: ./packages/actions/src/yarnCache
- name: Build dependencies
run: yarn build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -19,7 +30,7 @@ jobs:
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Build the image
run: docker build -t discordjs/proxy:latest -f packages/proxy-container/Dockerfile .
run: yarn docker build @discordjs/proxy-container -t discordjs/proxy:latest
- name: Push image to DockerHub
run: docker push discordjs/proxy:latest

View File

@@ -9,6 +9,17 @@ jobs:
- name: Checkout repository
uses: actions/checkout@v3
- name: Install node.js v16
uses: actions/setup-node@v3
with:
node-version: 16
- name: Install dependencies
uses: ./packages/actions/src/yarnCache
- name: Build dependencies
run: yarn build
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
@@ -16,7 +27,7 @@ jobs:
run: echo ${{ secrets.DOCKER_ACCESS_TOKEN }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Build docker image
run: docker build -t discordjs/proxy:latest -f packages/proxy-container/Dockerfile .
run: yarn docker build @discordjs/proxy-container -t discordjs/proxy:latest
- name: Tag image with major
run: docker tag discordjs/proxy discordjs/proxy:$(cut -d '.' -f1 <<< $(jq --raw-output '.version' packages/proxy-container/package.json))

1
.gitignore vendored
View File

@@ -42,3 +42,4 @@ out/
# Cache
.prettiercache
.eslintcache
.vercel

View File

@@ -1,5 +1,5 @@
diff --git a/lib/TSDocConfigFile.js b/lib/TSDocConfigFile.js
index caf3515d60fd386c5909db5a0aa8b4180b10d602..6fa4f1984b6ba6b3a7aecd05e54477ebf141af94 100644
index caf3515d60fd386c5909db5a0aa8b4180b10d602..5f7cfed7611e3fe660b5265ff99c5da0beb7caec 100644
--- a/lib/TSDocConfigFile.js
+++ b/lib/TSDocConfigFile.js
@@ -31,8 +31,7 @@ const ajv_1 = __importDefault(require("ajv"));
@@ -8,7 +8,7 @@ index caf3515d60fd386c5909db5a0aa8b4180b10d602..6fa4f1984b6ba6b3a7aecd05e54477eb
function initializeSchemaValidator() {
- const jsonSchemaPath = resolve.sync('@microsoft/tsdoc/schemas/tsdoc.schema.json', { basedir: __dirname });
- const jsonSchemaContent = fs.readFileSync(jsonSchemaPath).toString();
+ const jsonSchemaContent = "{\"title\":\"TSDoc Configuration\",\"description\":\"Describes the TSDoc configuration for a TypeScript project\",\"type\":\"object\",\"properties\":{\"$schema\":{\"description\":\"Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.\",\"type\":\"string\"},\"extends\":{\"description\":\"Optionally specifies one or more JSON config files that will be combined with this file. This provides a way for standard settings to be shared across multiple projects. Important: The \\\"extends\\\" paths are resolved using NodeJS module resolution, so a path to a local file MUST be prefixed with \\\"./\\\".\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"noStandardTags\":{\"description\":\"By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and start with a completely empty configuration, set \\\"noStandardTags\\\"=true.\",\"type\":\"boolean\"},\"tagDefinitions\":{\"description\":\"Additional tags to support when parsing documentation comments with TSDoc.\",\"type\":\"array\",\"items\":{\"$ref\":\"#/definitions/tsdocTagDefinition\"}},\"supportedHtmlElements\":{\"description\":\"The HTML element names that are supported in this configuration. Used in conjunction with the \\\"reportUnsupportedHtmlElements\\\" setting.\",\"type\":\"array\",\"items\":{\"type\":\"string\",\"pattern\":\"^[a-zA-Z0-9-]+$\"}},\"reportUnsupportedHtmlElements\":{\"description\":\"Whether an error should be reported when an unsupported HTML element is encountered in a doc comment. Defaults to \\\"true\\\" if the \\\"supportedHtmlElements\\\" field is present in this file, \\\"false\\\" if not.\",\"type\":\"boolean\"},\"supportForTags\":{\"description\":\"A collection of key/value pairs. The key is a TSDoc tag name (e.g. \\\"@myTag\\\") that must be defined in this configuration. The value is a boolean indicating whether the tag is supported. The TSDoc parser may report warnings when unsupported tags are encountered. If \\\"supportForTags\\\" is specified for at least one tag, then the \\\"reportUnsupportedTags\\\" validation check is enabled by default.\",\"type\":\"object\",\"patternProperties\":{\"@[a-zA-Z][a-zA-Z0-9]*$\":{\"type\":\"boolean\"}},\"additionalItems\":false}},\"required\":[\"$schema\"],\"additionalProperties\":false,\"definitions\":{\"tsdocTagDefinition\":{\"description\":\"Configuration for a custom supported TSDoc tag.\",\"type\":\"object\",\"properties\":{\"tagName\":{\"description\":\"Name of the custom tag. TSDoc tag names start with an at-sign (@) followed by ASCII letters using camelCase capitalization.\",\"type\":\"string\"},\"syntaxKind\":{\"description\":\"Syntax kind of the custom tag. \\\"inline\\\" means that this tag can appear inside other documentation sections (example: {@link}). \\\"block\\\" means that this tag starts a new documentation section (example: @remarks). \\\"modifier\\\" means that this tag's presence indicates an aspect of the associated API item (example: @internal).\",\"type\":\"string\",\"enum\":[\"inline\",\"block\",\"modifier\"]},\"allowMultiple\":{\"description\":\"If true, then this tag may appear multiple times in a doc comment. By default, a tag may only appear once.\",\"type\":\"boolean\"}},\"required\":[\"tagName\",\"syntaxKind\"],\"additionalProperties\":false}}}";
+ const jsonSchemaContent = '{\"title\":\"TSDoc Configuration\",\"description\":\"Describes the TSDoc configuration for a TypeScript project\",\"type\":\"object\",\"properties\":{\"$schema\":{\"description\":\"Part of the JSON Schema standard, this optional keyword declares the URL of the schema that the file conforms to. Editors may download the schema and use it to perform syntax highlighting.\",\"type\":\"string\"},\"extends\":{\"description\":\"Optionally specifies one or more JSON config files that will be combined with this file. This provides a way for standard settings to be shared across multiple projects. Important: The \\\"extends\\\" paths are resolved using NodeJS module resolution, so a path to a local file MUST be prefixed with \\\".\/\\\".\",\"type\":\"array\",\"items\":{\"type\":\"string\"}},\"noStandardTags\":{\"description\":\"By default, the config file loader will predefine all of the standardized TSDoc tags. To disable this and start with a completely empty configuration, set \\\"noStandardTags\\\"=true.\",\"type\":\"boolean\"},\"tagDefinitions\":{\"description\":\"Additional tags to support when parsing documentation comments with TSDoc.\",\"type\":\"array\",\"items\":{\"$ref\":\"#\/definitions\/tsdocTagDefinition\"}},\"supportedHtmlElements\":{\"description\":\"The HTML element names that are supported in this configuration. Used in conjunction with the \\\"reportUnsupportedHtmlElements\\\" setting.\",\"type\":\"array\",\"items\":{\"type\":\"string\",\"pattern\":\"^[a-zA-Z0-9-]+$\"}},\"reportUnsupportedHtmlElements\":{\"description\":\"Whether an error should be reported when an unsupported HTML element is encountered in a doc comment. Defaults to \\\"true\\\" if the \\\"supportedHtmlElements\\\" field is present in this file, \\\"false\\\" if not.\",\"type\":\"boolean\"},\"supportForTags\":{\"description\":\"A collection of key\/value pairs. The key is a TSDoc tag name (e.g. \\\"@myTag\\\") that must be defined in this configuration. The value is a boolean indicating whether the tag is supported. The TSDoc parser may report warnings when unsupported tags are encountered. If \\\"supportForTags\\\" is specified for at least one tag, then the \\\"reportUnsupportedTags\\\" validation check is enabled by default.\",\"type\":\"object\",\"patternProperties\":{\"@[a-zA-Z][a-zA-Z0-9]*$\":{\"type\":\"boolean\"}},\"additionalItems\":false}},\"required\":[\"$schema\"],\"additionalProperties\":false,\"definitions\":{\"tsdocTagDefinition\":{\"description\":\"Configuration for a custom supported TSDoc tag.\",\"type\":\"object\",\"properties\":{\"tagName\":{\"description\":\"Name of the custom tag. TSDoc tag names start with an at-sign (@) followed by ASCII letters using camelCase capitalization.\",\"type\":\"string\"},\"syntaxKind\":{\"description\":\"Syntax kind of the custom tag. \\\"inline\\\" means that this tag can appear inside other documentation sections (example: {@link}). \\\"block\\\" means that this tag starts a new documentation section (example: @remarks). \\\"modifier\\\" means that this tag\'s presence indicates an aspect of the associated API item (example: @internal).\",\"type\":\"string\",\"enum\":[\"inline\",\"block\",\"modifier\"]},\"allowMultiple\":{\"description\":\"If true, then this tag may appear multiple times in a doc comment. By default, a tag may only appear once.\",\"type\":\"boolean\"}},\"required\":[\"tagName\",\"syntaxKind\"],\"additionalProperties\":false}}}';
const jsonSchema = jju.parse(jsonSchemaContent, { mode: 'cjson' });
return ajv.compile(jsonSchema);
}

View File

@@ -0,0 +1,257 @@
/* eslint-disable */
module.exports = {
name: '@yarnpkg/plugin-docker-build',
factory: function (require) {
var plugin;
(() => {
'use strict';
var t = {
d: (e, o) => {
for (var r in o) t.o(o, r) && !t.o(e, r) && Object.defineProperty(e, r, { enumerable: !0, get: o[r] });
},
o: (t, e) => Object.prototype.hasOwnProperty.call(t, e),
r: (t) => {
'undefined' != typeof Symbol &&
Symbol.toStringTag &&
Object.defineProperty(t, Symbol.toStringTag, { value: 'Module' }),
Object.defineProperty(t, '__esModule', { value: !0 });
},
},
e = {};
t.r(e), t.d(e, { default: () => u });
const o = require('@yarnpkg/cli'),
r = require('clipanion'),
i = require('@yarnpkg/core'),
a = require('@yarnpkg/plugin-patch'),
n = require('@yarnpkg/fslib');
const s = require('@yarnpkg/plugin-pack');
async function c({ workspace: t, destination: e, report: o }) {
await s.packUtils.prepareForPack(t, { report: o }, async () => {
const r = await s.packUtils.genPackList(t),
a = i.Report.progressViaCounter(r.length),
c = o.reportProgress(a);
try {
for (const i of r) {
const r = n.ppath.join(t.cwd, i),
s = n.ppath.join(e, t.relativeCwd, i);
o.reportInfo(null, i), await n.xfs.copyPromise(s, r, { overwrite: !0 }), a.tick();
}
} finally {
c.stop();
}
});
}
function p(t, e) {
const o = (0, n.toFilename)(e);
return n.ppath.isAbsolute(o) ? n.ppath.relative(t, o) : o;
}
const l = /^builtin<([^>]+)>$/;
var d = function (t, e, o, r) {
var i,
a = arguments.length,
n = a < 3 ? e : null === r ? (r = Object.getOwnPropertyDescriptor(e, o)) : r;
if ('object' == typeof Reflect && 'function' == typeof Reflect.decorate) n = Reflect.decorate(t, e, o, r);
else
for (var s = t.length - 1; s >= 0; s--)
(i = t[s]) && (n = (a < 3 ? i(n) : a > 3 ? i(e, o, n) : i(e, o)) || n);
return a > 3 && n && Object.defineProperty(e, o, n), n;
};
class f extends o.BaseCommand {
constructor() {
super(...arguments), (this.args = []);
}
async execute() {
const t = await i.Configuration.find(this.context.cwd, this.context.plugins),
{ project: e } = await i.Project.find(t, this.context.cwd),
o = e.getWorkspaceByIdent(i.structUtils.parseIdent(this.workspaceName)),
r = (function ({
project: t,
workspaces: e,
production: o = !1,
scopes: r = o ? ['dependencies'] : i.Manifest.hardDependencies,
}) {
const a = new Set([...e]);
for (const e of a)
for (const o of r) {
const r = e.manifest.getForScope(o).values();
for (const e of r) {
const o = t.tryWorkspaceByDescriptor(e);
o && a.add(o);
}
}
for (const e of t.workspaces)
a.has(e)
? o && e.manifest.devDependencies.clear()
: (e.manifest.dependencies.clear(),
e.manifest.devDependencies.clear(),
e.manifest.peerDependencies.clear());
return a;
})({ project: e, workspaces: [o], production: this.production }),
s = await (async function (t, e = 'Dockerfile') {
const o = (0, n.toFilename)(e);
if (n.ppath.isAbsolute(o)) return o;
const r = [n.ppath.join(t.cwd, o), n.ppath.join(t.project.cwd, o)];
for (const t of r) if (await n.xfs.existsPromise(t)) return t;
throw new Error('Dockerfile is required');
})(o, this.dockerFilePath),
d = await i.Cache.find(t);
return (
await i.StreamReport.start(
{ configuration: t, stdout: this.context.stdout, includeLogs: !this.context.quiet },
async (t) => {
await t.startTimerPromise('Resolution Step', async () => {
await e.resolveEverything({ report: t, cache: d });
}),
await t.startTimerPromise('Fetch Step', async () => {
await e.fetchEverything({ report: t, cache: d });
}),
await n.xfs.mktempPromise(async (o) => {
const f = n.ppath.join(o, (0, n.toFilename)('manifests')),
u = n.ppath.join(o, (0, n.toFilename)('packs'));
await t.startTimerPromise('Copy files', async () => {
await (async function ({ destination: t, project: e, report: o }) {
const r = e.configuration.get('rcFilename');
o.reportInfo(null, r),
await n.xfs.copyPromise(n.ppath.join(t, r), n.ppath.join(e.cwd, r), { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = n.ppath.join((0, n.toFilename)('.yarn'), (0, n.toFilename)('plugins'));
o.reportInfo(null, r),
await n.xfs.copyPromise(n.ppath.join(t, r), n.ppath.join(e.cwd, r), { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = e.configuration.get('yarnPath'),
i = n.ppath.relative(e.cwd, r),
a = n.ppath.join(t, i);
o.reportInfo(null, i), await n.xfs.copyPromise(a, r, { overwrite: !0 });
})({ destination: f, project: e, report: t }),
await (async function ({ destination: t, workspaces: e, report: o }) {
for (const r of e) {
const e = n.ppath.join(r.relativeCwd, i.Manifest.fileName),
a = n.ppath.join(t, e),
s = {};
r.manifest.exportTo(s),
o.reportInfo(null, e),
await n.xfs.mkdirpPromise(n.ppath.dirname(a)),
await n.xfs.writeJsonPromise(a, s);
}
})({ destination: f, workspaces: e.workspaces, report: t }),
await (async function ({ destination: t, report: e, project: o, parseDescriptor: r }) {
const a = new Set();
for (const s of o.storedDescriptors.values()) {
const c = r(
i.structUtils.isVirtualDescriptor(s) ? i.structUtils.devirtualizeDescriptor(s) : s,
);
if (!c) continue;
const { parentLocator: p, paths: d } = c;
for (const r of d) {
if (l.test(r)) continue;
if (n.ppath.isAbsolute(r)) continue;
const i = o.getWorkspaceByLocator(p),
s = n.ppath.join(i.relativeCwd, r);
if (a.has(s)) continue;
a.add(s);
const c = n.ppath.join(i.cwd, r),
d = n.ppath.join(t, s);
e.reportInfo(null, s),
await n.xfs.mkdirpPromise(n.ppath.dirname(d)),
await n.xfs.copyFilePromise(c, d);
}
}
})({
destination: f,
report: t,
project: e,
parseDescriptor: (t) => {
if (t.range.startsWith('exec:')) {
const e = (function (t) {
const { params: e, selector: o } = i.structUtils.parseRange(t),
r = n.npath.toPortablePath(o);
return {
parentLocator:
e && 'string' == typeof e.locator ? i.structUtils.parseLocator(e.locator) : null,
path: r,
};
})(t.range);
if (!e || !e.parentLocator) return;
return { parentLocator: e.parentLocator, paths: [e.path] };
}
if (t.range.startsWith('patch:')) {
const { parentLocator: e, patchPaths: o } = a.patchUtils.parseDescriptor(t);
if (!e) return;
return { parentLocator: e, paths: o };
}
},
}),
await (async function ({ destination: t, project: e, cache: o, report: r }) {
for (const i of o.markedFiles) {
const o = n.ppath.relative(e.cwd, i);
(await n.xfs.existsPromise(i)) &&
(r.reportInfo(null, o), await n.xfs.copyPromise(n.ppath.join(t, o), i));
}
})({ destination: f, project: e, cache: d, report: t }),
await (async function ({ destination: t, project: e, report: o }) {
const r = (0, n.toFilename)(e.configuration.get('lockfileFilename')),
i = n.ppath.join(t, r);
o.reportInfo(null, r),
await n.xfs.mkdirpPromise(n.ppath.dirname(i)),
await n.xfs.writeFilePromise(i, e.generateLockfile());
})({ destination: f, project: e, report: t }),
this.copyFiles &&
this.copyFiles.length &&
(await (async function ({ destination: t, files: e, dockerFilePath: o, report: r }) {
const i = n.ppath.dirname(o);
for (const o of e) {
const e = p(i, o),
a = n.ppath.join(i, e),
s = n.ppath.join(t, e);
r.reportInfo(null, e), await n.xfs.copyPromise(s, a);
}
})({ destination: f, files: this.copyFiles, dockerFilePath: s, report: t }));
});
for (const e of r) {
const o = e.manifest.name ? i.structUtils.stringifyIdent(e.manifest.name) : '';
await t.startTimerPromise('Pack workspace ' + o, async () => {
await c({ workspace: e, report: t, destination: u });
});
}
await i.execUtils.pipevp('docker', ['build', ...this.args, '-f', s, '.'], {
cwd: o,
strict: !0,
stdin: this.context.stdin,
stdout: this.context.stdout,
stderr: this.context.stderr,
});
});
},
)
).exitCode();
}
}
(f.usage = r.Command.Usage({
category: 'Docker-related commands',
description: 'Build a Docker image for a workspace',
details:
'\n This command will build a efficient Docker image which only contains necessary dependencies for the specified workspace.\n\n You have to create a Dockerfile in your workspace or your project. You can also specify the path to Dockerfile using the "-f, --file" option.\n\n Additional arguments can be passed to "docker build" directly, please check the Docker docs for more info: https://docs.docker.com/engine/reference/commandline/build/\n\n You can copy additional files or folders to a Docker image using the "--copy" option. This is useful for secret keys or configuration files. The files will be copied to "manifests" folder. The path can be either a path relative to the Dockerfile or an absolute path.\n ',
examples: [
['Build a Docker image for a workspace', 'yarn docker build @foo/bar'],
['Pass additional arguments to docker build command', 'yarn docker build @foo/bar -t image-tag'],
[
'Copy additional files to a Docker image',
'yarn docker build --copy secret.key --copy config.json @foo/bar',
],
['Install production dependencies only', 'yarn docker build --production @foo/bar'],
],
})),
d([r.Command.String()], f.prototype, 'workspaceName', void 0),
d([r.Command.Proxy()], f.prototype, 'args', void 0),
d([r.Command.String('-f,--file')], f.prototype, 'dockerFilePath', void 0),
d([r.Command.Array('--copy')], f.prototype, 'copyFiles', void 0),
d([r.Command.Boolean('--production')], f.prototype, 'production', void 0),
d([r.Command.Path('docker', 'build')], f.prototype, 'execute', null);
const u = { commands: [f] };
plugin = e;
})();
return plugin;
},
};

File diff suppressed because one or more lines are too long

View File

@@ -7,5 +7,7 @@ plugins:
spec: '@yarnpkg/plugin-workspace-tools'
- path: .yarn/plugins/@yarnpkg/plugin-version.cjs
spec: '@yarnpkg/plugin-version'
- path: .yarn/plugins/@yarnpkg/plugin-docker-build.cjs
spec: 'https://github.com/Dcard/yarn-plugins/releases/latest/download/plugin-docker-build.js'
yarnPath: .yarn/releases/yarn-3.4.1.cjs
yarnPath: .yarn/releases/yarn-3.5.0.cjs

119
README.md
View File

@@ -18,96 +18,28 @@
## About
discord.js is a powerful [Node.js](https://nodejs.org) module that allows you to easily interact with the
[Discord API](https://discord.com/developers/docs/intro).
This repository contains multiple packages with separate [releases][github-releases]. You can find the assembled Discord API wrapper at [`discord.js`][source]. It is a powerful [Node.js](https://nodejs.org/en) module that allows you to easily interact with the [Discord API](https://discord.com/developers/docs/intro).
- Object-oriented
- Predictable abstractions
- Performant
- 100% coverage of the Discord API
## Packages
## Installation
**Node.js 16.9.0 or newer is required.**
```sh-session
npm install discord.js
yarn add discord.js
pnpm add discord.js
```
### Optional packages
- [zlib-sync](https://www.npmjs.com/package/zlib-sync) for WebSocket data compression and inflation (`npm install zlib-sync`)
- [erlpack](https://github.com/discord/erlpack) for significantly faster WebSocket data (de)serialisation (`npm install discord/erlpack`)
- [bufferutil](https://www.npmjs.com/package/bufferutil) for a much faster WebSocket connection (`npm install bufferutil`)
- [utf-8-validate](https://www.npmjs.com/package/utf-8-validate) in combination with `bufferutil` for much faster WebSocket processing (`npm install utf-8-validate`)
- [@discordjs/voice](https://www.npmjs.com/package/@discordjs/voice) for interacting with the Discord Voice API (`npm install @discordjs/voice`)
## Example usage
Install discord.js:
```sh-session
npm install discord.js
yarn add discord.js
pnpm add discord.js
```
Register a slash command against the Discord API:
```js
const { REST, Routes } = require('discord.js');
const commands = [
{
name: 'ping',
description: 'Replies with Pong!',
},
];
const rest = new REST({ version: '10' }).setToken(TOKEN);
(async () => {
try {
console.log('Started refreshing application (/) commands.');
await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands });
console.log('Successfully reloaded application (/) commands.');
} catch (error) {
console.error(error);
}
})();
```
Afterwards we can create a quite simple example bot:
```js
const { Client, GatewayIntentBits } = require('discord.js');
const client = new Client({ intents: [GatewayIntentBits.Guilds] });
client.on('ready', () => {
console.log(`Logged in as ${client.user.tag}!`);
});
client.on('interactionCreate', async (interaction) => {
if (!interaction.isChatInputCommand()) return;
if (interaction.commandName === 'ping') {
await interaction.reply('Pong!');
}
});
client.login(TOKEN);
```
- `discord.js` ([source][source]) - A powerful Node.js module for interacting with the Discord API
- `@discordjs/brokers` ([source][brokers-source]) - A collection of brokers for use with discord.js
- `@discordjs/builders` ([source][builders-source]) - A utility package for easily building Discord API payloads
- `@discordjs/collection` ([source][collection-source]) - A powerful utility data structure
- `@discordjs/core` ([source][core-source]) - A thinly abstracted wrapper around the core components of the Discord API
- `@discordjs/formatters` ([source][formatters-source]) - A collection of functions for formatting strings
- `@discordjs/proxy` ([source][proxy-source]) - A wrapper around `@discordjs/rest` for running an HTTP proxy
- `@discordjs/rest` ([source][rest-source]) - A module for interacting with the Discord REST API
- `@discordjs/voice` ([source][voice-source]) - A module for interacting with the Discord Voice API
- `@discordjs/util` ([source][util-source]) - A collection of utility functions
- `@discordjs/ws` ([source][ws-source]) - A wrapper around Discord's gateway
## Links
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
See also the [Update Guide][guide-update], including updated and removed items in the library.
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -120,18 +52,15 @@ client.login(TOKEN);
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
Please read through our [contribution guidelines][contributing] before starting a pull request. We welcome contributions of all kinds, not just code! If you're stuck for ideas, look for the [good first issue][good-first-issue] label on issues in the repository. If you have any questions about the project, feel free to ask them on [Discord][discord]. Before creating your own issue or pull request, always check to see if one already exists! Don't rush contributions, take your time and ensure you're doing it correctly.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please join our [Discord server][discord].
[website]: https://discord.js.org/
[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/#/docs
[documentation]: https://discord.js.org/docs
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html
@@ -143,3 +72,15 @@ nudge in the right direction, please don't hesitate to join our official [discor
[rpc]: https://www.npmjs.com/package/discord-rpc
[rpc-source]: https://github.com/discordjs/RPC
[contributing]: https://github.com/discordjs/discord.js/blob/main/.github/CONTRIBUTING.md
[github-releases]: https://github.com/discordjs/discord.js/releases
[brokers-source]: https://github.com/discordjs/discord.js/tree/main/packages/brokers
[builders-source]: https://github.com/discordjs/discord.js/tree/main/packages/builders
[collection-source]: https://github.com/discordjs/discord.js/tree/main/packages/collection
[core-source]: https://github.com/discordjs/discord.js/tree/main/packages/core
[formatters-source]: https://github.com/discordjs/discord.js/tree/main/packages/formatters
[proxy-source]: https://github.com/discordjs/discord.js/tree/main/packages/proxy
[rest-source]: https://github.com/discordjs/discord.js/tree/main/packages/rest
[voice-source]: https://github.com/discordjs/discord.js/tree/main/packages/voice
[util-source]: https://github.com/discordjs/discord.js/tree/main/packages/util
[ws-source]: https://github.com/discordjs/discord.js/tree/main/packages/ws
[good-first-issue]: https://github.com/discordjs/discord.js/contribute

View File

@@ -1,11 +1,12 @@
{
"extends": ["../../.eslintrc.json", "neon/react", "neon/astro", "neon/prettier"],
"extends": ["../../.eslintrc.json", "neon/react", "neon/next", "neon/edge", "neon/prettier"],
"settings": {
"react": {
"version": "detect"
}
},
"rules": {
"react/jsx-filename-extension": [1, { "extensions": [".tsx", ".astro"] }]
"react/react-in-jsx-scope": 0,
"react/jsx-filename-extension": [1, { "extensions": [".tsx"] }]
}
}

View File

@@ -13,13 +13,13 @@ pids
# Env
.env
.env*.local
# Dist
dist/
typings/
.cache/
build/
api/
src/styles/unocss.css
.next/
@@ -28,3 +28,6 @@ src/styles/unocss.css
coverage/
.vercel
public/searchIndex
.vscode
lighthouse-results/
.contentlayer

View File

@@ -1,7 +1,6 @@
module.exports = {
...require('../../.prettierrc.json'),
plugins: [
'prettier-plugin-astro',
'prettier-plugin-tailwindcss', // MUST come last
],
pluginSearchDirs: false,

View File

@@ -13,12 +13,16 @@
</p>
</div>
## About
The official guide for discord.js, made to help you get started easily with the library.
## Links
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
See also the [Update Guide][guide-update], including updated and removed items in the library.
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -26,16 +30,17 @@
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[website]: https://discord.js.org/
[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/
[documentation]: https://discord.js.org/docs
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html

View File

@@ -1,118 +0,0 @@
import { fileURLToPath, URL } from 'node:url';
import image from '@astrojs/image';
import mdx from '@astrojs/mdx';
import prefetch from '@astrojs/prefetch';
import react from '@astrojs/react';
import { remarkCodeHike } from '@code-hike/mdx';
import { defineConfig } from 'astro/config';
import compress from 'astro-compress';
import critters from 'astro-critters';
import { type Node, toString } from 'hast-util-to-string';
import { h } from 'hastscript';
import { escape } from 'html-escaper';
import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';
import shikiThemeDarkPlus from 'shiki/themes/dark-plus.json' assert { type: 'json' };
import Unocss from 'unocss/astro';
const LinkIcon = h(
'svg',
{
width: '1rem',
height: '1rem',
viewBox: '0 0 24 24',
fill: 'none',
stroke: 'currentColor',
strokeWidth: '2',
strokeLinecap: 'round',
strokeLinejoin: 'round',
},
h('path', {
// eslint-disable-next-line id-length
d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',
}),
h('path', {
// eslint-disable-next-line id-length
d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
}),
);
const createSROnlyLabel = (text: string) => {
const node = h('span.sr-only', `Section titled ${escape(text)}`);
node.properties!['is:raw'] = true;
return node;
};
const rootDir = new URL('../../', import.meta.url);
export default defineConfig({
integrations: [
react(),
mdx({
remarkPlugins: [[remarkCodeHike, { autoImport: false, theme: shikiThemeDarkPlus, lineNumbers: true }]],
rehypePlugins: [
rehypeSlug,
[
rehypeAutolinkHeadings,
{
properties: {
class:
'relative inline-flex w-6 h-6 place-items-center place-content-center outline-0 text-black dark:text-white ml-2',
},
behavior: 'after',
group: ({ tagName }: { tagName: string }) =>
h('div', {
class: `[&>*]:inline-block [&>h1]:m-0 [&>h2]:m-0 [&>h3]:m-0 [&>h4]:m-0 level-${tagName}`,
tabIndex: -1,
}),
content: (heading: Node) => [
h(
`span.anchor-icon`,
{
ariaHidden: 'true',
},
LinkIcon,
),
createSROnlyLabel(toString(heading)),
],
},
],
],
}),
image({
serviceEntryPoint: '@astrojs/image/sharp',
}),
prefetch({
throttle: 3,
}),
Unocss({
configFile: fileURLToPath(new URL('unocss.config.ts', rootDir)),
}),
critters(),
compress(),
],
markdown: {
extendDefaultPlugins: true,
syntaxHighlight: false,
},
vite: {
resolve: {
alias: {
'ariakit/button': fileURLToPath(new URL('node_modules/ariakit/esm/button/index.js', rootDir)),
'ariakit/disclosure': fileURLToPath(new URL('node_modules/ariakit/esm/disclosure/index.js', rootDir)),
'ariakit/separator': fileURLToPath(new URL('node_modules/ariakit/esm/separator/index.js', rootDir)),
'ariakit-utils/dom': fileURLToPath(new URL('node_modules/ariakit-utils/esm/dom.js', rootDir)),
'ariakit-utils/events': fileURLToPath(new URL('node_modules/ariakit-utils/esm/events.js', rootDir)),
'ariakit-utils/focus': fileURLToPath(new URL('node_modules/ariakit-utils/esm/focus.js', rootDir)),
'ariakit-utils/misc': fileURLToPath(new URL('node_modules/ariakit-utils/esm/misc.js', rootDir)),
'ariakit-utils/platform': fileURLToPath(new URL('node_modules/ariakit-utils/esm/platform.js', rootDir)),
'ariakit-react-utils/hooks': fileURLToPath(new URL('node_modules/ariakit-react-utils/esm/hooks.js', rootDir)),
'ariakit-react-utils/misc': fileURLToPath(new URL('node_modules/ariakit-react-utils/esm/misc.js', rootDir)),
'ariakit-react-utils/system': fileURLToPath(new URL('node_modules/ariakit-react-utils/esm/system.js', rootDir)),
'react-icons/fi': fileURLToPath(new URL('node_modules/react-icons/fi/index.esm.js', rootDir)),
'react-icons/vsc': fileURLToPath(new URL('node_modules/react-icons/vsc/index.esm.js', rootDir)),
'react-use': fileURLToPath(new URL('node_modules/react-use/esm/index.js', rootDir)),
},
},
},
});

View File

@@ -0,0 +1,100 @@
import { remarkCodeHike } from '@code-hike/mdx';
import { defineDocumentType, makeSource } from 'contentlayer/source-files';
// import { type Node, toString } from 'hast-util-to-string';
// import { h } from 'hastscript';
// import { escape } from 'html-escaper';
// import rehypeAutolinkHeadings from 'rehype-autolink-headings';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
export const Content = defineDocumentType(() => ({
name: 'Content',
filePathPattern: `**/*.mdx`,
contentType: 'mdx',
fields: {
title: {
type: 'string',
required: true,
},
summary: {
type: 'string',
},
image: {
type: 'string',
},
},
computedFields: {
slug: {
type: 'string',
resolve: (doc) => doc._raw.flattenedPath,
},
url: {
type: 'string',
resolve: (post) => `/posts/${post._raw.flattenedPath}`,
},
},
}));
// const LinkIcon = h(
// 'svg',
// {
// width: '1rem',
// height: '1rem',
// viewBox: '0 0 24 24',
// fill: 'none',
// stroke: 'currentColor',
// strokeWidth: '2',
// strokeLinecap: 'round',
// strokeLinejoin: 'round',
// },
// h('path', {
// // eslint-disable-next-line id-length
// d: 'M10 13a5 5 0 0 0 7.54.54l3-3a5 5 0 0 0-7.07-7.07l-1.72 1.71',
// }),
// h('path', {
// // eslint-disable-next-line id-length
// d: 'M14 11a5 5 0 0 0-7.54-.54l-3 3a5 5 0 0 0 7.07 7.07l1.71-1.71',
// }),
// );
// const createSROnlyLabel = (text: any) => {
// const node = h('span.sr-only', `Section titled ${escape(text)}`);
// node.properties!['is:raw'] = true;
// return node;
// };
export default makeSource({
contentDirPath: 'src/content',
documentTypes: [Content],
mdx: {
remarkPlugins: [remarkGfm, [remarkCodeHike, { theme: 'css-variables', lineNumbers: true }]],
rehypePlugins: [
rehypeSlug,
// [
// rehypeAutolinkHeadings,
// {
// properties: {
// class:
// 'relative inline-flex w-6 h-6 place-items-center place-content-center outline-0 text-black dark:text-white ml-2',
// },
// behavior: 'after',
// group: async ({ tagName }: { tagName: string }) =>
// h('div', {
// class: `[&>*]:inline-block [&>h1]:m-0 [&>h2]:m-0 [&>h3]:m-0 [&>h4]:m-0 level-${tagName}`,
// tabIndex: -1,
// }),
// content: (heading: Node) => [
// h(
// `span.anchor-icon`,
// {
// ariaHidden: 'true',
// },
// LinkIcon,
// ),
// createSROnlyLabel(toString(heading)),
// ],
// },
// ],
],
},
});

5
apps/guide/next-env.d.ts vendored Normal file
View File

@@ -0,0 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

32
apps/guide/next.config.js Normal file
View File

@@ -0,0 +1,32 @@
// import { fileURLToPath } from 'node:url';
// import bundleAnalyzer from '@next/bundle-analyzer';
// import { withContentlayer } from 'next-contentlayer';
const { fileURLToPath } = require('node:url');
const bundleAnalyzer = require('@next/bundle-analyzer');
const { withContentlayer } = require('next-contentlayer');
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
module.exports = withContentlayer(
withBundleAnalyzer({
reactStrictMode: true,
eslint: {
ignoreDuringBuilds: true,
},
// Until Next.js fixes their type issues
typescript: {
ignoreBuildErrors: true,
},
experimental: {
appDir: true,
fallbackNodePolyfills: false,
},
images: {
dangerouslyAllowSVG: true,
contentDispositionType: 'attachment',
contentSecurityPolicy: "default-src 'self'; frame-src 'none'; sandbox;",
},
}),
);

View File

@@ -5,15 +5,22 @@
"private": true,
"scripts": {
"test": "vitest run",
"test:lighthouse": "lighthouse http://localhost:3000 --output-path=./lighthouse-results",
"build:local": "yarn build:prod",
"build:prod": "yarn workspaces foreach -ptR run build && astro build",
"dev": "yarn workspaces foreach -ptR run build && astro dev",
"preview": "astro preview",
"lint": "prettier --check . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx,.astro --format=pretty",
"format": "prettier --write . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx,.astro --fix --format=pretty",
"build:prod": "yarn workspaces foreach -ptR run build && yarn build:css && yarn build:next",
"build:next": "next build",
"build:css": "yarn generate:css",
"build:analyze": "cross-env-shell ANALYZE=true yarn build:prod",
"preview": "next start",
"dev": "concurrently 'yarn dev:css' 'yarn dev:next'",
"dev:next": "next dev",
"dev:css": "yarn generate:css --watch",
"generate:css": "unocss 'src/**/*.tsx' '../../packages/ui/src/lib/components/**/*.tsx' --out-file ./src/styles/unocss.css --config ../../unocss.config.ts",
"lint": "prettier --check . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx --format=pretty",
"format": "prettier --write . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx --fix --format=pretty",
"fmt": "yarn format"
},
"type": "module",
"type": "commonjs",
"contributors": [
"Crawl <icrawltogo@gmail.com>"
],
@@ -36,54 +43,60 @@
},
"homepage": "https://discord.js.org",
"dependencies": {
"@code-hike/mdx": "^0.8.0",
"@code-hike/mdx": "^0.7.5-next.0",
"@discordjs/ui": "workspace:^",
"@react-icons/all-files": "^4.1.0",
"@vercel/analytics": "^0.1.11",
"@vercel/edge-config": "^0.1.5",
"@vercel/og": "^0.5.0",
"ariakit": "^2.0.0-next.43",
"cmdk": "^0.2.0",
"contentlayer": "^0.3.1",
"next": "^13.2.4",
"next-contentlayer": "^0.3.1",
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-custom-scrollbars-2": "^4.5.0",
"react-dom": "^18.2.0",
"react-icons": "^4.7.1",
"react-use": "^17.4.0"
"react-icons": "^4.8.0",
"react-use": "^17.4.0",
"rehype-autolink-headings": "^6.1.1",
"rehype-ignore": "^1.0.4",
"rehype-raw": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"sharp": "^0.32.0"
},
"devDependencies": {
"@astrojs/image": "^0.15.1",
"@astrojs/mdx": "^0.17.2",
"@astrojs/prefetch": "^0.1.2",
"@astrojs/react": "^2.0.2",
"@next/bundle-analyzer": "^13.2.4",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "16.18.13",
"@types/react": "^18.0.28",
"@types/node": "18.15.11",
"@types/react": "^18.0.31",
"@types/react-dom": "^18.0.11",
"@types/react-syntax-highlighter": "^15.5.6",
"@unocss/cli": "^0.50.1",
"@unocss/reset": "^0.50.1",
"@unocss/cli": "^0.50.6",
"@unocss/reset": "^0.50.6",
"@vitejs/plugin-react": "^3.1.0",
"@vitest/coverage-c8": "^0.29.1",
"astro": "^1.9.2",
"astro-compress": "^1.1.35",
"astro-critters": "^1.1.31",
"@vitest/coverage-c8": "^0.29.8",
"concurrently": "^8.0.1",
"cross-env": "^7.0.3",
"eslint": "^8.35.0",
"eslint-config-neon": "^0.1.40",
"eslint-formatter-pretty": "^4.1.0",
"eslint": "^8.37.0",
"eslint-config-neon": "^0.1.41",
"eslint-formatter-pretty": "^5.0.0",
"happy-dom": "^8.9.0",
"hast-util-to-string": "^2.0.0",
"hastscript": "^7.2.0",
"html-escaper": "^3.0.3",
"prettier": "^2.8.4",
"lighthouse": "^10.1.0",
"prettier": "^2.8.7",
"prettier-plugin-astro": "^0.8.0",
"prettier-plugin-tailwindcss": "^0.2.3",
"rehype-autolink-headings": "^6.1.1",
"rehype-slug": "^5.1.0",
"sharp": "^0.31.3",
"shiki": "^0.14.1",
"typescript": "^4.9.5",
"unocss": "^0.50.1",
"vercel": "^28.16.7",
"vitest": "^0.29.1"
"prettier-plugin-tailwindcss": "^0.2.6",
"typescript": "^5.0.3",
"unocss": "^0.50.6",
"vercel": "^28.18.3",
"vitest": "^0.29.8"
},
"engines": {
"node": ">=16.9.0"
"node": ">=18.13.0"
}
}

View File

@@ -0,0 +1,12 @@
'use client';
export default function Error({ error }: { error: Error }) {
console.error(error);
return (
<div className="mx-auto flex h-full max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
);
}

View File

@@ -0,0 +1,23 @@
'use client';
import { Providers } from './providers';
import { inter } from '~/util/fonts';
export default function GlobalError({ error }: { error: Error }) {
console.error(error);
return (
<html className={inter.variable} lang="en" suppressHydrationWarning>
<body className="dark:bg-dark-800 bg-light-600">
<Providers>
<main className="mx-auto h-screen max-w-2xl">
<div className="mx-auto flex h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
</main>
</Providers>
</body>
</html>
);
}

View File

@@ -0,0 +1,21 @@
import { allContents } from 'contentlayer/generated';
import { notFound } from 'next/navigation';
import { Mdx } from '~/components/Mdx';
export async function generateStaticParams() {
return allContents.map((content) => ({ slug: content.slug }));
}
export default function Page({ params }: { params: { slug: string[] } }) {
const content = allContents.find((content) => content.slug === params.slug?.join('/'));
if (!content) {
notFound();
}
return (
<article className="prose mx-auto max-w-4xl py-8">
<Mdx code={content?.body.code ?? ''} />
</article>
);
}

View File

@@ -0,0 +1,83 @@
import { Analytics } from '@vercel/analytics/react';
import type { Metadata } from 'next/types';
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import { DESCRIPTION } from '~/util/constants';
import { inter, jetBrainsMono } from '~/util/fonts';
import '@unocss/reset/tailwind-compat.css';
import '~/styles/unocss.css';
import '~/styles/cmdk.css';
import '@code-hike/mdx/styles.css';
import '~/styles/ch.css';
import '~/styles/main.css';
export const metadata: Metadata = {
title: 'discord.js',
description: DESCRIPTION,
viewport: {
minimumScale: 1,
initialScale: 1,
width: 'device-width',
},
icons: {
other: [
{
url: '/favicon-32x32.png',
sizes: '32x32',
type: 'image/png',
},
{
url: '/favicon-16x16.png',
sizes: '16x16',
type: 'image/png',
},
],
apple: [
'/apple-touch-icon.png',
{
url: '/safari-pinned-tab.svg',
rel: 'mask-icon',
},
],
},
manifest: '/site.webmanifest',
themeColor: '#5865f2',
colorScheme: 'light dark',
appleWebApp: {
title: 'discord.js',
},
applicationName: 'discord.js',
openGraph: {
siteName: 'discord.js',
type: 'website',
title: 'discord.js',
description: DESCRIPTION,
images: 'https://discordjs.dev/api/open-graph.png',
},
twitter: {
card: 'summary_large_image',
creator: '@iCrawlToGo',
},
other: {
'msapplication-TileColor': '#090a16',
},
};
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html className={`${inter.variable} ${jetBrainsMono.variable}`} lang="en" suppressHydrationWarning>
<body className="dark:bg-dark-800 bg-light-600">
<Providers>{children}</Providers>
<Analytics />
</body>
</html>
);
}

View File

@@ -0,0 +1,20 @@
export default function Loading() {
return (
<div className="mx-4 flex min-h-screen flex-col items-center justify-center gap-4">
<svg
className="h-9 w-9 animate-spin text-black dark:text-white"
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path
className="opacity-75 dark:opacity-100"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
fill="currentColor"
/>
</svg>
<div className="text-lg font-medium">Loading...</div>
</div>
);
}

View File

@@ -0,0 +1,16 @@
import Link from 'next/link';
export default function NotFound() {
return (
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">404</h1>
<h2 className="text-[2rem] md:text-[3rem]">Not found.</h2>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/docs/packages"
>
Take me back
</Link>
</div>
);
}

View File

@@ -0,0 +1,26 @@
import Image from 'next/image';
import vercelLogo from '~/assets/powered-by-vercel.svg';
export default function Page() {
return (
<div className="mx-auto flex min-h-screen max-w-6xl flex-col place-items-center gap-12 px-8 py-16 lg:place-content-center lg:px-8 lg:py-0">
<div className="flex flex-row place-content-center">
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="noopener noreferrer"
target="_blank"
title="Vercel"
>
<Image
alt="Vercel"
blurDataURL="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAQAAAABLCAQAAAA1k5H2AAAAi0lEQVR42u3SMQEAAAgDoC251a3gL2SgmfBYBRAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARAAARCAgwWEOSWBnYbKggAAAABJRU5ErkJggg=="
placeholder="blur"
priority
src={vercelLogo}
/>
</a>
</div>
</div>
);
}

View File

@@ -0,0 +1,8 @@
'use client';
import { ThemeProvider } from 'next-themes';
import type { PropsWithChildren } from 'react';
export function Providers({ children }: PropsWithChildren) {
return <ThemeProvider attribute="class">{children}</ThemeProvider>;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="212" height="44" fill="none"><rect width="212" height="44" fill="#000" rx="8"/><path fill="#fff" d="M60.438 15.227V26.5h1.406v-4.023h2.836c2.117 0 3.625-1.493 3.625-3.602 0-2.148-1.477-3.648-3.61-3.648h-4.257Zm1.406 1.25h2.484c1.633 0 2.531.851 2.531 2.398 0 1.492-.93 2.352-2.53 2.352h-2.485v-4.75Zm11.5 10.171c2.399 0 3.883-1.656 3.883-4.359 0-2.71-1.484-4.36-3.883-4.36-2.398 0-3.883 1.65-3.883 4.36 0 2.703 1.485 4.36 3.883 4.36Zm0-1.21c-1.594 0-2.492-1.157-2.492-3.149 0-2 .898-3.148 2.492-3.148 1.594 0 2.492 1.148 2.492 3.148 0 1.992-.898 3.148-2.492 3.148Zm15.954-7.36h-1.352l-1.656 6.735h-.125l-1.883-6.735h-1.29l-1.882 6.735h-.125l-1.656-6.735h-1.36l2.36 8.422h1.36l1.874-6.516h.125l1.883 6.516h1.367l2.36-8.422Zm4.523 1.04c1.336 0 2.227.984 2.258 2.476h-4.64c.101-1.492 1.039-2.477 2.382-2.477Zm2.219 5.202c-.352.742-1.086 1.14-2.172 1.14-1.43 0-2.36-1.054-2.43-2.718v-.062h6.055v-.516c0-2.617-1.383-4.234-3.656-4.234-2.313 0-3.797 1.718-3.797 4.367 0 2.664 1.46 4.351 3.797 4.351 1.844 0 3.156-.89 3.547-2.328H96.04Zm3.242 2.18h1.344v-5.219c0-1.187.93-2.047 2.211-2.047.266 0 .75.047.86.078V17.97a5.77 5.77 0 0 0-.672-.04c-1.117 0-2.086.579-2.336 1.4h-.125v-1.25h-1.281V26.5Zm8.899-7.383c1.336 0 2.227.985 2.258 2.477h-4.641c.102-1.492 1.04-2.477 2.383-2.477Zm2.219 5.203c-.352.742-1.086 1.14-2.172 1.14-1.43 0-2.359-1.054-2.43-2.718v-.062h6.055v-.516c0-2.617-1.383-4.234-3.656-4.234-2.313 0-3.797 1.718-3.797 4.367 0 2.664 1.461 4.351 3.797 4.351 1.844 0 3.156-.89 3.547-2.328H110.4Zm6.36 2.328c1.164 0 2.164-.554 2.695-1.492h.125V26.5h1.281V14.734h-1.343v4.672h-.118c-.476-.922-1.468-1.476-2.64-1.476-2.141 0-3.539 1.718-3.539 4.36 0 2.648 1.382 4.358 3.539 4.358Zm.312-7.507c1.524 0 2.477 1.218 2.477 3.148 0 1.945-.946 3.148-2.477 3.148-1.539 0-2.461-1.18-2.461-3.148 0-1.96.93-3.148 2.461-3.148Zm14.462 7.507c2.133 0 3.531-1.726 3.531-4.359 0-2.648-1.391-4.36-3.531-4.36-1.156 0-2.18.571-2.641 1.477h-.125v-4.672h-1.344V26.5h1.282v-1.344h.125c.531.938 1.531 1.492 2.703 1.492Zm-.313-7.507c1.539 0 2.453 1.18 2.453 3.148 0 1.969-.914 3.148-2.453 3.148-1.531 0-2.484-1.203-2.484-3.148s.953-3.148 2.484-3.148Zm6.04 10.406c1.492 0 2.164-.578 2.882-2.531l3.29-8.938h-1.43l-2.305 6.93h-.125l-2.312-6.93h-1.453l3.117 8.43-.157.5c-.351 1.015-.773 1.383-1.546 1.383-.188 0-.399-.008-.563-.04V29.5c.188.031.422.047.602.047Zm17.391-3.047 3.898-11.273h-2.148l-2.813 8.921h-.132l-2.836-8.921h-2.227l3.938 11.273h2.32Zm8.016-7.18c1.164 0 1.93.813 1.969 2.078h-4.024c.086-1.25.899-2.078 2.055-2.078Zm1.984 4.828c-.281.633-.945.985-1.906.985-1.273 0-2.094-.89-2.141-2.313v-.101h5.969v-.625c0-2.696-1.461-4.313-3.898-4.313-2.477 0-4.016 1.727-4.016 4.477s1.516 4.414 4.031 4.414c2.016 0 3.446-.969 3.797-2.524h-1.836Zm3.547 2.352h1.938v-4.938c0-1.195.875-1.976 2.133-1.976.328 0 .843.055.992.11v-1.798c-.18-.054-.524-.085-.805-.085-1.101 0-2.023.625-2.258 1.468h-.132v-1.328h-1.868V26.5Zm13.501-5.672c-.203-1.797-1.532-3.047-3.727-3.047-2.57 0-4.078 1.649-4.078 4.422 0 2.813 1.516 4.469 4.086 4.469 2.164 0 3.508-1.203 3.719-2.992h-1.844c-.203.89-.875 1.367-1.883 1.367-1.32 0-2.117-1.047-2.117-2.844 0-1.773.789-2.797 2.117-2.797 1.063 0 1.703.594 1.883 1.422h1.844Zm5.117-1.508c1.164 0 1.93.813 1.969 2.078h-4.024c.086-1.25.899-2.078 2.055-2.078Zm1.985 4.828c-.282.633-.946.985-1.907.985-1.273 0-2.093-.89-2.14-2.313v-.101h5.968v-.625c0-2.696-1.461-4.313-3.898-4.313-2.477 0-4.016 1.727-4.016 4.477s1.516 4.414 4.032 4.414c2.015 0 3.445-.969 3.796-2.524h-1.835Zm3.625 2.352h1.937V14.648h-1.937V26.5ZM23.325 13l9.325 16H14l9.325-16Z"/><path stroke="#5E5E5E" d="M43.5 0v44"/></svg>

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

@@ -0,0 +1,16 @@
'use client';
import { Alert, Section, DiscordMessages, DiscordMessage, DiscordMessageEmbed } from '@discordjs/ui';
import { useMDXComponent } from 'next-contentlayer/hooks';
import { DocsLink } from '~/components/DocsLink';
import { ResultingCode } from '~/components/ResultingCode';
export function Mdx({ code }: { code: string }) {
const Component = useMDXComponent(code);
return (
<Component
components={{ Alert, Section, DiscordMessages, DiscordMessage, DiscordMessageEmbed, DocsLink, ResultingCode }}
/>
);
}

View File

@@ -18,8 +18,8 @@ export function Navbar({ pages }: { pages?: MDXPage[] | undefined }) {
return (
<>
<header className="dark:bg-dark-600 dark:border-dark-100 bg-light-600 border-light-800 fixed top-0 left-0 z-20 w-full border-b">
<div className="h-18 block px-6">
<header className="dark:bg-dark-400 dark:border-dark-100 bg-light-600 border-light-800 fixed left-0 top-0 z-20 w-full border-b">
<div className="block h-16 px-6">
<div className="flex h-full flex-row place-content-between place-items-center">
<Button
aria-label="Menu"
@@ -55,7 +55,7 @@ export function Navbar({ pages }: { pages?: MDXPage[] | undefined }) {
</Button>
<Button
aria-label="Toggle theme"
className="focus:ring-width-2 focus:ring-blurple flex h-6 w-6 transform-gpu cursor-pointer select-none appearance-none place-items-center rounded-full rounded border-0 bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-0 focus:ring active:translate-y-px"
className="focus:ring-width-2 focus:ring-blurple flex h-6 w-6 transform-gpu cursor-pointer select-none appearance-none place-items-center rounded rounded-full border-0 bg-transparent p-0 text-sm font-semibold leading-none no-underline outline-0 focus:ring active:translate-y-px"
// onClick={() => toggleTheme()}
>
<VscColorMode size={24} />

View File

@@ -45,16 +45,16 @@ export function Outline({ headings }: { headings: MarkdownHeading[] }) {
hideTracksWhenNotNeeded
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
renderTrackVertical={(props) => (
<div {...props} className="absolute top-0.5 right-0.5 bottom-0.5 z-30 w-1.5 rounded" />
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
)}
universal
>
<div className="flex flex-col break-all p-3 pb-8">
<div className="mt-4 ml-2 flex flex-row gap-2">
<div className="ml-2 mt-4 flex flex-row gap-2">
<VscListSelection size={25} />
<span className="font-semibold">Contents</span>
</div>
<div className="mt-4 ml-2 flex flex-col gap-2">
<div className="ml-2 mt-4 flex flex-col gap-2">
<div className="relative flex flex-col">
<div
className="bg-blurple absolute h-[10px] w-[10px] rounded-full border-2 border-black dark:border-white"

View File

@@ -1,7 +1,7 @@
export function PageButton({ url, title, direction }: { direction: 'next' | 'prev'; title: string; url: string }) {
return (
<a
className="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-600 dark:hover:bg-dark-500 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple flex transform-gpu cursor-pointer select-none appearance-none flex-row flex-col place-items-center gap-2 rounded py-3 px-4 leading-none no-underline outline-0 focus:ring active:translate-y-px"
className="bg-light-600 hover:bg-light-700 active:bg-light-800 dark:bg-dark-600 dark:hover:bg-dark-500 dark:active:bg-dark-400 focus:ring-width-2 focus:ring-blurple flex transform-gpu cursor-pointer select-none appearance-none flex-row flex-col place-items-center gap-2 rounded px-4 py-3 leading-none no-underline outline-0 focus:ring active:translate-y-px"
href={url}
>
<h3 className="text-md font-semibold">{title}</h3>

View File

@@ -4,7 +4,7 @@ import type { MDXPage } from './SidebarItems.jsx';
export function Sidebar({ pages, opened }: { opened: boolean; pages?: MDXPage[] | undefined }) {
return (
<nav
className={`h-[calc(100vh - 73px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed top-[73px] left-0 bottom-0 z-20 w-full border-r bg-white ${
className={`h-[calc(100vh - 65px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed bottom-0 left-0 top-[65px] z-20 w-full border-r bg-white ${
opened ? 'block' : 'hidden'
} lg:w-76 lg:max-w-76 lg:block`}
>
@@ -13,7 +13,7 @@ export function Sidebar({ pages, opened }: { opened: boolean; pages?: MDXPage[]
hideTracksWhenNotNeeded
renderThumbVertical={(props) => <div {...props} className="dark:bg-dark-100 bg-light-900 z-30 rounded" />}
renderTrackVertical={(props) => (
<div {...props} className="absolute top-0.5 right-0.5 bottom-0.5 z-30 w-1.5 rounded" />
<div {...props} className="absolute bottom-0.5 right-0.5 top-0.5 z-30 w-1.5 rounded" />
)}
universal
>

View File

@@ -28,7 +28,7 @@ export function SidebarItems({ pages }: { pages: MDXPage[] }) {
}, [state]);
return Object.keys(categories).map((category, idx) => (
<Section key={idx} title={category}>
<Section key={`${category}-${idx}`} title={category}>
{categories[category]?.map((member, index) => (
<a
className={`dark:border-dark-100 border-light-800 focus:ring-width-2 focus:ring-blurple ml-5 flex flex-col border-l p-[5px] pl-6 outline-0 focus:rounded focus:border-0 focus:ring ${
@@ -38,7 +38,7 @@ export function SidebarItems({ pages }: { pages: MDXPage[] }) {
}`}
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
href={member.url || '/'}
key={index}
key={`${member.frontmatter.title}-${index}}`}
title={member.frontmatter.title}
>
<div className="flex flex-row place-items-center gap-2 lg:text-sm">

View File

@@ -1,180 +0,0 @@
---
import { Separator } from 'ariakit/separator';
import type { MarkdownLayoutProps } from 'astro';
import { ExternalLink } from './ExternalLink.jsx';
import { Navbar } from './Navbar.jsx';
import { Outline } from './Outline.jsx';
import { PageButton } from './PageButton.jsx';
import { SidebarItems } from './SidebarItems.jsx';
import { generateGithubURL } from '~/util/url.js';
const pages = await Astro.glob<{ category: string; title: string }>('../pages/**/*.mdx');
type Props = MarkdownLayoutProps<{}>;
const { headings, url, frontmatter } = Astro.props;
const groupedPages = pages.reduce<Record<string, typeof pages>>((acc, page) => {
const { category } = page.frontmatter;
acc[category] ??= [];
acc[category]?.push(page);
return acc;
}, {});
// @ts-expect-error props is not typed
const category = frontmatter.category as string;
const curCategoryPages = groupedPages[category];
const curCategoryIndex = curCategoryPages!.findIndex((page) => page.url === url);
const pagePrev = curCategoryPages![curCategoryIndex - 1];
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands
const pageNext = curCategoryPages![curCategoryIndex + 1];
---
<script>
window.addEventListener('load', () => {
const headings = document.querySelectorAll(
'div.level-h1 > h1, div.level-h2 > h2, div.level-h3 > h3, div.level-h4 > h4',
);
const headingsObserver = new IntersectionObserver(
(entries) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
const location = window.location.toString().split('#')[0];
history.replaceState(null, '', location + '#' + entry.target.id);
}
});
},
{
root: null,
rootMargin: '-100px 0% -66%',
threshold: 1.0,
},
);
headings.forEach((heading) => headingsObserver.observe(heading));
});
</script>
<Navbar client:load>
<div class="flex flex-col gap-3 p-3 pb-32 lg:pb-12" slot="pages">
<SidebarItems client:load pages={pages} />
</div>
</Navbar>
<main class="pt-18 lg:pl-76 xl:pr-64">
<article class="dark:bg-dark-600 bg-light-600">
<div class="dark:bg-dark-800 relative z-10 min-h-[calc(100vh_-_70px)] bg-white p-6 pb-20 shadow">
<div class="prose max-w-full">
<slot />
</div>
<div
class="h-[calc(100vh - 72px)] dark:bg-dark-600 dark:border-dark-100 border-light-800 fixed top-[72px] right-0 bottom-0 z-20 hidden w-64 border-l bg-white pr-2 xl:block"
>
<Outline client:load headings={headings} />
</div>
<Separator className="my-5 border-light-800 dark:border-dark-100" />
<div class="flex flex-col space-y-5">
<div class="flex place-content-end">
<ExternalLink client:load href={generateGithubURL(url!)} title="Edit this page on github" />
</div>
<div class="flex w-full">
{
pagePrev && (
<PageButton
direction="prev"
title={pagePrev.frontmatter.title}
url={pagePrev.url === '' ? '/' : pagePrev.url!}
/>
)
}
<div class="ml-auto self-end justify-self-end">
{
pageNext && (
<PageButton
direction="next"
title={pageNext.frontmatter.title}
url={pageNext.url === '' ? '/' : pageNext.url!}
/>
)
}
</div>
</div>
</div>
</div>
<div class="h-76 md:h-52"></div>
<footer
class="dark:bg-dark-600 h-76 lg:pl-84 bg-light-600 xl:pr-76 fixed bottom-0 left-0 right-0 md:h-52 md:pl-4 md:pr-16"
>
<div class="mx-auto flex max-w-6xl flex-col place-items-center gap-12 pt-12 lg:place-content-center">
<div class="flex w-full flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="noopener noreferrer"
target="_blank"
title="Vercel"
>
<img alt="Vercel" src="/powered-by-vercel.svg" />
</a>
<div class="flex flex-row gap-6 md:gap-12">
<div class="flex flex-col gap-2">
<div class="text-lg font-semibold">Community</div>
<div class="flex flex-col gap-1">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord.gg/djs"
rel="noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js/discussions"
rel="noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
</div>
<div class="flex flex-col gap-2">
<div class="text-lg font-semibold">Project</div>
<div class="flex flex-col gap-1">
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js"
rel="noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discordjs.guide"
rel="noopener noreferrer"
target="_blank"
>
discord.js guide
</a>
<a
class="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord-api-types.dev"
rel="noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>
</div>
</div>
</footer>
</article>
<div>Test</div>
</main>

View File

@@ -1,12 +1,8 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Understanding async/await
category: Additional info
---
import { CH } from '@code-hike/mdx/components';
import { Alert } from '@discordjs/ui';
# Understanding async/await
If you aren't very familiar with ECMAScript 2017, you may not know about async/await. It's a useful way to handle Promises in a hoisted manner. It's also slightly faster and increases overall readability.
@@ -30,7 +26,7 @@ One important thing to know is that a Promise can only have one state simultaneo
[here](/additional-info/es6-syntax.md).
</Alert>
<CH.Code client:load>
<CH.Code>
```js
function deleteMessages(amount) {
@@ -63,7 +59,7 @@ The following information is essential to know before working with async/await.
A simple example would be:
<CH.Code client:load>
<CH.Code>
```js
async function declaredAsAsync() {
@@ -75,7 +71,7 @@ async function declaredAsAsync() {
or
<CH.Code client:load>
<CH.Code>
```js
const declaredAsAsync = async () => {
@@ -87,7 +83,7 @@ const declaredAsAsync = async () => {
You can use that as well if you use the arrow function as an event listener.
<CH.Code client:load>
<CH.Code>
```js
client.on('event', async (first, last) => {
@@ -103,7 +99,7 @@ An important thing to know is that a function declared as _`async`_ will always
Now that you know how Promises work and what they are used for, let's look at an example that handles multiple Promises. Let's say you want to react with letters (regional indicators) in a specific order. For this example, here's a basic template for a discord.js bot with some ES6 adjustments.
<CH.Code client:load>
<CH.Code>
```js
const { Client, GatewayIntentBits } = require('discord.js');
@@ -129,7 +125,7 @@ client.login('your-token-goes-here');
If you don't know how Node.js asynchronous execution works, you would probably try something like this:
<CH.Code client:load>
<CH.Code>
```js mark=4:7
client.on('interactionCreate', (interaction) => {
@@ -147,7 +143,7 @@ client.on('interactionCreate', (interaction) => {
But since all of these methods are started at the same time, it would just be a race to which server request finished first, so there would be no guarantee that it would react at all (if the message isn't fetched) or in the order you wanted it to. In order to make sure it reacts after the message is sent and in order (a, b, c), you'd need to use the _`.then()`_ callback from the Promises that these methods return. The code would look like this:
<CH.Code client:load>
<CH.Code>
```js mark=4:12
client.on('interactionCreate', (interaction) => {
@@ -170,7 +166,7 @@ client.on('interactionCreate', (interaction) => {
In this piece of code, the Promises are [chain resolved](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/then#Chaining) with each other, and if one of the Promises gets rejected, the function passed to _`.catch()`_ gets called. Here's the same code but with async/await:
<CH.Code client:load>
<CH.Code>
```js mark=1,4:7
client.on('interactionCreate', async (interaction) => {
@@ -188,7 +184,7 @@ client.on('interactionCreate', async (interaction) => {
It's mostly the same code, but how would you catch Promise rejections now since _`.catch()`_ isn't there anymore? That is also a useful feature with async/await; the error will be thrown if you await it so that you can wrap the awaited Promises inside a try/catch, and you're good to go.
<CH.Code client:load>
<CH.Code>
```js mark=1,4:11
client.on('interactionCreate', async (interaction) => {
@@ -213,7 +209,7 @@ So you may be asking, "How would I get the value the Promise resolved with?".
Let's look at an example where you want to delete a sent reply.
<CH.Code client:load>
<CH.Code>
```js mark=3:10
client.on('interactionCreate', (interaction) => {
@@ -233,7 +229,7 @@ client.on('interactionCreate', (interaction) => {
The return value of a _`.reply()`_ with the _`fetchReply`_ option set to _`true`_ is a Promise which resolves with the reply when it has been sent, but how would the same code with async/await look?
<CH.Code client:load>
<CH.Code>
```js mark=1,4:10
client.on('interactionCreate', async (interaction) => {

View File

@@ -1,12 +1,8 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Collections
category: Additional info
---
import { CH } from '@code-hike/mdx/components';
import { Alert } from '@discordjs/ui';
# Collections
discord.js comes with a utility class known as _`Collection`_.
@@ -28,7 +24,7 @@ This is the point of the _`Collection`_ class!
Many of the methods on _`Collection`_ correspond to their namesake in _`Array`_. One of them is _`find`_:
<CH.Code client:load>
<CH.Code>
```js
// Assume we have an array of users and a collection of the same users.
@@ -58,7 +54,7 @@ Methods that follow this philosophy of staying close to the _`Array`_ interface
Since _`Collection`_ extends _`Map`_, it is an [iterable](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Iteration_protocols), and can be converted to an _`Array`_ through either _`Array.from()`_ or spread syntax (_`...collection`_).
<CH.Code client:load>
<CH.Code>
```js
// For values.
@@ -86,7 +82,7 @@ Array.from(collection);
Some methods are not from _`Array`_ and are instead entirely new to standard JavaScript.
<CH.Code client:load>
<CH.Code>
```js
// A random value.
@@ -112,7 +108,7 @@ collection.sweep((user) => user.username === 'Bob');
A more complicated method is _`partition`_, which splits a single Collection into two new Collections based on the provided function.
You can think of it as two \_`filter`\_s, but done at the same time:
<CH.Code client:load>
<CH.Code>
```js
// `bots` is a Collection of users where their `bot` property was true.

View File

@@ -1,14 +1,8 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Creating commands
category: Creating your bot
---
import { CH } from '@code-hike/mdx/components';
import { Alert, DiscordMessages, DiscordMessage } from '@discordjs/ui';
import { DocsLink } from '../../components/DocsLink.jsx';
import { ResultingCode } from '../../components/ResultingCode.jsx';
# Creating commands
<Alert title="Tip" type="success">
@@ -62,7 +56,7 @@ Below is a deployment script you can use. Focus on these variables:
user's profile, etc.
</Alert>
<CH.Code client:load>
<CH.Code>
```js deploy-commands.js mark=4,6:10
const { REST, SlashCommandBuilder, Routes } = require('discord.js');
@@ -107,7 +101,7 @@ Once you've registered your commands, you can listen for interactions via <DocsL
You should first check if an interaction is a chat input command via <DocsLink path="class/Interaction?scrollTo=isChatInputCommand" type="method">_`.isChatInputCommand()`_</DocsLink>, and then check the <DocsLink path="class/CommandInteraction?scrollTo=commandName">_`.commandName`_</DocsLink> property to know which command it is. You can respond to interactions with <DocsLink path="class/CommandInteraction?scrollTo=reply">_`.reply()`_</DocsLink>.
<CH.Code client:load>
<CH.Code>
```js mark=5:16
client.once('ready', () => {
@@ -134,7 +128,7 @@ client.login(token);
Note that servers are referred to as "guilds" in the Discord API and discord.js library. _`interaction.guild`_ refers to the guild the interaction was sent in (a <DocsLink path="class/Guild" /> instance), which exposes properties such as _`.name`_ or _`.memberCount`_.
<CH.Code client:load>
<CH.Code>
```js focus=7
client.on('interactionCreate', async (interaction) => {
@@ -184,7 +178,7 @@ You could also display the date the server was created, or the server's verifica
A "user" refers to a Discord user. _`interaction.user`_ refers to the user the interaction was sent by (a <DocsLink path="class/User" /> instance), which exposes properties such as _`.tag`_ or _`.id`_.
<CH.Code client:load>
<CH.Code>
```js focus=9
client.on('interactionCreate', async (interaction) => {

View File

@@ -1,14 +1,8 @@
---
layout: '../../layouts/SidebarLayout.astro'
title: Initial files
category: Creating your bot
---
import { CH } from '@code-hike/mdx/components';
import { Alert, Section } from '@discordjs/ui';
import { DocsLink } from '../../components/DocsLink.jsx';
import { ResultingCode } from '../../components/ResultingCode.jsx';
# Initial files
Once you [add your bot to a server](/preparations/adding-your-bot-to-servers.md), the next step is to start coding and get it online! Let's start by creating a config file for your client token and a main file for your bot application.
@@ -23,7 +17,7 @@ Open your application in the [Discord Developer Portal](https://discord.com/deve
Storing data in a _`config.json`_ file is a common way of keeping your sensitive values safe. Create a _`config.json`_ file in your project directory and paste in your token. You can access your token inside other files by using _`require()`_.
<CH.Code client:load>
<CH.Code>
```json config.json
{
@@ -54,7 +48,7 @@ One way to pass in environment variables is via the command line interface. When
You can access the set values in your code via the _`process.env`_ global variable, accessible in any file. Note that values passed this way will always be strings and that you might need to parse them to a number, if using them to do calculations.
<CH.Code client:load>
<CH.Code>
```shellscript Command line
A=123 B=456 DISCORD_TOKEN=your-token-goes-here node index.js
@@ -76,17 +70,17 @@ Another common approach is storing these values in a _`.env`_ file. This spares
You can use the [_`dotenv`_ package](https://www.npmjs.com/package/dotenv) for this. Once installed, require and use the package to load your _`.env`_ file and attach the variables to _`process.env`_:
<CH.Code client:load>
<CH.Code>
```shellscript npm
```sh npm
npm install dotenv
```
```shellscript yarn
```sh yarn
yarn add dotenv
```
```shellscript pnpm
```sh pnpm
pnpm add dotenv
```
@@ -117,7 +111,7 @@ console.log(process.env.DISCORD_TOKEN);
_`.gitignore`_](/creating-your-bot/#git-and-gitignore).
</Alert>
<Section client:load title="Online editors (Glitch, Heroku, Replit, etc.)" defaultClosed padded background gutter>
<Section title="Online editors (Glitch, Heroku, Replit, etc.)" defaultClosed padded background gutter>
While we generally do not recommend using online editors as hosting solutions, but rather invest in a proper virtual private server, these services do offer ways to keep your credentials safe as well! Please see the respective service's documentation and help articles for more information on how to keep sensitive values safe:
- Glitch: [Storing secrets in .env](https://glitch.happyfox.com/kb/article/18)
@@ -132,7 +126,7 @@ Git is a fantastic tool to keep track of your code changes and allows you to upl
You can specify files that Git should ignore in its versioning systems with a _`.gitignore`_ file. Create a _`.gitignore`_ file in your project directory and add the names of the files and folders you want to ignore:
<CH.Code client:load>
<CH.Code>
```
node_modules
@@ -155,7 +149,7 @@ Open your code editor and create a new file. We suggest that you save the file a
Here's the base code to get you started:
<CH.Code client:load>
<CH.Code>
```js
// Require the necessary discord.js classes

View File

@@ -1,5 +1,4 @@
---
layout: '../layouts/SidebarLayout.astro'
title: Introduction
category: Home
---

View File

@@ -1,11 +1,8 @@
---
layout: '../layouts/SidebarLayout.astro'
title: Requesting more content
category: Home
---
import { Alert } from '@discordjs/ui';
# Requesting more content
Since this guide is made specifically for the discord.js community, we want to be sure to provide the most relevant and up-to-date content. We will, of course, make additions to the current pages and add new ones as we see fit, but fulfilling requests is how we know we're providing content you all want the most.

View File

@@ -3,8 +3,6 @@ title: Test
category: Test
---
import { DiscordMessages, DiscordMessage, DiscordMessageEmbed } from '@discordjs/ui';
<DiscordMessages>
<DiscordMessage
reply={{

View File

@@ -1,12 +1,8 @@
---
layout: '../layouts/SidebarLayout.astro'
title: What's new
category: Home
---
import { CH } from '@code-hike/mdx/components';
import { DiscordMessages, DiscordMessage } from '@discordjs/ui';
# What's new
<DiscordMessages rounded>

View File

@@ -1,63 +0,0 @@
---
import '../styles/main.css';
import '@code-hike/mdx/styles.css';
import '../styles/ch.css';
import type { MarkdownLayoutProps } from 'astro';
import SidebarLayout from '../components/SidebarLayout.astro';
import { DESCRIPTION } from '../util/constants.js';
type Props = MarkdownLayoutProps<{}>;
const props = Astro.props;
---
<html lang="en">
<head>
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
<link href="/site.webmanifest" rel="manifest" />
<link color="#090a16" href="/safari-pinned-tab.svg" rel="mask-icon" />
<meta content="light dark" name="color-scheme" />
<meta content="discord.js" name="apple-mobile-web-app-title" />
<meta content="discord.js" name="application-name" />
<meta content="#090a16" name="msapplication-TileColor" />
<meta content={DESCRIPTION} name="description" />
<meta content="discord.js" property="og:site_name" />
<meta content="website" property="og:type" />
<meta content="discord.js guide" property="og:title" />
<meta content={DESCRIPTION} name="og:description" />
<meta content="https://discordjs.dev/open-graph.png" property="og:image" />
<meta content="summary_large_image" name="twitter:card" />
<meta content="@iCrawlToGo" name="twitter:creator" />
<title>discord.js</title>
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
<meta content="#5865f2" name="theme-color" />
</head>
<body class="dark:bg-dark-800 bg-white">
<script is:inline>
function setTheme(prefersDarkMode, persistedColorPreference) {
if (persistedColorPreference === 'dark' || (prefersDarkMode && persistedColorPreference !== 'light')) {
document.documentElement.classList.toggle('dark', true);
} else {
document.documentElement.classList.toggle('dark', false);
}
}
(() => {
const prefersDarkMode = window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches;
const persistedColorPreference = localStorage.getItem('theme') || 'auto';
setTheme(prefersDarkMode, persistedColorPreference);
const listener =
window.matchMedia &&
window
.matchMedia('(prefers-color-scheme: dark)')
.addEventListener('change', (ev) => setTheme(ev.matches, persistedColorPreference));
})();
</script>
<SidebarLayout {...props}>
<slot />
</SidebarLayout>
</body>
</html>

View File

@@ -1,3 +1,82 @@
.ch-frame-buttons {
display: none;
:root {
--shiki-color-text: #24292eff;
--shiki-color-background: #ffffff;
--shiki-token-constant: #1976d2;
--shiki-token-string: #6f42c1;
--shiki-token-comment: #c2c3c5;
--shiki-token-keyword: #d32f2f;
--shiki-token-parameter: #ff9800;
--shiki-token-function: #6f42c1;
--shiki-token-string-expression: #22863a;
--shiki-token-punctuation: #212121;
--shiki-token-link: #22863a;
--ch-tabs-bg: #f6f6f6;
--ch-tab-border: #f6f6f6;
--ch-tab-active-border: #fff;
--ch-tab-active-bg: #24292eff;
--ch-tab-inactive-color: #bdbdbd;
--ch-tab-inactive-bg: #f6f6f6;
--ch-icon-text: #24292eff;
}
.ch-code,
.ch-inline-code > code {
background: var(--shiki-color-background) !important;
}
.ch-code {
color-scheme: light !important;
}
.ch-code-multiline-mark {
background: rgba(253, 255, 0, 0.2) !important;
}
.ch-codegroup .ch-editor-button,
.ch-codeblock .ch-code-button {
color: var(--ch-icon-text) !important;
}
div.ch-editor-tab-active {
color: var(--ch-tab-active-color) !important;
}
html.dark {
--shiki-color-text: #adbac7;
--shiki-color-background: #22272e;
--shiki-token-constant: #f47067;
--shiki-token-string: #96d0ff;
--shiki-token-comment: #768390;
--shiki-token-keyword: #f47067;
--shiki-token-parameter: #adbac7;
--shiki-token-function: #dcbdfb;
--shiki-token-string-expression: #8ddb8c;
--shiki-token-punctuation: #adbac7;
--shiki-token-link: #adbac7;
--ch-tabs-bg: #1c2128;
--ch-tab-border: #444c56;
--ch-tab-active-border: #22272e;
--ch-tab-active-bg: #22272e;
--ch-tab-inactive-color: #768390;
--ch-tab-inactive-bg: #1c2128;
--ch-icon-text: #768390;
}
.dark .ch-codegroup .ch-editor-button,
.ch-codeblock .ch-code-button {
color: var(--ch-icon-text) !important;
}
.dark div.ch-editor-tab-active {
color: var(--ch-tab-active-color) !important;
}
.dark .ch-code {
color-scheme: dark !important;
}
.dark .ch-code-multiline-mark {
background: rgba(255, 255, 255, 0.043) !important;
}

View File

@@ -0,0 +1,3 @@
[data-backdrop] {
background-color: rgb(0 0 0 / 35%);
}

View File

@@ -1,16 +1,8 @@
@import url('https://rsms.me/inter/inter.css');
:root {
font-family: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
font-feature-settings: 'cv02', 'cv03', 'cv04', 'cv11';
body {
font-family: var(--font-inter);
min-height: 100vh;
}
@supports (font-variation-settings: normal) {
:root {
font-family: 'Inter var', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
'Helvetica Neue', Arial, 'Noto Sans', sans-serif, 'Apple Color Emoji', 'Segoe UI Emoji', 'Segoe UI Symbol',
'Noto Color Emoji';
}
code {
font-family: var(--font-mono);
}

View File

@@ -0,0 +1,4 @@
export const fetcher = async (url: string) => {
const res = await fetch(url);
return res.json();
};

View File

@@ -0,0 +1,13 @@
import { Inter, JetBrains_Mono } from 'next/font/google';
export const inter = Inter({
subsets: ['latin'],
display: 'swap',
variable: '--font-inter',
});
export const jetBrainsMono = JetBrains_Mono({
subsets: ['latin'],
display: 'swap',
variable: '--font-mono',
});

View File

@@ -10,7 +10,6 @@
"**/*.cjs",
"**/*.mjs",
"**/*.jsx",
"**/*.astro",
"**/*.test.ts",
"**/*.test.js",
"**/*.test.mjs",

View File

@@ -9,11 +9,25 @@
"allowJs": false,
"incremental": true,
"skipLibCheck": true,
"types": ["@astrojs/image/client"],
"sourceMap": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"~/*": ["./src/*"]
}
"~/*": ["./src/*"],
"contentlayer/generated": ["./.contentlayer/generated"]
},
"strictNullChecks": true
},
"include": ["src/**/*.ts", "src/**/*.tsx", "types.d.ts"],
"include": [
"src/**/*.ts",
"src/**/*.tsx",
"next-env.d.ts",
"types.d.ts",
".next/types/**/*.ts",
".contentlayer/generated"
],
"exclude": ["node_modules"]
}

View File

@@ -1,3 +0,0 @@
{
"cleanUrls": true
}

View File

@@ -13,6 +13,7 @@ pids
# Env
.env
.env*.local
# Dist
dist/
@@ -29,3 +30,4 @@ coverage/
.vercel
public/searchIndex
.vscode
lighthouse-results/

View File

@@ -18,7 +18,7 @@
- [Website][website] ([source][website-source])
- [Documentation][documentation]
- [Guide][guide] ([source][guide-source])
See also the [Update Guide][guide-update], including updated and removed items in the library.
Also see the v13 to v14 [Update Guide][guide-update], which includes updated and removed items from the library.
- [discord.js Discord server][discord]
- [Discord API Discord server][discord-api]
- [GitHub][source]
@@ -26,16 +26,17 @@
## Contributing
Before creating an issue, please ensure that it hasn't already been reported/suggested, and double-check the
[documentation][documentation].
See [the contribution guide][contributing] if you'd like to submit a PR.
## Help
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle
nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
If you don't understand something in the documentation, you are experiencing problems, or you just need a gentle nudge in the right direction, please don't hesitate to join our official [discord.js Server][discord].
[website]: https://discord.js.org/
[website]: https://discord.js.org
[website-source]: https://github.com/discordjs/discord.js/tree/main/apps/website
[documentation]: https://discord.js.org/
[documentation]: https://discord.js.org/docs
[guide]: https://discordjs.guide/
[guide-source]: https://github.com/discordjs/guide
[guide-update]: https://discordjs.guide/additional-info/changes-in-v14.html

View File

@@ -1,6 +1,5 @@
/// <reference types="next" />
/// <reference types="next/image-types/global" />
/// <reference types="next/navigation-types/compat/navigation" />
// NOTE: This file should not be edited
// see https://nextjs.org/docs/basic-features/typescript for more information.

View File

@@ -1,4 +1,3 @@
/* eslint-disable tsdoc/syntax */
import { fileURLToPath } from 'node:url';
import bundleAnalyzer from '@next/bundle-analyzer';
@@ -6,9 +5,6 @@ const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === 'true',
});
/**
* @type {import('next').NextConfig}
*/
export default withBundleAnalyzer({
reactStrictMode: true,
eslint: {
@@ -18,16 +14,25 @@ export default withBundleAnalyzer({
typescript: {
ignoreBuildErrors: true,
},
cleanDistDir: true,
outputFileTracing: true,
experimental: {
appDir: true,
serverComponentsExternalPackages: ['@microsoft/api-extractor-model', 'jju', 'shiki'],
outputFileTracingRoot: fileURLToPath(new URL('../../', import.meta.url)),
fallbackNodePolyfills: false,
serverComponentsExternalPackages: ['@microsoft/api-extractor-model', 'jju'],
},
images: {
dangerouslyAllowSVG: true,
contentSecurityPolicy: "default-src 'self'; script-src 'none'; sandbox;",
contentDispositionType: 'attachment',
contentSecurityPolicy: "default-src 'self'; frame-src 'none'; sandbox;",
},
async redirects() {
return [
{
source: '/static/logo.svg',
destination: '/logo.svg',
permanent: true,
},
];
},
});

View File

@@ -5,6 +5,7 @@
"private": true,
"scripts": {
"test": "vitest run",
"test:lighthouse": "lighthouse http://localhost:3000 --output-path=./lighthouse-results",
"build:copy_readme": "cpy '../../packages/*/README.md' 'src/assets/readme' --rename='home-{{basename}}'",
"build:local": "yarn run --top-level docs --force && yarn build:copy_readme && cross-env-shell NEXT_PUBLIC_LOCAL_DEV=true yarn build:prod",
"build:prod": "yarn workspaces foreach -ptR run build && yarn build:copy_readme && yarn build:css && yarn build:next",
@@ -12,8 +13,9 @@
"build:css": "yarn generate:css",
"build:search_indices": "yarn node scripts/generateAllIndices.js",
"build:analyze": "yarn run --top-level docs --force && cross-env-shell ANALYZE=true NEXT_PUBLIC_LOCAL_DEV=true yarn build:prod",
"preview": "next start",
"dev": "yarn run --top-level docs && concurrently 'yarn dev:css' 'yarn dev:next'",
"dev:next": "next dev",
"dev:next": "yarn workspaces foreach -ptR run build && next dev",
"dev:css": "yarn generate:css --watch",
"generate:css": "unocss 'src/**/*.tsx' '../../packages/ui/src/lib/components/**/*.tsx' --out-file ./src/styles/unocss.css --config ../../unocss.config.ts",
"lint": "prettier --check . && cross-env TIMING=1 eslint src --ext .mjs,.js,.cjs,.ts,.tsx --format=pretty",
@@ -46,59 +48,60 @@
"@discordjs/api-extractor-utils": "workspace:^",
"@discordjs/scripts": "workspace:^",
"@discordjs/ui": "workspace:^",
"@microsoft/api-extractor-model": "7.25.3",
"@microsoft/api-extractor-model": "7.26.4",
"@microsoft/tsdoc": "0.14.2",
"@planetscale/database": "^1.6.0",
"@react-icons/all-files": "^4.1.0",
"@vercel/og": "^0.2.0",
"@vercel/analytics": "^0.1.11",
"@vercel/edge-config": "^0.1.5",
"@vercel/og": "^0.5.0",
"@vscode/codicons": "^0.0.32",
"ariakit": "^2.0.0-next.43",
"cmdk": "^0.1.22",
"meilisearch": "^0.31.1",
"next": "^13.2.1",
"next-mdx-remote": "^4.3.0",
"bright": "^0.7.0",
"cmdk": "^0.2.0",
"meilisearch": "^0.32.0",
"next": "^13.2.5-canary.23",
"next-mdx-remote": "^4.4.1",
"next-themes": "^0.2.1",
"react": "^18.2.0",
"react-custom-scrollbars-2": "^4.5.0",
"react-dom": "^18.2.0",
"react-syntax-highlighter": "^15.5.0",
"react-use": "^17.4.0",
"rehype-ignore": "^1.0.4",
"rehype-pretty-code": "^0.9.4",
"rehype-raw": "^6.1.1",
"rehype-slug": "^5.1.0",
"remark-gfm": "^3.0.1",
"sharp": "^0.31.3",
"shiki": "^0.14.1",
"swr": "^2.0.4"
"sharp": "^0.32.0",
"swr": "^2.1.1"
},
"devDependencies": {
"@next/bundle-analyzer": "^13.2.1",
"@next/bundle-analyzer": "^13.2.4",
"@testing-library/react": "^14.0.0",
"@testing-library/user-event": "^14.4.3",
"@types/node": "16.18.13",
"@types/react": "^18.0.28",
"@types/node": "18.15.11",
"@types/react": "^18.0.31",
"@types/react-dom": "^18.0.11",
"@types/react-syntax-highlighter": "^15.5.6",
"@unocss/cli": "^0.50.1",
"@unocss/reset": "^0.50.1",
"@unocss/cli": "^0.50.6",
"@unocss/reset": "^0.50.6",
"@vitejs/plugin-react": "^3.1.0",
"@vitest/coverage-c8": "^0.29.1",
"concurrently": "^7.6.0",
"@vitest/coverage-c8": "^0.29.8",
"concurrently": "^8.0.1",
"cpy-cli": "^4.2.0",
"cross-env": "^7.0.3",
"eslint": "^8.35.0",
"eslint-config-neon": "^0.1.40",
"eslint-formatter-pretty": "^4.1.0",
"eslint": "^8.37.0",
"eslint-config-neon": "^0.1.41",
"eslint-formatter-pretty": "^5.0.0",
"happy-dom": "^8.9.0",
"prettier": "^2.8.4",
"prettier-plugin-tailwindcss": "^0.2.3",
"typescript": "^4.9.5",
"unocss": "^0.50.1",
"vercel": "^28.16.7",
"vitest": "^0.29.1"
"lighthouse": "^10.1.0",
"prettier": "^2.8.7",
"prettier-plugin-tailwindcss": "^0.2.6",
"typescript": "^5.0.3",
"unocss": "^0.50.6",
"vercel": "^28.18.3",
"vitest": "^0.29.8"
},
"engines": {
"node": ">=16.9.0"
"node": ">=18.13.0"
},
"nextBundleAnalysis": {
"budget": 358400,

View File

@@ -0,0 +1,35 @@
<svg width="5232" height="945" viewBox="0 0 5232 945" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#filter0_dd)">
<mask id="mask0" mask-type="alpha" maskUnits="userSpaceOnUse" x="3979" y="20" width="1245" height="907">
<path d="M4685.1 692.37C4747.89 751.167 4832.06 791.257 4913.55 791.257C5011.09 791.257 5065.87 747.156 5065.87 679.006C5065.87 606.85 5009.75 584.134 4929.59 550.728L4810.68 498.614C4723.84 462.533 4634.33 394.383 4634.33 266.097C4634.33 127.126 4757.25 20.2217 4926.92 20.2217C5029.79 20.2217 5128.66 62.9858 5196.8 131.136L5116.63 230.019C5061.85 183.252 5001.74 155.187 4926.92 155.187C4844.08 155.187 4790.64 193.941 4790.64 258.082C4790.64 326.232 4857.45 351.623 4929.59 381.019L5047.17 430.464C5151.37 474.558 5223.51 540.035 5223.51 666.98C5223.51 808.627 5105.94 926.221 4909.56 926.221C4791.98 926.221 4678.42 879.451 4595.59 797.937L4685.1 692.37Z" fill="white"/>
<path d="M4362.62 20.2217H4514.42V625.218C4514.42 785.559 4419.32 925.689 4236.89 925.689C4112.78 933.776 4006.36 848.244 3979.19 761.134C4001.8 757.707 4023.82 754.196 4051.3 745.549C4073.15 738.673 4105.83 723.903 4105.83 723.903C4130.43 763.127 4173.98 789.193 4223.6 789.193C4300.39 789.193 4362.64 726.761 4362.64 649.746L4362.62 20.2217Z" fill="white"/>
</mask>
<g mask="url(#mask0)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M3958.82 72.292L4012.02 47.467C4066.83 24.1022 4174.84 -22.6272 4282.85 -34.3096C4390.86 -45.992 4498.87 -22.6272 4606.88 -28.4684C4713.28 -34.3096 4821.29 -69.3567 4929.3 -45.992C5037.31 -22.6272 5145.32 59.1493 5200.14 101.498L5253.33 142.386V247.527H5200.14C5145.32 247.527 5037.31 247.527 4929.3 247.527C4821.29 247.527 4713.28 247.527 4606.88 247.527C4498.87 247.527 4390.86 247.527 4282.85 247.527C4174.84 247.527 4066.83 247.527 4012.02 247.527H3958.82V72.292Z" fill="#FF5C5C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3958.82 76.645L4012.02 115.335C4066.83 154.026 4174.84 233.019 4282.85 233.019C4390.86 233.019 4498.87 154.026 4606.88 128.232C4713.28 102.439 4821.29 128.232 4929.3 141.129C5037.31 154.026 5145.32 154.026 5200.14 154.026H5253.33V426.47H5200.14C5145.32 426.47 5037.31 426.47 4929.3 426.47C4821.29 426.47 4713.28 426.47 4606.88 426.47C4498.87 426.47 4390.86 426.47 4282.85 426.47C4174.84 426.47 4066.83 426.47 4012.02 426.47H3958.82V76.645Z" fill="#F79454"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3958.82 247.527L4012.02 265.951C4066.83 284.375 4174.84 321.223 4282.85 321.223C4390.86 321.223 4498.87 284.375 4606.88 275.163C4713.28 265.951 4821.29 284.375 4929.3 316.617C5037.31 348.859 5145.32 396.071 5200.14 419.101L5253.33 442.131V497.403H5200.14C5145.32 497.403 5037.31 497.403 4929.3 497.403C4821.29 497.403 4713.28 497.403 4606.88 497.403C4498.87 497.403 4390.86 497.403 4282.85 497.403C4174.84 497.403 4066.83 497.403 4012.02 497.403H3958.82V247.527Z" fill="#FFDB5C"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3958.82 407.125L4012.76 420.44C4066.7 433.755 4174.57 460.384 4282.45 460.384C4390.32 460.384 4498.2 433.755 4606.08 440.412C4713.95 447.07 4821.83 487.014 4929.71 487.014C5037.58 487.014 5145.46 447.07 5199.4 427.098L5253.33 407.125V766.624H5199.4C5145.46 766.624 5037.58 766.624 4929.71 766.624C4821.83 766.624 4713.95 766.624 4606.08 766.624C4498.2 766.624 4390.32 766.624 4282.45 766.624C4174.57 766.624 4066.7 766.624 4012.76 766.624H3958.82V407.125Z" fill="#5CFF9D"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M5253.34 600.577L5200.14 613.169C5145.33 625.76 5037.31 650.943 4929.3 644.648C4821.29 638.352 4713.28 600.577 4605.27 600.577C4498.87 600.577 4390.86 638.352 4282.85 657.239C4174.84 677.7 4066.83 677.7 4012.02 677.7H3958.82V866.573H4012.02C4066.83 866.573 4174.84 866.573 4282.85 866.573C4390.86 866.573 4498.87 866.573 4605.27 866.573C4713.28 866.573 4821.29 866.573 4929.3 866.573C5037.31 866.573 5145.33 866.573 5200.14 866.573H5253.34V600.577Z" fill="#5C6CFF"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M3958.82 760.175L4090.21 692.467C4132.12 760.175 4174.84 794.363 4282.85 798.637C4390.86 802.91 4498.87 772.266 4606.88 772.266C4713.28 772.266 4821.29 802.91 4929.3 798.637C5037.31 794.363 5179.98 760.175 5229.96 740.024L5253.33 760.175V940.73H5200.14C5145.32 940.73 5037.31 940.73 4929.3 940.73C4821.29 940.73 4713.28 940.73 4606.88 940.73C4498.87 940.73 4390.86 940.73 4282.85 940.73C4174.84 940.73 4066.83 940.73 4012.02 940.73H3958.82V760.175Z" fill="#B75CFF"/>
</g>
<path fill-rule="evenodd" clip-rule="evenodd" d="M4264.21 348.906C4264.21 282.978 4251.78 225.648 4226.94 175.965C4201.14 127.234 4163.88 89.0164 4114.19 61.3076C4064.51 33.5989 4004.32 20.2217 3932.65 20.2217H3667.03V689.056H3892.98H3920.23C3986.6 689.056 4037.45 678.548 4084.65 654.747C4084.59 653.088 4084.57 651.421 4084.57 649.746C4084.57 572.732 4146.82 510.3 4223.61 510.3C4225.89 510.3 4228.16 510.355 4230.41 510.464C4254.5 461.424 4264.21 412.805 4264.21 348.906ZM3827.55 163.544V545.734H3918.32C3976.61 545.734 4020.56 528.534 4050.18 493.183C4079.8 458.785 4095.08 411.967 4095.08 351.772C4095.08 292.533 4080.75 246.67 4052.09 213.229C4023.42 179.786 3980.43 163.544 3924.05 163.544H3827.55Z" fill="#5865F2"/>
<path d="M4311.87 649.747C4311.87 698.271 4272.53 737.606 4224.01 737.606C4175.49 737.606 4136.15 698.271 4136.15 649.747C4136.15 601.222 4175.49 561.887 4224.01 561.887C4272.53 561.887 4311.87 601.222 4311.87 649.747Z" fill="#5865F2"/>
<path d="M261.386 689.469C335.011 689.469 398.119 675.125 449.752 645.481C501.386 616.793 540.589 576.63 566.405 524.991C592.222 474.309 605.609 415.02 605.609 349.038C605.609 283.055 593.178 225.679 568.318 175.953C542.501 127.184 505.21 88.933 455.489 61.2012C405.768 33.4694 345.529 20.0816 273.816 20.0816H8V689.469H261.386ZM168.637 546.029V163.522H265.211C321.625 163.522 364.653 179.778 393.338 213.248C422.023 246.717 436.366 292.618 436.366 351.907C436.366 412.152 421.067 459.009 391.426 493.434C361.784 528.816 317.8 546.029 259.474 546.029H168.637ZM878.299 20.0816H717.662V689.469H878.299V20.0816ZM1237.12 709.551C1316.48 709.551 1379.59 690.426 1425.48 651.219C1470.42 612.968 1493.37 560.373 1493.37 494.391C1493.37 444.665 1479.03 403.545 1450.34 371.032C1421.66 339.475 1375.76 312.7 1311.7 292.618L1242.85 270.624C1217.04 260.105 1198.87 249.586 1187.4 239.067C1174.97 228.548 1169.23 216.117 1169.23 199.86C1169.23 159.697 1200.78 139.615 1264.85 139.615C1332.74 139.615 1397.76 161.609 1460.86 206.554V59.2886C1393.93 20.0816 1323.17 0 1247.64 0C1170.19 0 1108.99 18.1691 1065.01 54.5072C1021.02 91.8017 999.031 141.528 999.031 205.598C999.031 253.411 1012.42 292.618 1038.23 323.219C1064.05 354.775 1106.12 379.638 1163.49 399.72L1241.9 425.539C1269.63 437.014 1288.75 447.534 1299.27 458.052C1309.79 468.571 1314.57 482.915 1314.57 499.172C1314.57 545.073 1283.01 568.023 1218.95 568.023C1180.7 568.023 1142.46 560.373 1103.25 546.029C1064.05 531.685 1029.63 513.516 999.031 489.609V638.787C1070.74 685.644 1150.11 709.551 1237.12 709.551ZM1921.29 708.595C1962.43 708.595 2002.57 702.857 2039.85 692.338C2077.17 681.819 2109.67 667.475 2137.39 649.306V502.997C2112.53 520.21 2084.8 533.598 2053.26 544.116C2021.69 554.635 1990.15 560.373 1957.64 560.373C1912.69 560.373 1872.53 551.767 1839.06 533.598C1805.6 516.385 1779.78 492.478 1761.61 460.921C1743.45 429.364 1733.89 393.982 1733.89 353.819C1733.89 313.656 1743.45 278.274 1761.61 246.717C1779.78 215.16 1805.6 191.254 1839.06 174.041C1872.53 156.828 1910.77 148.221 1955.72 148.221C2020.73 148.221 2080.02 168.303 2134.54 207.51V55.4635C2072.39 19.1253 2002.57 0.956277 1923.22 0.956277C1851.49 0.956277 1788.39 16.2564 1734.84 46.857C1680.34 77.4576 1639.22 119.533 1609.58 174.041C1579.94 228.548 1565.6 289.749 1565.6 358.601C1565.6 423.627 1579.94 482.915 1607.67 535.51C1635.4 589.061 1676.51 631.137 1730.06 661.737C1783.61 693.294 1847.67 708.595 1921.29 708.595ZM2561.67 708.595C2629.56 708.595 2689.82 693.294 2743.34 663.65C2795.93 634.006 2838.02 591.93 2867.64 538.379C2897.29 484.828 2911.63 423.627 2911.63 355.732C2911.63 287.837 2897.29 226.635 2867.64 172.128C2838.02 118.577 2795.93 76.5013 2743.34 45.9007C2689.82 16.2564 2629.56 0.956277 2561.67 0.956277C2494.73 0.956277 2434.51 16.2564 2381.92 45.9007C2329.33 76.5013 2288.22 118.577 2258.58 172.128C2228.93 226.635 2213.62 287.837 2213.62 355.732C2213.62 423.627 2228.93 484.828 2258.58 538.379C2288.22 591.93 2329.33 634.006 2381.92 663.65C2434.51 693.294 2494.73 708.595 2561.67 708.595ZM2561.67 556.548C2525.34 556.548 2493.8 547.942 2467.01 530.729C2439.29 513.516 2418.24 489.609 2403.9 459.009C2389.56 429.364 2381.92 394.939 2381.92 356.688C2381.92 318.437 2389.56 284.012 2403.9 252.455C2418.24 221.854 2439.29 197.948 2467.01 179.778C2493.8 161.609 2525.34 153.003 2561.67 153.003C2598.98 153.003 2630.52 161.609 2658.25 179.778C2685.97 197.948 2707.02 221.854 2721.36 252.455C2735.7 284.012 2742.41 318.437 2742.41 356.688C2742.41 394.939 2734.74 429.364 2720.4 459.009C2706.05 489.609 2685.04 513.516 2658.25 530.729C2630.52 547.942 2598.98 556.548 2561.67 556.548ZM3373.13 419.802C3431.46 413.108 3475.42 392.07 3507 357.644C3538.54 323.219 3553.84 279.23 3553.84 226.635C3553.84 162.565 3532.8 112.84 3489.77 75.5452C3446.74 38.2507 3388.44 20.0816 3315.76 20.0816H3021.24V689.469H3181.9V407.37L3379.81 689.469H3572L3373.13 419.802ZM3181.9 154.915H3285.15C3316.72 154.915 3340.63 162.566 3356.87 176.91C3373.13 192.21 3381.73 214.204 3381.73 241.936C3381.73 271.58 3372.17 293.574 3354.01 309.831C3335.85 326.087 3309.06 333.738 3273.7 333.738H3181.9V154.915Z" fill="#5865F2"/>
</g>
<defs>
<filter id="filter0_dd" x="0" y="0" width="5232" height="945" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="10"/>
<feGaussianBlur stdDeviation="4"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.04 0"/>
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="4"/>
<feGaussianBlur stdDeviation="1.5"/>
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
</filter>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -0,0 +1,28 @@
import { get } from '@vercel/edge-config';
import { NextResponse } from 'next/server';
import type { ServerRuntime } from 'next/types';
export const runtime: ServerRuntime = 'edge';
export async function GET() {
const url = await get<string>('DISCORD_WEBHOOK_URL');
const imageUrl = await get<string>('IT_IS_WEDNESDAY_MY_DUDES');
if (url && imageUrl) {
await fetch(url, {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'It is wednesday, my dudes',
embeds: [
{
image: {
url: imageUrl,
},
},
],
}),
});
}
return NextResponse.json({ message: 'It is wednesday, my dudes' });
}

View File

@@ -1,11 +1,15 @@
/* eslint-disable react/no-unknown-property */
import type { ApiItemKind } from '@microsoft/api-extractor-model';
import { ImageResponse } from '@vercel/og';
import type { NextRequest } from 'next/server';
import type { ServerRuntime } from 'next/types';
export const runtime: ServerRuntime = 'edge';
const fonts = Promise.all([
fetch(new URL('../../assets/fonts/Inter-Regular.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()),
fetch(new URL('../../assets/fonts/Inter-Bold.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()),
fetch(new URL('../../../assets/fonts/Inter-Regular.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()),
fetch(new URL('../../../assets/fonts/Inter-Bold.ttf', import.meta.url)).then(async (res) => res.arrayBuffer()),
]);
function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) {
@@ -20,9 +24,9 @@ function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) {
return (
<svg fill="white" height={size} viewBox="0 0 16 16" width={size} xmlns="http://www.w3.org/2000/svg">
<path
clip-rule="evenodd"
clipRule="evenodd"
d="M14 2H8L7 3v3h1V3h6v5h-4v1h4l1-1V3l-1-1zM9 6h4v1H9.41L9 6.59V6zM7 7H2L1 8v5l1 1h6l1-1V8L8 7H7zm1 6H2V8h6v5zM3 9h4v1H3V9zm0 2h4v1H3v-1zm6-7h4v1H9V4z"
fill-rule="evenodd"
fillRule="evenodd"
/>
</svg>
);
@@ -30,9 +34,9 @@ function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) {
return (
<svg fill="white" height={size} viewBox="0 0 16 16" width={size} xmlns="http://www.w3.org/2000/svg">
<path
clip-rule="evenodd"
clipRule="evenodd"
d="M7 3l1-1h6l1 1v5l-1 1h-4V8h4V3H8v3H7V3zm2 6V8L8 7H2L1 8v5l1 1h6l1-1V9zM8 8v5H2V8h6zm1.414-1L9 6.586V6h4v1H9.414zM9 4h4v1H9V4zm-2 6H3v1h4v-1z"
fill-rule="evenodd"
fillRule="evenodd"
/>
</svg>
);
@@ -52,9 +56,9 @@ function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) {
return (
<svg fill="white" height={size} viewBox="0 0 16 16" width={size} xmlns="http://www.w3.org/2000/svg">
<path
clip-rule="evenodd"
clipRule="evenodd"
d="M2 5h2V4H1.5l-.5.5v8l.5.5H4v-1H2V5zm12.5-1H12v1h2v7h-2v1h2.5l.5-.5v-8l-.5-.5zm-2.74 2.57L12 7v2.51l-.3.45-4.5 2h-.46l-2.5-1.5-.24-.43v-2.5l.3-.46 4.5-2h.46l2.5 1.5zM5 9.71l1.5.9V9.28L5 8.38v1.33zm.58-2.15l1.45.87 3.39-1.5-1.45-.87-3.39 1.5zm1.95 3.17l3.5-1.56v-1.4l-3.5 1.55v1.41z"
fill-rule="evenodd"
fillRule="evenodd"
/>
</svg>
);
@@ -73,10 +77,10 @@ function resolveIcon(icon: keyof typeof ApiItemKind, size = 88) {
}
}
export default async function handler(req: NextRequest) {
export async function GET(request: NextRequest) {
const fontData = await fonts;
const { searchParams } = new URL(req.url);
const { searchParams } = new URL(request.url);
const hasPkg = searchParams.has('pkg');
const hasKind = searchParams.has('kind');
@@ -164,7 +168,3 @@ export default async function handler(req: NextRequest) {
},
);
}
export const config = {
runtime: 'edge',
};

View File

@@ -1,11 +1,15 @@
/* eslint-disable react/no-unknown-property */
import { ImageResponse } from '@vercel/og';
const fonts = fetch(new URL('../../assets/fonts/Inter-Black.ttf', import.meta.url)).then(async (res) =>
import { ImageResponse } from '@vercel/og';
import type { ServerRuntime } from 'next/types';
export const runtime: ServerRuntime = 'edge';
const fonts = fetch(new URL('../../../assets/fonts/Inter-Black.ttf', import.meta.url)).then(async (res) =>
res.arrayBuffer(),
);
export default async function handler() {
export async function GET() {
const fontData = await fonts;
return new ImageResponse(
@@ -38,7 +42,3 @@ export default async function handler() {
},
);
}
export const config = {
runtime: 'edge',
};

View File

@@ -1,5 +1,9 @@
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { connect } from '@planetscale/database';
import { cache } from 'react';
const sql = connect({ url: process.env.DATABASE_URL! });
export async function fetchVersions(packageName: string): Promise<string[]> {
const response = await fetch(`https://docs.discordjs.dev/api/info?package=${packageName}`, {
@@ -9,18 +13,26 @@ export async function fetchVersions(packageName: string): Promise<string[]> {
return response.json();
}
export async function fetchModelJSON(packageName: string, version: string): Promise<unknown> {
export const fetchModelJSON = cache(async (packageName: string, version: string): Promise<unknown> => {
if (process.env.NEXT_PUBLIC_LOCAL_DEV) {
const res = await readFile(
join(process.cwd(), '..', '..', 'packages', packageName, 'docs', 'docs.api.json'),
'utf8',
);
return JSON.parse(res);
try {
return JSON.parse(res);
} catch {
console.log(res);
return {};
}
}
const response = await fetch(`https://docs.discordjs.dev/docs/${packageName}/${version}.api.json`, {
next: { revalidate: 3_600 },
});
const { rows } = await sql.execute('select data from documentation where name = ? and version = ?', [
packageName,
version,
]);
return response.json();
}
// @ts-expect-error: https://github.com/planetscale/database-js/issues/71
return rows[0].data;
});

View File

@@ -1,89 +0,0 @@
import { createApiModel, tryResolveSummaryText } from '@discordjs/scripts';
import type {
ApiDeclaredItem,
ApiEnum,
ApiItem,
ApiItemContainerMixin,
ApiMethod,
ApiMethodSignature,
ApiProperty,
ApiPropertySignature,
} from '@microsoft/api-extractor-model';
import { ApiItemKind } from '@microsoft/api-extractor-model';
import type { ItemRouteParams } from './page';
import { fetchModelJSON } from '~/app/docAPI';
import { OVERLOAD_SEPARATOR } from '~/util/constants';
import { findMember } from '~/util/model.server';
async function fetchMember({ package: packageName, version, item }: ItemRouteParams): Promise<ApiItem | undefined> {
const modelJSON = await fetchModelJSON(packageName, version);
const model = createApiModel(modelJSON);
const pkg = model.tryGetPackageByName(packageName);
const entry = pkg?.entryPoints[0];
if (!entry) {
return undefined;
}
const [memberName] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
return findMember(model, packageName, memberName);
}
function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSearchParams {
const params = new URLSearchParams({
pkg: packageName,
kind: member?.kind,
name: member?.displayName,
});
switch (member?.kind) {
case ApiItemKind.Interface:
case ApiItemKind.Class: {
const typedMember = member as ApiItemContainerMixin;
const properties = typedMember.members.filter((member) =>
[ApiItemKind.Property, ApiItemKind.PropertySignature].includes(member.kind),
) as (ApiProperty | ApiPropertySignature)[];
const methods = typedMember.members.filter((member) =>
[ApiItemKind.Method, ApiItemKind.Method].includes(member.kind),
) as (ApiMethod | ApiMethodSignature)[];
params.append('methods', methods.length.toString());
params.append('props', properties.length.toString());
break;
}
case ApiItemKind.Enum: {
const typedMember = member as ApiEnum;
params.append('members', typedMember.members.length.toString());
break;
}
default:
break;
}
return params;
}
export default async function Head({ params }: { params: ItemRouteParams }) {
const member = (await fetchMember(params))!;
const name = `discord.js${member?.displayName ? ` | ${member.displayName}` : ''}`;
const ogTitle = `${params.package ?? 'discord.js'}${member?.displayName ? ` | ${member.displayName}` : ''}`;
const searchParams = resolveMemberSearchParams(params.package, member);
const url = new URL('https://discordjs.dev/api/og_model');
url.search = searchParams.toString();
const ogImage = url.toString();
const description = tryResolveSummaryText(member as ApiDeclaredItem);
return (
<>
<title key="title">{name}</title>
<meta content={description ?? ''} key="description" name="description" />
<meta content={ogTitle} key="og_title" property="og:title" />
<meta content={description ?? ''} key="og_description" property="og:description" />
<meta content={ogImage} key="og_image" property="og:image" />
</>
);
}

View File

@@ -1,12 +0,0 @@
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import { CmdKDialog } from '~/components/CmdK';
export default function ItemLayout({ children }: PropsWithChildren) {
return (
<Providers>
<>{children}</>
<CmdKDialog />
</Providers>
);
}

View File

@@ -0,0 +1 @@
export { default } from '~/app/loading';

View File

@@ -1,19 +1,21 @@
/* eslint-disable no-case-declarations */
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
// eslint-disable-next-line n/prefer-global/process
import process, { cwd } from 'node:process';
import { createApiModel } from '@discordjs/scripts';
import { addPackageToModel, tryResolveSummaryText } from '@discordjs/scripts';
import type {
ApiClass,
ApiDeclaredItem,
ApiEnum,
ApiInterface,
ApiItem,
ApiItemContainerMixin,
ApiMethod,
ApiMethodSignature,
ApiProperty,
ApiPropertySignature,
ApiTypeAlias,
ApiVariable,
} from '@microsoft/api-extractor-model';
import { ApiFunction } from '@microsoft/api-extractor-model';
import { ApiItemKind, ApiModel, ApiFunction } from '@microsoft/api-extractor-model';
import { notFound } from 'next/navigation';
import type { Metadata } from 'next/types';
import { fetchModelJSON } from '~/app/docAPI';
import { Class } from '~/components/model/Class';
import { Interface } from '~/components/model/Interface';
@@ -30,18 +32,94 @@ export interface ItemRouteParams {
version: string;
}
async function fetchHeadMember({ package: packageName, version, item }: ItemRouteParams): Promise<ApiItem | undefined> {
const modelJSON = await fetchModelJSON(packageName, version);
const model = addPackageToModel(new ApiModel(), modelJSON);
const pkg = model.tryGetPackageByName(packageName);
const entry = pkg?.entryPoints[0];
if (!entry) {
return undefined;
}
const [memberName] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
return findMember(model, packageName, memberName);
}
function resolveMemberSearchParams(packageName: string, member: ApiItem): URLSearchParams {
const params = new URLSearchParams({
pkg: packageName,
kind: member?.kind,
name: member?.displayName,
});
switch (member?.kind) {
case ApiItemKind.Interface:
case ApiItemKind.Class: {
const typedMember = member as ApiItemContainerMixin;
const properties = typedMember.members.filter((member) =>
[ApiItemKind.Property, ApiItemKind.PropertySignature].includes(member.kind),
) as (ApiProperty | ApiPropertySignature)[];
const methods = typedMember.members.filter((member) =>
[ApiItemKind.Method, ApiItemKind.Method].includes(member.kind),
) as (ApiMethod | ApiMethodSignature)[];
params.append('methods', methods.length.toString());
params.append('props', properties.length.toString());
break;
}
case ApiItemKind.Enum: {
const typedMember = member as ApiEnum;
params.append('members', typedMember.members.length.toString());
break;
}
default:
break;
}
return params;
}
// eslint-disable-next-line unicorn/numeric-separators-style
export const revalidate = 3600;
export async function generateMetadata({ params }: { params: ItemRouteParams }) {
const member = (await fetchHeadMember(params))!;
const name = `discord.js${member?.displayName ? ` | ${member.displayName}` : ''}`;
const ogTitle = `${params.package ?? 'discord.js'}${member?.displayName ? ` | ${member.displayName}` : ''}`;
const url = new URL('https://discordjs.dev/api/dynamic-open-graph.png');
const searchParams = resolveMemberSearchParams(params.package, member);
url.search = searchParams.toString();
const ogImage = url.toString();
const description = tryResolveSummaryText(member as ApiDeclaredItem);
return {
title: name,
description: description ?? 'Discord.js API Documentation',
openGraph: {
title: ogTitle,
description: description ?? 'Discord.js API Documentation',
images: ogImage,
},
} satisfies Metadata;
}
export async function generateStaticParams({ params: { package: packageName, version } }: { params: ItemRouteParams }) {
const modelJSON = await fetchModelJSON(packageName, version);
const model = createApiModel(modelJSON);
const model = addPackageToModel(new ApiModel(), modelJSON);
const pkg = model.tryGetPackageByName(packageName);
const entry = pkg?.entryPoints[0];
if (!entry) {
return notFound();
notFound();
}
return entry.members.map((member) => ({
return entry.members.map((member: ApiItem) => ({
item: member.displayName,
}));
}
@@ -51,21 +129,20 @@ async function fetchMember({ package: packageName, version: branchName = 'main',
notFound();
}
let data;
try {
if (process.env.NEXT_PUBLIC_LOCAL_DEV) {
const res = await readFile(join(cwd(), '..', '..', 'packages', packageName, 'docs', 'docs.api.json'), 'utf8');
data = JSON.parse(res);
} else {
const res = await fetch(`https://docs.discordjs.dev/docs/${packageName}/${branchName}.api.json`);
data = await res.json();
const model = new ApiModel();
if (branchName === 'main') {
const modelJSONFiles = await Promise.all(PACKAGES.map(async (pkg) => fetchModelJSON(pkg, branchName)));
for (const modelJSONFile of modelJSONFiles) {
addPackageToModel(model, modelJSONFile);
}
} catch {
notFound();
} else {
const modelJSON = await fetchModelJSON(packageName, branchName);
addPackageToModel(model, modelJSON);
}
const [memberName, overloadIndex] = decodeURIComponent(item).split(OVERLOAD_SEPARATOR);
const model = createApiModel(data);
// eslint-disable-next-line prefer-const
let { containerKey, displayName: name } = findMember(model, packageName, memberName) ?? {};
@@ -81,7 +158,7 @@ function Member({ member }: { member?: ApiItem }) {
case 'Class':
return <Class clazz={member as ApiClass} />;
case 'Function':
return <Function item={member as ApiFunction} key={member.containerKey} />;
return <Function item={member as ApiFunction} />;
case 'Interface':
return <Interface item={member as ApiInterface} />;
case 'TypeAlias':
@@ -98,17 +175,5 @@ function Member({ member }: { member?: ApiItem }) {
export default async function Page({ params }: { params: ItemRouteParams }) {
const member = await fetchMember(params);
return (
<main
className={
(member?.kind === 'Class' || member?.kind === 'Interface') && (member as ApiClass | ApiInterface).members.length
? 'xl:pr-64'
: ''
}
>
<article className="dark:bg-dark-600 bg-light-600">
<div className="dark:bg-dark-800 bg-white p-6 pb-20 shadow">{member ? <Member member={member} /> : null}</div>
</article>
</main>
);
return <div className="relative top-6">{member ? <Member member={member} /> : null}</div>;
}

View File

@@ -1,27 +0,0 @@
'use client';
// import { ThemeProvider } from 'next-themes';
import type { PropsWithChildren } from 'react';
import { CmdKProvider } from '~/contexts/cmdK';
import { NavProvider } from '~/contexts/nav';
export function Providers({ children }: PropsWithChildren) {
return (
<NavProvider>
<CmdKProvider>
{/* <ThemeProvider
attribute="class"
cookieName="theme"
defaultTheme="system"
disableTransitionOnChange
value={{
light: 'light',
dark: 'dark',
}}
> */}
{children}
{/* </ThemeProvider> */}
</CmdKProvider>
</NavProvider>
);
}

View File

@@ -0,0 +1,12 @@
'use client';
export default function Error({ error }: { error: Error }) {
console.error(error);
return (
<div className="mx-auto flex h-full max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
);
}

View File

@@ -1,21 +1,28 @@
import { createApiModel } from '@discordjs/scripts';
import { addPackageToModel } from '@discordjs/scripts';
import type { ApiFunction, ApiItem } from '@microsoft/api-extractor-model';
import Image from 'next/image';
import { ApiModel } from '@microsoft/api-extractor-model';
import dynamic from 'next/dynamic';
import { notFound } from 'next/navigation';
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import { fetchModelJSON, fetchVersions } from '~/app/docAPI';
import vercelLogo from '~/assets/powered-by-vercel.svg';
import { Header } from '~/components/Header';
import { CmdKDialog } from '~/components/CmdK';
import { Nav } from '~/components/Nav';
import type { SidebarSectionItemData } from '~/components/Sidebar';
import { resolveItemURI } from '~/components/documentation/util';
import { N_RECENT_VERSIONS, PACKAGES } from '~/util/constants';
const Header = dynamic(async () => import('~/components/Header'));
const Footer = dynamic(async () => import('~/components/Footer'));
export interface VersionRouteParams {
package: string;
version: string;
}
// eslint-disable-next-line unicorn/numeric-separators-style
export const revalidate = 3600;
export async function generateStaticParams() {
const params: VersionRouteParams[] = [];
@@ -41,18 +48,18 @@ function serializeIntoSidebarItemData(item: ApiItem): SidebarSectionItemData {
export default async function PackageLayout({ children, params }: PropsWithChildren<{ params: VersionRouteParams }>) {
const modelJSON = await fetchModelJSON(params.package, params.version);
const model = createApiModel(modelJSON);
const model = addPackageToModel(new ApiModel(), modelJSON);
const pkg = model.tryGetPackageByName(params.package);
if (!pkg) {
return notFound();
notFound();
}
const entry = pkg.entryPoints[0];
if (!entry) {
return notFound();
notFound();
}
const members = entry.members.filter((member) => {
@@ -64,80 +71,21 @@ export default async function PackageLayout({ children, params }: PropsWithChild
});
return (
<>
<Header />
<Nav members={members.map((member) => serializeIntoSidebarItemData(member))} />
<article className="pt-18 lg:pl-76">
<div className="relative z-10 min-h-[calc(100vh_-_70px)]">{children}</div>
<div className="h-76 md:h-52" />
<footer className="dark:bg-dark-600 h-76 lg:pl-84 bg-light-600 fixed bottom-0 left-0 right-0 md:h-52 md:pl-4 md:pr-16">
<div className="mx-auto flex max-w-6xl flex-col place-items-center gap-12 pt-12 lg:place-content-center">
<div className="flex w-full flex-col place-content-between place-items-center gap-12 md:flex-row md:gap-0">
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://vercel.com/?utm_source=discordjs&utm_campaign=oss"
rel="noopener noreferrer"
target="_blank"
title="Vercel"
>
<Image alt="Vercel" src={vercelLogo} />
</a>
<div className="flex flex-row gap-6 md:gap-12">
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Community</div>
<div className="flex flex-col gap-1">
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord.gg/djs"
rel="noopener noreferrer"
target="_blank"
>
Discord
</a>
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js/discussions"
rel="noopener noreferrer"
target="_blank"
>
GitHub discussions
</a>
</div>
</div>
<div className="flex flex-col gap-2">
<div className="text-lg font-semibold">Project</div>
<div className="flex flex-col gap-1">
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://github.com/discordjs/discord.js"
rel="noopener noreferrer"
target="_blank"
>
discord.js
</a>
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discordjs.guide"
rel="noopener noreferrer"
target="_blank"
>
discord.js guide
</a>
<a
className="focus:ring-width-2 focus:ring-blurple rounded outline-0 focus:ring"
href="https://discord-api-types.dev"
rel="noopener noreferrer"
target="_blank"
>
discord-api-types
</a>
</div>
</div>
</div>
</div>
<Providers>
<main className="mx-auto max-w-7xl px-4 lg:max-w-full">
<Header />
<div className="relative top-6 mx-auto max-w-7xl gap-6 lg:flex lg:max-w-full">
<div className="lg:top-23 lg:sticky lg:h-[calc(100vh_-_100px)]">
<Nav members={members.map((member) => serializeIntoSidebarItemData(member))} />
</div>
</footer>
</article>
</>
<div className="min-w-xs mx-auto w-full max-w-5xl pb-10">
{children}
<Footer />
</div>
</div>
</main>
<CmdKDialog />
</Providers>
);
}

View File

@@ -0,0 +1 @@
export { default } from '~/app/loading';

View File

@@ -1,67 +1,35 @@
import { readFile } from 'node:fs/promises';
import { join } from 'node:path';
import { serialize } from 'next-mdx-remote/serialize';
import type { SerializeOptions } from 'next-mdx-remote/dist/types';
import { MDXRemote } from 'next-mdx-remote/rsc';
import rehypeIgnore from 'rehype-ignore';
import rehypePrettyCode, { type Options } from 'rehype-pretty-code';
import rehypeRaw from 'rehype-raw';
import rehypeSlug from 'rehype-slug';
import remarkGfm from 'remark-gfm';
import { getHighlighter } from 'shiki';
import shikiLangJavascript from 'shiki/languages/javascript.tmLanguage.json';
import shikiLangTypescript from 'shiki/languages/typescript.tmLanguage.json';
import shikiThemeDarkPlus from 'shiki/themes/dark-plus.json';
import shikiThemeLightPlus from 'shiki/themes/light-plus.json';
import type { VersionRouteParams } from './layout';
import { MDXRemote } from '~/components/MDXRemote';
import { SyntaxHighlighter } from '~/components/SyntaxHighlighter';
async function loadREADME(packageName: string) {
return readFile(join(process.cwd(), 'src', 'assets', 'readme', packageName, 'home-README.md'), 'utf8');
}
async function generateMDX(readme: string) {
return serialize(readme, {
mdxOptions: {
remarkPlugins: [remarkGfm],
remarkRehypeOptions: { allowDangerousHtml: true },
rehypePlugins: [
rehypeRaw,
rehypeIgnore,
rehypeSlug,
[
rehypePrettyCode,
{
theme: {
dark: shikiThemeDarkPlus,
light: shikiThemeLightPlus,
},
getHighlighter: async (options?: Partial<Options>) =>
getHighlighter({
...options,
langs: [
// @ts-expect-error: Working as intended
{ id: 'javascript', aliases: ['js'], scopeName: 'source.js', grammar: shikiLangJavascript },
// @ts-expect-error: Working as intended
{ id: 'typescript', aliases: ['ts'], scopeName: 'source.ts', grammar: shikiLangTypescript },
],
}),
},
],
],
format: 'md',
},
});
}
const mdxOptions = {
mdxOptions: {
remarkPlugins: [remarkGfm],
remarkRehypeOptions: { allowDangerousHtml: true },
rehypePlugins: [rehypeRaw, rehypeIgnore, rehypeSlug],
format: 'md',
},
} satisfies SerializeOptions;
export default async function Page({ params }: { params: VersionRouteParams }) {
const { package: packageName } = params;
const readmeSource = await loadREADME(packageName);
const mdxSource = await generateMDX(readmeSource);
return (
<article className="dark:bg-dark-600 bg-white p-10">
<div className="prose max-w-none">
<MDXRemote {...mdxSource} />
</div>
</article>
<div className="prose max-w-none">
{/* @ts-expect-error async component */}
<MDXRemote components={{ pre: SyntaxHighlighter }} options={mdxOptions} source={readmeSource} />
</div>
);
}

View File

@@ -0,0 +1,16 @@
'use client';
import type { PropsWithChildren } from 'react';
import { CmdKProvider } from '~/contexts/cmdK';
import { MemberProvider } from '~/contexts/member';
import { NavProvider } from '~/contexts/nav';
export function Providers({ children }: PropsWithChildren) {
return (
<NavProvider>
<MemberProvider>
<CmdKProvider>{children}</CmdKProvider>
</MemberProvider>
</NavProvider>
);
}

View File

@@ -0,0 +1 @@
export { default } from '~/app/loading';

View File

@@ -3,8 +3,11 @@ import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
import { VscVersions } from '@react-icons/all-files/vsc/VscVersions';
import Link from 'next/link';
import { notFound } from 'next/navigation';
import type { ServerRuntime } from 'next/types';
import { PACKAGES } from '~/util/constants';
export const runtime: ServerRuntime = 'edge';
async function getData(pkg: string) {
if (!PACKAGES.includes(pkg)) {
notFound();
@@ -24,14 +27,14 @@ export default async function Page({ params }: { params: { package: string } })
const data = await getData(params.package);
return (
<div className="min-w-xs sm:w-md mx-auto flex h-full flex-row place-content-center place-items-center gap-8 py-0 px-4 lg:py-0 lg:px-6">
<div className="flex grow flex-col place-content-center gap-4">
<h1 className="text-2xl font-semibold">Select a version:</h1>
{data.map((version) => (
<div className="min-w-xs sm:w-md mx-auto flex min-h-screen flex-col gap-8 px-4 py-6 lg:px-6 lg:py-6">
<h1 className="text-2xl font-semibold">Select a version:</h1>
<div className="flex flex-col gap-4">
{data.map((version, idx) => (
<Link
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-col place-content-center rounded border border-neutral-300 bg-transparent p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-col place-content-center rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
href={`/docs/packages/${params.package}/${version}`}
key={version}
key={`${version}-${idx}`}
>
<div className="flex flex-row place-content-between place-items-center gap-4">
<div className="flex flex-row place-content-between place-items-center gap-4">
@@ -42,13 +45,13 @@ export default async function Page({ params }: { params: { package: string } })
</div>
</Link>
)) ?? null}
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/docs/packages"
>
<VscArrowLeft size={20} /> Go back
</Link>
</div>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/docs/packages"
>
<VscArrowLeft size={20} /> Go back
</Link>
</div>
);
}

View File

@@ -0,0 +1 @@
export { default } from '~/app/loading';

View File

@@ -3,16 +3,19 @@ import { VscArrowLeft } from '@react-icons/all-files/vsc/VscArrowLeft';
import { VscArrowRight } from '@react-icons/all-files/vsc/VscArrowRight';
import { VscPackage } from '@react-icons/all-files/vsc/VscPackage';
import Link from 'next/link';
import type { ServerRuntime } from 'next/types';
import { PACKAGES } from '~/util/constants';
export default async function Page() {
export const runtime: ServerRuntime = 'edge';
export default function Page() {
return (
<div className="min-w-xs sm:w-md mx-auto flex min-h-screen flex-row place-content-center place-items-center gap-8 py-0 px-4 lg:py-0 lg:px-6">
<div className="flex grow flex-col place-content-center gap-4">
<h1 className="text-2xl font-semibold">Select a package:</h1>
<div className="min-w-xs sm:w-md mx-auto flex min-h-screen flex-col gap-8 px-4 py-6 lg:px-6 lg:py-6">
<h1 className="text-2xl font-semibold">Select a package:</h1>
<div className="flex flex-col gap-4">
<a
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-transparent p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
href="https://discord.js.org/#/docs/discord.js"
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
href="https://old.discordjs.dev/#/docs/discord.js"
>
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
@@ -24,11 +27,11 @@ export default async function Page() {
<VscArrowRight size={20} />
</div>
</a>
{PACKAGES.map((pkg) => (
{PACKAGES.map((pkg, idx) => (
<Link
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-between rounded border border-neutral-300 bg-transparent p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
href={`/docs/packages/${pkg}`}
key={pkg}
key={`${pkg}-${idx}`}
>
<div className="flex grow flex-row place-content-between place-items-center gap-4">
<div className="flex grow flex-row place-content-between place-items-center gap-4">
@@ -50,7 +53,7 @@ export default async function Page() {
</Link>
))}
<a
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-transparent p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
className="dark:bg-dark-400 dark:border-dark-100 dark:hover:bg-dark-300 dark:active:bg-dark-200 focus:ring-width-2 focus:ring-blurple flex h-11 transform-gpu cursor-pointer select-none appearance-none place-content-between rounded border border-neutral-300 bg-white p-4 text-base font-semibold leading-none text-black outline-0 hover:bg-neutral-100 focus:ring active:translate-y-px active:bg-neutral-200 dark:text-white"
href="https://discord-api-types.dev/"
>
<div className="flex grow flex-row place-content-between place-items-center gap-4">
@@ -63,13 +66,13 @@ export default async function Page() {
<FiExternalLink size={20} />
</div>
</a>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/"
>
<VscArrowLeft size={20} /> Go back
</Link>
</div>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center gap-2 place-self-center rounded border-0 px-4 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/"
>
<VscArrowLeft size={20} /> Go back
</Link>
</div>
);
}

View File

@@ -0,0 +1,12 @@
'use client';
export default function Error({ error }: { error: Error }) {
console.error(error);
return (
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
);
}

View File

@@ -0,0 +1,23 @@
'use client';
import { Providers } from './providers';
import { inter } from '~/util/fonts';
export default function GlobalError({ error }: { error: Error }) {
console.error(error);
return (
<html className={inter.variable} lang="en" suppressHydrationWarning>
<body className="dark:bg-dark-800 bg-light-600">
<Providers>
<main className="mx-auto min-h-screen max-w-2xl">
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">500</h1>
<h2 className="text-[2rem] md:text-[3rem]">Error.</h2>
</div>
</main>
</Providers>
</body>
</html>
);
}

View File

@@ -1,28 +0,0 @@
import { DESCRIPTION } from '~/util/constants';
export default function Head() {
return (
<>
<link href="/apple-touch-icon.png" rel="apple-touch-icon" sizes="180x180" />
<link href="/favicon-32x32.png" rel="icon" sizes="32x32" type="image/png" />
<link href="/favicon-16x16.png" rel="icon" sizes="16x16" type="image/png" />
<link href="/site.webmanifest" rel="manifest" />
<link color="#090a16" href="/safari-pinned-tab.svg" rel="mask-icon" />
<meta content="light dark" name="color-scheme" />
<meta content="discord.js" name="apple-mobile-web-app-title" />
<meta content="discord.js" name="application-name" />
<meta content="#090a16" name="msapplication-TileColor" />
<meta content={DESCRIPTION} key="description" name="description" />
<meta content="discord.js" property="og:site_name" />
<meta content="website" property="og:type" />
<meta content="discord.js" key="og_title" property="og:title" />
<meta content={DESCRIPTION} key="og_description" property="og:description" />
<meta content="https://discordjs.dev/api/og" key="og_image" property="og:image" />
<meta content="summary_large_image" name="twitter:card" />
<meta content="@iCrawlToGo" name="twitter:creator" />
<title key="title">discord.js</title>
<meta content="minimum-scale=1, initial-scale=1, width=device-width" name="viewport" />
<meta content="#5865f2" name="theme-color" />
</>
);
}

View File

@@ -1,15 +1,84 @@
import { Analytics } from '@vercel/analytics/react';
import type { Metadata } from 'next/types';
import type { PropsWithChildren } from 'react';
import { Providers } from './providers';
import { DESCRIPTION } from '~/util/constants';
import { inter, jetBrainsMono } from '~/util/fonts';
import '@unocss/reset/tailwind.css';
import '../styles/inter.css';
import '../styles/unocss.css';
import '../styles/cmdk.css';
import '../styles/main.css';
import '@unocss/reset/tailwind-compat.css';
import '~/styles/unocss.css';
import '~/styles/cmdk.css';
import '~/styles/main.css';
export const metadata: Metadata = {
title: 'discord.js',
description: DESCRIPTION,
viewport: {
minimumScale: 1,
initialScale: 1,
width: 'device-width',
},
icons: {
other: [
{
url: '/favicon-32x32.png',
sizes: '32x32',
type: 'image/png',
},
{
url: '/favicon-16x16.png',
sizes: '16x16',
type: 'image/png',
},
],
apple: [
'/apple-touch-icon.png',
{
url: '/safari-pinned-tab.svg',
rel: 'mask-icon',
},
],
},
manifest: '/site.webmanifest',
themeColor: [
{ media: '(prefers-color-scheme: light)', color: '#f1f3f5' },
{ media: '(prefers-color-scheme: dark)', color: '#181818' },
],
colorScheme: 'light dark',
appleWebApp: {
title: 'discord.js',
},
applicationName: 'discord.js',
openGraph: {
siteName: 'discord.js',
type: 'website',
title: 'discord.js',
description: DESCRIPTION,
images: 'https://discordjs.dev/api/open-graph.png',
},
twitter: {
card: 'summary_large_image',
creator: '@iCrawlToGo',
},
other: {
'msapplication-TileColor': '#090a16',
},
};
export default function RootLayout({ children }: PropsWithChildren) {
return (
<html lang="en">
<body className="dark:bg-dark-800 bg-white">{children}</body>
<html className={`${inter.variable} ${jetBrainsMono.variable}`} lang="en" suppressHydrationWarning>
<body className="dark:bg-dark-800 bg-light-600">
<Providers>{children}</Providers>
<Analytics />
</body>
</html>
);
}

View File

@@ -0,0 +1,20 @@
export default function Loading() {
return (
<div className="mx-4 flex min-h-screen flex-col items-center justify-center gap-4">
<svg
className="h-9 w-9 animate-spin text-black dark:text-white"
fill="none"
viewBox="0 0 24 24"
xmlns="http://www.w3.org/2000/svg"
>
<circle className="opacity-25" cx="12" cy="12" r="10" stroke="currentColor" strokeWidth="4" />
<path
className="opacity-75 dark:opacity-100"
d="M4 12a8 8 0 018-8V0C5.373 0 0 5.373 0 12h4zm2 5.291A7.962 7.962 0 014 12H0c0 3.042 1.135 5.824 3 7.938l3-2.647z"
fill="currentColor"
/>
</svg>
<div className="text-lg font-medium">Loading...</div>
</div>
);
}

View File

@@ -1,23 +1,16 @@
// import Head from 'next/head';
import Link from 'next/link';
export default function NotFound() {
return (
<>
{/* <Head>
<title key="title">discord.js | 404</title>
<meta content="discord.js | 404" key="og_title" property="og:title" />
</Head> */}
<div className="mx-auto flex h-full max-w-lg flex-col place-content-center place-items-center gap-8 py-16 px-8 lg:py-0 lg:px-6">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">404</h1>
<h2 className="text-[2rem] md:text-[3rem]">Not found.</h2>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/docs/packages"
>
Take me back
</Link>
</div>
</>
<div className="mx-auto flex min-h-screen max-w-lg flex-col place-content-center place-items-center gap-8 px-8 py-16 lg:px-6 lg:py-0">
<h1 className="text-[9rem] font-black leading-none md:text-[12rem]">404</h1>
<h2 className="text-[2rem] md:text-[3rem]">Not found.</h2>
<Link
className="bg-blurple focus:ring-width-2 flex h-11 transform-gpu cursor-pointer select-none appearance-none flex-row place-items-center rounded border-0 px-6 text-base font-semibold leading-none text-white no-underline outline-0 focus:ring focus:ring-white active:translate-y-px"
href="/docs/packages"
>
Take me back
</Link>
</div>
);
}

Some files were not shown because too many files have changed in this diff Show More