create-commandkit 1.2.0-rc.12 → 1.2.0-rc.13

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (33) hide show
  1. package/{COPYING.md → LICENSE.md} +3 -3
  2. package/README.md +73 -4
  3. package/dist/cli.d.ts +2 -0
  4. package/dist/cli.js +39 -0
  5. package/dist/functions/fetchExample.d.ts +6 -0
  6. package/dist/functions/fetchExample.js +63 -0
  7. package/dist/functions/validate.d.ts +12 -0
  8. package/dist/functions/validate.js +70 -0
  9. package/dist/index.js +188 -86
  10. package/dist/types.d.ts +15 -1
  11. package/dist/utils.d.ts +20 -7
  12. package/dist/utils.js +75 -23
  13. package/package.json +12 -8
  14. package/dist/functions/copyTemplates.d.ts +0 -5
  15. package/dist/functions/copyTemplates.js +0 -47
  16. package/dist/functions/installDeps.d.ts +0 -10
  17. package/dist/functions/installDeps.js +0 -49
  18. package/dist/functions/setup.d.ts +0 -10
  19. package/dist/functions/setup.js +0 -68
  20. package/templates/JavaScript/README.md +0 -16
  21. package/templates/JavaScript/commandkit-env.d.ts +0 -1
  22. package/templates/JavaScript/commandkit.config.mjs +0 -3
  23. package/templates/JavaScript/jsconfig.json +0 -30
  24. package/templates/JavaScript/src/app/commands/ping.js +0 -27
  25. package/templates/JavaScript/src/app/events/clientReady/log.js +0 -10
  26. package/templates/JavaScript/src/app.js +0 -7
  27. package/templates/TypeScript/README.md +0 -16
  28. package/templates/TypeScript/commandkit-env.d.ts +0 -1
  29. package/templates/TypeScript/commandkit.config.ts +0 -3
  30. package/templates/TypeScript/src/app/commands/ping.ts +0 -20
  31. package/templates/TypeScript/src/app/events/clientReady/log.ts +0 -8
  32. package/templates/TypeScript/src/app.ts +0 -7
  33. package/templates/TypeScript/tsconfig.json +0 -29
@@ -639,8 +639,8 @@ attach them to the start of each source file to most effectively state
639
639
  the exclusion of warranty; and each file should have at least the
640
640
  "copyright" line and a pointer to where the full notice is found.
641
641
 
642
- <one line to give the program's name and a brief idea of what it does.>
643
- Copyright (C) <year> <name of author>
642
+ CommandKit is a discord.js metaframework
643
+ Copyright (C) 2026 Neplex
644
644
 
645
645
  This program is free software: you can redistribute it and/or modify
646
646
  it under the terms of the GNU General Public License as published by
@@ -661,7 +661,7 @@ mail.
661
661
  If the program does terminal interaction, make it output a short
662
662
  notice like this when it starts in an interactive mode:
663
663
 
664
- <program> Copyright (C) <year> <name of author>
664
+ CommandKit Copyright (C) 2026 Neplex
665
665
  This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
666
666
  This is free software, and you are welcome to redistribute it
667
667
  under certain conditions; type `show c' for details.
package/README.md CHANGED
@@ -1,7 +1,7 @@
1
1
  <div align="center">
2
- <img src="https://raw.githubusercontent.com/underctrl-io/commandkit/main/apps/website/static/img/ckit_logo.svg" width="60%" />
2
+ <img src="https://raw.githubusercontent.com/neplextech/commandkit/main/apps/website/static/img/ckit_logo.svg" width="60%" />
3
3
  <br />
4
- <a href="https://ctrl.lol/discord"><img src="https://img.shields.io/discord/1055188344188973066?color=5865F2&logo=discord&logoColor=white" alt="support server" /></a>
4
+ <a href="https://commandkit.dev/discord"><img src="https://img.shields.io/discord/1055188344188973066?color=5865F2&logo=discord&logoColor=white" alt="support server" /></a>
5
5
  <a href="https://www.npmjs.com/package/create-commandkit"><img src="https://img.shields.io/npm/v/create-commandkit?maxAge=3600" alt="npm version" /></a>
6
6
  <a href="https://www.npmjs.com/package/create-commandkit"><img src="https://img.shields.io/npm/dt/create-commandkit?maxAge=3600" alt="npm downloads" /></a>
7
7
  </div>
@@ -14,6 +14,9 @@ create-commandkit is a CLI utility to quickly instantiate a Discord bot with Com
14
14
 
15
15
  - Interactive, beautiful command-line interface 🖥️
16
16
  - Supports CommonJS and ES Modules 📦
17
+ - Dynamic template system with examples from GitHub 🚀
18
+ - Support for all major package managers (npm, pnpm, yarn, bun, deno) 📦
19
+ - TypeScript and JavaScript support 🔧
17
20
 
18
21
  ## Documentation
19
22
 
@@ -21,12 +24,78 @@ You can find the full documentation [here](https://commandkit.dev).
21
24
 
22
25
  ## Usage
23
26
 
24
- Run the following command in your terminal:
27
+ ### Basic Usage
25
28
 
26
29
  ```sh
27
30
  npx create-commandkit@latest
