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:
|
Example:
|
||||||
|
|
||||||
```ts
|
```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".
|
// 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 {
|
export interface EditMemberOptions {
|
||||||
/** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */
|
/** Value to set users nickname to. Requires MANAGE_NICKNAMES permission. */
|
||||||
|
|||||||
@@ -5,14 +5,14 @@ export function handleApplicationCommandCreate(
|
|||||||
data: DiscordPayload,
|
data: DiscordPayload,
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
application_id: applicationID,
|
application_id: applicationId,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as ApplicationCommandEvent;
|
} = data.d as ApplicationCommandEvent;
|
||||||
|
|
||||||
eventHandlers.applicationCommandCreate?.({
|
eventHandlers.applicationCommandCreate?.({
|
||||||
...rest,
|
...rest,
|
||||||
guildID,
|
guildId,
|
||||||
applicationID,
|
applicationId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { ApplicationCommandEvent, DiscordPayload } from "../../types/mod.ts";
|
|||||||
|
|
||||||
export function handleApplicationCommandDelete(data: DiscordPayload) {
|
export function handleApplicationCommandDelete(data: DiscordPayload) {
|
||||||
const {
|
const {
|
||||||
application_id: applicationID,
|
application_id: applicationId,
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as ApplicationCommandEvent;
|
} = data.d as ApplicationCommandEvent;
|
||||||
|
|
||||||
eventHandlers.applicationCommandDelete?.({
|
eventHandlers.applicationCommandDelete?.({
|
||||||
...rest,
|
...rest,
|
||||||
guildID,
|
guildId,
|
||||||
applicationID,
|
applicationId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { ApplicationCommandEvent, DiscordPayload } from "../../types/mod.ts";
|
|||||||
|
|
||||||
export function handleApplicationCommandUpdate(data: DiscordPayload) {
|
export function handleApplicationCommandUpdate(data: DiscordPayload) {
|
||||||
const {
|
const {
|
||||||
application_id: applicationID,
|
application_id: applicationId,
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as ApplicationCommandEvent;
|
} = data.d as ApplicationCommandEvent;
|
||||||
|
|
||||||
eventHandlers.applicationCommandUpdate?.({
|
eventHandlers.applicationCommandUpdate?.({
|
||||||
...rest,
|
...rest,
|
||||||
guildID,
|
guildId,
|
||||||
applicationID,
|
applicationId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,24 +8,24 @@ export function handleIntegrationCreate(
|
|||||||
data: DiscordPayload,
|
data: DiscordPayload,
|
||||||
) {
|
) {
|
||||||
const {
|
const {
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
enable_emoticons: enableEmoticons,
|
enable_emoticons: enableEmoticons,
|
||||||
expire_behavior: expireBehavior,
|
expire_behavior: expireBehavior,
|
||||||
expire_grace_period: expireGracePeriod,
|
expire_grace_period: expireGracePeriod,
|
||||||
subscriber_count: subscriberCount,
|
subscriber_count: subscriberCount,
|
||||||
role_id: roleID,
|
role_id: roleId,
|
||||||
synced_at: syncedAt,
|
synced_at: syncedAt,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as IntegrationCreateUpdateEvent;
|
} = data.d as IntegrationCreateUpdateEvent;
|
||||||
|
|
||||||
eventHandlers.integrationCreate?.({
|
eventHandlers.integrationCreate?.({
|
||||||
...rest,
|
...rest,
|
||||||
guildID,
|
guildId,
|
||||||
enableEmoticons,
|
enableEmoticons,
|
||||||
expireBehavior,
|
expireBehavior,
|
||||||
expireGracePeriod,
|
expireGracePeriod,
|
||||||
syncedAt,
|
syncedAt,
|
||||||
subscriberCount,
|
subscriberCount,
|
||||||
roleID,
|
roleId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,14 @@ import { DiscordPayload, IntegrationDeleteEvent } from "../../types/mod.ts";
|
|||||||
|
|
||||||
export function handleIntegrationDelete(data: DiscordPayload) {
|
export function handleIntegrationDelete(data: DiscordPayload) {
|
||||||
const {
|
const {
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
application_id: applicationID,
|
application_id: applicationId,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as IntegrationDeleteEvent;
|
} = data.d as IntegrationDeleteEvent;
|
||||||
|
|
||||||
eventHandlers.integrationDelete?.({
|
eventHandlers.integrationDelete?.({
|
||||||
...rest,
|
...rest,
|
||||||
applicationID,
|
applicationId,
|
||||||
guildID,
|
guildId,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,20 +9,20 @@ export function handleIntegrationUpdate(data: DiscordPayload) {
|
|||||||
enable_emoticons: enableEmoticons,
|
enable_emoticons: enableEmoticons,
|
||||||
expire_behavior: expireBehavior,
|
expire_behavior: expireBehavior,
|
||||||
expire_grace_period: expireGracePeriod,
|
expire_grace_period: expireGracePeriod,
|
||||||
role_id: roleID,
|
role_id: roleId,
|
||||||
subscriber_count: subscriberCount,
|
subscriber_count: subscriberCount,
|
||||||
synced_at: syncedAt,
|
synced_at: syncedAt,
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
...rest
|
...rest
|
||||||
} = data.d as IntegrationCreateUpdateEvent;
|
} = data.d as IntegrationCreateUpdateEvent;
|
||||||
|
|
||||||
eventHandlers.integrationUpdate?.({
|
eventHandlers.integrationUpdate?.({
|
||||||
...rest,
|
...rest,
|
||||||
guildID,
|
guildId,
|
||||||
subscriberCount,
|
subscriberCount,
|
||||||
enableEmoticons,
|
enableEmoticons,
|
||||||
expireGracePeriod,
|
expireGracePeriod,
|
||||||
roleID,
|
roleId,
|
||||||
expireBehavior,
|
expireBehavior,
|
||||||
syncedAt,
|
syncedAt,
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ export function handleInviteCreate(payload: DiscordPayload) {
|
|||||||
if (payload.t !== "INVITE_CREATE") return;
|
if (payload.t !== "INVITE_CREATE") return;
|
||||||
//TODO: replace with tocamelcase
|
//TODO: replace with tocamelcase
|
||||||
const {
|
const {
|
||||||
channel_id: channelID,
|
channel_id: channelId,
|
||||||
created_at: createdAt,
|
created_at: createdAt,
|
||||||
max_age: maxAge,
|
max_age: maxAge,
|
||||||
guild_id: guildID,
|
guild_id: guildId,
|
||||||
target_user: targetUser,
|
target_user: targetUser,
|
||||||
target_user_type: targetUserType,
|
target_user_type: targetUserType,
|
||||||
max_uses: maxUses,
|
max_uses: maxUses,
|
||||||
@@ -17,8 +17,8 @@ export function handleInviteCreate(payload: DiscordPayload) {
|
|||||||
|
|
||||||
eventHandlers.inviteCreate?.({
|
eventHandlers.inviteCreate?.({
|
||||||
...rest,
|
...rest,
|
||||||
channelID,
|
channelId,
|
||||||
guildID,
|
guildId,
|
||||||
maxAge,
|
maxAge,
|
||||||
targetUser,
|
targetUser,
|
||||||
targetUserType,
|
targetUserType,
|
||||||
|
|||||||
+15
-9
@@ -25,7 +25,7 @@ import {
|
|||||||
PartialMessage,
|
PartialMessage,
|
||||||
ReactionPayload,
|
ReactionPayload,
|
||||||
} from "./message.ts";
|
} from "./message.ts";
|
||||||
import { Camelize } from "./util.ts";
|
import { CamelCaseProps } from "./util.ts";
|
||||||
|
|
||||||
export interface BotConfig {
|
export interface BotConfig {
|
||||||
token: string;
|
token: string;
|
||||||
@@ -93,15 +93,15 @@ export interface EventHandlers {
|
|||||||
rateLimit?: (data: RateLimitData) => unknown;
|
rateLimit?: (data: RateLimitData) => unknown;
|
||||||
/** Sent when a new Slash Command is created, relevant to the current user. */
|
/** Sent when a new Slash Command is created, relevant to the current user. */
|
||||||
applicationCommandCreate?: (
|
applicationCommandCreate?: (
|
||||||
data: Camelize<ApplicationCommandEvent>,
|
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||||
) => unknown;
|
) => unknown;
|
||||||
/** Sent when a Slash Command relevant to the current user is updated. */
|
/** Sent when a Slash Command relevant to the current user is updated. */
|
||||||
applicationCommandUpdate?: (
|
applicationCommandUpdate?: (
|
||||||
data: Camelize<ApplicationCommandEvent>,
|
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||||
) => unknown;
|
) => unknown;
|
||||||
/** Sent when a Slash Command relevant to the current user is deleted. */
|
/** Sent when a Slash Command relevant to the current user is deleted. */
|
||||||
applicationCommandDelete?: (
|
applicationCommandDelete?: (
|
||||||
data: Camelize<ApplicationCommandEvent>,
|
data: CamelCaseProps<ApplicationCommandEvent>,
|
||||||
) => unknown;
|
) => unknown;
|
||||||
/** Sent when properties about the user change. */
|
/** Sent when properties about the user change. */
|
||||||
botUpdate?: (user: UserPayload) => unknown;
|
botUpdate?: (user: UserPayload) => unknown;
|
||||||
@@ -242,15 +242,21 @@ export interface EventHandlers {
|
|||||||
/** Sent when a member has passed the guild's Membership Screening requirements */
|
/** Sent when a member has passed the guild's Membership Screening requirements */
|
||||||
membershipScreeningPassed?: (guild: Guild, member: Member) => unknown;
|
membershipScreeningPassed?: (guild: Guild, member: Member) => unknown;
|
||||||
/** Sent when an integration is created on a server such as twitch, youtube etc.. */
|
/** 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. */
|
/** Sent when an integration is updated. */
|
||||||
integrationUpdate?: (data: Camelize<IntegrationCreateUpdateEvent>) => unknown;
|
integrationUpdate?: (
|
||||||
|
data: CamelCaseProps<IntegrationCreateUpdateEvent>,
|
||||||
|
) => unknown;
|
||||||
/** Sent when an integration is deleted. */
|
/** 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. */
|
/** 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. */
|
/** 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 */
|
/** 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
|
type UpperCaseCharacters =
|
||||||
? string extends T ? string
|
| "A"
|
||||||
: T extends `${infer F}_${infer R}`
|
| "B"
|
||||||
? `${F}${T extends `${infer F}_id` ? Uppercase<R>
|
| "C"
|
||||||
: Capitalize<CamelizeString<R>>}`
|
| "D"
|
||||||
: T
|
| "E"
|
||||||
: T;
|
| "F"
|
||||||
|
| "G"
|
||||||
|
| "H"
|
||||||
|
| "I"
|
||||||
|
| "J"
|
||||||
|
| "K"
|
||||||
|
| "L"
|
||||||
|
| "M"
|
||||||
|
| "N"
|
||||||
|
| "O"
|
||||||
|
| "P"
|
||||||
|
| "Q"
|
||||||
|
| "R"
|
||||||
|
| "S"
|
||||||
|
| "T"
|
||||||
|
| "U"
|
||||||
|
| "V"
|
||||||
|
| "W"
|
||||||
|
| "X"
|
||||||
|
| "Y"
|
||||||
|
| "Z";
|
||||||
|
|
||||||
// deno-fmt-ignore
|
type WordSeparators = "-" | "_" | " ";
|
||||||
export type Camelize<T> = { [K in keyof T as CamelizeString<K>]: T[K] };
|
|
||||||
|
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