mirror of
https://github.com/discordeno/discordeno.git
synced 2026-06-16 03:18:17 +00:00
types(util): add case utility types (#683)
* types(util): add case utility types * Rename *ID to *Id
This commit is contained in:
@@ -66,9 +66,9 @@ Examples of bad PR title:
|
||||
Example:
|
||||
|
||||
```ts
|
||||
// Discordeno has utility type Camelize<T>, where T is an interface with keys in snake case.
|
||||
// Discordeno has utility type CamelCaseProps<T>, where T is an interface with keys in snake case.
|
||||
// It can be used to "generate" corresponding "Discordeno type" from "Discord type".
|
||||
// Example: export type BanOptions = Camelize<DiscordBanOptions>
|
||||
// Example: export type BanOptions = CamelCaseProps<DiscordBanOptions>
|
||||
|
||||
export interface EditMemberOptions {
|
||||
/** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */
|
||||
|
||||
@@ -5,14 +5,14 @@ export function handleApplicationCommandCreate(
|
||||
data: DiscordPayload,
|
||||
) {
|
||||
const {
|
||||
guild_id: guildID,
|
||||
application_id: applicationID,
|
||||
guild_id: guildId,
|
||||
application_id: applicationId,
|
||||
...rest
|
||||
} = data.d as ApplicationCommandEvent;
|
||||
|
||||
eventHandlers.applicationCommandCreate?.({
|
||||
...rest,
|
||||
guildID,
|
||||
applicationID,
|
||||
guildId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ import { ApplicationCommandEvent, DiscordPayload } from "../../types/mod.ts";
|
||||
|
||||
export function handleApplicationCommandDelete(data: DiscordPayload) {
|
||||
const {
|
||||
application_id: applicationID,
|
||||
guild_id: guildID,
|
||||
application_id: applicationId,
|
||||
guild_id: guildId,
|
||||
...rest
|
||||
} = data.d as ApplicationCommandEvent;
|
||||
|
||||
eventHandlers.applicationCommandDelete?.({
|
||||
...rest,
|
||||
guildID,
|
||||
applicationID,
|
||||
guildId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ import { ApplicationCommandEvent, DiscordPayload } from "../../types/mod.ts";
|
||||
|
||||
export function handleApplicationCommandUpdate(data: DiscordPayload) {
|
||||
const {
|
||||
application_id: applicationID,
|
||||
guild_id: guildID,
|
||||
application_id: applicationId,
|
||||
guild_id: guildId,
|
||||
...rest
|
||||
} = data.d as ApplicationCommandEvent;
|
||||
|
||||
eventHandlers.applicationCommandUpdate?.({
|
||||
...rest,
|
||||
guildID,
|
||||
applicationID,
|
||||
guildId,
|
||||
applicationId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -8,24 +8,24 @@ export function handleIntegrationCreate(
|
||||
data: DiscordPayload,
|
||||
) {
|
||||
const {
|
||||
guild_id: guildID,
|
||||
guild_id: guildId,
|
||||
enable_emoticons: enableEmoticons,
|
||||
expire_behavior: expireBehavior,
|
||||
expire_grace_period: expireGracePeriod,
|
||||
subscriber_count: subscriberCount,
|
||||
role_id: roleID,
|
||||
role_id: roleId,
|
||||
synced_at: syncedAt,
|
||||
...rest
|
||||
} = data.d as IntegrationCreateUpdateEvent;
|
||||
|
||||
eventHandlers.integrationCreate?.({
|
||||
...rest,
|
||||
guildID,
|
||||
guildId,
|
||||
enableEmoticons,
|
||||
expireBehavior,
|
||||
expireGracePeriod,
|
||||
syncedAt,
|
||||
subscriberCount,
|
||||
roleID,
|
||||
roleId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -3,14 +3,14 @@ import { DiscordPayload, IntegrationDeleteEvent } from "../../types/mod.ts";
|
||||
|
||||
export function handleIntegrationDelete(data: DiscordPayload) {
|
||||
const {
|
||||
guild_id: guildID,
|
||||
application_id: applicationID,
|
||||
guild_id: guildId,
|
||||
application_id: applicationId,
|
||||
...rest
|
||||
} = data.d as IntegrationDeleteEvent;
|
||||
|
||||
eventHandlers.integrationDelete?.({
|
||||
...rest,
|
||||
applicationID,
|
||||
guildID,
|
||||
applicationId,
|
||||
guildId,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -9,20 +9,20 @@ export function handleIntegrationUpdate(data: DiscordPayload) {
|
||||
enable_emoticons: enableEmoticons,
|
||||
expire_behavior: expireBehavior,
|
||||
expire_grace_period: expireGracePeriod,
|
||||
role_id: roleID,
|
||||
role_id: roleId,
|
||||
subscriber_count: subscriberCount,
|
||||
synced_at: syncedAt,
|
||||
guild_id: guildID,
|
||||
guild_id: guildId,
|
||||
...rest
|
||||
} = data.d as IntegrationCreateUpdateEvent;
|
||||
|
||||
eventHandlers.integrationUpdate?.({
|
||||
...rest,
|
||||
guildID,
|
||||
guildId,
|
||||
subscriberCount,
|
||||
enableEmoticons,
|
||||
expireGracePeriod,
|
||||
roleID,
|
||||
roleId,
|
||||
expireBehavior,
|
||||
syncedAt,
|
||||
});
|
||||
|
||||
@@ -5,10 +5,10 @@ export function handleInviteCreate(payload: DiscordPayload) {
|
||||
if (payload.t !== "INVITE_CREATE") return;
|
||||
//TODO: replace with tocamelcase
|
||||
const {
|
||||
channel_id: channelID,
|
||||
channel_id: channelId,
|
||||
created_at: createdAt,
|
||||
max_age: maxAge,
|
||||
guild_id: guildID,
|
||||
guild_id: guildId,
|
||||
target_user: targetUser,
|
||||
target_user_type: targetUserType,
|
||||
max_uses: maxUses,
|
||||
@@ -17,8 +17,8 @@ export function handleInviteCreate(payload: DiscordPayload) {
|
||||
|
||||
eventHandlers.inviteCreate?.({
|
||||
...rest,
|
||||
channelID,
|
||||
guildID,
|
||||
channelId,
|
||||
guildId,
|
||||
maxAge,
|
||||
targetUser,
|
||||
targetUserType,
|
||||
|
||||
+15
-9
@@ -25,7 +25,7 @@ import {
|
||||
PartialMessage,
|
||||
ReactionPayload,
|
||||
} from "./message.ts";
|
||||
import { Camelize } from "./util.ts";
|
||||
import { CamelCaseProps } from "./util.ts";
|
||||
|
||||
export interface BotConfig {
|
||||
token: string;
|
||||
@@ -93,15 +93,15 @@ export interface EventHandlers {
|
||||
rateLimit?: (data: RateLimitData) => unknown;
|
||||
/** Sent when a new Slash Command is created, relevant to the current user. */
|
||||
applicationCommandCreate?: (
|
||||
data: Camelize<ApplicationCommandEvent>,
|
||||
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||
) => unknown;
|
||||
/** Sent when a Slash Command relevant to the current user is updated. */
|
||||
applicationCommandUpdate?: (
|
||||
data: Camelize<ApplicationCommandEvent>,
|
||||
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||
) => unknown;
|
||||
/** Sent when a Slash Command relevant to the current user is deleted. */
|
||||
applicationCommandDelete?: (
|
||||
data: Camelize<ApplicationCommandEvent>,
|
||||
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||
) => unknown;
|
||||
/** Sent when properties about the user change. */
|
||||
botUpdate?: (user: UserPayload) => unknown;
|
||||
@@ -242,15 +242,21 @@ export interface EventHandlers {
|
||||
/** Sent when a member has passed the guild's Membership Screening requirements */
|
||||
membershipScreeningPassed?: (guild: Guild, member: Member) => unknown;
|
||||
/** Sent when an integration is created on a server such as twitch, youtube etc.. */
|
||||
integrationCreate?: (data: Camelize<IntegrationCreateUpdateEvent>) => unknown;
|
||||
integrationCreate?: (
|
||||
data: CamelCaseProps<IntegrationCreateUpdateEvent>,
|
||||
) => unknown;
|
||||
/** Sent when an integration is updated. */
|
||||
integrationUpdate?: (data: Camelize<IntegrationCreateUpdateEvent>) => unknown;
|
||||
integrationUpdate?: (
|
||||
data: CamelCaseProps<IntegrationCreateUpdateEvent>,
|
||||
) => unknown;
|
||||
/** Sent when an integration is deleted. */
|
||||
integrationDelete?: (data: Camelize<IntegrationDeleteEvent>) => undefined;
|
||||
integrationDelete?: (
|
||||
data: CamelCaseProps<IntegrationDeleteEvent>,
|
||||
) => undefined;
|
||||
/** Sent when a new invite to a channel is created. */
|
||||
inviteCreate?: (data: Camelize<InviteCreateEvent>) => unknown;
|
||||
inviteCreate?: (data: CamelCaseProps<InviteCreateEvent>) => unknown;
|
||||
/** Sent when an invite is deleted. */
|
||||
inviteDelete?: (data: Camelize<InviteDeleteEvent>) => unknown;
|
||||
inviteDelete?: (data: CamelCaseProps<InviteDeleteEvent>) => unknown;
|
||||
}
|
||||
|
||||
/** https://discord.com/developers/docs/topics/gateway#list-of-intents */
|
||||
|
||||
+116
-9
@@ -1,10 +1,117 @@
|
||||
export type CamelizeString<T extends PropertyKey> = T extends string
|
||||
? string extends T ? string
|
||||
: T extends `${infer F}_${infer R}`
|
||||
? `${F}${T extends `${infer F}_id` ? Uppercase<R>
|
||||
: Capitalize<CamelizeString<R>>}`
|
||||
: T
|
||||
: T;
|
||||
type UpperCaseCharacters =
|
||||
| "A"
|
||||
| "B"
|
||||
| "C"
|
||||
| "D"
|
||||
| "E"
|
||||
| "F"
|
||||
| "G"
|
||||
| "H"
|
||||
| "I"
|
||||
| "J"
|
||||
| "K"
|
||||
| "L"
|
||||
| "M"
|
||||
| "N"
|
||||
| "O"
|
||||
| "P"
|
||||
| "Q"
|
||||
| "R"
|
||||
| "S"
|
||||
| "T"
|
||||
| "U"
|
||||
| "V"
|
||||
| "W"
|
||||
| "X"
|
||||
| "Y"
|
||||
| "Z";
|
||||
|
||||
// deno-fmt-ignore
|
||||
export type Camelize<T> = { [K in keyof T as CamelizeString<K>]: T[K] };
|
||||
type WordSeparators = "-" | "_" | " ";
|
||||
|
||||
type SplitIncludingDelimiters<
|
||||
Source extends string,
|
||||
Delimiter extends string,
|
||||
> = Source extends "" ? []
|
||||
: Source extends `${infer FirstPart}${Delimiter}${infer SecondPart}` ? (
|
||||
Source extends `${FirstPart}${infer UsedDelimiter}${SecondPart}`
|
||||
? UsedDelimiter extends Delimiter
|
||||
? Source extends `${infer FirstPart}${UsedDelimiter}${infer SecondPart}`
|
||||
? [
|
||||
...SplitIncludingDelimiters<FirstPart, Delimiter>,
|
||||
UsedDelimiter,
|
||||
...SplitIncludingDelimiters<SecondPart, Delimiter>,
|
||||
]
|
||||
: never
|
||||
: never
|
||||
: never
|
||||
)
|
||||
: [Source];
|
||||
type StringPartToDelimiterCase<
|
||||
StringPart extends string,
|
||||
UsedWordSeparators extends string,
|
||||
UsedUpperCaseCharacters extends string,
|
||||
Delimiter extends string,
|
||||
> = StringPart extends UsedWordSeparators ? Delimiter
|
||||
: StringPart extends UsedUpperCaseCharacters
|
||||
? `${Delimiter}${Lowercase<StringPart>}`
|
||||
: StringPart;
|
||||
type StringArrayToDelimiterCase<
|
||||
Parts extends any[],
|
||||
UsedWordSeparators extends string,
|
||||
UsedUpperCaseCharacters extends string,
|
||||
Delimiter extends string,
|
||||
> = Parts extends [`${infer FirstPart}`, ...infer RemainingParts]
|
||||
? `${StringPartToDelimiterCase<
|
||||
FirstPart,
|
||||
UsedWordSeparators,
|
||||
UsedUpperCaseCharacters,
|
||||
Delimiter
|
||||
>}${StringArrayToDelimiterCase<
|
||||
RemainingParts,
|
||||
UsedWordSeparators,
|
||||
UsedUpperCaseCharacters,
|
||||
Delimiter
|
||||
>}`
|
||||
: "";
|
||||
type DelimiterCase<Value, Delimiter extends string> = Value extends string
|
||||
? StringArrayToDelimiterCase<
|
||||
SplitIncludingDelimiters<Value, WordSeparators | UpperCaseCharacters>,
|
||||
WordSeparators,
|
||||
UpperCaseCharacters,
|
||||
Delimiter
|
||||
>
|
||||
: Value;
|
||||
type InnerCamelCaseStringArray<Parts extends any[], PreviousPart> =
|
||||
Parts extends [`${infer FirstPart}`, ...infer RemainingParts]
|
||||
? FirstPart extends undefined ? ""
|
||||
: FirstPart extends ""
|
||||
? InnerCamelCaseStringArray<RemainingParts, PreviousPart>
|
||||
: `${PreviousPart extends "" ? FirstPart
|
||||
: Capitalize<FirstPart>}${InnerCamelCaseStringArray<
|
||||
RemainingParts,
|
||||
FirstPart
|
||||
>}`
|
||||
: "";
|
||||
type CamelCaseStringArray<Parts extends string[]> = Parts extends
|
||||
[`${infer FirstPart}`, ...infer RemainingParts] ? Uncapitalize<
|
||||
`${FirstPart}${InnerCamelCaseStringArray<RemainingParts, FirstPart>}`
|
||||
>
|
||||
: never;
|
||||
type Split<S extends string, D extends string> = string extends S ? string[]
|
||||
: S extends "" ? []
|
||||
: S extends `${infer T}${D}${infer U}` ? [T, ...Split<U, D>]
|
||||
: [S];
|
||||
|
||||
export type SnakeCase<Value> = DelimiterCase<Value, "_">;
|
||||
|
||||
export type CamelCase<K> = K extends string
|
||||
? CamelCaseStringArray<Split<K, WordSeparators>>
|
||||
: K;
|
||||
|
||||
export type CamelCaseProps<T> = {
|
||||
[K in keyof T as CamelCase<K>]: T[K];
|
||||
};
|
||||
|
||||
export type SnakeCaseProps<T> = {
|
||||
[K in keyof T as SnakeCase<K>]: T[K];
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user