28
31
  ```
29
32
 
33
+ ### With Project Name
34
+
35
+ ```sh
36
+ npx create-commandkit@latest my-bot
37
+ ```
38
+
39
+ ### Using Examples
40
+
41
+ ```sh
42
+ # Use a curated example
43
+ npx create-commandkit@latest --example with-database
44
+
45
+ # Use a custom GitHub repository
46
+ npx create-commandkit@latest --example "https://github.com/user/repo"
47
+
48
+ # Use a specific path within a repository
49
+ npx create-commandkit@latest --example "https://github.com/user/repo" --example-path "examples/bot"
50
+ ```
51
+
52
+ ### CLI Options
53
+
54
+ - `-h, --help` - Show all available options
55
+ - `-V, --version` - Output the version number
56
+ - `-e, --example <name-or-url>` - An example to bootstrap the app with
57
+ - `--example-path <path>` - Specify the path to the example separately
58
+ - `--use-npm` - Use npm as package manager
59
+ - `--use-pnpm` - Use pnpm as package manager
60
+ - `--use-yarn` - Use yarn as package manager
61
+ - `--use-bun` - Use bun as package manager
62
+ - `--use-deno` - Use deno as package manager
63
+ - `--skip-install` - Skip installing packages
64
+ - `--no-git` - Skip git initialization
65
+ - `--yes` - Use defaults for all options
66
+ - `--list-examples` - List all available examples from the official repository
67
+
68
+ ### Available Examples
69
+
70
+ <!-- BEGIN_AVAILABLE_EXAMPLES -->
71
+ - `basic-js` - [examples/basic-js](https://github.com/neplextech/commandkit/tree/main/examples/basic-js)
72
+ - `basic-ts` - [examples/basic-ts](https://github.com/neplextech/commandkit/tree/main/examples/basic-ts)
73
+ - `deno-ts` - [examples/deno-ts](https://github.com/neplextech/commandkit/tree/main/examples/deno-ts)
74
+ - `with-ai` - [examples/with-ai](https://github.com/neplextech/commandkit/tree/main/examples/with-ai)
75
+ - `with-leveling-system` - [examples/with-leveling-system](https://github.com/neplextech/commandkit/tree/main/examples/with-leveling-system)
76
+ - `with-workflow` - [examples/with-workflow](https://github.com/neplextech/commandkit/tree/main/examples/with-workflow)
77
+ - `without-cli` - [examples/without-cli](https://github.com/neplextech/commandkit/tree/main/examples/without-cli)
78
+ <!-- END_AVAILABLE_EXAMPLES -->
79
+
80
+ ### Examples
81
+
82
+ ```sh
83
+ # Create a basic TypeScript bot, skip installation
84
+ npx create-commandkit@latest --example basic-ts --skip-install
85
+
86
+ # Create a bot with all defaults (no prompts)
87
+ npx create-commandkit@latest --yes
88
+
89
+ # Create a bot from custom repository
90
+ npx create-commandkit@latest --example "https://github.com/username/my-commandkit-template"
91
+
92
+ # Create a bot with pnpm
93
+ npx create-commandkit@latest --use-pnpm
94
+
95
+ # List all available examples
96
+ npx create-commandkit@latest --list-examples
97
+ ```
98
+
30
99
  ## Support and Suggestions
31
100
 
32
- Submit any queries or suggestions in our [Discord community](https://ctrl.lol/discord).
101
+ Submit any queries or suggestions in our [Discord community](https://commandkit.dev/discord).
package/dist/cli.d.ts ADDED
@@ -0,0 +1,2 @@
1
+ import type { CLIOptions } from './types.js';
2
+ export declare function parseCLI(): CLIOptions;
package/dist/cli.js ADDED
@@ -0,0 +1,39 @@
1
+ import { Command } from 'commander';
2
+ export function parseCLI() {
3
+ const program = new Command();
4
+ program
5
+ .name('create-commandkit')
6
+ .description('Effortlessly create a CommandKit project')
7
+ .version(process.env.npm_package_version || '1.0.0')
8
+ .argument('[project-directory]', 'Project directory name')
9
+ .option('-h, --help', 'Show all available options')
10
+ .option('-e, --example <name-or-url>', 'An example to bootstrap the app with')
11
+ .option('--example-path <path>', 'Specify the path to the example separately')
12
+ .option('--use-npm', 'Explicitly tell the CLI to bootstrap using npm')
13
+ .option('--use-pnpm', 'Explicitly tell the CLI to bootstrap using pnpm')
14
+ .option('--use-yarn', 'Explicitly tell the CLI to bootstrap using yarn')
15
+ .option('--use-bun', 'Explicitly tell the CLI to bootstrap using bun')
16
+ .option('--use-deno', 'Explicitly tell the CLI to bootstrap using deno')
17
+ .option('--skip-install', 'Explicitly tell the CLI to skip installing packages')
18
+ .option('--no-git', 'Explicitly tell the CLI to disable git initialization')
19
+ .option('--yes', 'Use previous preferences or defaults for all options')
20
+ .option('--list-examples', 'List all available examples from the official repository');
21
+ program.parse();
22
+ const options = program.opts();
23
+ const args = program.args;
24
+ return {
25
+ help: options.help,
26
+ example: options.example,
27
+ examplePath: options.examplePath,
28
+ useNpm: options.useNpm,
29
+ usePnpm: options.usePnpm,
30
+ useYarn: options.useYarn,
31
+ useBun: options.useBun,
32
+ useDeno: options.useDeno,
33
+ skipInstall: options.skipInstall,
34
+ noGit: options.noGit,
35
+ yes: options.yes,
36
+ listExamples: options.listExamples,
37
+ projectDirectory: args[0],
38
+ };
39
+ }
@@ -0,0 +1,6 @@
1
+ export interface FetchExampleOptions {
2
+ example: string;
3
+ examplePath?: string;
4
+ targetDir: string;
5
+ }
6
+ export declare function fetchExample({ example, examplePath, targetDir, }: FetchExampleOptions): Promise<void>;
@@ -0,0 +1,63 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ // @ts-ignore
4
+ import tiged from 'tiged';
5
+ import { validateExampleName } from './validate.js';
6
+ export async function fetchExample({ example, examplePath, targetDir, }) {
7
+ const validation = validateExampleName(example);
8
+ if (!validation.valid) {
9
+ throw new Error(validation.error);
10
+ }
11
+ let sourceUrl;
12
+ // Check if it's a GitHub URL
13
+ if (example.startsWith('http://') || example.startsWith('https://')) {
14
+ sourceUrl = example;
15
+ }
16
+ else {
17
+ // Construct URL for curated examples
18
+ sourceUrl = `neplextech/commandkit/examples/${example}`;
19
+ }
20
+ // Create temporary directory for download
21
+ const tempDir = path.join(targetDir, '.temp-example');
22
+ try {
23
+ // Download the example
24
+ const emitter = tiged(sourceUrl, {
25
+ mode: 'tar',
26
+ disableCache: true,
27
+ });
28
+ await emitter.clone(tempDir);
29
+ // If examplePath is specified, navigate to that subdirectory
30
+ const sourceDir = examplePath ? path.join(tempDir, examplePath) : tempDir;
31
+ if (examplePath && !fs.existsSync(sourceDir)) {
32
+ throw new Error(`Example path '${examplePath}' not found in the repository`);
33
+ }
34
+ // Copy contents to target directory
35
+ const contents = fs.readdirSync(sourceDir);
36
+ for (const item of contents) {
37
+ const srcPath = path.join(sourceDir, item);
38
+ const destPath = path.join(targetDir, item);
39
+ if (fs.statSync(srcPath).isDirectory()) {
40
+ await fs.copy(srcPath, destPath);
41
+ }
42
+ else {
43
+ await fs.copy(srcPath, destPath);
44
+ }
45
+ }
46
+ // Clean up temporary directory
47
+ await fs.remove(tempDir);
48
+ }
49
+ catch (error) {
50
+ // Clean up on error
51
+ if (fs.existsSync(tempDir)) {
52
+ await fs.remove(tempDir);
53
+ }
54
+ if (error instanceof Error) {
55
+ if (error.message.includes('not found') ||
56
+ error.message.includes('404')) {
57
+ throw new Error(`Example '${example}' not found. Available examples: basic-ts, basic-js, deno-ts, without-cli`);
58
+ }
59
+ throw new Error(`Failed to fetch example: ${error.message}`);
60
+ }
61
+ throw new Error('Failed to fetch example due to an unknown error');
62
+ }
63
+ }
@@ -0,0 +1,12 @@
1
+ export declare function validateProjectName(name: string): {
2
+ valid: boolean;
3
+ error?: string;
4
+ };
5
+ export declare function validateDirectory(dir: string): {
6
+ valid: boolean;
7
+ error?: string;
8
+ };
9
+ export declare function validateExampleName(example: string): {
10
+ valid: boolean;
11
+ error?: string;
12
+ };
@@ -0,0 +1,70 @@
1
+ import fs from 'fs-extra';
2
+ import path from 'node:path';
3
+ import validateNpmPackageName from 'validate-npm-package-name';
4
+ export function validateProjectName(name) {
5
+ const result = validateNpmPackageName(name);
6
+ if (!result.validForNewPackages) {
7
+ const errors = result.errors || [];
8
+ const warnings = result.warnings || [];
9
+ const allIssues = [...errors, ...warnings];
10
+ return {
11
+ valid: false,
12
+ error: allIssues.length > 0 ? allIssues[0] : 'Invalid project name',
13
+ };
14
+ }
15
+ return { valid: true };
16
+ }
17
+ export function validateDirectory(dir) {
18
+ const resolvedDir = path.resolve(process.cwd(), dir);
19
+ try {
20
+ const exists = fs.existsSync(resolvedDir);
21
+ if (!exists) {
22
+ return { valid: true };
23
+ }
24
+ const contents = fs.readdirSync(resolvedDir);
25
+ const isEmpty = contents.length === 0;
26
+ if (!isEmpty) {
27
+ return {
28
+ valid: false,
29
+ error: 'Directory is not empty!',
30
+ };
31
+ }
32
+ return { valid: true };
33
+ }
34
+ catch (error) {
35
+ return {
36
+ valid: false,
37
+ error: 'Unable to access directory',
38
+ };
39
+ }
40
+ }
41
+ export function validateExampleName(example) {
42
+ // Check if it's a GitHub URL
43
+ if (example.startsWith('http://') || example.startsWith('https://')) {
44
+ try {
45
+ const url = new URL(example);
46
+ if (url.hostname === 'github.com' || url.hostname === 'www.github.com') {
47
+ return { valid: true };
48
+ }
49
+ return {
50
+ valid: false,
51
+ error: 'Only GitHub URLs are supported',
52
+ };
53
+ }
54
+ catch {
55
+ return {
56
+ valid: false,
57
+ error: 'Invalid URL format',
58
+ };
59
+ }
60
+ }
61
+ // Check if it's a valid example name (alphanumeric, hyphens, underscores)
62
+ const exampleNameRegex = /^[a-zA-Z0-9-_]+$/;
63
+ if (!exampleNameRegex.test(example)) {
64
+ return {
65
+ valid: false,
66
+ error: 'Example name can only contain letters, numbers, hyphens, and underscores',
67
+ };
68
+ }
69
+ return { valid: true };
70
+ }
package/dist/index.js CHANGED
@@ -1,107 +1,209 @@
1
1
  #!/usr/bin/env node
2
- console.clear();
3
- import { confirm, intro, outro, password, select, text } from '@clack/prompts';
2
+ import { confirm, intro, outro, password, text } from '@clack/prompts';
4
3
  import fs from 'fs-extra';
5
4
  import gradient from 'gradient-string';
6
5
  import { execSync } from 'node:child_process';
7
- import path from 'node:path';
6
+ import path, { join } from 'node:path';
8
7
  import colors from 'picocolors';
9
- import { copyTemplates } from './functions/copyTemplates.js';
10
- import { installDeps } from './functions/installDeps.js';
11
- import { setup } from './functions/setup.js';
12
- import { detectPackageManager, textColors } from './utils.js';
13
- const commandkitGradient = gradient(textColors.commandkit)('CommandKit');
14
- intro(`Welcome to ${commandkitGradient}!`);
15
- const dir = path.resolve(process.cwd(), (await text({
16
- message: 'Enter a project directory:',
17
- placeholder: 'Leave blank for current directory',
18
- defaultValue: '.',
19
- validate: (value) => {
20
- value = path.resolve(process.cwd(), value);
21
- let isEmpty;
8
+ import { parseCLI } from './cli.js';
9
+ import { fetchExample } from './functions/fetchExample.js';
10
+ import { validateDirectory, validateProjectName, } from './functions/validate.js';
11
+ import { fetchAvailableExamples, getDefaultExample, getInstallCommand, isOfficialExample, resolvePackageManager, textColors, } from './utils.js';
12
+ import { readFile } from 'node:fs/promises';
13
+ async function main() {
14
+ const cliOptions = parseCLI();
15
+ // Handle help and version flags
16
+ if (cliOptions.help) {
17
+ console.log(`
18
+ Usage: create-commandkit [options] [project-directory]
19
+
20
+ Options:
21
+ -h, --help Show all available options
22
+ -V, --version Output the version number
23
+ -e, --example <name-or-url> An example to bootstrap the app with
24
+ --example-path <path> Specify the path to the example separately
25
+ --use-npm Explicitly tell the CLI to bootstrap using npm
26
+ --use-pnpm Explicitly tell the CLI to bootstrap using pnpm
27
+ --use-yarn Explicitly tell the CLI to bootstrap using yarn
28
+ --use-bun Explicitly tell the CLI to bootstrap using bun
29
+ --use-deno Explicitly tell the CLI to bootstrap using deno
30
+ --skip-install Explicitly tell the CLI to skip installing packages
31
+ --no-git Explicitly tell the CLI to disable git initialization
32
+ --yes Use previous preferences or defaults for all options
33
+ --list-examples List all available examples from the official repository
34
+
35
+ Examples:
36
+ npx create-commandkit@latest
37
+ npx create-commandkit@latest my-bot
38
+ npx create-commandkit@latest --example basic-ts
39
+ npx create-commandkit@latest --example "https://github.com/user/repo" --example-path "examples/bot"
40
+ npx create-commandkit@latest --use-pnpm --yes
41
+ npx create-commandkit@latest --list-examples
42
+ `);
43
+ process.exit(0);
44
+ }
45
+ // Handle list examples flag
46
+ if (cliOptions.listExamples) {
47
+ console.log(colors.cyan('Fetching available examples...'));
22
48
  try {
23
- const contents = fs.readdirSync(value);
24
- isEmpty = contents.length === 0;
49
+ const examples = await fetchAvailableExamples();
50
+ console.log(colors.green('\nAvailable examples:'));
51
+ console.log('');
52
+ for (const example of examples) {
53
+ console.log(` ${colors.magenta(example)}`);
54
+ }
55
+ console.log('');
56
+ console.log(colors.gray('Usage: npx create-commandkit@latest --example <example-name>'));
57
+ console.log(colors.gray('Example: npx create-commandkit@latest --example basic-ts'));
25
58
  }
26
- catch {
27
- isEmpty = true;
59
+ catch (error) {
60
+ console.error(colors.red('Failed to fetch examples list. Please check your internet connection.'));
61
+ process.exit(1);
28
62
  }
29
- return isEmpty ? undefined : 'Directory is not empty!';
30
- },
31
- })));
32
- const manager = (await select({
33
- message: 'Select a package manager:',
34
- initialValue: detectPackageManager(),
35
- options: [
36
- { label: 'npm', value: 'npm' },
37
- { label: 'pnpm', value: 'pnpm' },
38
- { label: 'yarn', value: 'yarn' },
39
- { label: 'bun', value: 'bun' },
40
- { label: 'deno', value: 'deno' },
41
- ],
42
- }));
43
- const lang = (await select({
44
- message: 'Select the language to use:',
45
- initialValue: 'ts',
46
- options: [
47
- { label: 'TypeScript', value: 'ts' },
48
- { label: 'JavaScript', value: 'js' },
49
- ],
50
- }));
51
- const token = (await password({
52
- message: 'Enter your Discord bot token (stored in .env, optional):',
53
- mask: colors.gray('*'),
54
- }));
55
- const gitInit = await confirm({
56
- message: 'Initialize a git repository?',
57
- initialValue: true,
58
- });
59
- outro(colors.cyan('Setup complete.'));
60
- await setup({
61
- manager,
62
- dir,
63
- token,
64
- });
65
- await copyTemplates({ dir, lang });
66
- if (gitInit) {
63
+ process.exit(0);
64
+ }
65
+ const commandkitGradient = gradient(textColors.commandkit)('CommandKit');
66
+ intro(`Welcome to ${commandkitGradient}!`);
67
+ // Determine project directory
68
+ let projectDir;
69
+ if (cliOptions.projectDirectory) {
70
+ projectDir = path.resolve(process.cwd(), cliOptions.projectDirectory);
71
+ // Validate project name if provided
72
+ const projectName = path.basename(projectDir);
73
+ const nameValidation = validateProjectName(projectName);
74
+ if (!nameValidation.valid) {
75
+ console.error(colors.red(`Error: ${nameValidation.error}`));
76
+ process.exit(1);
77
+ }
78
+ }
79
+ else if (cliOptions.yes) {
80
+ projectDir = path.resolve(process.cwd(), 'commandkit-project');
81
+ }
82
+ else {
83
+ projectDir = path.resolve(process.cwd(), (await text({
84
+ message: 'Enter a project directory:',
85
+ placeholder: 'Leave blank for current directory',
86
+ defaultValue: '.',
87
+ validate: (value) => {
88
+ value = path.resolve(process.cwd(), value);
89
+ const validation = validateDirectory(value);
90
+ return validation.valid ? undefined : validation.error;
91
+ },
92
+ })));
93
+ }
94
+ // Validate directory
95
+ const dirValidation = validateDirectory(projectDir);
96
+ if (!dirValidation.valid) {
97
+ console.error(colors.red(`Error: ${dirValidation.error}`));
98
+ process.exit(1);
99
+ }
100
+ // Get Discord token
101
+ let token;
102
+ if (cliOptions.yes) {
103
+ token = '';
104
+ }
105
+ else {
106
+ token = (await password({
107
+ message: 'Enter your Discord bot token (stored in .env, optional):',
108
+ mask: colors.gray('*'),
109
+ }));
110
+ }
111
+ // Determine git initialization
112
+ const gitInit = cliOptions.noGit
113
+ ? false
114
+ : cliOptions.yes
115
+ ? true
116
+ : await confirm({
117
+ message: 'Initialize a git repository?',
118
+ initialValue: true,
119
+ });
120
+ outro(colors.cyan('Setup complete.'));
121
+ const example = cliOptions.example || getDefaultExample(cliOptions);
122
+ // Determine package manager
123
+ const manager = resolvePackageManager(cliOptions, example);
124
+ // Fetch example from GitHub
67
125
  try {
68
- execSync('git init', { cwd: dir, stdio: 'pipe' });
126
+ await fetchExample({
127
+ example,
128
+ examplePath: cliOptions.examplePath,
129
+ targetDir: projectDir,
130
+ });
131
+ // Create .env file with token
132
+ await fs.writeFile(`${projectDir}/.env`, `DISCORD_TOKEN="${token || ''}"`);
133
+ // Install packages for official examples
134
+ if (isOfficialExample(example) && !cliOptions.skipInstall) {
135
+ console.log(colors.cyan('Installing dependencies for official example...'));
136
+ try {
137
+ const tagMap = [
138
+ ['-dev.', 'dev'],
139
+ ['-rc.', 'next'],
140
+ ];
141
+ const tag = await readFile(join(import.meta.dirname, '..', 'package.json'), 'utf-8')
142
+ .then((data) => {
143
+ const version = JSON.parse(data).version;
144
+ return (tagMap.find(([suffix]) => version.includes(suffix))?.[1] ||
145
+ 'latest');
146
+ })
147
+ .catch(() => 'latest');
148
+ // Install dependencies
149
+ const depsCommand = getInstallCommand(manager, [
150
+ `commandkit@${tag}`,
151
+ 'discord.js',
152
+ ]);
153
+ execSync(depsCommand, { cwd: projectDir, stdio: 'pipe' });
154
+ // Install dev dependencies
155
+ const devDepsCommand = getInstallCommand(manager, ['typescript', '@types/node'], true);
156
+ execSync(devDepsCommand, { cwd: projectDir, stdio: 'pipe' });
157
+ console.log(colors.green('Dependencies installed successfully!'));
158
+ }
159
+ catch (error) {
160
+ console.log(colors.yellow('Warning: Failed to install dependencies. You may need to install them manually.'));
161
+ }
162
+ }
69
163
  }
70
164
  catch (error) {
71
- console.log(colors.yellow('Warning: Git initialization failed. Make sure Git is installed on your system.'));
165
+ console.error(colors.red(`Error fetching example: ${error instanceof Error ? error.message : 'Unknown error'}`));
166
+ process.exit(1);
72
167
  }
73
- }
74
- installDeps({
75
- dir,
76
- manager,
77
- lang,
78
- stdio: 'pipe',
79
- });
80
- const command = (cmd) => {
81
- switch (manager) {
82
- case 'npm':
83
- // bun build runs bundler instead of the build script
84
- case 'bun':
85
- return `${manager} run ${cmd}`;
86
- case 'pnpm':
87
- case 'yarn':
88
- return `${manager} ${cmd}`;
89
- case 'deno':
90
- return `deno task ${cmd}`;
91
- default:
92
- return manager;
168
+ // Initialize git if requested
169
+ if (gitInit) {
170
+ try {
171
+ execSync('git init', { cwd: projectDir, stdio: 'pipe' });
172
+ }
173
+ catch (error) {
174
+ console.log(colors.yellow('Warning: Git initialization failed. Make sure Git is installed on your system.'));
175
+ }
93
176
  }
94
- };
95
- console.log(`${gradient(textColors.commandkit)('Thank you for choosing CommandKit!')}
177
+ const command = (cmd) => {
178
+ switch (manager) {
179
+ case 'npm':
180
+ // bun build runs bundler instead of the build script
181
+ case 'bun':
182
+ return `${manager} run ${cmd}`;
183
+ case 'pnpm':
184
+ case 'yarn':
185
+ return `${manager} ${cmd}`;
186
+ case 'deno':
187
+ return `deno task ${cmd}`;
188
+ default:
189
+ return manager;
190
+ }
191
+ };
192
+ console.log(`${gradient(textColors.commandkit)('Thank you for choosing CommandKit!')}
96
193
 
97
- To start your bot, use the following commands:
194
+ To start your bot${projectDir !== '.' ? `, ${colors.magenta(`cd ${projectDir}`)}` : ''}${projectDir !== '.' ? ' and' : ''} use the following commands:
98
195
  ${colors.magenta(command('dev'))} - Run your bot in development mode
99
196
  ${colors.magenta(command('build'))} - Build your bot for production
100
197
  ${colors.magenta(command('start'))} - Run your bot in production mode
101
198
 
102
199
  • Documentation: ${colors.blue('https://commandkit.dev')}
103
- • GitHub: ${colors.blue('https://github.com/underctrl-io/commandkit')}
104
- Under Ctrl: ${colors.blue('https://underctrl.io')}
105
- • Discord community: ${colors.blue('https://ctrl.lol/discord')}
200
+ • GitHub: ${colors.blue('https://github.com/neplextech/commandkit')}
201
+ Neplex: ${colors.blue('https://neplextech.com')}
202
+ • Discord community: ${colors.blue('https://commandkit.dev/discord')}
106
203
 
107
204
  Happy coding! 🚀`);
