Skip to content

Commit

Permalink
feat: createFactory, refactor: rest, toJSON
Browse files Browse the repository at this point in the history
  • Loading branch information
luisfun committed Jan 18, 2025
1 parent ffd07d0 commit 7f54696
Show file tree
Hide file tree
Showing 10 changed files with 39 additions and 36 deletions.
9 changes: 4 additions & 5 deletions src/builders/command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import type {
Locale,
RESTPostAPIApplicationCommandsJSONBody,
} from 'discord-api-types/v10'
import { toJSON } from '../utils'
import { Builder, warnBuilder } from './utils'

abstract class CommandBase<
Expand Down Expand Up @@ -75,7 +76,7 @@ export class Command extends CommandBase<RESTPostAPIApplicationCommandsJSONBody>
* @returns {this}
*/
options = (...e: (Option<any> | SubGroup | SubCommand | APIApplicationCommandOption)[]) =>
this.a({ options: e.map(option => ('toJSON' in option ? option.toJSON() : option)) })
this.a({ options: e.map(toJSON) })
/**
* @param {string | null} e
* @returns {this}
Expand Down Expand Up @@ -150,8 +151,7 @@ export class SubGroup extends CommandBase<APIApplicationCommandSubcommandGroupOp
* @param {...(SubCommand | APIApplicationCommandSubcommandOption)} e
* @returns {this}
*/
options = (...e: (SubCommand | APIApplicationCommandSubcommandOption)[]) =>
this.a({ options: e.map(option => ('toJSON' in option ? option.toJSON() : option)) })
options = (...e: (SubCommand | APIApplicationCommandSubcommandOption)[]) => this.a({ options: e.map(toJSON) })
}

export class SubCommand extends CommandBase<APIApplicationCommandSubcommandOption> {
Expand All @@ -168,8 +168,7 @@ export class SubCommand extends CommandBase<APIApplicationCommandSubcommandOptio
* @param {...(Option | APIApplicationCommandBasicOption)} e
* @returns {this}
*/
options = (...e: (Option<any> | APIApplicationCommandBasicOption)[]) =>
this.a({ options: e.map(option => ('toJSON' in option ? option.toJSON() : option)) })
options = (...e: (Option<any> | APIApplicationCommandBasicOption)[]) => this.a({ options: e.map(toJSON) })
}

type OptionType =
Expand Down
4 changes: 2 additions & 2 deletions src/builders/components.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ import type {
APIUserSelectComponent,
ChannelType,
} from 'discord-api-types/v10'
import { CUSTOM_ID_SEPARATOR } from '../utils'
import { CUSTOM_ID_SEPARATOR, toJSON } from '../utils'
import { Builder, ifThrowHasSemicolon, warnBuilder } from './utils'

/**
Expand All @@ -28,7 +28,7 @@ export class Components {
if (this.#components.length >= 5) console.warn('You can have up to 5 Action Rows per message')
this.#components.push({
type: 1,
components: e.map(component => ('toJSON' in component ? component.toJSON() : component)),
components: e.map(toJSON),
})
return this
}
Expand Down
4 changes: 2 additions & 2 deletions src/builders/modal.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import type { APIModalInteractionResponseCallbackData, APITextInputComponent } from 'discord-api-types/v10'
import { CUSTOM_ID_SEPARATOR } from '../utils'
import { CUSTOM_ID_SEPARATOR, toJSON } from '../utils'
import { Builder, ifThrowHasSemicolon } from './utils'

export class Modal {
Expand Down Expand Up @@ -34,7 +34,7 @@ export class Modal {
row = (...e: (TextInput | APITextInputComponent)[]) => {
this.#data.components.push({
type: 1,
components: e.map(component => ('toJSON' in component ? component.toJSON() : component)),
components: e.map(toJSON),
})
return this
}
Expand Down
6 changes: 3 additions & 3 deletions src/context.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import type {
FetchEventLike,
FileData,
} from './types'
import { ResponseObject, errorDev, errorSys, formData, prepareData } from './utils'
import { ResponseObject, errorDev, errorSys, formData, prepareData, toJSON } from './utils'

type ExecutionCtx = FetchEventLike | ExecutionContext | undefined

Expand Down Expand Up @@ -188,7 +188,7 @@ abstract class Context235<E extends Env, D extends APIInteraction<2 | 3 | 5>> ex
body = { data: { ...this.#flags, ...(data as CallbackData<5>) }, type }
break
case 9:
body = { data: 'toJSON' in data! ? data.toJSON() : (data as APIModalInteractionResponseCallbackData), type }
body = { data: toJSON(data as CallbackData<9>), type }
break
default: // 1, 6, 10, 12
body = { type }
Expand Down Expand Up @@ -433,7 +433,7 @@ export class AutocompleteContext<E extends Env = any> extends Context2345<E, API
* @returns {Response}
*/
resAutocomplete = (data: Autocomplete | APICommandAutocompleteInteractionResponseCallbackData) =>
new ResponseObject({ data: 'toJSON' in data ? data.toJSON() : data, type: 8 })
new ResponseObject({ data: toJSON(data), type: 8 })
}

