+
+### macro
+
+
+
+The macro compiler options to use with CommandKit.
+### tsdown
+
+
+
+The tsdown compiler options to use with CommandKit.
+**DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING** as it alters the behavior of the build process.
+### disableChunking
+
+
+
+Disables chunking of the output (production only, development never chunks).
+
+
+
diff --git a/apps/website/docs/api-reference/commandkit/interfaces/command-kit-config.mdx b/apps/website/docs/api-reference/commandkit/interfaces/command-kit-config.mdx
index f151ab8f..f83db735 100644
--- a/apps/website/docs/api-reference/commandkit/interfaces/command-kit-config.mdx
+++ b/apps/website/docs/api-reference/commandkit/interfaces/command-kit-config.mdx
@@ -13,7 +13,7 @@ import MemberDescription from '@site/src/components/MemberDescription';
## CommandKitConfig
-
+
@@ -21,18 +21,8 @@ import MemberDescription from '@site/src/components/MemberDescription';
interface CommandKitConfig {
plugins?: MaybeArray[] | Array;
rolldownPlugins?: any[];
- compilerOptions?: {
- /**
- * Macro compiler configuration.
- */
- macro?: {
- /**
- * Whether to enable macro function compilation in development mode.
- * @default false
- */
- development?: boolean;
- };
- };
+ entrypoints?: string[];
+ compilerOptions?: CommandKitCompilerOptions;
typescript?: {
/**
* Whether to ignore type checking during builds.
@@ -42,6 +32,18 @@ interface CommandKitConfig {
static?: boolean;
env?: Record;
distDir?: string;
+ antiCrashScript?: {
+ /**
+ * Whether to enable the anti-crash script in development mode.
+ * @default true
+ */
+ development?: boolean;
+ /**
+ * Whether to enable the anti-crash script in production mode. Usually, you should use other means to handle errors.
+ * @default false
+ */
+ production?: boolean;
+ };
sourceMap?: {
/**
* Whether to enable source map generation in development mode.
@@ -71,9 +73,15 @@ Can be a single plugin, an array of plugins, or a nested array of plugins.
The rolldown plugins to use with CommandKit.
+### entrypoints
+
+
+
+The list of additional entrypoints to compile. Eg, `dir` or `dir/index.ts` or `dir/*.ts`, etc.
+Similarly, negative patterns can be used to exclude files. Eg, `!dir/index.ts` or `!dir/*.ts`, etc.
### compilerOptions
-
+CommandKitCompilerOptions`} />
The compiler options to use with CommandKit.
### typescript
@@ -96,6 +104,11 @@ Statically define the environment variables to use.
The custom build directory name to use.
+### antiCrashScript
+
+
+
+The anti-crash script configuration.
### sourceMap
diff --git a/apps/website/docs/api-reference/commandkit/types/resolved-command-kit-config.mdx b/apps/website/docs/api-reference/commandkit/types/resolved-command-kit-config.mdx
index d6dd48a7..4cb91dfe 100644
--- a/apps/website/docs/api-reference/commandkit/types/resolved-command-kit-config.mdx
+++ b/apps/website/docs/api-reference/commandkit/types/resolved-command-kit-config.mdx
@@ -13,10 +13,13 @@ import MemberDescription from '@site/src/components/MemberDescription';
## ResolvedCommandKitConfig
-
+
```ts title="Signature"
-type ResolvedCommandKitConfig = DeepRequired
+type ResolvedCommandKitConfig = DeepRequired<
+ CommandKitConfig,
+ 'compilerOptions'
+>
```
diff --git a/packages/commandkit/src/cli/build.ts b/packages/commandkit/src/cli/build.ts
index ebb6bf48..de82d07e 100644
--- a/packages/commandkit/src/cli/build.ts
+++ b/packages/commandkit/src/cli/build.ts
@@ -1,4 +1,4 @@
-import { build } from 'tsdown';
+import { build, Options } from 'tsdown';
import { CompilerPlugin, CompilerPluginRuntime } from '../plugins';
import { loadConfigFile } from '../config/loader';
import { writeFile } from 'node:fs/promises';
@@ -9,6 +9,8 @@ import { performTypeCheck } from './type-checker';
import { copyLocaleFiles } from './common';
import { MaybeArray } from '../components';
import { COMMANDKIT_CWD } from '../utils/constants';
+import { mergeDeep } from '../config/utils';
+import { existsSync } from 'node:fs';
/**
* @private
@@ -84,60 +86,70 @@ export async function buildApplication({
await pluginRuntime.init();
- await build({
- watch: false,
- dts: false,
- clean: true,
- format: ['esm'],
- shims: true,
- minify: false,
- silent: !!isDev,
- inputOptions: {
- transform: {
- jsx: {
- runtime: 'automatic',
- importSource: 'commandkit',
+ await build(
+ mergeDeep(
+ {
+ watch: false,
+ dts: false,
+ clean: true,
+ format: ['esm'],
+ shims: true,
+ minify: false,
+ silent: !!isDev,
+ inputOptions: {
+ transform: {
+ jsx: {
+ runtime: 'automatic',
+ importSource: 'commandkit',
+ },
+ },
+ checks: {
+ circularDependency: true,
+ },
+ onwarn: (warning, defaultWarn) => {
+ if (warning?.message?.includes('compilerOptions.jsx')) return;
+
+ return defaultWarn(warning);
+ },
+ onLog: (level, log, defaultLog) => {
+ if (isDev) return;
+
+ return defaultLog(level, log);
+ },
+ moduleTypes: {
+ '.json': 'js',
+ '.node': 'binary',
+ },
},
- },
- checks: {
- circularDependency: true,
- },
- onwarn: (warning, defaultWarn) => {
- if (warning?.message?.includes('compilerOptions.jsx')) return;
-
- return defaultWarn(warning);
- },
- onLog: (level, log, defaultLog) => {
- if (isDev) return;
-
- return defaultLog(level, log);
- },
- moduleTypes: {
- '.json': 'js',
- '.node': 'binary',
- },
- },
- plugins: rolldownPlugins,
- platform: 'node',
- skipNodeModulesBundle: true,
- sourcemap: true,
- target: 'node16',
- outDir: dest,
- env: mergeDefinitionsIfNeeded(config.env || {}, !!isDev),
- entry: [
- 'src',
- `!${config.distDir}`,
- '!.commandkit',
- '!**/*.test.*',
- '!**/*.spec.*',
- ],
- unbundle: !!isDev,
- });
+ plugins: rolldownPlugins,
+ platform: 'node',
+ skipNodeModulesBundle: true,
+ sourcemap:
+ config.sourceMap?.[isDev ? 'development' : 'production'] ?? true,
+ target: 'node16',
+ outDir: dest,
+ env: mergeDefinitionsIfNeeded(config.env || {}, !!isDev),
+ entry: [
+ 'src',
+ `!${config.distDir}`,
+ '!.commandkit',
+ '!**/*.test.*',
+ '!**/*.spec.*',
+ ],
+ unbundle: !!isDev,
+ } satisfies Options,
+ config.compilerOptions?.tsdown,
+ ),
+ );
await copyLocaleFiles('src', dest);
await injectEntryFile(
configPath || COMMANDKIT_CWD,
!!isDev,
+ !!(
+ config.antiCrashScript?.[isDev ? 'development' : 'production'] ??
+ (isDev ? true : false)
+ ),
config.distDir,
);
} catch (error) {
@@ -185,10 +197,17 @@ const wrapInAsyncIIFE = (code: string[]) =>
async function injectEntryFile(
configPath: string,
isDev: boolean,
+ emitAntiCrashScript: boolean,
distDir?: string,
) {
+ const dist = isDev ? '.commandkit' : distDir || 'dist';
+ const entryFilePath = join(configPath, dist, 'index.js');
+
+ // skip if the entry file already exists
+ if (existsSync(entryFilePath)) return;
+
const code = `/* Entrypoint File Generated By CommandKit */
-${isDev ? `\n\n// Injected for development\n${wrapInAsyncIIFE([envScript(isDev), antiCrashScript])}\n\n` : wrapInAsyncIIFE([envScript(isDev)])}
+${isDev ? `\n\n// Injected for development\n${wrapInAsyncIIFE([envScript(isDev), emitAntiCrashScript ? antiCrashScript : ''])}\n\n` : wrapInAsyncIIFE([envScript(isDev)])}
import { commandkit } from 'commandkit';
import { Client } from 'discord.js';
@@ -210,7 +229,5 @@ await bootstrap().catch((e) => {
})
`;
- const dist = isDev ? '.commandkit' : distDir || 'dist';
-
- await writeFile(join(configPath, dist, 'index.js'), code);
+ await writeFile(entryFilePath, code);
}
diff --git a/packages/commandkit/src/config/config.ts b/packages/commandkit/src/config/config.ts
index 659c2b13..a3937a99 100644
--- a/packages/commandkit/src/config/config.ts
+++ b/packages/commandkit/src/config/config.ts
@@ -2,7 +2,7 @@ import { MaybeArray } from '../components';
import { CommandKitPlugin } from '../plugins';
import { defaultConfig } from './default';
import { CommandKitConfig } from './types';
-import { ResolvedCommandKitConfig } from './utils';
+import { mergeDeep, ResolvedCommandKitConfig } from './utils';
let defined: ResolvedCommandKitConfig = defaultConfig;
@@ -20,10 +20,10 @@ export function getConfig(): ResolvedCommandKitConfig {
export function defineConfig(
config: Partial = {},
): ResolvedCommandKitConfig {
- // defined = mergeDeep(
- // config as ResolvedCommandKitConfig,
- // mergeDeep({} as ResolvedCommandKitConfig, defaultConfig),
- // );
+ defined = mergeDeep(
+ config as ResolvedCommandKitConfig,
+ mergeDeep({} as ResolvedCommandKitConfig, defaultConfig),
+ );
defined = {
compilerOptions: {
@@ -31,7 +31,18 @@ export function defineConfig(
...defaultConfig.compilerOptions.macro,
...config.compilerOptions?.macro,
},
+ tsdown: {
+ ...defaultConfig.compilerOptions.tsdown,
+ ...config.compilerOptions?.tsdown,
+ },
+ disableChunking:
+ config.compilerOptions?.disableChunking ??
+ defaultConfig.compilerOptions.disableChunking,
},
+ entrypoints: [
+ ...(config.entrypoints ?? []),
+ ...(defaultConfig.entrypoints ?? []),
+ ],
distDir: config.distDir ?? defaultConfig.distDir,
env: {
...defaultConfig.env,
@@ -59,6 +70,10 @@ export function defineConfig(
showUnknownPrefixCommandsWarning:
config.showUnknownPrefixCommandsWarning ??
defaultConfig.showUnknownPrefixCommandsWarning,
+ antiCrashScript: {
+ ...defaultConfig.antiCrashScript,
+ ...config.antiCrashScript,
+ },
};
return defined;
diff --git a/packages/commandkit/src/config/default.ts b/packages/commandkit/src/config/default.ts
index 40b888cd..a4b4ff3c 100644
--- a/packages/commandkit/src/config/default.ts
+++ b/packages/commandkit/src/config/default.ts
@@ -12,7 +12,10 @@ export const defaultConfig: ResolvedCommandKitConfig = {
macro: {
development: false,
},
+ tsdown: {},
+ disableChunking: false,
},
+ entrypoints: [],
static: true,
typescript: {
ignoreBuildErrors: false,
@@ -26,4 +29,8 @@ export const defaultConfig: ResolvedCommandKitConfig = {
typedCommands: true,
disablePrefixCommands: false,
showUnknownPrefixCommandsWarning: true,
+ antiCrashScript: {
+ development: true,
+ production: false,
+ },
};
diff --git a/packages/commandkit/src/config/types.ts b/packages/commandkit/src/config/types.ts
index 0662adfe..156da75e 100644
--- a/packages/commandkit/src/config/types.ts
+++ b/packages/commandkit/src/config/types.ts
@@ -1,5 +1,29 @@
import { MaybeArray } from '../components';
import { CommandKitPlugin } from '../plugins';
+import type { Options as TsDownOptions } from 'tsdown';
+
+export interface CommandKitCompilerOptions {
+ /**
+ * The macro compiler options to use with CommandKit.
+ */
+ macro?: {
+ /**
+ * Whether to enable macro function compilation in development mode.
+ * @default false
+ */
+ development?: boolean;
+ };
+ /**
+ * The tsdown compiler options to use with CommandKit.
+ * **DO NOT USE THIS UNLESS YOU KNOW WHAT YOU ARE DOING** as it alters the behavior of the build process.
+ */
+ tsdown?: Partial;
+ /**
+ * Disables chunking of the output (production only, development never chunks).
+ * @default false
+ */
+ disableChunking?: boolean;
+}
export interface CommandKitConfig {
/**
@@ -11,21 +35,15 @@ export interface CommandKitConfig {
* The rolldown plugins to use with CommandKit.
*/
rolldownPlugins?: any[];
+ /**
+ * The list of additional entrypoints to compile. Eg, `dir` or `dir/index.ts` or `dir/*.ts`, etc.
+ * Similarly, negative patterns can be used to exclude files. Eg, `!dir/index.ts` or `!dir/*.ts`, etc.
+ */
+ entrypoints?: string[];
/**
* The compiler options to use with CommandKit.
*/
- compilerOptions?: {
- /**
- * Macro compiler configuration.
- */
- macro?: {
- /**
- * Whether to enable macro function compilation in development mode.
- * @default false
- */
- development?: boolean;
- };
- };
+ compilerOptions?: CommandKitCompilerOptions;
/**
* The typescript configuration to use with CommandKit.
*/
@@ -48,6 +66,21 @@ export interface CommandKitConfig {
* @default `dist`
*/
distDir?: string;
+ /**
+ * The anti-crash script configuration.
+ */
+ antiCrashScript?: {
+ /**
+ * Whether to enable the anti-crash script in development mode.
+ * @default true
+ */
+ development?: boolean;
+ /**
+ * Whether to enable the anti-crash script in production mode. Usually, you should use other means to handle errors.
+ * @default false
+ */
+ production?: boolean;
+ };
/**
* Whether or not to enable the source map generation.
*/
diff --git a/packages/commandkit/src/config/utils.ts b/packages/commandkit/src/config/utils.ts
index a8e8cf0d..459d7276 100644
--- a/packages/commandkit/src/config/utils.ts
+++ b/packages/commandkit/src/config/utils.ts
@@ -3,8 +3,8 @@ import { CommandKitConfig } from './types';
/**
* @private
*/
-export type DeepRequired = {
- [P in keyof T]-?: DeepRequired;
+export type DeepRequired = {
+ [P in keyof T]-?: P extends OptionalKeys ? Partial : DeepRequired;
};
/**
@@ -16,14 +16,31 @@ export type DeepPartial = {
/**
* @private
+ * @example
+ * ```ts
+ * const target = { a: 1, b: { c: 2 } };
+ * const source = { b: { d: 3 } };
+ * const result = mergeDeep(target, source);
+ * // result = { a: 1, b: { c: 2, d: 3 } }
+ * ```
*/
export const mergeDeep = >(
target: T,
- source: T,
+ source?: T,
+ tracker = new WeakMap