205
+ }
206
+ main().catch((error) => {
207
+ console.error(colors.red(`Error: ${error instanceof Error ? error.message : 'Unknown error'}`));
208
+ process.exit(1);
209
+ });
package/dist/types.d.ts CHANGED
@@ -1,2 +1,16 @@
1
- export type Language = 'js' | 'ts';
2
1
  export type PackageManager = 'npm' | 'pnpm' | 'yarn' | 'bun' | 'deno';
2
+ export interface CLIOptions {
3
+ help?: boolean;
4
+ example?: string;
5
+ examplePath?: string;
6
+ useNpm?: boolean;
7
+ usePnpm?: boolean;
8
+ useYarn?: boolean;
9
+ useBun?: boolean;
10
+ useDeno?: boolean;
11
+ skipInstall?: boolean;
12
+ noGit?: boolean;
13
+ yes?: boolean;
14
+ listExamples?: boolean;
15
+ projectDirectory?: string;
16
+ }
package/dist/utils.d.ts CHANGED
@@ -1,13 +1,26 @@
1
- import type { PackageManager } from './types';
1
+ import type { CLIOptions, PackageManager } from './types';
2
2
  export declare const textColors: {
3
3
  commandkit: string[];
4
4
  js: string[];
5
5
  ts: string[];
6
6
  };
