Skip to content

Commit e1be061

Browse files
committed
feat: commands options can be null if not required
1 parent ba286c9 commit e1be061

File tree

2 files changed

+42
-154
lines changed

2 files changed

+42
-154
lines changed

Diff for: src/register.ts

+18-14
Original file line numberDiff line numberDiff line change
@@ -36,23 +36,27 @@ export const registerCommands = (harmonix: Harmonix) => {
3636
harmonix.client?.on(Events.InteractionCreate, async (interaction) => {
3737
if (!interaction.isChatInputCommand()) return
3838
const cmd = harmonix.commands.get(interaction.commandName)
39+
const cmdOptions = Object.entries(cmd?.config.options ?? {}).map(
40+
([key, _]) => ({ name: key })
41+
)
3942

4043
if (!cmd) return
41-
const options = await interaction.options.data.reduce<
42-
Promise<ParsedOptions>
43-
>(async (acc, opt) => {
44-
const resolvedAcc = await acc
45-
const resolvedOption = await resolveOption(
46-
interaction,
47-
cmd.config.options![opt.name]?.type,
48-
opt.name
49-
)
44+
const options = await cmdOptions.reduce<Promise<ParsedOptions>>(
45+
async (acc, opt) => {
46+
const resolvedAcc = await acc
47+
const resolvedOption = await resolveOption(
48+
interaction,
49+
cmd.config.options![opt.name]?.type,
50+
opt.name
51+
)
5052

51-
return {
52-
...resolvedAcc,
53-
[opt.name]: resolvedOption
54-
}
55-
}, Promise.resolve({}))
53+
return {
54+
...resolvedAcc,
55+
[opt.name]: resolvedOption
56+
}
57+
},
58+
Promise.resolve({})
59+
)
5660

5761
if (cmd.config.preconditions) {
5862
for (const prc of cmd.config.preconditions) {

Diff for: src/types/commands.ts

+24-140
Original file line numberDiff line numberDiff line change
@@ -136,146 +136,30 @@ export type ParsedOptionType =
136136
| URL
137137
| null
138138

139-
export type ParsedOptions<T extends OptionsDef = OptionsDef> = Record<
140-
{
141-
[K in keyof T]: T[K] extends {
142-
type: 'String'
143-
}
144-
? K
145-
: never
146-
}[keyof T],
147-
string | null
148-
> &
149-
Record<
150-
{
151-
[K in keyof T]: T[K] extends {
152-
type: 'Integer'
153-
}
154-
? K
155-
: never
156-
}[keyof T],
157-
number | null
158-
> &
159-
Record<
160-
{
161-
[K in keyof T]: T[K] extends {
162-
type: 'Boolean'
163-
}
164-
? K
165-
: never
166-
}[keyof T],
167-
boolean | null
168-
> &
169-
Record<
170-
{
171-
[K in keyof T]: T[K] extends {
172-
type: 'User'
173-
}
174-
? K
175-
: never
176-
}[keyof T],
177-
User | null
178-
> &
179-
Record<
180-
{
181-
[K in keyof T]: T[K] extends {
182-
type: 'Channel'
183-
}
184-
? K
185-
: never
186-
}[keyof T],
187-
GuildBasedChannel | APIInteractionDataResolvedChannel | null
188-
> &
189-
Record<
190-
{
191-
[K in keyof T]: T[K] extends {
192-
type: 'Role'
193-
}
194-
? K
195-
: never
196-
}[keyof T],
197-
Role | APIRole | null
198-
> &
199-
Record<
200-
{
201-
[K in keyof T]: T[K] extends {
202-
type: 'Number'
203-
}
204-
? K
205-
: never
206-
}[keyof T],
207-
number | null
208-
> &
209-
Record<
210-
{
211-
[K in keyof T]: T[K] extends {
212-
type: 'Mentionable'
213-
}
214-
? K
215-
: never
216-
}[keyof T],
217-
GuildMember | APIInteractionDataResolvedGuildMember | null
218-
> &
219-
Record<
220-
{
221-
[K in keyof T]: T[K] extends {
222-
type: 'Attachment'
223-
}
224-
? K
225-
: never
226-
}[keyof T],
227-
Attachment | null
228-
> &
229-
Record<
230-
{
231-
[K in keyof T]: T[K] extends {
232-
type: 'SubCommand'
233-
}
234-
? K
235-
: never
236-
}[keyof T],
237-
boolean | null
238-
> &
239-
Record<
240-
{
241-
[K in keyof T]: T[K] extends {
242-
type: 'Message'
243-
}
244-
? K
245-
: never
246-
}[keyof T],
247-
Message | null
248-
> &
249-
Record<
250-
{
251-
[K in keyof T]: T[K] extends {
252-
type: 'Emoji'
253-
}
254-
? K
255-
: never
256-
}[keyof T],
257-
GuildEmoji | PartialEmoji | null
258-
> &
259-
Record<
260-
{
261-
[K in keyof T]: T[K] extends {
262-
type: 'Date'
263-
}
264-
? K
265-
: never
266-
}[keyof T],
267-
Date | null
268-
> &
269-
Record<
270-
{
271-
[K in keyof T]: T[K] extends {
272-
type: 'Url'
273-
}
274-
? K
275-
: never
276-
}[keyof T],
277-
URL | null
278-
>
139+
type OptionTypeMap = {
140+
String: string
141+
Integer: number
142+
Boolean: boolean
143+
User: User
144+
Channel: GuildBasedChannel | APIInteractionDataResolvedChannel
145+
Role: Role | APIRole
146+
Number: number
147+
Mentionable: GuildMember | APIInteractionDataResolvedGuildMember
148+
Attachment: Attachment
149+
SubCommand: boolean
150+
Message: Message | null
151+
Emoji: GuildEmoji | PartialEmoji | null
152+
Date: Date | null
153+
Url: URL | null
154+
}
155+
156+
type RequiredOptionValue<T extends OptionDef> = T['required'] extends false
157+
? OptionTypeMap[T['type']] | null
158+
: OptionTypeMap[T['type']]
159+
160+
export type ParsedOptions<T extends OptionsDef = OptionsDef> = {
161+
[K in keyof T]: RequiredOptionValue<T[K]>
162+
}
279163

280164
interface CommandContext<T extends OptionsDef = OptionsDef> {
281165
options: ParsedOptions<T>

0 commit comments

Comments
 (0)