Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions packages/commandkit/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@
"scripts": {
"lint": "tsc --noEmit",
"dev": "pnpm run --filter=test-bot dev",
"build": "tsup",
"build": "tsdown",
"publish-package": "npm publish",
"test": "vitest"
},
Expand All @@ -80,6 +80,7 @@
"event handler"
],
"dependencies": {
"@rollup/plugin-json": "^6.1.0",
"chokidar": "^4.0.3",
"commander": "^13.0.0",
"directive-to-hof": "^0.0.2",
Expand All @@ -89,7 +90,7 @@
"picocolors": "^1.1.1",
"rfdc": "^1.3.1",
"rimraf": "^6.0.0",
"tsup": "^8.4.0",
"tsdown": "^0.12.4",
"use-macro": "^1.1.0"
},
"devDependencies": {
Expand Down
19 changes: 13 additions & 6 deletions packages/commandkit/src/CommandKit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ export function onApplicationBootstrap<F extends BootstrapFunction>(

export class CommandKit extends EventEmitter {
#started = false;
private options: CommandKitOptions;
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The options field is assigned in the constructor but never referenced elsewhere; consider removing it or using it to drive configuration.

Suggested change
private options: CommandKitOptions;
// Removed unused options field

Copilot uses AI. Check for mistakes.
public eventInterceptor!: EventInterceptor;

public static readonly createElement = createElement;
Expand All @@ -89,10 +90,10 @@ export class CommandKit extends EventEmitter {

public commandsRouter!: CommandsRouter;
public eventsRouter!: EventsRouter;
public readonly commandHandler = new AppCommandHandler(this);
public readonly eventHandler = new AppEventsHandler(this);
public readonly plugins: CommandKitPluginRuntime;
public readonly events = new CommandKitEventsChannel(this);
public commandHandler!: AppCommandHandler;
public eventHandler!: AppEventsHandler;
public plugins!: CommandKitPluginRuntime;
public events!: CommandKitEventsChannel;

static instance: CommandKit | undefined = undefined;

Expand All @@ -102,7 +103,7 @@ export class CommandKit extends EventEmitter {
* @param options - The default CommandKit configuration.
* @see {@link https://commandkit.js.org/docs/guide/commandkit-setup}
*/
constructor(private readonly options: CommandKitOptions) {
constructor(options: CommandKitOptions) {
if (CommandKit.instance) {
process.emitWarning(
'CommandKit instance already exists. Having multiple instance in same project is discouraged and it may lead to unexpected behavior.',
Expand All @@ -120,12 +121,14 @@ export class CommandKit extends EventEmitter {

super();

this.plugins = new CommandKitPluginRuntime(this);
this.options = options;

if (!CommandKit.instance) {
CommandKit.instance = this;
}

this.plugins = new CommandKitPluginRuntime(this);

// @ts-ignore
commandkit = CommandKit.instance;

Expand Down Expand Up @@ -280,6 +283,10 @@ export class CommandKit extends EventEmitter {
const commandsPath = this.getPath('commands')!;
const events = this.getPath('events')!;

this.commandHandler = new AppCommandHandler(this);
this.eventHandler = new AppEventsHandler(this);
this.events = new CommandKitEventsChannel(this);

this.commandsRouter = new CommandsRouter({
entrypoint: commandsPath,
});
Expand Down
75 changes: 25 additions & 50 deletions packages/commandkit/src/cli/build.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
import { build } from 'tsup';
import {
CompilerPlugin,
CompilerPluginRuntime,
fromEsbuildPlugin,
} from '../plugins';
import { build } from 'tsdown';
import { CompilerPlugin, CompilerPluginRuntime } from '../plugins';
import { loadConfigFile } from '../config/loader';
import { writeFile } from 'node:fs/promises';
import { join } from 'node:path';
Expand All @@ -15,14 +11,14 @@ import { MaybeArray } from '../components';

export interface ApplicationBuildOptions {
plugins?: MaybeArray<CompilerPlugin>[] | Array<CompilerPlugin>;
esbuildPlugins?: any[];
rolldownPlugins?: any[];
isDev?: boolean;
configPath?: string;
}

export async function buildApplication({
plugins,
esbuildPlugins,
rolldownPlugins,
isDev,
configPath,
}: ApplicationBuildOptions) {
Expand All @@ -35,45 +31,40 @@ export async function buildApplication({
const pluginRuntime = new CompilerPluginRuntime(
(plugins || []) as CompilerPlugin[],
);
const esbuildPluginList: any[] = pluginRuntime.isEmpty()
? []
: [pluginRuntime.toEsbuildPlugin()];

if (esbuildPlugins?.length) {
esbuildPluginList.push(...esbuildPlugins.map(fromEsbuildPlugin));
}
rolldownPlugins ??= [];

rolldownPlugins.push(pluginRuntime.toJSON());

try {
const dest = isDev ? '.commandkit' : config.distDir;

// Clean the destination directory
await rimraf(dest);

await pluginRuntime.init();

await build({
esbuildPlugins: esbuildPluginList,
watch: false,
banner: {
js: !isDev
? '/* Optimized production build generated by commandkit */'
: '',
},
cjsInterop: true,
dts: false,
clean: true,
format: ['esm'],
shims: true,
keepNames: true,
minify: false,
esbuildOptions: (options) => {
options.jsx = 'automatic';
options.jsxImportSource = 'commandkit';

return options;
},
minifyIdentifiers: false,
minifySyntax: false,
silent: !!isDev,
splitting: true,
inputOptions: {
transform: {
jsx: {
runtime: 'automatic',
importSource: 'commandkit',
},
},
moduleTypes: {
'.json': 'js',
},
},
plugins: rolldownPlugins,
platform: 'node',
skipNodeModulesBundle: true,
name: 'CommandKit',
sourcemap: true,
Expand All @@ -87,6 +78,7 @@ export async function buildApplication({
'!**/*.test.*',
'!**/*.spec.*',
],
unbundle: false,
});

await copyLocaleFiles('src', dest);
Expand All @@ -99,7 +91,7 @@ export async function buildApplication({
process.exit(1); // Force exit on error
} finally {
// Ensure plugins are cleaned up
await pluginRuntime.cleanup();
await pluginRuntime.destroy();
}
}

Expand All @@ -113,23 +105,6 @@ for (const file of $env) {
}
`;

const requireScript = [
'// --- CommandKit require() polyfill ---',
' if (typeof require === "undefined") {',
' const { createRequire } = await import("node:module");',
' const __require = createRequire(import.meta.url);',
' Object.defineProperty(globalThis, "require", {',
' value: (id) => {',
' return __require(id);',
' },',
' configurable: true,',
' enumerable: false,',
' writable: true,',
' });',
' }',
'// --- CommandKit require() polyfill ---',
].join('\n');

const antiCrashScript = [
'// --- CommandKit Anti-Crash Monitor ---',
" // 'uncaughtException' event is supposed to be used to perform synchronous cleanup before shutting down the process",
Expand All @@ -156,7 +131,7 @@ async function injectEntryFile(
distDir?: string,
) {
const code = `/* Entrypoint File Generated By CommandKit */
${isDev ? `\n\n// Injected for development\n${wrapInAsyncIIFE([envScript(isDev), antiCrashScript, requireScript])}\n\n` : wrapInAsyncIIFE([envScript(isDev), requireScript])}
${isDev ? `\n\n// Injected for development\n${wrapInAsyncIIFE([envScript(isDev), antiCrashScript])}\n\n` : wrapInAsyncIIFE([envScript(isDev)])}

import { CommandKit } from 'commandkit';

Expand Down
2 changes: 1 addition & 1 deletion packages/commandkit/src/cli/development.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ async function buildAndStart(configPath: string, skipStart = false) {
configPath,
isDev: true,
plugins: config.plugins.flat(2).filter((p) => isCompilerPlugin(p)),
esbuildPlugins: config.esbuildPlugins,
rolldownPlugins: config.rolldownPlugins,
});

if (skipStart) return null as never;
Expand Down
2 changes: 1 addition & 1 deletion packages/commandkit/src/cli/production.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export async function createProductionBuild(configPath?: string) {
plugins: config.plugins.filter((p) =>
isCompilerPlugin(p),
) as CompilerPlugin[],
esbuildPlugins: config.esbuildPlugins,
rolldownPlugins: config.rolldownPlugins,
});

spinner.succeed('Production build completed!');
Expand Down
6 changes: 3 additions & 3 deletions packages/commandkit/src/config/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,9 +37,9 @@ export function defineConfig(
...defaultConfig.env,
...config.env,
},
esbuildPlugins: [
...(config.esbuildPlugins ?? []),
...(defaultConfig.esbuildPlugins ?? []),
rolldownPlugins: [
...(config.rolldownPlugins ?? []),
...(defaultConfig.rolldownPlugins ?? []),
],
plugins: [...(config.plugins ?? []), ...(defaultConfig.plugins ?? [])].flat(
Infinity,
Expand Down
3 changes: 2 additions & 1 deletion packages/commandkit/src/config/default.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import { MacroPlugin } from '../plugins/plugin-runtime/builtin/MacroPlugin';
import { ResolvedCommandKitConfig } from './utils';
import json from '@rollup/plugin-json';

export const defaultConfig: ResolvedCommandKitConfig = {
plugins: [new MacroPlugin({ enabled: true })],
esbuildPlugins: [],
rolldownPlugins: [json() as any],
compilerOptions: {
macro: {
development: false,
Expand Down
4 changes: 2 additions & 2 deletions packages/commandkit/src/config/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,9 @@ export interface CommandKitConfig {
*/
plugins?: MaybeArray<CommandKitPlugin>[] | Array<CommandKitPlugin>;
/**
* The esbuild plugins to use with CommandKit.
* The rolldown plugins to use with CommandKit.
*/
esbuildPlugins?: any[];
rolldownPlugins?: any[];
/**
* The compiler options to use with CommandKit.
*/
Expand Down
2 changes: 0 additions & 2 deletions packages/commandkit/src/flags/feature-flags.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,11 @@ import {
Client,
ClientEvents,
ContextMenuCommandInteraction,
Events,
Guild,
Message,
TextBasedChannel,
} from 'discord.js';
import { LoadedCommand } from '../app';
import { FlagStore } from './store';

export type MaybePromise<T> = T | Promise<T>;

Expand Down
43 changes: 5 additions & 38 deletions packages/commandkit/src/plugins/CompilerPlugin.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,4 @@
import {
Loader,
OnLoadArgs,
OnResolveArgs,
OnResolveResult,
} from './plugin-runtime/types';
import { OnResolveArgs } from './plugin-runtime/types';
Copy link

Copilot AI May 29, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The import OnResolveArgs is no longer used in this file; consider removing it to clean up unused code.

Suggested change
import { OnResolveArgs } from './plugin-runtime/types';

Copilot uses AI. Check for mistakes.
import {
isPlugin,
PluginCommon,
Expand All @@ -14,20 +9,13 @@ import { MaybeFalsey } from './types';
import { CompilerPluginRuntime } from './plugin-runtime/CompilerPluginRuntime';

export interface PluginTransformParameters {
args: OnLoadArgs;
path: string;
contents: string | Uint8Array;
loader?: Loader;
code: string;
id: string;
}

export interface TransformedResult {
contents?: string | Uint8Array;
loader?: Loader;
}

export interface ResolveResult {
path?: string;
external?: boolean;
code?: string;
map?: string | null;
}

export abstract class CompilerPlugin<
Expand All @@ -45,27 +33,6 @@ export abstract class CompilerPlugin<
): Promise<MaybeFalsey<TransformedResult>> {
return null;
}

/**
* Called when a resolve is requested to this plugin
* @param args The arguments for the resolve
* @returns The resolved result
*/
public async resolve(
args: OnResolveArgs,
): Promise<MaybeFalsey<ResolveResult>> {
return null;
}

/**
* Called when a build is started
*/
public async onBuildStart(): Promise<void> {}

/**
* Called when a build is ended
*/
public async onBuildEnd(): Promise<void> {}
}

export function isCompilerPlugin(plugin: unknown): plugin is CompilerPlugin {
Expand Down
Loading