7
- export declare const commands: {
8
- init: {
9
- yarn: string;
10
- };
11
- };
12
7
  export declare function detectPackageManager(): PackageManager;
13
- export declare function getCommandKitVersion(): string;
8
+ export declare function getPackageManagerFromCLI(options: {
9
+ useNpm?: boolean;
10
+ usePnpm?: boolean;
11
+ useYarn?: boolean;
12
+ useBun?: boolean;
13
+ useDeno?: boolean;
14
+ }): PackageManager | null;
15
+ export declare function resolvePackageManager(cliOptions: {
16
+ useNpm?: boolean;
17
+ usePnpm?: boolean;
18
+ useYarn?: boolean;
19
+ useBun?: boolean;
20
+ useDeno?: boolean;
21
+ }, name: string): PackageManager;
22
+ export declare function getDefaultExample(cliOptions: CLIOptions): string;
23
+ export declare function isOfficialExample(example: string): boolean;
24
+ export declare function getInstallCommand(manager: PackageManager, deps: string[], dev?: boolean): string;
25
+ export declare function fetchAvailableExamples(): Promise<string[]>;
26
+ export declare function isDenoProject(example: string): boolean;
package/dist/utils.js CHANGED
@@ -1,16 +1,8 @@
1
- import fs from 'fs-extra';
2
- import path from 'node:path';
3
- import { fileURLToPath } from 'node:url';
4
1
  export const textColors = {
5
2
  commandkit: ['#fdba74', '#e4a5a2', '#c288de', '#b27bf9'],
6
3
  js: ['#f7e01c', '#f7e01c'],
7
4
  ts: ['#2480c5', '#2480c5'],
8
5
  };
