diff --git a/packages/create-discord-bot/template/Bun/JavaScript/package.json b/packages/create-discord-bot/template/Bun/JavaScript/package.json index cfd294ab1..b34def786 100644 --- a/packages/create-discord-bot/template/Bun/JavaScript/package.json +++ b/packages/create-discord-bot/template/Bun/JavaScript/package.json @@ -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" } } diff --git a/packages/create-discord-bot/template/Bun/TypeScript/package.json b/packages/create-discord-bot/template/Bun/TypeScript/package.json index be2df343f..341bd5c6d 100644 --- a/packages/create-discord-bot/template/Bun/TypeScript/package.json +++ b/packages/create-discord-bot/template/Bun/TypeScript/package.json @@ -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" } } diff --git a/packages/create-discord-bot/template/Deno/src/commands/index.ts b/packages/create-discord-bot/template/Deno/src/commands/index.ts index aced0ab68..33a4f8198 100644 --- a/packages/create-discord-bot/template/Deno/src/commands/index.ts +++ b/packages/create-discord-bot/template/Deno/src/commands/index.ts @@ -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; }; -// 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 = (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; diff --git a/packages/create-discord-bot/template/Deno/src/events/index.ts b/packages/create-discord-bot/template/Deno/src/events/index.ts index c57906dcf..dc3854874 100644 --- a/packages/create-discord-bot/template/Deno/src/events/index.ts +++ b/packages/create-discord-bot/template/Deno/src/events/index.ts @@ -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 = { once?: boolean; }; -// Defines the predicate to check if an object is a valid Event type. -export const predicate: StructurePredicate = (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 = (structure: unknown): structure is Event => + schema.safeParse(structure).success; diff --git a/packages/create-discord-bot/template/Deno/src/util/loaders.ts b/packages/create-discord-bot/template/Deno/src/util/loaders.ts index 83ddb6343..46d991323 100644 --- a/packages/create-discord-bot/template/Deno/src/util/loaders.ts +++ b/packages/create-discord-bot/template/Deno/src/util/loaders.ts @@ -58,7 +58,9 @@ export async function loadStructures( 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; diff --git a/packages/create-discord-bot/template/JavaScript/package.json b/packages/create-discord-bot/template/JavaScript/package.json index 61509a398..746eddf04 100644 --- a/packages/create-discord-bot/template/JavaScript/package.json +++ b/packages/create-discord-bot/template/JavaScript/package.json @@ -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" } } diff --git a/packages/create-discord-bot/template/JavaScript/src/commands/index.js b/packages/create-discord-bot/template/JavaScript/src/commands/index.js index ea7dbf22c..a0ba2e011 100644 --- a/packages/create-discord-bot/template/JavaScript/src/commands/index.js +++ b/packages/create-discord-bot/template/JavaScript/src/commands/index.js @@ -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} 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} * @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; diff --git a/packages/create-discord-bot/template/JavaScript/src/events/index.js b/packages/create-discord-bot/template/JavaScript/src/events/index.js index 57b2c6e4e..52365eefc 100644 --- a/packages/create-discord-bot/template/JavaScript/src/events/index.js +++ b/packages/create-discord-bot/template/JavaScript/src/events/index.js @@ -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} * @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; diff --git a/packages/create-discord-bot/template/JavaScript/src/util/loaders.js b/packages/create-discord-bot/template/JavaScript/src/util/loaders.js index 621134fac..c3c437573 100644 --- a/packages/create-discord-bot/template/JavaScript/src/util/loaders.js +++ b/packages/create-discord-bot/template/JavaScript/src/util/loaders.js @@ -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; diff --git a/packages/create-discord-bot/template/TypeScript/package.json b/packages/create-discord-bot/template/TypeScript/package.json index b0b7e8f1a..ec0cf1f2e 100644 --- a/packages/create-discord-bot/template/TypeScript/package.json +++ b/packages/create-discord-bot/template/TypeScript/package.json @@ -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" } } diff --git a/packages/create-discord-bot/template/TypeScript/src/commands/index.ts b/packages/create-discord-bot/template/TypeScript/src/commands/index.ts index cb4dee4f4..5b261e32e 100644 --- a/packages/create-discord-bot/template/TypeScript/src/commands/index.ts +++ b/packages/create-discord-bot/template/TypeScript/src/commands/index.ts @@ -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; }; -// Defines the predicate to check if an object is a valid Command type -export const predicate: StructurePredicate = (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 = (structure: unknown): structure is Command => + schema.safeParse(structure).success; diff --git a/packages/create-discord-bot/template/TypeScript/src/events/index.ts b/packages/create-discord-bot/template/TypeScript/src/events/index.ts index f347433f7..2d14857fd 100644 --- a/packages/create-discord-bot/template/TypeScript/src/events/index.ts +++ b/packages/create-discord-bot/template/TypeScript/src/events/index.ts @@ -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 = { once?: boolean; }; -// Defines the predicate to check if an object is a valid Event type. -export const predicate: StructurePredicate = (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 = (structure: unknown): structure is Event => + schema.safeParse(structure).success;