From dd5e7453e89ae918b94de1c13ce53c7cfd373721 Mon Sep 17 00:00:00 2001 From: Noel Date: Mon, 21 Aug 2023 22:48:13 +0200 Subject: [PATCH] feat(create-discord-bot): bun/deno templates (#9795) --- .gitignore | 7 ++ .vscode/settings.json | 6 +- packages/create-discord-bot/.eslintrc.json | 3 +- packages/create-discord-bot/.gitignore | 2 + packages/create-discord-bot/package.json | 4 +- .../src/create-discord-bot.ts | 113 +++++++++++------- .../src/helpers/packageManager.ts | 69 ++++++++--- packages/create-discord-bot/src/index.ts | 79 ++++++++++-- .../create-discord-bot/src/util/constants.ts | 10 ++ .../template/Bun/JavaScript/package.json | 23 ++++ .../template/Bun/TypeScript/package.json | 25 ++++ .../Bun/TypeScript/tsconfig.eslint.json | 8 ++ .../template/Bun/TypeScript/tsconfig.json | 15 +++ .../create-discord-bot/template/Deno/.env | 2 + .../template/Deno/.prettierrc.json | 8 ++ .../template/Deno/.vscode/extensions.json | 3 + .../template/Deno/.vscode/settings.json | 15 +++ .../template/Deno/deno.jsonc | 40 +++++++ .../template/Deno/src/commands/index.ts | 27 +++++ .../template/Deno/src/commands/ping.ts | 11 ++ .../template/Deno/src/events/index.ts | 33 +++++ .../template/Deno/src/events/ready.ts | 10 ++ .../template/Deno/src/index.ts | 18 +++ .../template/Deno/src/util/deploy.ts | 15 +++ .../template/Deno/src/util/loaders.ts | 76 ++++++++++++ .../template/Deno/src/util/registerEvents.ts | 25 ++++ .../JavaScript/.vscode/extensions.json | 10 ++ .../template/JavaScript/.vscode/settings.json | 13 ++ .../template/JavaScript/package.json | 12 +- .../template/JavaScript/src/index.js | 3 +- .../template/JavaScript/src/util/deploy.js | 4 +- .../TypeScript/.vscode/extensions.json | 10 ++ .../template/TypeScript/.vscode/settings.json | 13 ++ .../template/TypeScript/package.json | 20 ++-- .../template/TypeScript/src/commands/index.ts | 2 +- .../template/TypeScript/src/commands/ping.ts | 2 +- .../template/TypeScript/src/events/index.ts | 2 +- .../template/TypeScript/src/events/ready.ts | 4 +- .../template/TypeScript/src/index.ts | 7 +- .../template/TypeScript/src/util/deploy.ts | 6 +- .../template/TypeScript/src/util/loaders.ts | 12 +- .../TypeScript/src/util/registerEvents.ts | 4 +- .../template/TypeScript/tsconfig.json | 3 +- .../create-discord-bot/tsconfig.eslint.json | 2 +- packages/create-discord-bot/tsup.config.ts | 3 +- yarn.lock | 36 +++++- 46 files changed, 700 insertions(+), 115 deletions(-) create mode 100644 packages/create-discord-bot/template/Bun/JavaScript/package.json create mode 100644 packages/create-discord-bot/template/Bun/TypeScript/package.json create mode 100644 packages/create-discord-bot/template/Bun/TypeScript/tsconfig.eslint.json create mode 100644 packages/create-discord-bot/template/Bun/TypeScript/tsconfig.json create mode 100644 packages/create-discord-bot/template/Deno/.env create mode 100644 packages/create-discord-bot/template/Deno/.prettierrc.json create mode 100644 packages/create-discord-bot/template/Deno/.vscode/extensions.json create mode 100644 packages/create-discord-bot/template/Deno/.vscode/settings.json create mode 100644 packages/create-discord-bot/template/Deno/deno.jsonc create mode 100644 packages/create-discord-bot/template/Deno/src/commands/index.ts create mode 100644 packages/create-discord-bot/template/Deno/src/commands/ping.ts create mode 100644 packages/create-discord-bot/template/Deno/src/events/index.ts create mode 100644 packages/create-discord-bot/template/Deno/src/events/ready.ts create mode 100644 packages/create-discord-bot/template/Deno/src/index.ts create mode 100644 packages/create-discord-bot/template/Deno/src/util/deploy.ts create mode 100644 packages/create-discord-bot/template/Deno/src/util/loaders.ts create mode 100644 packages/create-discord-bot/template/Deno/src/util/registerEvents.ts create mode 100644 packages/create-discord-bot/template/JavaScript/.vscode/extensions.json create mode 100644 packages/create-discord-bot/template/JavaScript/.vscode/settings.json create mode 100644 packages/create-discord-bot/template/TypeScript/.vscode/extensions.json create mode 100644 packages/create-discord-bot/template/TypeScript/.vscode/settings.json diff --git a/.gitignore b/.gitignore index ba9c3ed8c..9abd1d67e 100644 --- a/.gitignore +++ b/.gitignore @@ -23,6 +23,7 @@ dist-docs .vscode !.vscode/extensions.json !.vscode/settings.json +!packages/create-discord-bot/template/**/.vscode .idea .DS_Store .turbo @@ -30,6 +31,12 @@ tsconfig.tsbuildinfo coverage out +# Deno +deno.lock + +# Bun +bun.lockb + # yarn .pnp.* .yarn/* diff --git a/.vscode/settings.json b/.vscode/settings.json index 3eeabcc7c..b08ba83ca 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -14,5 +14,9 @@ "files.insertFinalNewline": true, "files.eol": "\n", "npm.packageManager": "yarn", - "typescript.tsdk": "node_modules/typescript/lib" + "typescript.tsdk": "node_modules/typescript/lib", + "deno.enablePaths": ["./packages/create-discord-bot/template/Deno"], + "deno.lint": true, + "deno.unstable": false, + "deno.config": "./packages/create-discord-bot/template/Deno/deno.jsonc" } diff --git a/packages/create-discord-bot/.eslintrc.json b/packages/create-discord-bot/.eslintrc.json index 99ef7cec8..584e2cdb1 100644 --- a/packages/create-discord-bot/.eslintrc.json +++ b/packages/create-discord-bot/.eslintrc.json @@ -1,3 +1,4 @@ { - "extends": "../../.eslintrc.json" + "extends": "../../.eslintrc.json", + "ignorePatterns": ["**/template/Deno/*"] } diff --git a/packages/create-discord-bot/.gitignore b/packages/create-discord-bot/.gitignore index 376d3bf09..548bac7e8 100644 --- a/packages/create-discord-bot/.gitignore +++ b/packages/create-discord-bot/.gitignore @@ -13,6 +13,8 @@ pids # Env .env +!template/Bun/.env +!template/Deno/.env !template/JavaScript/.env !template/TypeScript/.env diff --git a/packages/create-discord-bot/package.json b/packages/create-discord-bot/package.json index 1945fcbd4..ed986d41d 100644 --- a/packages/create-discord-bot/package.json +++ b/packages/create-discord-bot/package.json @@ -45,8 +45,9 @@ }, "homepage": "https://discord.js.org", "dependencies": { - "chalk": "^5.3.0", "commander": "^11.0.0", + "fast-glob": "^3.3.1", + "picocolors": "^1.0.0", "prompts": "^2.4.2", "validate-npm-package-name": "^5.0.0" }, @@ -62,6 +63,7 @@ "eslint-config-neon": "^0.1.47", "eslint-formatter-pretty": "^5.0.0", "prettier": "^2.8.8", + "terser": "^5.19.2", "tsup": "^7.2.0", "typescript": "^5.1.6", "vitest": "^0.34.2" diff --git a/packages/create-discord-bot/src/create-discord-bot.ts b/packages/create-discord-bot/src/create-discord-bot.ts index 44e5ba8f8..2cb194f17 100755 --- a/packages/create-discord-bot/src/create-discord-bot.ts +++ b/packages/create-discord-bot/src/create-discord-bot.ts @@ -1,27 +1,26 @@ +import type { ExecException } from 'node:child_process'; import { cp, stat, mkdir, readdir, readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; import { URL } from 'node:url'; -import chalk from 'chalk'; -import validateProjectName from 'validate-npm-package-name'; -import { install, resolvePackageManager } from './helpers/packageManager.js'; +import glob from 'fast-glob'; +import { red, yellow, green, cyan } from 'picocolors'; +import type { PackageManager } from './helpers/packageManager.js'; +import { install } from './helpers/packageManager.js'; import { GUIDE_URL } from './util/constants.js'; interface Options { directory: string; - javascript?: boolean; + packageManager: PackageManager; typescript?: boolean; } -export async function createDiscordBot({ typescript, javascript, directory }: Options) { - if (!directory) { - console.error(chalk.red('Please specify the project directory.')); - process.exit(1); - } - +export async function createDiscordBot({ directory, typescript, packageManager }: Options) { const root = path.resolve(directory); const directoryName = path.basename(root); + console.log(); + const directoryStats = await stat(root).catch(async (error) => { // Create a new directory if the specified one does not exist. if (error.code === 'ENOENT') { @@ -34,47 +33,75 @@ export async function createDiscordBot({ typescript, javascript, directory }: Op // If the directory is actually a file or if it's not empty, throw an error. if (!directoryStats.isDirectory() || (await readdir(root)).length > 0) { - console.error( - chalk.red(`The directory ${chalk.yellow(`"${directoryName}"`)} is either not a directory or is not empty.`), - ); - console.error(chalk.red(`Please specify an empty directory.`)); + console.error(red(`The directory ${yellow(`"${directoryName}"`)} is either not a directory or is not empty.`)); + console.error(red(`Please specify an empty directory.`)); process.exit(1); } - // We'll use the directory name as the project name. Check npm name validity. - const validationResult = validateProjectName(directoryName); - - if (!validationResult.validForNewPackages) { - console.error( - chalk.red( - `Cannot create a project named ${chalk.yellow( - `"${directoryName}"`, - )} due to npm naming restrictions.\n\nErrors:`, - ), - ); - - for (const error of [...(validationResult.errors ?? []), ...(validationResult.warnings ?? [])]) { - console.error(chalk.red(`- ${error}`)); - } - - console.error(chalk.red('\nSee https://docs.npmjs.com/cli/configuring-npm/package-json for more details.')); - process.exit(1); - } - - console.log(`Creating ${directoryName} in ${chalk.green(root)}.`); - await cp(new URL(`../template/${typescript ? 'TypeScript' : 'JavaScript'}`, import.meta.url), root, { + console.log(`Creating ${directoryName} in ${green(root)}.`); + const deno = packageManager === 'deno'; + await cp(new URL(`../template/${deno ? 'Deno' : typescript ? 'TypeScript' : 'JavaScript'}`, import.meta.url), root, { recursive: true, }); + const bun = packageManager === 'bun'; + if (bun) { + await cp( + new URL(`../template/Bun/${typescript ? 'TypeScript' : 'JavaScript'}/package.json`, import.meta.url), + `${root}/package.json`, + ); + + if (typescript) { + await cp( + new URL('../template/Bun/Typescript/tsconfig.eslint.json', import.meta.url), + `${root}/tsconfig.eslint.json`, + ); + await cp(new URL('../template/Bun/Typescript/tsconfig.json', import.meta.url), `${root}/tsconfig.json`); + } + } + process.chdir(root); - const newPackageJSON = await readFile('./package.json', { encoding: 'utf8' }).then((str) => - str.replace('[REPLACE-NAME]', directoryName), - ); + const newVSCodeSettings = await readFile('./.vscode/settings.json', { encoding: 'utf8' }).then((str) => { + let newStr = str.replace('[REPLACE_ME]', deno || bun ? 'auto' : packageManager); + if (deno) { + // @ts-expect-error: This is fine + newStr = newStr.replaceAll('"[REPLACE_BOOL]"', true); + } + + return newStr; + }); + await writeFile('./.vscode/settings.json', newVSCodeSettings); + + const globStream = glob.stream('./src/**/*.ts'); + for await (const file of globStream) { + const newData = await readFile(file, { encoding: 'utf8' }).then((str) => + str.replaceAll('[REPLACE_IMPORT_EXT]', typescript ? 'ts' : 'js'), + ); + await writeFile(file, newData); + } + + const newPackageJSON = await readFile('./package.json', { encoding: 'utf8' }).then((str) => { + let newStr = str.replace('[REPLACE_ME]', directoryName); + newStr = newStr.replaceAll('[REPLACE_IMPORT_EXT]', typescript ? 'ts' : 'js'); + return newStr; + }); await writeFile('./package.json', newPackageJSON); - const packageManager = resolvePackageManager(); - install(packageManager); - console.log(chalk.green('All done! Be sure to read through the discord.js guide for help on your journey.')); - console.log(`Link: ${chalk.cyan(GUIDE_URL)}`); + try { + install(packageManager); + } catch (error) { + console.log(); + const err = error as ExecException; + if (err.signal === 'SIGINT') { + console.log(red('Installation aborted.')); + } else { + console.error(red('Installation failed.')); + process.exit(1); + } + } + + console.log(); + console.log(green('All done! Be sure to read through the discord.js guide for help on your journey.')); + console.log(`Link: ${cyan(GUIDE_URL)}`); } diff --git a/packages/create-discord-bot/src/helpers/packageManager.ts b/packages/create-discord-bot/src/helpers/packageManager.ts index cc524bf50..c103e86b0 100644 --- a/packages/create-discord-bot/src/helpers/packageManager.ts +++ b/packages/create-discord-bot/src/helpers/packageManager.ts @@ -1,12 +1,12 @@ import { execSync } from 'node:child_process'; import process from 'node:process'; -import chalk from 'chalk'; +import { yellow } from 'picocolors'; import { DEFAULT_PACKAGE_MANAGER } from '../util/constants.js'; /** * A union of supported package managers. */ -export type PackageManager = 'npm' | 'pnpm' | 'yarn'; +export type PackageManager = 'bun' | 'deno' | 'npm' | 'pnpm' | 'yarn'; /** * Resolves the package manager from `npm_config_user_agent`. @@ -32,7 +32,7 @@ export function resolvePackageManager(): PackageManager { } console.error( - chalk.yellow( + yellow( `Detected an unsupported package manager (${npmConfigUserAgent}). Falling back to ${DEFAULT_PACKAGE_MANAGER}.`, ), ); @@ -47,21 +47,62 @@ export function resolvePackageManager(): PackageManager { * @param packageManager - The package manager to use */ export function install(packageManager: PackageManager) { - let installCommand; - - switch (packageManager) { - case 'npm': - case 'pnpm': - installCommand = `${packageManager} install`; - break; - case 'yarn': - installCommand = packageManager; - break; - } + let installCommand: string[] | string = `${packageManager} install`; console.log(`Installing dependencies with ${packageManager}...`); + switch (packageManager) { + case 'yarn': + console.log(); + installCommand = [ + `${packageManager} set version stable`, + `${packageManager} config set nodeLinker node-modules`, + `${packageManager} config set logFilters --json '[{ "code": "YN0002", "level": "discard" }, { "code": "YN0013", "level": "discard" }, { "code": "YN0032", "level": "discard" }, { "code": "YN0060", "level": "discard" }]'`, + `${packageManager} plugin import interactive-tools`, + `${packageManager} plugin import workspace-tools`, + installCommand, + ]; + break; + case 'deno': + installCommand = `${packageManager} cache --reload src/index.ts`; + break; + case 'pnpm': + case 'bun': + console.log(); + break; + default: + break; + } + + const env = { + ...process.env, + ADBLOCK: '1', + NODE_ENV: 'development', + DISABLE_OPENCOLLECTIVE: '1', + }; + + if (Array.isArray(installCommand)) { + for (const [index, command] of installCommand.entries()) { + if (index === installCommand.length - 1) { + execSync(command, { + stdio: 'inherit', + env, + }); + + break; + } + + execSync(command, { + stdio: 'ignore', + env, + }); + } + + return; + } + execSync(installCommand, { stdio: 'inherit', + env, }); } diff --git a/packages/create-discord-bot/src/index.ts b/packages/create-discord-bot/src/index.ts index 5413fbbd7..699924e6b 100644 --- a/packages/create-discord-bot/src/index.ts +++ b/packages/create-discord-bot/src/index.ts @@ -1,32 +1,94 @@ #!/usr/bin/env node // eslint-disable-next-line n/shebang -import { program } from 'commander'; +import process from 'node:process'; +import { Option, program } from 'commander'; +import { red, yellow, green } from 'picocolors'; import prompts from 'prompts'; +import validateProjectName from 'validate-npm-package-name'; +import packageJSON from '../package.json' assert { type: 'json' }; import { createDiscordBot } from './create-discord-bot.js'; +import { resolvePackageManager } from './helpers/packageManager.js'; +import { DEFAULT_PROJECT_NAME, PACKAGE_MANAGERS } from './util/constants.js'; + +let projectDirectory = ''; + +const handleSigTerm = () => process.exit(0); + +process.on('SIGINT', handleSigTerm); +process.on('SIGTERM', handleSigTerm); + +// https://github.com/vercel/next.js/blob/canary/packages/create-next-app/index.ts#L24-L32 +const onPromptState = (state: any) => { + if (state.aborted) { + // If we don't re-enable the terminal cursor before exiting + // the program, the cursor will remain hidden + process.stdout.write('\u001B[?25h'); + process.stdout.write('\n'); + process.exit(1); + } +}; program + .name(packageJSON.name) + .version(packageJSON.version) .description('Create a basic discord.js bot.') - .option('--directory', 'The directory where this will be created.') + .argument('[directory]', 'What is the name of the directory you want to create this project in?') + .usage(`${green('')}`) + .action((directory) => { + projectDirectory = directory; + }) .option('--typescript', 'Whether to use the TypeScript template.') .option('--javascript', 'Whether to use the JavaScript template.') + .addOption( + new Option('--packageManager ', 'The package manager to use.') + .choices(PACKAGE_MANAGERS) + .default(resolvePackageManager()), + ) + .allowUnknownOption() .parse(); -let { typescript, javascript, directory } = program.opts(); +// eslint-disable-next-line prefer-const +let { typescript, javascript, packageManager } = program.opts(); -if (!directory) { - directory = ( +if (!projectDirectory) { + projectDirectory = ( await prompts({ + onState: onPromptState, type: 'text', name: 'directory', - initial: 'my-bot', + initial: DEFAULT_PROJECT_NAME, message: 'What is the name of the directory you want to create this project in?', + validate: (directory) => { + // We'll use the directory name as the project name. Check npm name validity. + const validationResult = validateProjectName(directory); + + if (!validationResult.validForNewPackages) { + const errors = []; + + for (const error of [...(validationResult.errors ?? []), ...(validationResult.warnings ?? [])]) { + errors.push(red(`- ${error}`)); + } + + return red( + `Cannot create a project named ${yellow( + `"${directory}"`, + )} due to npm naming restrictions.\n\nErrors:\n${errors.join('\n')}\n\n${red( + '\nSee https://docs.npmjs.com/cli/configuring-npm/package-json for more details.', + )}}`, + ); + } + + return true; + }, }) ).directory; } -if (typescript === undefined && javascript === undefined) { +const deno = packageManager === 'deno'; +if (!deno && typescript === undefined && javascript === undefined) { const { useTypescript } = await prompts({ + onState: onPromptState, type: 'toggle', name: 'useTypescript', message: 'Do you want to use TypeScript?', @@ -36,7 +98,6 @@ if (typescript === undefined && javascript === undefined) { }); typescript = useTypescript; - javascript = !useTypescript; } -await createDiscordBot({ typescript, javascript, directory }); +await createDiscordBot({ typescript, directory: projectDirectory, packageManager }); diff --git a/packages/create-discord-bot/src/util/constants.ts b/packages/create-discord-bot/src/util/constants.ts index 7366008df..ff5fc9a5d 100644 --- a/packages/create-discord-bot/src/util/constants.ts +++ b/packages/create-discord-bot/src/util/constants.ts @@ -3,6 +3,16 @@ */ export const DEFAULT_PACKAGE_MANAGER = 'npm' as const; +/** + * The default project name. + */ +export const DEFAULT_PROJECT_NAME = 'my-bot' as const; + +/** + * The supported package managers. + */ +export const PACKAGE_MANAGERS = ['npm', 'pnpm', 'yarn', 'bun', 'deno'] as const; + /** * The URL to the guide. */ diff --git a/packages/create-discord-bot/template/Bun/JavaScript/package.json b/packages/create-discord-bot/template/Bun/JavaScript/package.json new file mode 100644 index 000000000..bb39d1d75 --- /dev/null +++ b/packages/create-discord-bot/template/Bun/JavaScript/package.json @@ -0,0 +1,23 @@ +{ + "name": "[REPLACE_ME]", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "lint": "prettier --check . && eslint ./src --ext .[REPLACE_IMPORT_EXT] --format=pretty", + "deploy": "bun run src/util/deploy.[REPLACE_IMPORT_EXT]", + "format": "prettier --write . && eslint ./src --ext .[REPLACE_IMPORT_EXT] --fix --format=pretty", + "start": "bun run src/index.[REPLACE_IMPORT_EXT]" + }, + "dependencies": { + "@discordjs/core": "^1.0.1", + "discord.js": "^14.13.0" + }, + "devDependencies": { + "@sapphire/ts-config": "^4.0.1", + "eslint": "^8.47.0", + "eslint-config-neon": "^0.1.47", + "eslint-formatter-pretty": "^5.0.0", + "prettier": "^3.0.2" + } +} diff --git a/packages/create-discord-bot/template/Bun/TypeScript/package.json b/packages/create-discord-bot/template/Bun/TypeScript/package.json new file mode 100644 index 000000000..be95e6353 --- /dev/null +++ b/packages/create-discord-bot/template/Bun/TypeScript/package.json @@ -0,0 +1,25 @@ +{ + "name": "[REPLACE_ME]", + "version": "0.1.0", + "private": true, + "type": "module", + "scripts": { + "lint": "tsc && prettier --check . && eslint ./src --ext .[REPLACE_IMPORT_EXT] --format=pretty", + "deploy": "bun run src/util/deploy.[REPLACE_IMPORT_EXT]", + "format": "prettier --write . && eslint ./src --ext .[REPLACE_IMPORT_EXT] --fix --format=pretty", + "start": "bun run src/index.[REPLACE_IMPORT_EXT]" + }, + "dependencies": { + "@discordjs/core": "^1.0.1", + "discord.js": "^14.13.0" + }, + "devDependencies": { + "@sapphire/ts-config": "^4.0.1", + "bun-types": "^0.7.3", + "eslint": "^8.47.0", + "eslint-config-neon": "^0.1.47", + "eslint-formatter-pretty": "^5.0.0", + "prettier": "^3.0.2", + "typescript": "^5.1.6" + } +} diff --git a/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.eslint.json b/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.eslint.json new file mode 100644 index 000000000..11bd8eafe --- /dev/null +++ b/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.eslint.json @@ -0,0 +1,8 @@ +{ + "extends": "./tsconfig.json", + "compilerOptions": { + "allowJs": true + }, + "include": ["**/*.ts", "**/*.js", "**/*.test.ts", "**/*.test.js"], + "exclude": [] +} diff --git a/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.json b/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.json new file mode 100644 index 000000000..224209f4c --- /dev/null +++ b/packages/create-discord-bot/template/Bun/TypeScript/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "@sapphire/ts-config/extra-strict", + "compilerOptions": { + "declaration": false, + "declarationMap": false, + "module": "ESNext", + "moduleResolution": "Bundler", + "target": "ESNext", + "outDir": "dist", + "noEmit": true, + "allowImportingTsExtensions": true, + "types": ["bun-types"], + "skipLibCheck": true + } +} diff --git a/packages/create-discord-bot/template/Deno/.env b/packages/create-discord-bot/template/Deno/.env new file mode 100644 index 000000000..b9edc2b71 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/.env @@ -0,0 +1,2 @@ +DISCORD_TOKEN= +APPLICATION_ID= diff --git a/packages/create-discord-bot/template/Deno/.prettierrc.json b/packages/create-discord-bot/template/Deno/.prettierrc.json new file mode 100644 index 000000000..eba3f4077 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/.prettierrc.json @@ -0,0 +1,8 @@ +{ + "printWidth": 120, + "useTabs": true, + "singleQuote": true, + "quoteProps": "as-needed", + "trailingComma": "all", + "endOfLine": "lf" +} diff --git a/packages/create-discord-bot/template/Deno/.vscode/extensions.json b/packages/create-discord-bot/template/Deno/.vscode/extensions.json new file mode 100644 index 000000000..9a3c0c3e0 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/.vscode/extensions.json @@ -0,0 +1,3 @@ +{ + "recommendations": ["denoland.vscode-deno", "tamasfe.even-better-toml", "codezombiech.gitignore"] +} diff --git a/packages/create-discord-bot/template/Deno/.vscode/settings.json b/packages/create-discord-bot/template/Deno/.vscode/settings.json new file mode 100644 index 000000000..93c3e5071 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/.vscode/settings.json @@ -0,0 +1,15 @@ +{ + "editor.defaultFormatter": "denoland.vscode-deno", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": true, + "source.organizeImports": false + }, + "editor.trimAutoWhitespace": false, + "files.insertFinalNewline": true, + "files.eol": "\n", + "npm.packageManager": "[REPLACE_ME]", + "deno.enable": "[REPLACE_BOOL]", + "deno.lint": "[REPLACE_BOOL]", + "deno.unstable": false +} diff --git a/packages/create-discord-bot/template/Deno/deno.jsonc b/packages/create-discord-bot/template/Deno/deno.jsonc new file mode 100644 index 000000000..e97eebafe --- /dev/null +++ b/packages/create-discord-bot/template/Deno/deno.jsonc @@ -0,0 +1,40 @@ +{ + "$schema": "https://raw.githubusercontent.com/denoland/deno/main/cli/schemas/config-file.v1.json", + "tasks": { + "lint": "deno lint", + "deploy": "deno run --allow-read --allow-env --allow-net src/util/deploy.ts", + "format": "deno fmt", + "start": "deno run --allow-read --allow-env --allow-net src/index.ts" + }, + "lint": { + "include": ["src/"], + "rules": { + "tags": ["recommended"], + "exclude": ["require-await", "no-await-in-sync-fn"] + } + }, + "fmt": { + "useTabs": true, + "lineWidth": 120, + "semiColons": true, + "singleQuote": true, + "proseWrap": "preserve", + "include": ["src/"] + }, + "compilerOptions": { + "alwaysStrict": true, + "emitDecoratorMetadata": true, + "verbatimModuleSyntax": true, + "lib": ["deno.window"], + "noFallthroughCasesInSwitch": true, + "noImplicitReturns": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "removeComments": false, + "strict": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "exactOptionalPropertyTypes": false, + "noImplicitOverride": true + } +} diff --git a/packages/create-discord-bot/template/Deno/src/commands/index.ts b/packages/create-discord-bot/template/Deno/src/commands/index.ts new file mode 100644 index 000000000..d2c0293a8 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/commands/index.ts @@ -0,0 +1,27 @@ +import type { RESTPostAPIApplicationCommandsJSONBody, CommandInteraction } from 'npm:discord.js@^14.13.0'; +import type { StructurePredicate } from '../util/loaders.ts'; + +/** + * Defines the structure of a command + */ +export type Command = { + /** + * The data for the command + */ + data: RESTPostAPIApplicationCommandsJSONBody; + /** + * The function to execute when the command is called + * + * @param interaction - The interaction of the 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'; diff --git a/packages/create-discord-bot/template/Deno/src/commands/ping.ts b/packages/create-discord-bot/template/Deno/src/commands/ping.ts new file mode 100644 index 000000000..7b30e8273 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/commands/ping.ts @@ -0,0 +1,11 @@ +import type { Command } from './index.ts'; + +export default { + data: { + name: 'ping', + description: 'Ping!', + }, + async execute(interaction) { + await interaction.reply('Pong!'); + }, +} satisfies Command; diff --git a/packages/create-discord-bot/template/Deno/src/events/index.ts b/packages/create-discord-bot/template/Deno/src/events/index.ts new file mode 100644 index 000000000..a8295cf00 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/events/index.ts @@ -0,0 +1,33 @@ +import type { ClientEvents } from 'npm:discord.js@^14.13.0'; +import type { StructurePredicate } from '../util/loaders.ts'; + +/** + * Defines the structure of an event. + */ +export type Event = { + /** + * The function to execute when the event is emitted. + * + * @param parameters - The parameters of the event + */ + execute(...parameters: ClientEvents[T]): Promise | void; + /** + * The name of the event to listen to + */ + name: T; + /** + * Whether or not the event should only be listened to once + * + * @defaultValue false + */ + 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'; diff --git a/packages/create-discord-bot/template/Deno/src/events/ready.ts b/packages/create-discord-bot/template/Deno/src/events/ready.ts new file mode 100644 index 000000000..c44f8510e --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/events/ready.ts @@ -0,0 +1,10 @@ +import { Events } from 'npm:discord.js@^14.13.0'; +import type { Event } from './index.ts'; + +export default { + name: Events.ClientReady, + once: true, + async execute(client) { + console.log(`Ready! Logged in as ${client.user.tag}`); + }, +} satisfies Event; diff --git a/packages/create-discord-bot/template/Deno/src/index.ts b/packages/create-discord-bot/template/Deno/src/index.ts new file mode 100644 index 000000000..b9550d764 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/index.ts @@ -0,0 +1,18 @@ +import 'https://deno.land/std@0.199.0/dotenv/load.ts'; +import { URL } from 'node:url'; +import { Client, GatewayIntentBits } from 'npm:discord.js@^14.13.0'; +import { loadCommands, loadEvents } from './util/loaders.ts'; +import { registerEvents } from './util/registerEvents.ts'; + +// Initialize the client +const client = new Client({ intents: [GatewayIntentBits.Guilds] }); + +// Load the events and commands +const events = await loadEvents(new URL('events/', import.meta.url)); +const commands = await loadCommands(new URL('commands/', import.meta.url)); + +// Register the event handlers +registerEvents(commands, events, client); + +// Login to the client +void client.login(Deno.env.get('DISCORD_TOKEN')); diff --git a/packages/create-discord-bot/template/Deno/src/util/deploy.ts b/packages/create-discord-bot/template/Deno/src/util/deploy.ts new file mode 100644 index 000000000..e5afcdbca --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/util/deploy.ts @@ -0,0 +1,15 @@ +import 'https://deno.land/std@0.199.0/dotenv/load.ts'; +import { URL } from 'node:url'; +import { API } from 'npm:@discordjs/core@^1.0.1/http-only'; +import { REST } from 'npm:discord.js@^14.13.0'; +import { loadCommands } from './loaders.ts'; + +const commands = await loadCommands(new URL('../commands/', import.meta.url)); +const commandData = [...commands.values()].map((command) => command.data); + +const rest = new REST({ version: '10' }).setToken(Deno.env.get('DISCORD_TOKEN')!); +const api = new API(rest); + +const result = await api.applicationCommands.bulkOverwriteGlobalCommands(Deno.env.get('APPLICATION_ID')!, commandData); + +console.log(`Successfully registered ${result.length} commands.`); diff --git a/packages/create-discord-bot/template/Deno/src/util/loaders.ts b/packages/create-discord-bot/template/Deno/src/util/loaders.ts new file mode 100644 index 000000000..83ddb6343 --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/util/loaders.ts @@ -0,0 +1,76 @@ +import type { PathLike } from 'node:fs'; +import { readdir, stat } from 'node:fs/promises'; +import { URL } from 'node:url'; +import type { Command } from '../commands/index.ts'; +import { predicate as commandPredicate } from '../commands/index.ts'; +import type { Event } from '../events/index.ts'; +import { predicate as eventPredicate } from '../events/index.ts'; + +/** + * A predicate to check if the structure is valid + */ +export type StructurePredicate = (structure: unknown) => structure is T; + +/** + * Loads all the structures in the provided directory + * + * @param dir - The directory to load the structures from + * @param predicate - The predicate to check if the structure is valid + * @param recursive - Whether to recursively load the structures in the directory + * @returns + */ +export async function loadStructures( + dir: PathLike, + predicate: StructurePredicate, + recursive = true, +): Promise { + // Get the stats of the directory + const statDir = await stat(dir); + + // If the provided directory path is not a directory, throw an error + if (!statDir.isDirectory()) { + throw new Error(`The directory '${dir}' is not a directory.`); + } + + // Get all the files in the directory + const files = await readdir(dir); + + // Create an empty array to store the structures + const structures: T[] = []; + + // Loop through all the files in the directory + for (const file of files) { + // If the file is index.js or the file does not end with .js, skip the file + if (file === 'index.ts' || !file.endsWith('.ts')) { + continue; + } + + // Get the stats of the file + const statFile = await stat(new URL(`${dir}/${file}`)); + + // If the file is a directory and recursive is true, recursively load the structures in the directory + if (statFile.isDirectory() && recursive) { + structures.push(...(await loadStructures(`${dir}/${file}`, predicate, recursive))); + continue; + } + + // Import the structure dynamically from the file + const structure = (await import(`${dir}/${file}`)).default; + + // If the structure is a valid structure, add it + if (predicate(structure)) structures.push(structure); + } + + return structures; +} + +export async function loadCommands(dir: PathLike, recursive = true): Promise> { + return (await loadStructures(dir, commandPredicate, recursive)).reduce( + (acc, cur) => acc.set(cur.data.name, cur), + new Map(), + ); +} + +export async function loadEvents(dir: PathLike, recursive = true): Promise { + return loadStructures(dir, eventPredicate, recursive); +} diff --git a/packages/create-discord-bot/template/Deno/src/util/registerEvents.ts b/packages/create-discord-bot/template/Deno/src/util/registerEvents.ts new file mode 100644 index 000000000..e598393bb --- /dev/null +++ b/packages/create-discord-bot/template/Deno/src/util/registerEvents.ts @@ -0,0 +1,25 @@ +import { Events, type Client } from 'npm:discord.js@^14.13.0'; +import type { Command } from '../commands/index.ts'; +import type { Event } from '../events/index.ts'; + +export function registerEvents(commands: Map, events: Event[], client: Client): void { + // Create an event to handle command interactions + const interactionCreateEvent: Event = { + name: Events.InteractionCreate, + async execute(interaction) { + if (interaction.isCommand()) { + const command = commands.get(interaction.commandName); + + if (!command) { + throw new Error(`Command '${interaction.commandName}' not found.`); + } + + await command.execute(interaction); + } + }, + }; + + for (const event of [...events, interactionCreateEvent]) { + client[event.once ? 'once' : 'on'](event.name, async (...args) => event.execute(...args)); + } +} diff --git a/packages/create-discord-bot/template/JavaScript/.vscode/extensions.json b/packages/create-discord-bot/template/JavaScript/.vscode/extensions.json new file mode 100644 index 000000000..3d5debb10 --- /dev/null +++ b/packages/create-discord-bot/template/JavaScript/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "tamasfe.even-better-toml", + "codezombiech.gitignore", + "christian-kohler.npm-intellisense", + "christian-kohler.path-intellisense" + ] +} diff --git a/packages/create-discord-bot/template/JavaScript/.vscode/settings.json b/packages/create-discord-bot/template/JavaScript/.vscode/settings.json new file mode 100644 index 000000000..a3ff3551e --- /dev/null +++ b/packages/create-discord-bot/template/JavaScript/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": true, + "source.organizeImports": false + }, + "editor.trimAutoWhitespace": false, + "files.insertFinalNewline": true, + "files.eol": "\n", + "npm.packageManager": "[REPLACE_ME]" +} diff --git a/packages/create-discord-bot/template/JavaScript/package.json b/packages/create-discord-bot/template/JavaScript/package.json index c81cf9a1f..b923137a8 100644 --- a/packages/create-discord-bot/template/JavaScript/package.json +++ b/packages/create-discord-bot/template/JavaScript/package.json @@ -1,5 +1,5 @@ { - "name": "[REPLACE-NAME]", + "name": "[REPLACE_ME]", "version": "0.1.0", "private": true, "type": "module", @@ -10,14 +10,14 @@ "deploy": "node --require dotenv/config src/util/deploy.js" }, "dependencies": { - "@discordjs/core": "^0.6.0", - "discord.js": "^14.11.0", - "dotenv": "^16.0.3" + "@discordjs/core": "^1.0.1", + "discord.js": "^14.13.0", + "dotenv": "^16.3.1" }, "devDependencies": { - "eslint": "^8.40.0", + "eslint": "^8.47.0", "eslint-config-neon": "^0.1.47", "eslint-formatter-pretty": "^5.0.0", - "prettier": "^2.8.8" + "prettier": "^3.0.2" } } diff --git a/packages/create-discord-bot/template/JavaScript/src/index.js b/packages/create-discord-bot/template/JavaScript/src/index.js index d45b56ef9..20d768829 100644 --- a/packages/create-discord-bot/template/JavaScript/src/index.js +++ b/packages/create-discord-bot/template/JavaScript/src/index.js @@ -1,3 +1,4 @@ +import process from 'node:process'; import { URL } from 'node:url'; import { Client, GatewayIntentBits } from 'discord.js'; import { loadCommands, loadEvents } from './util/loaders.js'; @@ -14,4 +15,4 @@ const commands = await loadCommands(new URL('commands/', import.meta.url)); registerEvents(commands, events, client); // Login to the client -void client.login(); +void client.login(process.env.DISCORD_TOKEN); diff --git a/packages/create-discord-bot/template/JavaScript/src/util/deploy.js b/packages/create-discord-bot/template/JavaScript/src/util/deploy.js index 523bdb8ed..7120c4a7e 100644 --- a/packages/create-discord-bot/template/JavaScript/src/util/deploy.js +++ b/packages/create-discord-bot/template/JavaScript/src/util/deploy.js @@ -4,10 +4,10 @@ import { API } from '@discordjs/core/http-only'; import { REST } from 'discord.js'; import { loadCommands } from './loaders.js'; -const commands = await loadCommands(new URL('commands/', import.meta.url)); +const commands = await loadCommands(new URL('../commands/', import.meta.url)); const commandData = [...commands.values()].map((command) => command.data); -const rest = new REST({ version: '10' }).setToken(process.env.TOKEN); +const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN); const api = new API(rest); const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID, commandData); diff --git a/packages/create-discord-bot/template/TypeScript/.vscode/extensions.json b/packages/create-discord-bot/template/TypeScript/.vscode/extensions.json new file mode 100644 index 000000000..3d5debb10 --- /dev/null +++ b/packages/create-discord-bot/template/TypeScript/.vscode/extensions.json @@ -0,0 +1,10 @@ +{ + "recommendations": [ + "esbenp.prettier-vscode", + "dbaeumer.vscode-eslint", + "tamasfe.even-better-toml", + "codezombiech.gitignore", + "christian-kohler.npm-intellisense", + "christian-kohler.path-intellisense" + ] +} diff --git a/packages/create-discord-bot/template/TypeScript/.vscode/settings.json b/packages/create-discord-bot/template/TypeScript/.vscode/settings.json new file mode 100644 index 000000000..a3ff3551e --- /dev/null +++ b/packages/create-discord-bot/template/TypeScript/.vscode/settings.json @@ -0,0 +1,13 @@ +{ + "eslint.validate": ["javascript", "javascriptreact", "typescript", "typescriptreact"], + "editor.defaultFormatter": "esbenp.prettier-vscode", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.fixAll": true, + "source.organizeImports": false + }, + "editor.trimAutoWhitespace": false, + "files.insertFinalNewline": true, + "files.eol": "\n", + "npm.packageManager": "[REPLACE_ME]" +} diff --git a/packages/create-discord-bot/template/TypeScript/package.json b/packages/create-discord-bot/template/TypeScript/package.json index 9066fd20c..34fdd956a 100644 --- a/packages/create-discord-bot/template/TypeScript/package.json +++ b/packages/create-discord-bot/template/TypeScript/package.json @@ -1,27 +1,27 @@ { - "name": "[REPLACE-NAME]", + "name": "[REPLACE_ME]", "version": "0.1.0", "private": true, "type": "module", "scripts": { - "test": "tsc", + "build": "tsc", "lint": "prettier --check . && eslint ./src --ext .ts --format=pretty", "deploy": "node --require dotenv/config dist/util/deploy.js", "format": "prettier --write . && eslint ./src --ext .ts --fix --format=pretty", "start": "node --require dotenv/config dist/index.js" }, "dependencies": { - "@discordjs/core": "^0.6.0", - "discord.js": "^14.11.0", - "dotenv": "^16.0.3" + "@discordjs/core": "^1.0.1", + "discord.js": "^14.13.0", + "dotenv": "^16.3.1" }, "devDependencies": { - "@sapphire/ts-config": "^4.0.0", - "@types/node": "^18.15.3", - "eslint": "^8.40.0", + "@sapphire/ts-config": "^4.0.1", + "@types/node": "^18.17.6", + "eslint": "^8.47.0", "eslint-config-neon": "^0.1.47", "eslint-formatter-pretty": "^5.0.0", - "prettier": "^2.8.8", - "typescript": "^5.0.4" + "prettier": "^3.0.2", + "typescript": "^5.1.6" } } 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 3da2b0739..cb4dee4f4 100644 --- a/packages/create-discord-bot/template/TypeScript/src/commands/index.ts +++ b/packages/create-discord-bot/template/TypeScript/src/commands/index.ts @@ -1,5 +1,5 @@ import type { RESTPostAPIApplicationCommandsJSONBody, CommandInteraction } from 'discord.js'; -import type { StructurePredicate } from '../util/loaders.js'; +import type { StructurePredicate } from '../util/loaders.[REPLACE_IMPORT_EXT]'; /** * Defines the structure of a command diff --git a/packages/create-discord-bot/template/TypeScript/src/commands/ping.ts b/packages/create-discord-bot/template/TypeScript/src/commands/ping.ts index f9d45a8d1..a72cc3a08 100644 --- a/packages/create-discord-bot/template/TypeScript/src/commands/ping.ts +++ b/packages/create-discord-bot/template/TypeScript/src/commands/ping.ts @@ -1,4 +1,4 @@ -import type { Command } from './index.js'; +import type { Command } from './index.[REPLACE_IMPORT_EXT]'; export default { data: { 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 f342a9fc2..f347433f7 100644 --- a/packages/create-discord-bot/template/TypeScript/src/events/index.ts +++ b/packages/create-discord-bot/template/TypeScript/src/events/index.ts @@ -1,5 +1,5 @@ import type { ClientEvents } from 'discord.js'; -import type { StructurePredicate } from '../util/loaders.js'; +import type { StructurePredicate } from '../util/loaders.[REPLACE_IMPORT_EXT]'; /** * Defines the structure of an event. diff --git a/packages/create-discord-bot/template/TypeScript/src/events/ready.ts b/packages/create-discord-bot/template/TypeScript/src/events/ready.ts index 830fb3525..c5917b923 100644 --- a/packages/create-discord-bot/template/TypeScript/src/events/ready.ts +++ b/packages/create-discord-bot/template/TypeScript/src/events/ready.ts @@ -1,5 +1,5 @@ import { Events } from 'discord.js'; -import type { Event } from './index.js'; +import type { Event } from './index.[REPLACE_IMPORT_EXT]'; export default { name: Events.ClientReady, @@ -7,4 +7,4 @@ export default { async execute(client) { console.log(`Ready! Logged in as ${client.user.tag}`); }, -} satisfies Event<'ready'>; +} satisfies Event; diff --git a/packages/create-discord-bot/template/TypeScript/src/index.ts b/packages/create-discord-bot/template/TypeScript/src/index.ts index d45b56ef9..f0cb8afcb 100644 --- a/packages/create-discord-bot/template/TypeScript/src/index.ts +++ b/packages/create-discord-bot/template/TypeScript/src/index.ts @@ -1,7 +1,8 @@ +import process from 'node:process'; import { URL } from 'node:url'; import { Client, GatewayIntentBits } from 'discord.js'; -import { loadCommands, loadEvents } from './util/loaders.js'; -import { registerEvents } from './util/registerEvents.js'; +import { loadCommands, loadEvents } from './util/loaders.[REPLACE_IMPORT_EXT]'; +import { registerEvents } from './util/registerEvents.[REPLACE_IMPORT_EXT]'; // Initialize the client const client = new Client({ intents: [GatewayIntentBits.Guilds] }); @@ -14,4 +15,4 @@ const commands = await loadCommands(new URL('commands/', import.meta.url)); registerEvents(commands, events, client); // Login to the client -void client.login(); +void client.login(process.env.DISCORD_TOKEN); diff --git a/packages/create-discord-bot/template/TypeScript/src/util/deploy.ts b/packages/create-discord-bot/template/TypeScript/src/util/deploy.ts index 2472cd156..ee2b429c5 100644 --- a/packages/create-discord-bot/template/TypeScript/src/util/deploy.ts +++ b/packages/create-discord-bot/template/TypeScript/src/util/deploy.ts @@ -2,12 +2,12 @@ import process from 'node:process'; import { URL } from 'node:url'; import { API } from '@discordjs/core/http-only'; import { REST } from 'discord.js'; -import { loadCommands } from './loaders.js'; +import { loadCommands } from './loaders.[REPLACE_IMPORT_EXT]'; -const commands = await loadCommands(new URL('commands/', import.meta.url)); +const commands = await loadCommands(new URL('../commands/', import.meta.url)); const commandData = [...commands.values()].map((command) => command.data); -const rest = new REST({ version: '10' }).setToken(process.env.TOKEN!); +const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_TOKEN!); const api = new API(rest); const result = await api.applicationCommands.bulkOverwriteGlobalCommands(process.env.APPLICATION_ID!, commandData); diff --git a/packages/create-discord-bot/template/TypeScript/src/util/loaders.ts b/packages/create-discord-bot/template/TypeScript/src/util/loaders.ts index fcd7a5349..7f1f89c51 100644 --- a/packages/create-discord-bot/template/TypeScript/src/util/loaders.ts +++ b/packages/create-discord-bot/template/TypeScript/src/util/loaders.ts @@ -1,10 +1,10 @@ import type { PathLike } from 'node:fs'; import { readdir, stat } from 'node:fs/promises'; import { URL } from 'node:url'; -import type { Command } from '../commands/index.js'; -import { predicate as commandPredicate } from '../commands/index.js'; -import type { Event } from '../events/index.js'; -import { predicate as eventPredicate } from '../events/index.js'; +import type { Command } from '../commands/index.[REPLACE_IMPORT_EXT]'; +import { predicate as commandPredicate } from '../commands/index.[REPLACE_IMPORT_EXT]'; +import type { Event } from '../events/index.[REPLACE_IMPORT_EXT]'; +import { predicate as eventPredicate } from '../events/index.[REPLACE_IMPORT_EXT]'; /** * A predicate to check if the structure is valid @@ -40,8 +40,8 @@ export async function loadStructures( // Loop through all the files in the directory for (const file of files) { - // If the file is index.js or the file does not end with .js, skip the file - if (file === 'index.js' || !file.endsWith('.js')) { + // If the file is index.[REPLACE_IMPORT_EXT] or the file does not end with .[REPLACE_IMPORT_EXT], skip the file + if (file === 'index.[REPLACE_IMPORT_EXT]' || !file.endsWith('.[REPLACE_IMPORT_EXT]')) { continue; } diff --git a/packages/create-discord-bot/template/TypeScript/src/util/registerEvents.ts b/packages/create-discord-bot/template/TypeScript/src/util/registerEvents.ts index 4ab7679d8..8613fdb15 100644 --- a/packages/create-discord-bot/template/TypeScript/src/util/registerEvents.ts +++ b/packages/create-discord-bot/template/TypeScript/src/util/registerEvents.ts @@ -1,6 +1,6 @@ import { Events, type Client } from 'discord.js'; -import type { Command } from '../commands/index.js'; -import type { Event } from '../events/index.js'; +import type { Command } from '../commands/index.[REPLACE_IMPORT_EXT]'; +import type { Event } from '../events/index.[REPLACE_IMPORT_EXT]'; export function registerEvents(commands: Map, events: Event[], client: Client): void { // Create an event to handle command interactions diff --git a/packages/create-discord-bot/template/TypeScript/tsconfig.json b/packages/create-discord-bot/template/TypeScript/tsconfig.json index 961c0d5b0..bd2ed1264 100644 --- a/packages/create-discord-bot/template/TypeScript/tsconfig.json +++ b/packages/create-discord-bot/template/TypeScript/tsconfig.json @@ -6,6 +6,7 @@ "module": "ESNext", "moduleResolution": "NodeNext", "target": "ESNext", - "outDir": "dist" + "outDir": "dist", + "skipLibCheck": true } } diff --git a/packages/create-discord-bot/tsconfig.eslint.json b/packages/create-discord-bot/tsconfig.eslint.json index d04d4be3a..e7900de0a 100644 --- a/packages/create-discord-bot/tsconfig.eslint.json +++ b/packages/create-discord-bot/tsconfig.eslint.json @@ -16,5 +16,5 @@ "**/*.spec.js", "**/*.spec.mjs" ], - "exclude": [] + "exclude": ["template/Deno"] } diff --git a/packages/create-discord-bot/tsup.config.ts b/packages/create-discord-bot/tsup.config.ts index 7b4c30510..bf294d573 100644 --- a/packages/create-discord-bot/tsup.config.ts +++ b/packages/create-discord-bot/tsup.config.ts @@ -4,6 +4,7 @@ export default createTsupConfig({ entry: ['src/index.ts'], dts: false, format: 'esm', - minify: true, + minify: 'terser', + keepNames: false, sourcemap: false, }); diff --git a/yarn.lock b/yarn.lock index f4b95a0c9..e6003892c 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3624,6 +3624,16 @@ __metadata: languageName: node linkType: hard +"@jridgewell/source-map@npm:^0.3.3": + version: 0.3.5 + resolution: "@jridgewell/source-map@npm:0.3.5" + dependencies: + "@jridgewell/gen-mapping": ^0.3.0 + "@jridgewell/trace-mapping": ^0.3.9 + checksum: 1ad4dec0bdafbade57920a50acec6634f88a0eb735851e0dda906fa9894e7f0549c492678aad1a10f8e144bfe87f238307bf2a914a1bc85b7781d345417e9f6f + languageName: node + linkType: hard + "@jridgewell/sourcemap-codec@npm:^1.4.10, @jridgewell/sourcemap-codec@npm:^1.4.13, @jridgewell/sourcemap-codec@npm:^1.4.14, @jridgewell/sourcemap-codec@npm:^1.4.15": version: 1.4.15 resolution: "@jridgewell/sourcemap-codec@npm:1.4.15" @@ -8214,7 +8224,7 @@ __metadata: languageName: node linkType: hard -"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.10.0, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.9.0": +"acorn@npm:^8.0.0, acorn@npm:^8.0.4, acorn@npm:^8.10.0, acorn@npm:^8.4.1, acorn@npm:^8.6.0, acorn@npm:^8.8.2, acorn@npm:^8.9.0": version: 8.10.0 resolution: "acorn@npm:8.10.0" bin: @@ -9610,7 +9620,7 @@ __metadata: languageName: node linkType: hard -"chalk@npm:5.3.0, chalk@npm:^5.3.0": +"chalk@npm:5.3.0": version: 5.3.0 resolution: "chalk@npm:5.3.0" checksum: 623922e077b7d1e9dedaea6f8b9e9352921f8ae3afe739132e0e00c275971bdd331268183b2628cf4ab1727c45ea1f28d7e24ac23ce1db1eb653c414ca8a5a80 @@ -10178,7 +10188,7 @@ __metadata: languageName: node linkType: hard -"commander@npm:^2.12.1, commander@npm:^2.19.0": +"commander@npm:^2.12.1, commander@npm:^2.19.0, commander@npm:^2.20.0": version: 2.20.3 resolution: "commander@npm:2.20.3" checksum: ab8c07884e42c3a8dbc5dd9592c606176c7eb5c1ca5ff274bcf907039b2c41de3626f684ea75ccf4d361ba004bbaff1f577d5384c155f3871e456bdf27becf9e @@ -10755,14 +10765,16 @@ __metadata: "@types/prompts": ^2.4.4 "@types/validate-npm-package-name": ^4.0.0 "@vitest/coverage-v8": ^0.34.2 - chalk: ^5.3.0 commander: ^11.0.0 cross-env: ^7.0.3 eslint: ^8.47.0 eslint-config-neon: ^0.1.47 eslint-formatter-pretty: ^5.0.0 + fast-glob: ^3.3.1 + picocolors: ^1.0.0 prettier: ^2.8.8 prompts: ^2.4.2 + terser: ^5.19.2 tsup: ^7.2.0 typescript: ^5.1.6 validate-npm-package-name: ^5.0.0 @@ -22217,7 +22229,7 @@ __metadata: languageName: node linkType: hard -"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.21": +"source-map-support@npm:^0.5.16, source-map-support@npm:^0.5.21, source-map-support@npm:~0.5.20": version: 0.5.21 resolution: "source-map-support@npm:0.5.21" dependencies: @@ -23074,6 +23086,20 @@ __metadata: languageName: node linkType: hard +"terser@npm:^5.19.2": + version: 5.19.2 + resolution: "terser@npm:5.19.2" + dependencies: + "@jridgewell/source-map": ^0.3.3 + acorn: ^8.8.2 + commander: ^2.20.0 + source-map-support: ~0.5.20 + bin: + terser: bin/terser + checksum: e059177775b4d4f4cff219ad89293175aefbd1b081252270444dc83e42a2c5f07824eb2a85eae6e22ef6eb7ef04b21af36dd7d1dd7cfb93912310e57d416a205 + languageName: node + linkType: hard + "test-exclude@npm:^6.0.0": version: 6.0.0 resolution: "test-exclude@npm:6.0.0"