Skip to content

Commit 0441e01

Browse files
committed
fix: update context api
1 parent 038c2fe commit 0441e01

File tree

24 files changed

+155
-75
lines changed

24 files changed

+155
-75
lines changed

apps/website/src/data/docs.json

Lines changed: 1 addition & 1 deletion
Large diffs are not rendered by default.

apps/website/src/pages/guide/[topic]/[page].tsx

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,17 @@ const pages = [
133133
}
134134
]
135135
},
136+
{
137+
name: 'hooks',
138+
displayName: 'Hooks',
139+
pages: [
140+
{
141+
name: 'using-hooks',
142+
displayName: 'Using Hooks',
143+
component: lazy(() => import('../_guides/hooks/using_hooks.mdx'))
144+
}
145+
]
146+
},
136147
{
137148
name: 'extractors',
138149
displayName: 'Extractors',
@@ -191,17 +202,7 @@ const pages = [
191202
}
192203
]
193204
},
194-
{
195-
name: 'hooks',
196-
displayName: 'Hooks',
197-
pages: [
198-
{
199-
name: 'using-hooks',
200-
displayName: 'Using Hooks',
201-
component: lazy(() => import('../_guides/hooks/using_hooks.mdx'))
202-
}
203-
]
204-
},
205+
205206
{
206207
name: 'migrating',
207208
displayName: 'Migrating',

apps/website/src/pages/guide/_guides/hooks/using_hooks.mdx

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,18 +25,20 @@ export async function execute(interaction) {
2525
First of all, your command handler needs to provide context to `HooksContextProvider`:
2626

2727
```js
28-
const { withContext } = require('discord-player');
28+
const { useMainPlayer } = require('discord-player');
2929

3030
client.on('interactionCreate', async (interaction) => {
3131
if (!interaction.isCommand()) return;
3232

33+
const player = useMainPlayer();
34+
3335
// assuming the following code is your target command to be executed
3436
const command = getCommandSomehow(); // shape is roughly { execute: Function }
3537

3638
const context = { guild: interaction.guild };
3739

3840
// provide context and execute the command
39-
await withContext(context, () => command.execute(interaction));
41+
await player.context.provide(context, () => command.execute(interaction));
4042
});
4143
```
4244

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,10 @@
4747
"esbuild-plugin-version-injector": "^1.0.2",
4848
"eslint": "^8.21.0",
4949
"fs-extra": "^11.1.0",
50+
"micro-docgen": "^0.2.0",
5051
"prettier": "^2.8.2",
5152
"rimraf": "^4.1.2",
5253
"turbo": "1.10.16",
53-
"typedoc-nextra": "0.1.5",
5454
"typescript": "^5.2.2",
5555
"vitest": "^0.34.6"
5656
}

packages/discord-player/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,4 @@
7777
"readmeFile": "./README.md",
7878
"tsconfig": "./tsconfig.json"
7979
}
80-
}
80+
}

packages/discord-player/src/Player.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { PlayerEventsEmitter } from './utils/PlayerEventsEmitter';
1515
import { Exceptions } from './errors';
1616
import { defaultVoiceStateHandler } from './DefaultVoiceStateHandler';
1717
import { IPRotator } from './utils/IPRotator';
18+
import { Context, createContext } from './hooks';
19+
import { HooksCtx } from './hooks/common';
1820

1921
const kSingleton = Symbol('InstanceDiscordPlayerSingleton');
2022

@@ -43,6 +45,7 @@ export class Player extends PlayerEventsEmitter<PlayerEvents> {
4345
#lagMonitorTimeout!: NodeJS.Timeout;
4446
#lagMonitorInterval!: NodeJS.Timer;
4547
#onVoiceStateUpdate: VoiceStateHandler = defaultVoiceStateHandler;
48+
#hooksCtx: Context<HooksCtx> | null = null;
4649
public static readonly version: string = '[VI]{{inject}}[/VI]';
4750
public static _singletonKey = kSingleton;
4851
public readonly id = SnowflakeUtil.generate().toString();
@@ -122,6 +125,17 @@ export class Player extends PlayerEventsEmitter<PlayerEvents> {
122125
}
123126
}
124127