export class CronContext<E extends Env = any> extends ContextAll<E> {
Expand Down
8 changes: 4 additions & 4 deletions src/helpers/create-factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ import type {
import { CUSTOM_ID_SEPARATOR } from '../utils'

type CreateReturn<E extends Env> = {
discord: (init: InitOptions<E>) => DiscordHono<E>
discord: (init?: InitOptions<E>) => DiscordHono<E>
command: (command: Command, handler: CommandHandler<E>) => { command: Command; handler: CommandHandler<E> }
component: (
component: Button | Select,
component: <C extends Button<any> | Select<any>>(
component: C,
handler: ComponentHandler<E>,
) => { component: Button | Select; handler: ComponentHandler<E> }
) => { component: C; handler: ComponentHandler<E> }
autocomplete: (
command: Command,
autocomplete: AutocompleteHandler<E>,
Expand Down
2 changes: 1 addition & 1 deletion src/helpers/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './register'
//export * from './create-factory'
export * from './create-factory'
export * from './retry429'
5 changes: 2 additions & 3 deletions src/helpers/register.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { RESTPostAPIApplicationCommandsJSONBody } from 'discord-api-types/v
import type { Command } from '../builders/command'
import { Rest } from '../rest/rest'
import { _applications_$_commands, _applications_$_guilds_$_commands } from '../rest/rest-path'
import { errorDev } from '../utils'
import { errorDev, toJSON } from '../utils'

/**
* [Docs](https://discord-hono.luis.fun/rest-api/register/)
Expand All @@ -22,9 +22,8 @@ export const register = async (
if (!application_id) throw errorDev('DISCORD_APPLICATION_ID')

const rest = new Rest(token)
const json = commands.map(cmd => ('toJSON' in cmd ? cmd.toJSON() : cmd))
const json = commands.map(toJSON)
let res: Response
// @ts-expect-error 何とかしたい
if (guild_id) res = await rest.put(_applications_$_guilds_$_commands, [application_id, guild_id], json)
else res = await rest.put(_applications_$_commands, [application_id], json)

Expand Down
4 changes: 4 additions & 0 deletions src/rest/rest-types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,15 @@ export type PostData<P extends PostPath> =
P extends typeof _channels_$_messages_bulkdelete ? RESTPostAPIChannelMessagesBulkDeleteJSONBody :
undefined

/*
// biome-ignore format: ternary operator
export type PostDataWithFile<P extends PostPath> =
// Receiving and Responding
P extends typeof _webhooks_$_$ ? RESTPostAPIInteractionFollowupJSONBody :
// Messages
P extends typeof _channels_$_messages ? RESTPostAPIChannelMessageJSONBody :
undefined
*/

// biome-ignore format: ternary operator
export type PostFile<P extends PostPath> = P extends
Expand Down Expand Up @@ -178,11 +180,13 @@ export type PatchData<P extends PatchPath> =
P extends typeof _channels_$_messages_$ ? RESTPatchAPIChannelMessageJSONBody :
undefined

/*
// biome-ignore format: ternary operator
export type PatchDataWithFile<P extends PatchPath> =
// Messages
P extends typeof _channels_$_messages_$ ? RESTPatchAPIChannelMessageJSONBody :
undefined
*/

export type PatchFile<P extends PatchPath> =
// Messages
Expand Down
26 changes: 12 additions & 14 deletions src/rest/rest.ts
Original file line number Diff line number Diff line change
@@ -1,15 +1,14 @@
import type { FileData } from '../types'
import { errorDev, formData } from '../utils'
import type {
DeletePath,
GetPath,
GetQuery,
GetResult,
PatchData,
PatchDataWithFile,
PatchFile,
PatchPath,
PostData,
PostDataWithFile,
PostFile,
PostPath,
PutData,
Expand All @@ -30,9 +29,12 @@ export class Rest {
path: string,
variables: string[],
method: 'GET' | 'PUT' | 'POST' | 'PATCH' | 'DELETE',
body?: FormData | string,
data?: object,
file?: FileData,
) => {
if (!token) throw errorDev('DISCORD_TOKEN')
const isJson = !file
const body = isJson ? JSON.stringify(data) : formData(data, file)
const Authorization = `Bot ${token}`
return fetch(
`https://discord.com/api/${
Expand All @@ -46,7 +48,7 @@ export class Rest {
{
method,
body,
headers: typeof body === 'string' ? { Authorization, 'content-type': 'application/json' } : { Authorization },
headers: isJson ? { Authorization, 'content-type': 'application/json' } : { Authorization },
},
)
}
Expand All @@ -58,7 +60,7 @@ export class Rest {
* @returns {Promise<{response: Response, result: any}>}
*/
get = async <P extends GetPath>(path: P, variables: Variables<P>, query?: GetQuery<P>) => {
const response = await this.#fetch(path, variables, 'GET', JSON.stringify(query))
const response = await this.#fetch(path, variables, 'GET', query)
return { response, result: (await response.json()) as GetResult<P> }
}
/**
Expand All @@ -67,29 +69,25 @@ export class Rest {
* @returns {Promise<Response>}
*/
put = <P extends PutPath>(path: P, variables: Variables<P>, data?: PutData<P>) =>
this.#fetch(path, variables, 'PUT', JSON.stringify(data))
this.#fetch(path, variables, 'PUT', data)
/**
* @param {string} path Official document path
* @param {string[]} variables Variable part of official document path
* @param data
* @param {FileData} file
* @returns {Promise<Response>}
*/
post = <P extends PostPath>(path: P, variables: Variables<P>, data: PostData<P>, file?: PostFile<P>) => {
const body = file ? formData(data as PostDataWithFile<P>, file) : JSON.stringify(data)
return this.#fetch(path, variables, 'POST', body)
}
post = <P extends PostPath>(path: P, variables: Variables<P>, data: PostData<P>, file?: PostFile<P>) =>
this.#fetch(path, variables, 'POST', data, file)
/**
* @param {string} path Official document path
* @param {string[]} variables Variable part of official document path
* @param data
* @param {FileData} file
* @returns {Promise<Response>}
*/
patch = <P extends PatchPath>(path: P, variables: Variables<P>, data: PatchData<P>, file?: PatchFile<P>) => {
const body = file ? formData(data as PatchDataWithFile<P>, file) : JSON.stringify(data)
return this.#fetch(path, variables, 'PATCH', body)
}
patch = <P extends PatchPath>(path: P, variables: Variables<P>, data: PatchData<P>, file?: PatchFile<P>) =>
this.#fetch(path, variables, 'PATCH', data, file)
/**
* @param {string} path Official document path
* @param {string[]} variables Variable part of official document path
Expand Down
7 changes: 5 additions & 2 deletions src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,12 +12,15 @@ export class ResponseObject extends Response {
}
}

// type any !!!!!!!!!
export const toJSON = (obj: object) => ('toJSON' in obj && typeof obj.toJSON === 'function' ? obj.toJSON() : obj)

export const prepareData = <T extends CustomCallbackBase>(data: CustomCallbackData<T>) => {
if (typeof data === 'string') return { content: data }
const components = data?.components
const embeds = data?.embeds
if (components) data = { ...data, components: 'toJSON' in components ? components.toJSON() : components }
if (embeds) data = { ...data, embeds: embeds.map(embed => ('toJSON' in embed ? embed.toJSON() : embed)) }
if (components) data = { ...data, components: toJSON(components) }
if (embeds) data = { ...data, embeds: embeds.map(toJSON) }
return data as T
}

Expand Down

0 comments on commit 7f54696

Please sign in to comment.