9
- export const commands = {
10
- init: {
11
- yarn: 'yarn set version stable; yarn config set nodeLinker node-modules;',
12
- },
13
- };
14
6
  export function detectPackageManager() {
15
7
  const packageManager = process.env.npm_config_user_agent;
16
8
  if (packageManager?.includes('pnpm'))
@@ -25,25 +17,85 @@ export function detectPackageManager() {
25
17
  return 'deno';
26
18
  return 'npm';
27
19
  }
28
- export function getCommandKitVersion() {
29
- try {
30
- const __filename = fileURLToPath(import.meta.url);
31
- const __dirname = path.dirname(__filename);
32
- const packageJsonPath = path.resolve(__dirname, '..', 'package.json');
33
- const packageJson = fs.readJsonSync(packageJsonPath);
34
- const currentVersion = packageJson.version;
35
- if (currentVersion.includes('dev.')) {
36
- return '@dev';
20
+ export function getPackageManagerFromCLI(options) {
21
+ if (options.useNpm)
22
+ return 'npm';
23
+ if (options.usePnpm)
24
+ return 'pnpm';
25
+ if (options.useYarn)
26
+ return 'yarn';
27
+ if (options.useBun)
28
+ return 'bun';
29
+ if (options.useDeno)
30
+ return 'deno';
31
+ return null;
32
+ }
33
+ export function resolvePackageManager(cliOptions, name) {
34
+ const cliManager = getPackageManagerFromCLI(cliOptions);
35
+ return cliManager || (isDenoProject(name) ? 'deno' : detectPackageManager());
36
+ }
37
+ export function getDefaultExample(cliOptions) {
38
+ if (cliOptions.useDeno) {
39
+ return 'deno-ts';
40
+ }
41
+ return 'basic-ts';
42
+ }
43
+ export function isOfficialExample(example) {
44
+ // Check if it's a GitHub URL pointing to neplextech/commandkit
45
+ if (example.startsWith('http://') || example.startsWith('https://')) {
46
+ try {
47
+ const url = new URL(example);
48
+ return (url.hostname === 'github.com' &&
49
+ url.pathname.startsWith('/neplextech/commandkit'));
37
50
  }
38
- else if (currentVersion.includes('rc.')) {
39
- return '@next';
51
+ catch {
52
+ return false;
40
53
  }
41
- else {
42
- return '@latest';
54
+ }
55
+ // If it's just an example name, it's official
56
+ return true;
57
+ }
58
+ export function getInstallCommand(manager, deps, dev = false) {
59
+ switch (manager) {
60
+ case 'npm':
61
+ case 'pnpm':
62
+ case 'yarn':
63
+ case 'bun':
64
+ return `${manager} add ${dev ? '-D' : ''} ${deps.join(' ')}`;
65
+ case 'deno':
66
+ return `deno add ${dev ? '--dev' : ''} ${deps.map((d) => `npm:${d}`).join(' ')}`;
67
+ default:
68
+ return manager;
69
+ }
70
+ }
71
+ export async function fetchAvailableExamples() {
72
+ try {
73
+ const response = await fetch('https://api.github.com/repos/neplextech/commandkit/contents/examples', {
74
+ signal: AbortSignal.timeout(10_000),
75
+ headers: {
76
+ 'User-Agent': 'create-commandkit',
77
+ },
78
+ });
79
+ if (!response.ok) {
80
+ throw new Error(`GitHub API error: ${response.status}`);
43
81
  }
82
+ const data = (await response.json());
83
+ // Filter for directories only and return their names
84
+ return data
85
+ .filter((item) => item.type === 'dir')
86
+ .map((item) => item.name)
87
+ .sort();
44
88
  }
45
89
  catch (error) {
46
- console.warn('Could not determine create-commandkit version, defaulting to commandkit@latest');
47
- return '@latest';
90
+ // Fallback to few known examples if API fails
91
+ return ['basic-ts', 'basic-js', 'deno-ts', 'without-cli'];
48
92
  }
49
93
  }
94
+ export function isDenoProject(example) {
95
+ const isOfficial = isOfficialExample(example);
96
+ // if it's not an official example, we can assume it's not a Deno project
97
+ // the user may use --use-deno to force a Deno project
98
+ if (!isOfficial)
99
+ return false;
100
+ return example.startsWith('deno-') || example.startsWith('with-deno-');
101
+ }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "create-commandkit",
3
3
  "description": "Effortlessly create a CommandKit project",
4
- "version": "1.2.0-rc.12",
4
+ "version": "1.2.0-rc.13",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.js",
7
7
  "bin": "./dist/index.js",
@@ -18,32 +18,36 @@
18
18
  "commands"
19
19
  ],
20
20
  "files": [
21
- "dist",
22
- "templates"
21
+ "dist"
23
22
  ],
24
23
  "repository": {
25
24
  "type": "git",
26
- "url": "https://github.com/underctrl-io/commandkit",
25
+ "url": "https://github.com/neplextech/commandkit",
27
26
  "directory": "packages/create-commandkit"
28
27
  },
29
28
  "homepage": "https://commandkit.dev",
30
29
  "dependencies": {
31
30
  "@clack/prompts": "^0.11.0",
31
+ "commander": "^14.0.1",
32
32
  "fs-extra": "^11.1.1",
33
33
  "gradient-string": "^3.0.0",
34
34
  "ora": "^8.0.1",
35
- "picocolors": "^1.1.1"
35
+ "picocolors": "^1.1.1",
36
+ "tiged": "^2.12.7",
37
+ "validate-npm-package-name": "^6.0.2"
36
38
  },
37
39
  "devDependencies": {
38
40
  "@types/fs-extra": "^11.0.4",
39
41
  "@types/gradient-string": "^1.1.5",
40
42
  "@types/node": "^22.0.0",
41
- "typescript": "^5.8.3",
42
- "tsconfig": "0.0.0-rc.12"
43
+ "@types/validate-npm-package-name": "^4.0.2",
44
+ "tsx": "^4.20.6",
45
+ "typescript": "^5.9.3",
46
+ "tsconfig": "0.0.0-rc.13"
43
47
  },
44
48
  "scripts": {
45
49
  "check-types": "tsc --noEmit",
46
50
  "dev": "tsc --watch",
47
- "build": "tsc"
51
+ "build": "tsc && tsx scripts/sync-available-examples.ts"
48
52
  }
49
53
  }
@@ -1,5 +0,0 @@
1
- import type { Language } from '../types';
2
- export declare function copyTemplates({ dir, lang, }: {
3
- lang: Language;
4
- dir: string;
5
- }): Promise<void>;
@@ -1,47 +0,0 @@
1
- import fs from 'fs-extra';
2
- import path from 'node:path';
3
- const templates = {
4
- js: path.join(import.meta.dirname, '..', '..', 'templates', 'JavaScript'),
5
- ts: path.join(import.meta.dirname, '..', '..', 'templates', 'TypeScript'),
6
- };
7
- const gitignore = `
8
- # dependencies
9
- node_modules
10
-
11
- # build output
12
- build
13
- out
14
- dist
15
-
16
- # commandkit
17
- .commandkit
18
- dist
19
- compiled-commandkit.config.mjs
20
-
21
- # env
22
- **/*.env*
23
- !**/*.env.example*
24
-
25
- # logging
26
- logs
27
- *.log
28
- npm-debug.log*
29
- yarn-debug.log*
30
- yarn-error.log*
31
- lerna-debug.log*
32
- .pnpm-debug.log*
33
-
34
- # yarn v2+
35
- .yarn/cache
36
- .yarn/unplugged
37
- .yarn/build-state.yml
38
- .yarn/install-state.gz
39
- .pnp.*
40
-
41
- # other
42
- **/*.DS_Store
43
- `;
44
- export async function copyTemplates({ dir, lang, }) {
45
- await fs.copy(templates[lang], dir);
46
- await fs.writeFile(path.join(dir, '.gitignore'), gitignore);
47
- }
@@ -1,10 +0,0 @@
1
- import { type IOType } from 'node:child_process';
2
- import type { Language, PackageManager } from '../types';
3
- interface InstallDepsProps {
4
- manager: PackageManager;
5
- dir: string;
6
- lang: Language;
7
- stdio: IOType;
8
- }
9
- export declare function installDeps({ manager, dir, lang, stdio, }: InstallDepsProps): void;
10
- export {};
@@ -1,49 +0,0 @@
1
- import { execSync } from 'node:child_process';
2
- import ora from 'ora';
3
- import { getCommandKitVersion } from '../utils.js';
4
- const getBaseDependencies = () => [
5
- `commandkit${getCommandKitVersion()}`,
6
- 'discord.js',
7
- ];
8
- const getDependencies = () => ({
9
- js: {
10
- dependencies: getBaseDependencies(),
11
- devDependencies: ['@types/node', 'typescript', 'prettier'],
12
- },
13
- ts: {
14
- dependencies: getBaseDependencies(),
15
- devDependencies: ['@types/node', 'typescript', 'prettier'],
16
- },
17
- });
18
- function getInstallCommand(manager, deps, dev = false) {
19
- switch (manager) {
20
- case 'npm':
21
- case 'pnpm':
22
- case 'yarn':
23
- case 'bun':
24
- return `${manager} add ${dev ? '-D' : ''} ${deps.join(' ')}`;
25
- case 'deno':
26
- return `deno add ${dev ? '--dev' : ''} ${deps.map((d) => `npm:${d}`).join(' ')}`;
27
- default:
28
- return manager;
29
- }
30
- }
31
- export function installDeps({ manager, dir, lang, stdio = 'inherit', }) {
32
- const spinner = ora('Installing dependencies...').start();
33
- try {
34
- const dependencies = getDependencies();
35
- if (dependencies[lang].dependencies.length) {
36
- const depsCommand = getInstallCommand(manager, dependencies[lang].dependencies);
37
- execSync(depsCommand, { cwd: dir, stdio });
38
- }
39
- if (dependencies[lang].devDependencies.length) {
40
- const devDepsCommand = getInstallCommand(manager, dependencies[lang].devDependencies, true);
41
- execSync(devDepsCommand, { cwd: dir, stdio });
42
- }
43
- spinner.succeed('Dependencies installed successfully!');
44
- }
45
- catch (error) {
46
- spinner.fail('Failed to install dependencies');
47
- throw error;
48
- }
49
- }
@@ -1,10 +0,0 @@
1
- import { type IOType } from 'child_process';
2
- import type { PackageManager } from '../types';
3
- interface SetupProps {
4
- manager: PackageManager;
5
- token: string;
6
- dir: string;
7
- stdio?: IOType;
8
- }
9
- export declare function setup({ manager, token, dir, stdio, }: SetupProps): Promise<void>;
10
- export {};
@@ -1,68 +0,0 @@
1
- import { execSync } from 'child_process';
2
- import fs from 'fs-extra';
3
- import path from 'node:path';
4
- import { commands } from '../utils.js';
5
- export async function setup({ manager, token, dir, stdio = 'pipe', }) {
6
- await fs.emptyDir(dir);
7
- if (manager === 'yarn') {
8
- execSync(commands.init.yarn, { cwd: dir, stdio });
9
- }
10
- if (manager === 'deno') {
11
- const denoJsonPath = path.join(dir, 'deno.json');
12
- const denoJson = {
13
- compilerOptions: {
14
- jsx: 'react-jsx',
15
- jsxImportSource: 'commandkit',
16
- },
17
- nodeModulesDir: 'auto',
18
- lock: true,
19
- lint: {
20
- include: ['src/'],
21
- exclude: ['node_modules/', 'dist/', '.commandkit/'],
22
- },
23
- fmt: {
24
- useTabs: false,
25
- lineWidth: 120,
26
- indentWidth: 2,
27
- endOfLine: 'lf',
28
- semiColons: true,
29
- singleQuote: true,
30
- include: ['src/'],
31
- exclude: ['node_modules/', 'dist/', '.commandkit/'],
32
- },
33
- };
34
- await fs.writeJSON(denoJsonPath, denoJson, { spaces: 2, EOL: '\n' });
35
- }
36
- const prettierrc = path.join(dir, '.prettierrc');
37
- const prettierConfig = {
38
- printWidth: 120,
39
- tabWidth: 2,
40
- useTabs: false,
41
- semi: true,
42
- endOfLine: 'lf',
43
- singleQuote: true,
44
- trailingComma: 'all',
45
- arrowParens: 'always',
46
- };
47
- await fs.writeJSON(prettierrc, prettierConfig, { spaces: 2, EOL: '\n' });
48
- const packageJsonPath = path.join(dir, 'package.json');
49
- const packageJson = {
50
- name: dir.replaceAll('\\', '/').split('/').pop()?.toLowerCase() ||
51
- 'commandkit-project',
52
- description: 'A CommandKit project',
53
- version: '0.1.0',
54
- type: 'module',
55
- private: true,
56
- main: 'dist/index.js',
57
- scripts: {
58
- dev: 'commandkit dev',
59
- build: 'commandkit build',
60
- start: 'commandkit start',
61
- format: 'prettier --write "src/**/*.{js,ts}"',
62
- },
63
- devDependencies: {},
64
- dependencies: {},
65
- };
66
- await fs.writeJSON(packageJsonPath, packageJson, { spaces: 2 });
67
- await fs.writeFile(`${dir}/.env`, `DISCORD_TOKEN="${token || ''}"`);
68
- }
@@ -1,16 +0,0 @@
1
- # Welcome to CommandKit
2
-
3
- > This project was generated by [create-commandkit](https://npmjs.com/package/create-commandkit).
4
-
5
- Thanks for choosing CommandKit to build your Discord bot!
6
-
7
- ## To run this project
8
-
9
- ```
10
- npx commandkit dev
11
- ```
12
-
13
- ## Useful links
14
-
15
- - [Documentation](https://commandkit.dev)
16
- - [Discord](https://ctrl.lol/discord)
@@ -1 +0,0 @@
1
- /// <reference path="node_modules/commandkit-types/index.d.ts" />
@@ -1,3 +0,0 @@
1
- import { defineConfig } from 'commandkit/config';
2
-
3
- export default defineConfig({});
@@ -1,30 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "compilerOptions": {
4
- "lib": ["ESNext", "DOM"],
5
- "target": "ESNext",
6
- "moduleResolution": "Node",
7
- "module": "Preserve",
8
- "allowImportingTsExtensions": true,
9
- "esModuleInterop": true,
10
- "resolveJsonModule": true,
11
- "skipLibCheck": true,
12
- "skipDefaultLibCheck": true,
13
- "noUncheckedIndexedAccess": true,
14
- "removeComments": true,
15
- "allowJs": true,
16
- "checkJs": false,
17
- "strict": true,
18
- "alwaysStrict": true,
19
- "noEmit": true,
20
- "declaration": false,
21
- "jsx": "react-jsx",
22
- "jsxImportSource": "commandkit",
23
- "baseUrl": ".",
24
- "paths": {
25
- "@/*": ["./src/*"]
26
- }
27
- },
28
- "include": ["src", "commandkit.config.mjs", "commandkit-env.d.ts"],
29
- "exclude": ["dist", "node_modules", ".commandkit"]
30
- }
@@ -1,27 +0,0 @@
1
- /**
2
- * @type {import('commandkit').CommandData}
3
- */
4
- export const command = {
5
- name: 'ping',
6
- description: "Ping the bot to check if it's online.",
7
- };
8
-
9
- /**
10
- * @param {import('commandkit').ChatInputCommandContext} ctx
11
- */
12
- export const chatInput = async (ctx) => {
13
- const latency = (ctx.client.ws.ping ?? -1).toString();
14
- const response = `Pong! Latency: ${latency}ms`;
15
-
16
- await ctx.interaction.reply(response);
17
- };
18
-
19
- /**
20
- * @param {import('commandkit').MessageCommandContext} ctx
21
- */
22
- export const message = async (ctx) => {
23
- const latency = (ctx.client.ws.ping ?? -1).toString();
24
- const response = `Pong! Latency: ${latency}ms`;
25
-
26
- await ctx.message.reply(response);
27
- };
@@ -1,10 +0,0 @@
1
- import { Logger } from 'commandkit/logger';
2
-
3
- /**
4
- * @type {import('commandkit').EventHandler<'clientReady'>}
5
- */
6
- const handler = async (client) => {
7
- Logger.info(`Logged in as ${client.user.username}!`);
8
- };
9
-
10
- export default handler;
@@ -1,7 +0,0 @@
1
- import { Client } from 'discord.js';
2
-
3
- const client = new Client({
4
- intents: ['Guilds', 'GuildMembers', 'GuildMessages', 'MessageContent'],
5
- });
6
-
7
- export default client;
@@ -1,16 +0,0 @@
1
- # Welcome to CommandKit
2
-
3
- > This project was generated by [create-commandkit](https://npmjs.com/package/create-commandkit).
4
-
5
- Thanks for choosing CommandKit to build your Discord bot!
6
-
7
- ## To run this project
8
-
9
- ```
10
- npx commandkit dev
11
- ```
12
-
13
- ## Useful links
14
-
15
- - [Documentation](https://commandkit.dev)
16
- - [Discord](https://ctrl.lol/discord)
@@ -1 +0,0 @@
1
- /// <reference path="node_modules/commandkit-types/index.d.ts" />
@@ -1,3 +0,0 @@
1
- import { defineConfig } from 'commandkit/config';
2
-
3
- export default defineConfig({});
@@ -1,20 +0,0 @@
1
- import type { ChatInputCommand, MessageCommand, CommandData } from 'commandkit';
2
-
3
- export const command: CommandData = {
4
- name: 'ping',
5
- description: "Ping the bot to check if it's online.",
6
- };
7
-
8
- export const chatInput: ChatInputCommand = async (ctx) => {
9
- const latency = (ctx.client.ws.ping ?? -1).toString();
10
- const response = `Pong! Latency: ${latency}ms`;
11
-
12
- await ctx.interaction.reply(response);
13
- };
14
-
15
- export const message: MessageCommand = async (ctx) => {
16
- const latency = (ctx.client.ws.ping ?? -1).toString();
17
- const response = `Pong! Latency: ${latency}ms`;
18
-
19
- await ctx.message.reply(response);
20
- };
@@ -1,8 +0,0 @@
1
- import type { EventHandler } from 'commandkit';
2
- import { Logger } from 'commandkit/logger';
3
-
4
- const handler: EventHandler<'clientReady'> = async (client) => {
5
- Logger.info(`Logged in as ${client.user.username}!`);
6
- };
7
-
8
- export default handler;
@@ -1,7 +0,0 @@
1
- import { Client } from 'discord.js';
2
-
3
- const client = new Client({
4
- intents: ['Guilds', 'GuildMembers', 'GuildMessages', 'MessageContent'],
5
- });
6
-
7
- export default client;
@@ -1,29 +0,0 @@
1
- {
2
- "$schema": "https://json.schemastore.org/tsconfig",
3
- "compilerOptions": {
4
- "lib": ["ESNext", "DOM"],
5
- "target": "ESNext",
6
- "moduleResolution": "Node",
7
- "module": "Preserve",
8
- "allowImportingTsExtensions": true,
9
- "esModuleInterop": true,
10
- "resolveJsonModule": true,
11
- "skipLibCheck": true,
12
- "skipDefaultLibCheck": true,
13
- "noUncheckedIndexedAccess": true,
14
- "removeComments": true,
15
- "allowJs": true,
16
- "strict": true,
17
- "alwaysStrict": true,
18
- "noEmit": true,
19
- "declaration": false,
20
- "jsx": "react-jsx",
21
- "jsxImportSource": "commandkit",
22
- "baseUrl": ".",
23
- "paths": {
24
- "@/*": ["./src/*"]
25
- }
26
- },
27
- "include": ["src", "commandkit.config.ts", "commandkit-env.d.ts"],
28
- "exclude": ["dist", "node_modules", ".commandkit"]
29
- }