From 52a69d77d02d47f0c1c80f334250c66d660b5463 Mon Sep 17 00:00:00 2001 From: jacobhumston <57332486+jacobhumston@users.noreply.github.com> Date: Fri, 16 Jan 2026 07:57:47 -0500 Subject: [PATCH] feat(create-discord-bot): allow certain files/folders to be included in the target directory (#11368) * feat(create-discord-bot): allow empty git repositories * feat(create-discord-bot): create a .gitignore for git repositories * fix(create-discord-bot): correctly handle .git file edge case * refactor(create-discord-bot): use next.js "is-folder-empty" utility * refactor(create-discord-bot): combine checks * revert: revert comment change This reverts commit 2f8422e90d79c7c37335720ee1811fb0c16bc321. * feat(create-discord-bot): add .gitignore to templates * docs(create-discord-bot): add source link to isFolderEmpty util * docs(create-discord-bot): add @license JSDoc tag to license comment --------- Co-authored-by: kodiakhq[bot] <49736102+kodiakhq[bot]@users.noreply.github.com> --- .../src/create-discord-bot.ts | 5 +- .../src/util/isFolderEmpty.ts | 78 ++++++++++ .../template/Bun/JavaScript/.gitignore | 141 ++++++++++++++++++ .../template/Bun/TypeScript/.gitignore | 141 ++++++++++++++++++ .../template/Deno/.gitignore | 141 ++++++++++++++++++ .../template/JavaScript/.gitignore | 141 ++++++++++++++++++ .../template/TypeScript/.gitignore | 141 ++++++++++++++++++ 7 files changed, 786 insertions(+), 2 deletions(-) create mode 100644 packages/create-discord-bot/src/util/isFolderEmpty.ts create mode 100644 packages/create-discord-bot/template/Bun/JavaScript/.gitignore create mode 100644 packages/create-discord-bot/template/Bun/TypeScript/.gitignore create mode 100644 packages/create-discord-bot/template/Deno/.gitignore create mode 100644 packages/create-discord-bot/template/JavaScript/.gitignore create mode 100644 packages/create-discord-bot/template/TypeScript/.gitignore diff --git a/packages/create-discord-bot/src/create-discord-bot.ts b/packages/create-discord-bot/src/create-discord-bot.ts index 303b25f52..16fc3e82b 100644 --- a/packages/create-discord-bot/src/create-discord-bot.ts +++ b/packages/create-discord-bot/src/create-discord-bot.ts @@ -1,11 +1,12 @@ import type { ExecException } from 'node:child_process'; -import { cp, mkdir, stat, readdir, readFile, writeFile } from 'node:fs/promises'; +import { cp, mkdir, stat, readFile, writeFile } from 'node:fs/promises'; import path from 'node:path'; import process from 'node:process'; import { styleText } from 'node:util'; import type { PackageManager } from './helpers/packageManager.js'; import { install } from './helpers/packageManager.js'; import { GUIDE_URL } from './util/constants.js'; +import { isFolderEmpty } from './util/isFolderEmpty.js'; interface Options { directory: string; @@ -31,7 +32,7 @@ export async function createDiscordBot({ directory, installPackages, typescript, }); // If the directory is actually a file or if it's not empty, throw an error. - if (!directoryStats.isDirectory() || (await readdir(root)).length > 0) { + if (!directoryStats.isDirectory() || !isFolderEmpty(root, directoryName)) { console.error( styleText( 'red', diff --git a/packages/create-discord-bot/src/util/isFolderEmpty.ts b/packages/create-discord-bot/src/util/isFolderEmpty.ts new file mode 100644 index 000000000..2bd17a417 --- /dev/null +++ b/packages/create-discord-bot/src/util/isFolderEmpty.ts @@ -0,0 +1,78 @@ +/** + * @license MIT + * + * Copyright (c) 2025 Vercel, Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE + * FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * Source: https://github.com/vercel/next.js/blob/7fb2aa908216fb3a910c7fa6d24524412b5af6e5/packages/create-next-app/helpers/is-folder-empty.ts + */ +import { lstatSync, readdirSync } from 'node:fs'; +import { join } from 'node:path'; +import { styleText } from 'node:util'; + +export function isFolderEmpty(root: string, name: string): boolean { + const validFiles = [ + '.DS_Store', + '.git', + '.gitattributes', + '.gitignore', + '.gitlab-ci.yml', + '.hg', + '.hgcheck', + '.hgignore', + '.idea', + '.npmignore', + '.travis.yml', + 'LICENSE', + 'Thumbs.db', + 'docs', + 'mkdocs.yml', + 'npm-debug.log', + 'yarn-debug.log', + 'yarn-error.log', + 'yarnrc.yml', + '.yarn', + ]; + + const conflicts = readdirSync(root).filter( + (file) => + !validFiles.includes(file) && + // Support IntelliJ IDEA-based editors + !file.endsWith('.iml'), + ); + + if (conflicts.length > 0) { + console.log(`The directory ${styleText('green', name)} contains files that could conflict:`); + console.log(); + for (const file of conflicts) { + try { + const stats = lstatSync(join(root, file)); + if (stats.isDirectory()) { + console.log(` ${styleText('blue', file)}/`); + } else { + console.log(` ${file}`); + } + } catch { + console.log(` ${file}`); + } + } + + console.log(); + console.log('Either try using a new directory name, or remove the files listed above.'); + console.log(); + return false; + } + + return true; +} diff --git a/packages/create-discord-bot/template/Bun/JavaScript/.gitignore b/packages/create-discord-bot/template/Bun/JavaScript/.gitignore new file mode 100644 index 000000000..0ccb8df8d --- /dev/null +++ b/packages/create-discord-bot/template/Bun/JavaScript/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/ diff --git a/packages/create-discord-bot/template/Bun/TypeScript/.gitignore b/packages/create-discord-bot/template/Bun/TypeScript/.gitignore new file mode 100644 index 000000000..0ccb8df8d --- /dev/null +++ b/packages/create-discord-bot/template/Bun/TypeScript/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/ diff --git a/packages/create-discord-bot/template/Deno/.gitignore b/packages/create-discord-bot/template/Deno/.gitignore new file mode 100644 index 000000000..0ccb8df8d --- /dev/null +++ b/packages/create-discord-bot/template/Deno/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/ diff --git a/packages/create-discord-bot/template/JavaScript/.gitignore b/packages/create-discord-bot/template/JavaScript/.gitignore new file mode 100644 index 000000000..0ccb8df8d --- /dev/null +++ b/packages/create-discord-bot/template/JavaScript/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/ diff --git a/packages/create-discord-bot/template/TypeScript/.gitignore b/packages/create-discord-bot/template/TypeScript/.gitignore new file mode 100644 index 000000000..0ccb8df8d --- /dev/null +++ b/packages/create-discord-bot/template/TypeScript/.gitignore @@ -0,0 +1,141 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.* +!.env.example + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist +.output + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Sveltekit cache directory +.svelte-kit/ + +# vitepress build output +**/.vitepress/dist + +# vitepress cache directory +**/.vitepress/cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# Firebase cache directory +.firebase/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v3 +.pnp.* +.yarn/* +!.yarn/patches +!.yarn/plugins +!.yarn/releases +!.yarn/sdks +!.yarn/versions + +# Vite files +vite.config.js.timestamp-* +vite.config.ts.timestamp-* +.vite/