128+
/**
129+
* The hooks context for this player instance.
130+
*/
131+
public get context() {
132+
if (!this.#hooksCtx) {
133+
this.#hooksCtx = createContext();
134+
}
135+
136+
return this.#hooksCtx;
137+
}
138+
125139
/**
126140
* Override default voice state update handler
127141
* @param handler The handler callback

packages/discord-player/src/hooks/common.ts

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import { Guild } from 'discord.js';
22
import type { Player } from '../Player';
3-
import { createContext, useContext } from './context/async-context';
43
import { GuildQueue, NodeResolvable } from '../manager';
54
import { instances } from '../utils/__internal__';
5+
import { Exceptions } from '../errors';
6+
import { useContext } from './context/async-context';
67

78
const preferredInstanceKey = '__discord_player_hook_instance_cache__';
89

@@ -14,15 +15,19 @@ export interface HooksCtx {
1415
guild: Guild;
1516
}
1617

17-
export const HooksContextProvider = createContext<HooksCtx>();
18-
export const withContext = HooksContextProvider.provide.bind(HooksContextProvider);
18+
/**
19+
* @private
20+
*/
21+
export function useHooksContext(hookName: string) {
22+
const player = getPlayer();
23+
if (!player) throw Exceptions.ERR_ILLEGAL_HOOK_INVOCATION('discord-player', 'Player instance must be created before using hooks');
1924

20-
export const useHooksContext = () => {
21-
const ctx = useContext(HooksContextProvider);
22-
if (!ctx) throw new Error('useHooksContext must be called inside a HooksContextProvider');
25+
const context = useContext(player.context);
2326

24-
return ctx;
25-
};
27+
if (!context) throw Exceptions.ERR_ILLEGAL_HOOK_INVOCATION(hookName, `${hookName} must be called inside a player context created by <Player>.context.provide()`);
28+
29+
return context;
30+
}
2631

2732
/**
2833
* Bind a player instance to the hook system, defaults to the first instance.

packages/discord-player/src/hooks/context/async-context.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,7 @@ export class Context<T> {
4444
/**
4545
* Get the current value of the context. If the context is lost and no default value is provided, undefined will be returned.
4646
*/
47-
public getValue(): T | undefined {
47+
public consume(): T | undefined {
4848
const data = this.storage.getStore();
4949

5050
if (data === undefined && this.defaultValue !== undefined) return this.defaultValue;
@@ -95,5 +95,5 @@ export function createContext<T = unsafe>(defaultValue?: T): Context<T> {
9595
* @example const value = useContext(context);
9696
*/
9797
export function useContext<T = unsafe>(context: Context<T>): T | undefined {
98-
return context.getValue();
98+
return context.consume();
9999
}

packages/discord-player/src/hooks/useHistory.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import { getQueue, useHooksContext } from './common';
88
export function useHistory<Meta = unknown>(): GuildQueueHistory<Meta> | null;
99
export function useHistory<Meta = unknown>(node: NodeResolvable): GuildQueueHistory<Meta> | null;
1010
export function useHistory<Meta = unknown>(node?: NodeResolvable): GuildQueueHistory<Meta> | null {
11-
const _node = node ?? useHooksContext().guild;
11+
const _node = node ?? useHooksContext('useHistory').guild;
1212

1313
const queue = getQueue<Meta>(_node);
1414
if (!queue) return null;

packages/discord-player/src/hooks/useMetadata.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export type MetadataDispatch<T> = readonly [() => T, (metadata: T | SetterFN<T,
1212
export function useMetadata<T = unknown>(): MetadataDispatch<T>;
1313
export function useMetadata<T = unknown>(node: NodeResolvable): MetadataDispatch<T>;
1414
export function useMetadata<T = unknown>(node?: NodeResolvable): MetadataDispatch<T> {
15-
const _node = node ?? useHooksContext().guild;
15+
const _node = node ?? useHooksContext('useMetadata').guild;
1616
const queue = getQueue<T>(_node);
1717
const setter = (metadata: T | SetterFN<T, T>) => {
1818
if (queue) {

0 commit comments

Comments
 (0)