feat: adding transformer

This commit is contained in:
H01001000
2022-12-19 15:36:41 +08:00
parent b76e8def5b
commit e095e2e066
48 changed files with 743 additions and 168 deletions

View File

@@ -125,6 +125,9 @@ export function transformAuditLogEntry (
actionType: payload.action_type,
options: payload.options
? {
autoModerationRuleName: payload.options.auto_moderation_rule_name,
autoModerationRuleTriggerType:
payload.options.auto_moderation_rule_trigger_type,
deleteMemberDays: payload.options.delete_member_days
? Number(payload.options.delete_member_days)
: 0,

View File

@@ -143,6 +143,9 @@ export function transformAuditLogEntryToDiscordAuditLogEntry (
options: payload.options
? {
// respect transformer as reference than type
auto_moderation_rule_name: payload.options.autoModerationRuleName,
auto_moderation_rule_trigger_type:
payload.options.autoModerationRuleTriggerType,
delete_member_days:
payload.options.deleteMemberDays === 0
? payload.options.deleteMemberDays.toString()

View File

@@ -1,15 +1,15 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordChannel,
DiscordCreateGuildChannel,
OverwriteReadable,
SnakeToCamelCaseNested,
SortOrderTypes,
WithReason,
DiscordCreateGuildChannel
WithReason
} from '@discordeno/types'
import { ChannelTypes } from '@discordeno/types'
import { calculateBits } from '@discordeno/utils'
import { routes } from '@discordeno/constant'
import type { RestManager } from '../../restManager.js'
import { snakeToCamelCaseNested } from '../../transformer.js'
@@ -36,13 +36,13 @@ export async function createChannel (
rest: RestManager,
guildId: BigString,
options: CreateGuildChannel
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
const result = await rest.runMethod<DiscordChannel>(
rest,
'POST',
routes.GUILD_CHANNELS(guildId),
options
? {
? ({
name: options.name,
topic: options.topic,
bitrate: options.bitrate,
@@ -85,7 +85,7 @@ export async function createChannel (
: undefined
}))
: undefined
} as DiscordCreateGuildChannel
} as DiscordCreateGuildChannel)
: {}
)

View File

@@ -1,11 +1,11 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
ChannelTypes,
DiscordChannel,
DiscordModifyChannel,
OverwriteReadable,
SnakeToCamelCaseNested,
SortOrderTypes,
VideoQualityModes,
WithReason
@@ -48,7 +48,7 @@ export async function editChannel (
rest: RestManager,
channelId: BigString,
options: ModifyChannel
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
if (options.name ?? options.topic) {
const request = editChannelNameTopicQueue.get(channelId)
if (request == null) {
@@ -65,15 +65,13 @@ export async function editChannel (
request.amount = 2
request.timestamp = Date.now() + 600000
} else {
return await new Promise<SnakeToCamelCaseNested<DiscordChannel>>(
(resolve, reject) => {
// 2 have already been used add to queue
request.items.push({ channelId, options, resolve, reject })
if (editChannelProcessing) return
editChannelProcessing = true
processEditChannelQueue(rest)
}
)
return await new Promise<Camelize<DiscordChannel>>((resolve, reject) => {
// 2 have already been used add to queue
request.items.push({ channelId, options, resolve, reject })
if (editChannelProcessing) return
editChannelProcessing = true
processEditChannelQueue(rest)
})
}
}
@@ -137,7 +135,7 @@ interface EditChannelRequest {
items: Array<{
channelId: BigString
options: ModifyChannel
resolve: (channel: SnakeToCamelCaseNested<DiscordChannel>) => void
resolve: (channel: Camelize<DiscordChannel>) => void
// deno-lint-ignore no-explicit-any
reject: (error: any) => void
}>

View File

@@ -2,11 +2,11 @@ import { routes } from '@discordeno/constant'
import type {
AllowedMentions,
BigString,
Camelize,
DiscordChannel,
DiscordCreateForumPostWithMessage,
FileContent,
MessageComponents,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
@@ -35,7 +35,7 @@ export async function createForumThread (
rest: RestManager,
channelId: BigString,
options: CreateForumPostWithMessage
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
const result = await rest.runMethod<DiscordChannel>(
rest,
'POST',

View File

@@ -1,9 +1,5 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordChannel,
SnakeToCamelCaseNested
} from '@discordeno/types'
import type { BigString, Camelize, DiscordChannel } from '@discordeno/types'
import type { RestManager } from '../../restManager.js'
import { snakeToCamelCaseNested } from '../../transformer.js'
@@ -22,7 +18,7 @@ import { snakeToCamelCaseNested } from '../../transformer.js'
export async function getChannel (
rest: RestManager,
channelId: BigString
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
const result = await rest.runMethod<DiscordChannel>(
rest,
'GET',

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordInviteMetadata,
SnakeToCamelCaseNested
Camelize,
DiscordInviteMetadata
} from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { RestManager } from '../../restManager.js'
@@ -25,7 +25,7 @@ import { snakeToCamelCaseNested } from '../../transformer.js'
export async function getChannelInvites (
rest: RestManager,
channelId: BigString
): Promise<Collection<string, SnakeToCamelCaseNested<DiscordInviteMetadata>>> {
): Promise<Collection<string, Camelize<DiscordInviteMetadata>>> {
const results = await rest.runMethod<DiscordInviteMetadata[]>(
rest,
'GET',
@@ -33,10 +33,8 @@ export async function getChannelInvites (
)
return new Collection(
results.map<[string, SnakeToCamelCaseNested<DiscordInviteMetadata>]>(
(result) => {
return [result.code, snakeToCamelCaseNested(result)]
}
)
results.map<[string, Camelize<DiscordInviteMetadata>]>((result) => {
return [result.code, snakeToCamelCaseNested(result)]
})
)
}

View File

@@ -1,9 +1,5 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordChannel,
SnakeToCamelCaseNested
} from '@discordeno/types'
import type { BigString, Camelize, DiscordChannel } from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { RestManager } from '../../restManager.js'
import { snakeToCamelCaseNested } from '../../transformer.js'
@@ -23,7 +19,7 @@ import { snakeToCamelCaseNested } from '../../transformer.js'
export async function getChannels (
rest: RestManager,
guildId: BigString
): Promise<Collection<string, SnakeToCamelCaseNested<DiscordChannel>>> {
): Promise<Collection<string, Camelize<DiscordChannel>>> {
const results = await rest.runMethod<DiscordChannel[]>(
rest,
'GET',

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordStageInstance,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
@@ -25,7 +25,7 @@ import { snakeToCamelCaseNested } from '../../../transformer.js'
export async function createStageInstance (
rest: RestManager,
options: CreateStageInstance
): Promise<SnakeToCamelCaseNested<DiscordStageInstance>> {
): Promise<Camelize<DiscordStageInstance>> {
const result = await rest.runMethod<DiscordStageInstance>(
rest,
'POST',

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordStageInstance,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
@@ -26,7 +26,7 @@ export async function editStageInstance (
rest: RestManager,
channelId: BigString,
data: EditStageInstanceOptions
): Promise<SnakeToCamelCaseNested<DiscordStageInstance>> {
): Promise<Camelize<DiscordStageInstance>> {
const result = await rest.runMethod<DiscordStageInstance>(
rest,
'PATCH',

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordStageInstance,
SnakeToCamelCaseNested
Camelize,
DiscordStageInstance
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
import { snakeToCamelCaseNested } from '../../../transformer.js'
@@ -19,7 +19,7 @@ import { snakeToCamelCaseNested } from '../../../transformer.js'
export async function getStageInstance (
rest: RestManager,
channelId: BigString
): Promise<SnakeToCamelCaseNested<DiscordStageInstance>> {
): Promise<Camelize<DiscordStageInstance>> {
const result = await rest.runMethod<DiscordStageInstance>(
rest,
'GET',

View File

@@ -1,10 +1,10 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordChannel,
DiscordListActiveThreads,
DiscordThreadMember,
SnakeToCamelCaseNested
DiscordThreadMember
} from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { RestManager } from '../../../restManager.js'
@@ -51,6 +51,6 @@ export async function getActiveThreads (
}
export interface DiscordActiveThreads {
threads: Collection<string, SnakeToCamelCaseNested<DiscordChannel>>
members: Collection<string, SnakeToCamelCaseNested<DiscordThreadMember>>
threads: Collection<string, Camelize<DiscordChannel>>
members: Collection<string, Camelize<DiscordThreadMember>>
}

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordThreadMember,
SnakeToCamelCaseNested
Camelize,
DiscordThreadMember
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
import { snakeToCamelCaseNested } from '../../../transformer.js'
@@ -21,7 +21,7 @@ export async function getThreadMember (
rest: RestManager,
channelId: BigString,
userId: BigString
): Promise<SnakeToCamelCaseNested<DiscordThreadMember>> {
): Promise<Camelize<DiscordThreadMember>> {
const result = await rest.runMethod<DiscordThreadMember>(
rest,
'GET',

View File

@@ -1,8 +1,8 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordThreadMember,
SnakeToCamelCaseNested
Camelize,
DiscordThreadMember
} from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { RestManager } from '../../../restManager.js'
@@ -23,7 +23,7 @@ import { snakeToCamelCaseNested } from '../../../transformer.js'
export async function getThreadMembers (
rest: RestManager,
channelId: BigString
): Promise<Collection<string, SnakeToCamelCaseNested<DiscordThreadMember>>> {
): Promise<Collection<string, Camelize<DiscordThreadMember>>> {
const results = await rest.runMethod<DiscordThreadMember[]>(
rest,
'GET',

View File

@@ -1,9 +1,9 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordChannel,
DiscordStartThreadWithMessage,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
@@ -34,7 +34,7 @@ export async function startThreadWithMessage (
channelId: BigString,
messageId: BigString,
options: StartThreadWithMessage
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
const result = await rest.runMethod<DiscordChannel>(
rest,
'POST',

View File

@@ -1,10 +1,10 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
ChannelTypes,
DiscordChannel,
DiscordStartThreadWithoutMessage,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../../restManager.js'
@@ -29,7 +29,7 @@ export async function startThreadWithoutMessage (
rest: RestManager,
channelId: BigString,
options: StartThreadWithoutMessage
): Promise<SnakeToCamelCaseNested<DiscordChannel>> {
): Promise<Camelize<DiscordChannel>> {
const result = await rest.runMethod<DiscordChannel>(
rest,
'POST',

View File

@@ -1,9 +1,9 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
Camelize,
DiscordCreateGuildEmoji,
DiscordEmoji,
SnakeToCamelCaseNested,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../restManager.js'
@@ -29,7 +29,7 @@ export async function createEmoji (
rest: RestManager,
guildId: BigString,
options: CreateGuildEmoji
): Promise<SnakeToCamelCaseNested<DiscordEmoji>> {
): Promise<Camelize<DiscordEmoji>> {
const result = await rest.runMethod<DiscordEmoji>(
rest,
'POST',

View File

@@ -1,7 +1,9 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordEmoji, DiscordModifyGuildEmoji, SnakeToCamelCaseNested,
Camelize,
DiscordEmoji,
DiscordModifyGuildEmoji,
WithReason
} from '@discordeno/types'
import type { RestManager } from '../../restManager.js'
@@ -27,7 +29,7 @@ export async function editEmoji (
guildId: BigString,
id: BigString,
options: ModifyGuildEmoji
): Promise<SnakeToCamelCaseNested<DiscordEmoji>> {
): Promise<Camelize<DiscordEmoji>> {
const result = await rest.runMethod<DiscordEmoji>(
rest,
'PATCH',

View File

@@ -1,9 +1,5 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordEmoji,
SnakeToCamelCaseNested
} from '@discordeno/types'
import type { BigString, Camelize, DiscordEmoji } from '@discordeno/types'
import type { RestManager } from '../../restManager.js'
/**
@@ -20,7 +16,7 @@ export async function getEmoji (
rest: RestManager,
guildId: BigString,
emojiId: BigString
): Promise<SnakeToCamelCaseNested<DiscordEmoji>> {
): Promise<Camelize<DiscordEmoji>> {
const result = await rest.runMethod<DiscordEmoji>(
rest,
'GET',

View File

@@ -1,9 +1,5 @@
import { routes } from '@discordeno/constant'
import type {
BigString,
DiscordEmoji,
SnakeToCamelCaseNested
} from '@discordeno/types'
import type { BigString, Camelize, DiscordEmoji } from '@discordeno/types'
import { Collection } from '@discordeno/utils'
import type { RestManager } from '../../restManager.js'
@@ -19,7 +15,7 @@ import type { RestManager } from '../../restManager.js'
export async function getEmojis (
rest: RestManager,
guildId: BigString
): Promise<Collection<string, SnakeToCamelCaseNested<DiscordEmoji>>> {
): Promise<Collection<string, Camelize<DiscordEmoji>>> {
const results = await rest.runMethod<DiscordEmoji[]>(
rest,
'GET',
@@ -28,7 +24,7 @@ export async function getEmojis (
return new Collection(
results.map((result) => {
const emoji: SnakeToCamelCaseNested<DiscordEmoji> = {
const emoji: Camelize<DiscordEmoji> = {
id: result.id,
name: result.name,
roles: result.roles,

View File

@@ -1,10 +1,10 @@
import { routes } from '@discordeno/constant'
import type {
Camelize,
DefaultMessageNotificationLevels,
DiscordCreateGuild,
DiscordGuild,
ExplicitContentFilterLevels,
SnakeToCamelCaseNested,
SystemChannelFlags,
VerificationLevels
} from '@discordeno/types'
@@ -29,7 +29,7 @@ import type { Role } from '../../transformers/role.js'
export async function createGuild (
rest: RestManager,
options: CreateGuild
): Promise<SnakeToCamelCaseNested<DiscordGuild>> {
): Promise<Camelize<DiscordGuild>> {
const result = await rest.runMethod<DiscordGuild>(
rest,
'POST',

View File

@@ -1,6 +1,7 @@
import type {
AllowedMentions,
BigString,
Camelize,
DiscordActivity,
DiscordAllowedMentions,
DiscordApplication,
@@ -42,8 +43,7 @@ import type {
DiscordVoiceState,
DiscordWebhook,
DiscordWelcomeScreen,
GetGatewayBot,
SnakeToCamelCaseNested
GetGatewayBot
} from '@discordeno/types'
import { bigintToSnowflake, snowflakeToBigint } from '@discordeno/utils'
import type { RestManager } from './restManager.js'
@@ -142,29 +142,28 @@ import {
} from './transformers/index.js'
import type { CreateApplicationCommand, InteractionResponse } from './types.js'
export const snakeToCamelCaseNested = <T>(
object: T
): SnakeToCamelCaseNested<T> => {
export const snakeToCamelCaseNested = <T>(object: T): Camelize<T> => {
if (Array.isArray(object)) {
return object.map((element) =>
snakeToCamelCaseNested(element)
) as SnakeToCamelCaseNested<T>
) as Camelize<T>
}
if (typeof object === 'object' && object !== null) {
const obj = {} as SnakeToCamelCaseNested<T>;
const obj = {} as Camelize<T>;
(Object.keys(object) as Array<keyof T>).forEach((key) => {
(obj[
(typeof key === 'string'
? key.replace(/([-_][a-z])/gi, ($1) => {
return $1.toUpperCase().replace('-', '').replace('_', '')
})
: key) as keyof SnakeToCamelCaseNested<T>
] as SnakeToCamelCaseNested<(T & object)[keyof T]>) =
snakeToCamelCaseNested(object[key])
: key) as keyof Camelize<T>
] as Camelize<(T & object)[keyof T]>) = snakeToCamelCaseNested(
object[key]
)
})
return obj
}
return object as SnakeToCamelCaseNested<T>
return object as Camelize<T>
}
export interface Transformers {

View File

@@ -125,6 +125,9 @@ export function transformAuditLogEntry (
actionType: payload.action_type,
options: payload.options
? {
autoModerationRuleName: payload.options.auto_moderation_rule_name,
autoModerationRuleTriggerType:
payload.options.auto_moderation_rule_trigger_type,
deleteMemberDays: payload.options.delete_member_days
? Number(payload.options.delete_member_days)
: 0,

View File

@@ -143,6 +143,9 @@ export function transformAuditLogEntryToDiscordAuditLogEntry (
options: payload.options
? {
// respect transformer as reference than type
auto_moderation_rule_name: payload.options.autoModerationRuleName,
auto_moderation_rule_trigger_type:
payload.options.autoModerationRuleTriggerType,
delete_member_days:
payload.options.deleteMemberDays === 0
? payload.options.deleteMemberDays.toString()

View File

@@ -1 +1 @@
export {}
export * from './transformers/index.js'

View File

@@ -0,0 +1,45 @@
import type { Camelize, DiscordActivity } from '@discordeno/types'
export function c1amelize1Activity (
payload: DiscordActivity
): Camelize<DiscordActivity> {
return {
name: payload.name,
type: payload.type,
url: payload.url,
createdAt: payload.created_at,
timestamps: payload.timestamps && {
start: payload.timestamps.start,
end: payload.timestamps.end
},
applicationId: payload.application_id,
details: payload.details,
state: payload.state,
emoji: payload.emoji && {
name: payload.emoji.name,
id: payload.emoji.id,
animated: payload.emoji.animated
},
party: payload.party && {
id: payload.party.id,
size: payload.party.size
},
assets: payload.assets && {
largeImage: payload.assets.large_image,
largeText: payload.assets.large_text,
smallImage: payload.assets.small_image,
smallText: payload.assets.small_text
},
secrets: payload.secrets && {
join: payload.secrets.join,
spectate: payload.secrets.spectate,
match: payload.secrets.match
},
instance: payload.instance,
flags: payload.flags,
buttons: payload.buttons?.map((button) => ({
label: button.label,
url: button.url
}))
}
}

View File

@@ -0,0 +1,38 @@
import type {
Camelize,
DiscordApplication,
DiscordUser
} from '@discordeno/types'
import { c1amelize1User } from './member.js'
import { c1amelize1Team } from './team.js'
export function c1amelize1Application (
payload: DiscordApplication
): Camelize<DiscordApplication> {
return {
id: payload.id,
name: payload.name,
icon: payload.icon,
description: payload.description,
rpcOrigins: payload.rpc_origins,
botPublic: payload.bot_public,
botRequireCodeGrant: payload.bot_require_code_grant,
termsOfServiceUrl: payload.terms_of_service_url,
privacyPolicyUrl: payload.privacy_policy_url,
owner: payload.owner && c1amelize1User(payload.owner as DiscordUser),
verifyKey: payload.verify_key,
team: payload.team && c1amelize1Team(payload.team),
guildId: payload.guild_id,
primarySkuId: payload.primary_sku_id,
slug: payload.slug,
coverImage: payload.cover_image,
flags: payload.flags,
tags: payload.tags,
installParams: payload.install_params && {
scopes: payload.install_params.scopes,
permissions: payload.install_params.permissions
},
customInstallUrl: payload.custom_install_url,
roleConnectionsVerificationUrl: payload.role_connections_verification_url
}
}

View File

@@ -0,0 +1,24 @@
import type { Camelize, DiscordApplicationCommand } from '@discordeno/types'
import { c1amelize1ApplicationCommandOption } from './applicationCommandOption.js'
export function c1amelize1ApplicationCommand (
payload: DiscordApplicationCommand
): Camelize<DiscordApplicationCommand> {
return {
id: payload.id,
type: payload.type,
applicationId: payload.application_id,
guildId: payload.guild_id,
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
description: payload.description,
descriptionLocalizations: payload.description_localizations ?? undefined,
options: payload.options?.map((option) =>
c1amelize1ApplicationCommandOption(option)
),
defaultMemberPermissions: payload.default_member_permissions,
dmPermission: payload.dm_permission ?? false,
nsfw: payload.nsfw ?? false,
version: payload.version
}
}

View File

@@ -0,0 +1,30 @@
import type {
Camelize,
DiscordApplicationCommandOption
} from '@discordeno/types'
import { c1amelize1ApplicationCommandOptionChoice } from './applicationCommandOptionChoice.js'
export function c1amelize1ApplicationCommandOption (
payload: DiscordApplicationCommandOption
): Camelize<DiscordApplicationCommandOption> {
return {
type: payload.type,
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
description: payload.description,
descriptionLocalizations: payload.description_localizations ?? undefined,
required: payload.required ?? false,
choices: payload.choices?.map((choice) =>
c1amelize1ApplicationCommandOptionChoice(choice)
),
autocomplete: payload.autocomplete,
channelTypes: payload.channel_types,
minValue: payload.min_value,
maxValue: payload.max_value,
minLength: payload.min_length,
maxLength: payload.max_length,
options: payload.options?.map((option) =>
c1amelize1ApplicationCommandOption(option)
)
}
}

View File

@@ -0,0 +1,14 @@
import type {
Camelize,
DiscordApplicationCommandOptionChoice
} from '@discordeno/types'
export function c1amelize1ApplicationCommandOptionChoice (
payload: DiscordApplicationCommandOptionChoice
): Camelize<DiscordApplicationCommandOptionChoice> {
return {
name: payload.name,
nameLocalizations: payload.name_localizations ?? undefined,
value: payload.value
}
}

View File

@@ -0,0 +1,19 @@
import type {
Camelize,
DiscordGuildApplicationCommandPermissions
} from '@discordeno/types'
export function c1amelize1ApplicationCommandPermission (
payload: DiscordGuildApplicationCommandPermissions
): Camelize<DiscordGuildApplicationCommandPermissions> {
return {
id: payload.id,
applicationId: payload.application_id,
guildId: payload.guild_id,
permissions: payload.permissions.map((perm) => ({
id: perm.id,
type: perm.type,
permission: perm.permission
}))
}
}

View File

@@ -0,0 +1,18 @@
import type { Camelize, DiscordAttachment } from '@discordeno/types'
export function c1amelize1Attachment (
payload: DiscordAttachment
): Camelize<DiscordAttachment> {
return {
id: payload.id,
filename: payload.filename,
description: payload.description,
contentType: payload.content_type,
size: payload.size,
url: payload.url,
proxyUrl: payload.proxy_url,
height: payload.height ?? undefined,
width: payload.width ?? undefined,
ephemeral: payload.ephemeral
}
}

View File

@@ -0,0 +1,28 @@
import type {
Camelize,
DiscordAutoModerationActionExecution
} from '@discordeno/types'
export function c1amelize1AutoModerationActionExecution (
payload: DiscordAutoModerationActionExecution
): Camelize<DiscordAutoModerationActionExecution> {
return {
guildId: payload.guild_id,
action: {
type: payload.action.type,
metadata: {
durationSeconds: payload.action.metadata.duration_seconds,
channelId: payload.action.metadata.channel_id
}
},
ruleId: payload.rule_id,
ruleTriggerType: payload.rule_trigger_type,
userId: payload.user_id,
channelId: payload.channel_id,
messageId: payload.message_id,
alertSystemMessageId: payload.alert_system_message_id,
content: payload.content,
matchedKeyword: payload.matched_keyword ?? '',
matchedContent: payload.matched_content ?? ''
}
}

View File

@@ -0,0 +1,30 @@
import type { Camelize, DiscordAutoModerationRule } from '@discordeno/types'
export function c1amelize1AutoModerationRule (
payload: DiscordAutoModerationRule
): Camelize<DiscordAutoModerationRule> {
return {
id: payload.id,
guildId: payload.guild_id,
name: payload.name,
creatorId: payload.creator_id,
eventType: payload.event_type,
triggerType: payload.trigger_type,
triggerMetadata: payload.trigger_metadata && {
keywordFilter: payload.trigger_metadata.keyword_filter,
presets: payload.trigger_metadata.presets,
allowList: payload.trigger_metadata.allow_list,
mentionTotalLimit: payload.trigger_metadata.mention_total_limit
},
actions: payload.actions.map((action) => ({
type: action.type,
metadata: action.metadata && {
channelId: action.metadata.channel_id,
durationSeconds: action.metadata.duration_seconds
}
})),
enabled: payload.enabled,
exemptRoles: payload.exempt_roles,
exemptChannels: payload.exempt_channels
}
}

View File

@@ -0,0 +1,65 @@
import type { Camelize, DiscordChannel } from '@discordeno/types'
import { c1amelize1User } from './member.js'
export function c1amelize1Channel (
payload: DiscordChannel
): Camelize<DiscordChannel> {
return {
id: payload.id,
type: payload.type,
guildId: payload.guild_id,
position: payload.position,
permissionOverwrites: payload.permission_overwrites,
name: payload.name,
topic: payload.topic ?? undefined,
nsfw: payload.nsfw,
lastMessageId: payload.last_message_id,
bitrate: payload.bitrate,
userLimit: payload.user_limit,
rateLimitPerUser: payload.rate_limit_per_user,
recipients: payload.recipients?.map((user) => c1amelize1User(user)),
icon: payload.icon,
ownerId: payload.owner_id,
applicationId: payload.application_id,
parentId: payload.parent_id,
lastPinTimestamp: payload.last_pin_timestamp,
rtcRegion: payload.rtc_region ?? undefined,
videoQualityMode: payload.video_quality_mode,
messageCount: payload.message_count,
memberCount: payload.member_count,
threadMetadata: payload.thread_metadata && {
archived: payload.thread_metadata.archived,
autoArchiveDuration: payload.thread_metadata.auto_archive_duration,
archiveTimestamp: payload.thread_metadata.archive_timestamp,
locked: payload.thread_metadata.locked,
invitable: payload.thread_metadata.invitable,
createTimestamp: payload.thread_metadata.create_timestamp
},
member: payload.member && {
flags: payload.member.flags,
id: payload.member.id,
userId: payload.member.user_id,
joinTimestamp: payload.member.join_timestamp
},
defaultAutoArchiveDuration: payload.default_auto_archive_duration,
permissions: payload.permissions,
flags: payload.flags,
totalMessageSent: payload.total_message_sent,
availableTags: payload.available_tags.map((tag) => ({
id: tag.id,
name: tag.name,
moderated: tag.moderated,
emojiId: tag.emoji_id,
emojiName: tag.name
})),
appliedTags: payload.applied_tags,
defaultReactionEmoji: payload.default_reaction_emoji && {
emojiId: payload.default_reaction_emoji.emoji_id,
emojiName: payload.default_reaction_emoji.emoji_name
},
defaultThreadRateLimitPerUser: payload.default_thread_rate_limit_per_user,
defaultSortOrder: payload.default_sort_order,
defaultForumLayout: payload.default_forum_layout,
newlyCreated: payload.newly_created
}
}

View File

@@ -0,0 +1,15 @@
import type { Camelize, DiscordEmoji } from '@discordeno/types'
import { c1amelize1User } from './member.js'
export function c1amelize1Emoji (payload: DiscordEmoji): Camelize<DiscordEmoji> {
return {
id: payload.id,
name: payload.name,
roles: payload.roles,
user: payload.user && c1amelize1User(payload.user),
requireColons: payload.require_colons,
managed: payload.managed,
animated: payload.animated,
available: payload.animated
}
}

View File

@@ -0,0 +1,16 @@
import type { Camelize, DiscordGetGatewayBot } from '@discordeno/types'
export function c1amelize1GatewayBot (
payload: DiscordGetGatewayBot
): Camelize<DiscordGetGatewayBot> {
return {
url: payload.url,
shards: payload.shards,
sessionStartLimit: {
total: payload.session_start_limit.total,
remaining: payload.session_start_limit.remaining,
resetAfter: payload.session_start_limit.reset_after,
maxConcurrency: payload.session_start_limit.max_concurrency
}
}
}

View File

@@ -0,0 +1,48 @@
import type { Camelize, DiscordGuild } from '@discordeno/types'
import { c1amelize1Role } from './role.js'
import { c1amelize1Sticker } from './sticker.js'
import { c1amelize1WelcomeScreen } from './welcomeScreen.js'
export function c1amelize1Guild (payload: DiscordGuild): Camelize<DiscordGuild> {
return {
id: payload.id,
name: payload.name,
icon: payload.icon,
iconHash: payload.icon_hash,
splash: payload.splash,
discoverySplash: payload.discovery_splash,
ownerId: payload.owner_id,
afkChannelId: payload.afk_channel_id,
afkTimeout: payload.afk_timeout,
widgetEnabled: payload.widget_enabled,
widgetChannelId: payload.widget_channel_id,
verificationLevel: payload.verification_level,
defaultMessageNotifications: payload.default_message_notifications,
explicitContentFilter: payload.explicit_content_filter,
roles: payload.roles.map((role) => c1amelize1Role(role)),
emojis: payload.emojis,
features: payload.features,
mfaLevel: payload.mfa_level,
applicationId: payload.application_id,
systemChannelId: payload.system_channel_id,
systemChannelFlags: payload.system_channel_flags,
rulesChannelId: payload.rules_channel_id,
maxPresences: payload.max_presences,
maxMembers: payload.max_members,
vanityUrlCode: payload.vanity_url_code,
description: payload.description,
banner: payload.banner,
premiumTier: payload.premium_tier,
premiumSubscriptionCount: payload.premium_subscription_count,
preferredLocale: payload.preferred_locale,
publicUpdatesChannelId: payload.public_updates_channel_id,
maxVideoChannelUsers: payload.max_video_channel_users,
approximateMemberCount: payload.approximate_member_count,
approximatePresenceCount: payload.approximate_presence_count,
welcomeScreen:
payload.welcome_screen && c1amelize1WelcomeScreen(payload.welcome_screen),
nsfwLevel: payload.nsfw_level,
stickers: payload.stickers?.map((sticker) => c1amelize1Sticker(sticker)),
premiumProgressBarEnabled: payload.premium_progress_bar_enabled
}
}

View File

@@ -0,0 +1,20 @@
export * from './activity.js'
export * from './application.js'
export * from './applicationCommand.js'
export * from './applicationCommandOption.js'
export * from './applicationCommandOptionChoice.js'
export * from './applicationCommandPermission.js'
export * from './attachment.js'
export * from './automodActionExecution.js'
export * from './automodRule.js'
export * from './channel.js'
export * from './emoji.js'
export * from './gatewayBot.js'
export * from './guild.js'
export * from './member.js'
export * from './role.js'
export * from './sticker.js'
export * from './team.js'
export * from './welcomeScreen.js'
export * from './widget.js'
export * from './widgetSettings.js'

View File

@@ -0,0 +1,39 @@
import type { Camelize, DiscordMember, DiscordUser } from '@discordeno/types'
export function c1amelize1User (payload: DiscordUser): Camelize<DiscordUser> {
return {
id: payload.id,
username: payload.username,
discriminator: payload.discriminator,
avatar: payload.avatar,
bot: payload.bot,
system: payload.system,
mfaEnabled: payload.mfa_enabled,
banner: payload.banner,
accentColor: payload.accent_color,
locale: payload.locale,
verified: payload.verified,
email: payload.email,
flags: payload.flags,
premiumType: payload.premium_type,
publicFlags: payload.public_flags
}
}
export function c1amelize1Member (
payload: DiscordMember
): Camelize<DiscordMember> {
return {
user: payload.user && c1amelize1User(payload.user),
nick: payload.nick,
avatar: payload.avatar,
roles: payload.roles,
joinedAt: payload.joined_at,
premiumSince: payload.premium_since,
deaf: payload.deaf,
mute: payload.mute,
pending: payload.pending,
permissions: payload.permissions,
communicationDisabledUntil: payload.communication_disabled_until
}
}

View File

@@ -0,0 +1,21 @@
import type { Camelize, DiscordRole } from '@discordeno/types'
export function c1amelize1Role (payload: DiscordRole): Camelize<DiscordRole> {
return {
id: payload.id,
name: payload.name,
color: payload.color,
hoist: payload.hoist,
icon: payload.icon,
unicodeEmoji: payload.unicode_emoji,
position: payload.position,
permissions: payload.permissions,
managed: payload.managed,
mentionable: payload.mentionable,
tags: payload.tags && {
botId: payload.tags.bot_id,
integrationId: payload.tags.integration_id,
premiumSubscriber: payload.tags.premium_subscriber
}
}
}

View File

@@ -0,0 +1,38 @@
import type {
Camelize,
DiscordSticker,
DiscordStickerPack
} from '@discordeno/types'
import { c1amelize1User } from './member.js'
export function c1amelize1Sticker (
payload: DiscordSticker
): Camelize<DiscordSticker> {
return {
id: payload.id,
packId: payload.pack_id,
name: payload.name,
description: payload.description,
tags: payload.tags,
type: payload.type,
formatType: payload.format_type,
available: payload.available,
guildId: payload.guild_id,
user: payload.user && c1amelize1User(payload.user),
sortValue: payload.sort_value
}
}
export function c1amelize1StickerPack (
payload: DiscordStickerPack
): Camelize<DiscordStickerPack> {
return {
id: payload.id,
stickers: payload.stickers.map((sticker) => c1amelize1Sticker(sticker)),
name: payload.name,
skuId: payload.sku_id,
coverStickerId: payload.cover_sticker_id,
description: payload.description,
bannerAssetId: payload.banner_asset_id
}
}

View File

@@ -0,0 +1,17 @@
import type { Camelize, DiscordTeam } from '@discordeno/types'
import { c1amelize1User } from './member.js'
export function c1amelize1Team (payload: DiscordTeam): Camelize<DiscordTeam> {
return {
icon: payload.icon,
id: payload.id,
members: payload.members.map((member) => ({
membershipState: member.membership_state,
permissions: member.permissions,
teamId: payload.id,
user: c1amelize1User(member.user)
})),
name: payload.name,
ownerUserId: payload.owner_user_id
}
}

View File

@@ -0,0 +1,15 @@
import type { Camelize, DiscordWelcomeScreen } from '@discordeno/types'
export function c1amelize1WelcomeScreen (
payload: DiscordWelcomeScreen
): Camelize<DiscordWelcomeScreen> {
return {
description: payload.description,
welcomeChannels: payload.welcome_channels.map((welcomeScreenChannel) => ({
channelId: welcomeScreenChannel.channel_id,
description: welcomeScreenChannel.description,
emojiId: welcomeScreenChannel.emoji_id,
emojiName: welcomeScreenChannel.emoji_name
}))
}
}

View File

@@ -0,0 +1,25 @@
import type { Camelize, DiscordGuildWidget } from '@discordeno/types'
export function c1amelize1Widget (
payload: DiscordGuildWidget
): Camelize<DiscordGuildWidget> {
return {
id: payload.id,
name: payload.name,
instantInvite: payload.instant_invite,
channels: payload.channels.map((channel) => ({
id: channel.id,
name: channel.name,
position: channel.position
})),
members: payload.members.map((member) => ({
id: member.id,
username: member.username,
discriminator: member.discriminator,
avatar: member.avatar,
status: member.status,
avatarUrl: member.avatar_url
})),
presenceCount: payload.presence_count
}
}

View File

@@ -0,0 +1,10 @@
import type { Camelize, DiscordGuildWidgetSettings } from '@discordeno/types'
export function c1amelize1WidgetSettings (
payload: DiscordGuildWidgetSettings
): Camelize<DiscordGuildWidgetSettings> {
return {
enabled: payload.enabled,
channelId: payload.channel_id
}
}

View File

@@ -248,7 +248,7 @@ export interface DiscordMember {
communication_disabled_until?: string | null
}
/** https://discord.com/developers/docs/topics/oauth2#application-object */
/** https://discord.com/developers/docs/resources/application#application-object */
export interface DiscordApplication {
/** The name of the app */
name: string
@@ -291,6 +291,8 @@ export interface DiscordApplication {
install_params?: DiscordInstallParams
/** the application's default custom authorization link, if enabled */
custom_install_url?: string
/** the application's role connection verification entry point, which when configured will render the app as a verification method in the guild role verification configuration */
role_connections_verification_url?: string
}
/** https://discord.com/developers/docs/topics/teams#data-models-team-object */
@@ -728,43 +730,34 @@ export interface DiscordVoiceState {
/** https://discord.com/developers/docs/resources/channel#channel-object */
export interface DiscordChannel {
/** The id of the channel */
id: string
/** The type of channel */
type: ChannelTypes
/** The flags of the channel */
flags?: ChannelFlags
/** The id of the guild */
guild_id?: string
/** Sorting position of the channel */
position?: number
/** Explicit permission overwrites for members and roles */
permission_overwrites?: DiscordOverwrite[]
/** The name of the channel (1-100 characters) */
name?: string
/** The channel topic (0-4096 characters for GUILD_FORUM channels, 0-1024 characters for all others) */
topic?: string | null
/** Whether the channel is nsfw */
nsfw?: boolean
/** The id of the last message sent in this channel (may not point to an existing or valid message) */
last_message_id?: string | null
/** The bitrate (in bits) of the voice or stage channel */
bitrate?: number
/** The user limit of the voice or stage channel */
user_limit?: number
/** Amount of seconds a user has to wait before sending another message (0-21600); bots, as well as users with the permission `manage_messages` or `manage_channel`, are unaffected */
rate_limit_per_user?: number
/** Voice region id for the voice or stage channel, automatic when set to null */
rtc_region?: string | null
/** The camera video quality mode of the voice channel, 1 when not present */
video_quality_mode?: VideoQualityModes
/** An approximate count of messages in a thread, stops counting at 50 */
message_count?: number
/** An approximate count of users in a thread, stops counting at 50 */
member_count?: number
/** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */
default_auto_archive_duration?: number
/** The id of the channel */
id: string
/** The id of the guild */
guild_id?: string
/** Explicit permission overwrites for members and roles */
permission_overwrites?: DiscordOverwrite[]
/** Whether the channel is nsfw */
nsfw?: boolean
/** The id of the last message sent in this channel (may not point to an existing or valid message) */
last_message_id?: string | null
/** the recipients of the DM */
recipients?: DiscordUser[]
/** icon hash of the group DM */
icon?: string
/** Id of the creator of the thread */
owner_id?: string
/** Application id of the group DM creator if it is bot-created */
@@ -773,14 +766,26 @@ export interface DiscordChannel {
parent_id?: string | null
/** When the last pinned message was pinned. This may be null in events such as GUILD_CREATE when a message is not pinned. */
last_pin_timestamp?: string | null
/** Voice region id for the voice or stage channel, automatic when set to null */
rtc_region?: string | null
/** The camera video quality mode of the voice channel, 1 when not present */
video_quality_mode?: VideoQualityModes
/** An approximate count of messages in a thread, stops counting at 50 */
message_count?: number
/** An approximate count of users in a thread, stops counting at 50 */
member_count?: number
/** Thread-specific fields not needed by other channels */
thread_metadata?: DiscordThreadMetadata
/** Thread member object for the current user, if they have joined the thread, only included on certain API endpoints */
member?: DiscordThreadMember
/** Default duration for newly created threads, in minutes, to automatically archive the thread after recent activity, can be set to: 60, 1440, 4320, 10080 */
default_auto_archive_duration?: number
/** computed permissions for the invoking user in the channel, including overwrites, only included when part of the resolved data received on a application command interaction */
permissions?: string
/** When a thread is created this will be true on that channel payload for the thread. */
newly_created?: boolean
/** The flags of the channel */
flags?: ChannelFlags
/** number of messages ever sent in a thread, it's similar to `message_count` on message creation, but will not decrement the number when a message is deleted */
total_message_sent?: number
/** The set of tags that can be used in a GUILD_FORUM channel */
available_tags: DiscordForumTag[]
/** The IDs of the set of tags that have been applied to a thread in a GUILD_FORUM channel */
@@ -791,6 +796,10 @@ export interface DiscordChannel {
default_thread_rate_limit_per_user: number
/** the default sort order type used to order posts in GUILD_FORUM channels. Defaults to null, which indicates a preferred sort order hasn't been set by a channel admin */
default_sort_order?: SortOrderTypes | null
/** the default forum layout view used to display posts in `GUILD_FORUM` channels. Defaults to `0`, which indicates a layout view has not been set by a channel admin */
default_forum_layout?: number
/** When a thread is created this will be true on that channel payload for the thread. */
newly_created?: boolean
}
/** https://discord.com/developers/docs/topics/gateway#presence-update */
@@ -880,7 +889,7 @@ export interface DiscordThreadMemberGuildCreate {
join_timestamp: string
}
/** https://discord.com/developers/docs/topics/gateway#activity-object */
/** https://discord.com/developers/docs/topics/gateway-events#activity-object */
export interface DiscordActivity {
/** The activity's name */
name: string
@@ -1474,6 +1483,7 @@ export interface DiscordAuditLog {
application_commands: DiscordApplicationCommand[]
}
/** https://discord.com/developers/docs/resources/auto-moderation#auto-moderation-rule-object */
export interface DiscordAutoModerationRule {
/** The id of this rule */
id: string
@@ -1556,6 +1566,7 @@ export interface DiscordAutoModerationActionMetadata {
duration_seconds?: number
}
/** https://discord.com/developers/docs/topics/gateway-events#auto-moderation-action-execution-auto-moderation-action-execution-event-fields */
export interface DiscordAutoModerationActionExecution {
/** The id of the guild */
guild_id: string
@@ -1697,35 +1708,41 @@ export type DiscordAuditLogChange =
/** https://discord.com/developers/docs/resources/audit-log#audit-log-entry-object-optional-audit-entry-info */
export interface DiscordOptionalAuditEntryInfo {
/**
* Number of days after which inactive members were kicked.
* ID of the app whose permissions were targeted.
*
* Event types: `MEMBER_PRUNE`
* Event types: `APPLICATION_COMMAND_PERMISSION_UPDATE`
*/
delete_member_days: string
application_id: string
/**
* Number of members removed by the prune.
* Name of the Auto Moderation rule that was triggered.
*
* Event types: `MEMBER_PRUNE`
* Event types: `AUTO_MODERATION_BLOCK_MESSAGE`, `AUTO_MODERATION_FLAG_TO_CHANNEL`, `AUTO_MODERATION_USER_COMMUNICATION_DISABLED`
*/
members_removed: string
auto_moderation_rule_name: string
/**
* Trigger type of the Auto Moderation rule that was triggered.
*
* Event types: `AUTO_MODERATION_BLOCK_MESSAGE`, `AUTO_MODERATION_FLAG_TO_CHANNEL`, `AUTO_MODERATION_USER_COMMUNICATION_DISABLED`
*/
auto_moderation_rule_trigger_type: string
/**
* Channel in which the entities were targeted.
*
* Event types: `MEMBER_MOVE`, `MESSAGE_PIN`, `MESSAGE_UNPIN`, `MESSAGE_DELETE`, `STAGE_INSTANCE_CREATE`, `STAGE_INSTANCE_UPDATE`, `STAGE_INSTANCE_DELETE`
*/
channel_id: string
/**
* ID of the message that was targeted.
*
* Event types: `MESSAGE_PIN`, `MESSAGE_UNPIN`, `STAGE_INSTANCE_CREATE`, `STAGE_INSTANCE_UPDATE`, `STAGE_INSTANCE_DELETE`
*/
message_id: string
/**
* Number of entities that were targeted.
*
* Event types: `MESSAGE_DELETE`, `MESSAGE_BULK_DELETE`, `MEMBER_DISCONNECT`, `MEMBER_MOVE`
*/
count: string
/**
* Number of days after which inactive members were kicked.
*
* Event types: `MEMBER_PRUNE`
*/
delete_member_days: string
/**
* ID of the overwritten entity.
*
@@ -1733,11 +1750,17 @@ export interface DiscordOptionalAuditEntryInfo {
*/
id: string
/**
* Type of overwritten entity - "0", for "role", or "1" for "member".
* Number of members removed by the prune.
*
* Event types: `CHANNEL_OVERWRITE_CREATE`, `CHANNEL_OVERWRITE_UPDATE`, `CHANNEL_OVERWRITE_DELETE`
* Event types: `MEMBER_PRUNE`
*/
type: string
members_removed: string
/**
* ID of the message that was targeted.
*
* Event types: `MESSAGE_PIN`, `MESSAGE_UNPIN`, `STAGE_INSTANCE_CREATE`, `STAGE_INSTANCE_UPDATE`, `STAGE_INSTANCE_DELETE`
*/
message_id: string
/**
* Name of the role if type is "0" (not present if type is "1").
*
@@ -1745,11 +1768,11 @@ export interface DiscordOptionalAuditEntryInfo {
*/
role_name: string
/**
* ID of the app whose permissions were targeted.
* Type of overwritten entity - "0", for "role", or "1" for "member".
*
* Event types: `APPLICATION_COMMAND_PERMISSION_UPDATE`
* Event types: `CHANNEL_OVERWRITE_CREATE`, `CHANNEL_OVERWRITE_UPDATE`, `CHANNEL_OVERWRITE_DELETE`
*/
application_id: string
type: string
}
export interface DiscordScheduledEvent {
@@ -1901,6 +1924,8 @@ export interface DiscordCreateApplicationCommand {
default_member_permissions?: string | null
/** Indicates whether the command is available in DMs with the app, only for globally-scoped commands. By default, commands are visible. */
dm_permission?: boolean
/** Indicates whether the command is age-restricted, defaults to false */
nsfw?: boolean
/** Auto incrementing version identifier updated during substantial record changes */
version?: string
}
@@ -1947,7 +1972,7 @@ export interface DiscordApplicationCommandOption {
max_length?: number
}
/** https://discord.com/developers/docs/interactions/application-commands#application-command-object-application-command-option-choice-structure */
/** https://discord.com/developers/docs/interactions/application-commands#application-command-permissions-object */
export interface DiscordApplicationCommandOptionChoice {
/** 1-100 character choice name */
name: string

View File

@@ -1439,20 +1439,17 @@ U[keyof U]
export type MakeRequired<T, K extends keyof T> = T & { [P in K]-?: T[P] }
// THANK YOU YUI FOR SHARING THIS!
export type CamelCase<S extends string> =
S extends `${infer P1}_${infer P2}${infer P3}`
? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
: Lowercase<S>
export type Camelize<T> = {
[K in keyof T as CamelCase<string & K>]: T[K] extends Array<infer U>
? U extends {}
? Array<Camelize<U>>
: T[K]
: T[K] extends {}
? Camelize<T[K]>
: never;
}
export type CamelCase<S extends string> = S extends `${infer T}_${infer U}`
? `${T}${Capitalize<CamelCase<U>>}`
: S
export type Camelize<T> = T extends any[]
? Array<Camelize<T[number]>>
: T extends object
? {
[K in keyof T as CamelCase<K & string>]: Camelize<T[K]>;
}
: T
/** Non object primitives */
export type Primitive =
@@ -1544,18 +1541,3 @@ export type PickPartial<T, K extends keyof T> = {
export type OmitFirstFnArg<F> = F extends (x: any, ...args: infer P) => infer R
? (...args: P) => R
: never
export type SnakeToCamelCase<S extends string> =
S extends `${infer T}_${infer U}`
? `${T}${Capitalize<SnakeToCamelCase<U>>}`
: S
export type SnakeToCamelCaseNested<T> = T extends any[]
? Array<SnakeToCamelCaseNested<T[number]>>
: T extends object
? {
[K in keyof T as SnakeToCamelCase<K & string>]: SnakeToCamelCaseNested<
T[K]
>;
}
: T