mirror of
https://github.com/discordjs/discord.js.git
synced 2026-03-09 16:13:31 +01:00
refactor: improve structure validation with zod (#10103)
Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com>
This commit is contained in:
@@ -19,6 +19,7 @@
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-neon": "^0.1.57",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"prettier": "^3.1.0"
|
||||
"prettier": "^3.1.0",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
"eslint-config-neon": "^0.1.57",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.2.2"
|
||||
"typescript": "^5.2.2",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RESTPostAPIApplicationCommandsJSONBody, CommandInteraction } from 'npm:discord.js@^14.14.1';
|
||||
import { z } from 'npm:zod@^3.22.4';
|
||||
import type { StructurePredicate } from '../util/loaders.ts';
|
||||
|
||||
/**
|
||||
@@ -17,11 +18,16 @@ export type Command = {
|
||||
execute(interaction: CommandInteraction): Promise<void> | void;
|
||||
};
|
||||
|
||||
// Defines the predicate to check if an object is a valid Command type
|
||||
/**
|
||||
* Defines the schema for a command
|
||||
*/
|
||||
export const schema = z.object({
|
||||
data: z.record(z.any()),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Command type.
|
||||
*/
|
||||
export const predicate: StructurePredicate<Command> = (structure): structure is Command =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'data' in structure! &&
|
||||
'execute' in structure &&
|
||||
typeof structure.data === 'object' &&
|
||||
typeof structure.execute === 'function';
|
||||
schema.safeParse(structure).success;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ClientEvents } from 'npm:discord.js@^14.14.1';
|
||||
import { z } from 'npm:zod@^3.22.4';
|
||||
import type { StructurePredicate } from '../util/loaders.ts';
|
||||
|
||||
/**
|
||||
@@ -23,11 +24,17 @@ export type Event<T extends keyof ClientEvents = keyof ClientEvents> = {
|
||||
once?: boolean;
|
||||
};
|
||||
|
||||
// Defines the predicate to check if an object is a valid Event type.
|
||||
export const predicate: StructurePredicate<Event> = (structure): structure is Event =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'name' in structure! &&
|
||||
'execute' in structure &&
|
||||
typeof structure.name === 'string' &&
|
||||
typeof structure.execute === 'function';
|
||||
/**
|
||||
* Defines the schema for an event.
|
||||
*/
|
||||
export const schema = z.object({
|
||||
name: z.string(),
|
||||
once: z.boolean().optional().default(false),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Event type.
|
||||
*/
|
||||
export const predicate: StructurePredicate<Event> = (structure: unknown): structure is Event =>
|
||||
schema.safeParse(structure).success;
|
||||
|
||||
@@ -58,7 +58,9 @@ export async function loadStructures<T>(
|
||||
const structure = (await import(`${dir}/${file}`)).default;
|
||||
|
||||
// If the structure is a valid structure, add it
|
||||
if (predicate(structure)) structures.push(structure);
|
||||
if (predicate(structure)) {
|
||||
structures.push(structure);
|
||||
}
|
||||
}
|
||||
|
||||
return structures;
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
"eslint": "^8.53.0",
|
||||
"eslint-config-neon": "^0.1.57",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"prettier": "^3.1.0"
|
||||
"prettier": "^3.1.0",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Defines the structure of a command.
|
||||
*
|
||||
@@ -6,16 +8,18 @@
|
||||
* @property {(interaction: import('discord.js').CommandInteraction) => Promise<void> | void} execute The function to execute when the command is called
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the schema for a command
|
||||
*/
|
||||
export const schema = z.object({
|
||||
data: z.record(z.any()),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Command type.
|
||||
*
|
||||
* @type {import('../util/loaders.js').StructurePredicate<Command>}
|
||||
* @returns {structure is Command}
|
||||
*/
|
||||
export const predicate = (structure) =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'data' in structure &&
|
||||
'execute' in structure &&
|
||||
typeof structure.data === 'object' &&
|
||||
typeof structure.execute === 'function';
|
||||
export const predicate = (structure) => schema.safeParse(structure).success;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { z } from 'zod';
|
||||
|
||||
/**
|
||||
* Defines the structure of an event.
|
||||
*
|
||||
@@ -8,16 +10,20 @@
|
||||
* @property {boolean} [once] Whether or not the event should only be listened to once
|
||||
*/
|
||||
|
||||
/**
|
||||
* Defines the schema for an event.
|
||||
*
|
||||
*/
|
||||
export const schema = z.object({
|
||||
name: z.string(),
|
||||
once: z.boolean().optional().default(false),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Event type.
|
||||
*
|
||||
* @type {import('../util/loaders').StructurePredicate<Event>}
|
||||
* @returns {structure is Event}
|
||||
*/
|
||||
export const predicate = (structure) =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'name' in structure &&
|
||||
'execute' in structure &&
|
||||
typeof structure.name === 'string' &&
|
||||
typeof structure.execute === 'function';
|
||||
export const predicate = (structure) => schema.safeParse(structure).success;
|
||||
|
||||
@@ -55,7 +55,9 @@ export async function loadStructures(dir, predicate, recursive = true) {
|
||||
const structure = (await import(`${dir}/${file}`)).default;
|
||||
|
||||
// If the structure is a valid structure, add it
|
||||
if (predicate(structure)) structures.push(structure);
|
||||
if (predicate(structure)) {
|
||||
structures.push(structure);
|
||||
}
|
||||
}
|
||||
|
||||
return structures;
|
||||
|
||||
@@ -23,6 +23,7 @@
|
||||
"eslint-config-neon": "^0.1.57",
|
||||
"eslint-formatter-pretty": "^5.0.0",
|
||||
"prettier": "^3.1.0",
|
||||
"typescript": "^5.2.2"
|
||||
"typescript": "^5.2.2",
|
||||
"zod": "^3.22.4"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { RESTPostAPIApplicationCommandsJSONBody, CommandInteraction } from 'discord.js';
|
||||
import { z } from 'zod';
|
||||
import type { StructurePredicate } from '../util/loaders.[REPLACE_IMPORT_EXT]';
|
||||
|
||||
/**
|
||||
@@ -17,11 +18,16 @@ export type Command = {
|
||||
execute(interaction: CommandInteraction): Promise<void> | void;
|
||||
};
|
||||
|
||||
// Defines the predicate to check if an object is a valid Command type
|
||||
export const predicate: StructurePredicate<Command> = (structure): structure is Command =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'data' in structure! &&
|
||||
'execute' in structure &&
|
||||
typeof structure.data === 'object' &&
|
||||
typeof structure.execute === 'function';
|
||||
/**
|
||||
* Defines the schema for a command
|
||||
*/
|
||||
export const schema = z.object({
|
||||
data: z.record(z.any()),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Command type.
|
||||
*/
|
||||
export const predicate: StructurePredicate<Command> = (structure: unknown): structure is Command =>
|
||||
schema.safeParse(structure).success;
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import type { ClientEvents } from 'discord.js';
|
||||
import { z } from 'zod';
|
||||
import type { StructurePredicate } from '../util/loaders.[REPLACE_IMPORT_EXT]';
|
||||
|
||||
/**
|
||||
@@ -23,11 +24,17 @@ export type Event<T extends keyof ClientEvents = keyof ClientEvents> = {
|
||||
once?: boolean;
|
||||
};
|
||||
|
||||
// Defines the predicate to check if an object is a valid Event type.
|
||||
export const predicate: StructurePredicate<Event> = (structure): structure is Event =>
|
||||
Boolean(structure) &&
|
||||
typeof structure === 'object' &&
|
||||
'name' in structure! &&
|
||||
'execute' in structure &&
|
||||
typeof structure.name === 'string' &&
|
||||
typeof structure.execute === 'function';
|
||||
/**
|
||||
* Defines the schema for an event.
|
||||
*/
|
||||
export const schema = z.object({
|
||||
name: z.string(),
|
||||
once: z.boolean().optional().default(false),
|
||||
execute: z.function(),
|
||||
});
|
||||
|
||||
/**
|
||||
* Defines the predicate to check if an object is a valid Event type.
|
||||
*/
|
||||
export const predicate: StructurePredicate<Event> = (structure: unknown): structure is Event =>
|
||||
schema.safeParse(structure).success;
|
||||
|
||||
Reference in New Issue
Block a user