@@ -20,6 +20,8 @@ import { CommandKitEventsChannel } from './events/CommandKitEventsChannel';
2020import { isRuntimePlugin } from './plugins' ;
2121import { generateTypesPackage } from './utils/types-package' ;
2222import { Logger } from './logger/Logger' ;
23+ import { GenericFunction } from './context/async-context' ;
24+ import { AsyncFunction } from './cache' ;
2325
2426export interface CommandKitConfiguration {
2527 defaultLocale : Locale ;
@@ -29,6 +31,49 @@ export interface CommandKitConfiguration {
2931// @ts -ignore
3032export let commandkit : CommandKit ;
3133
34+ export type BootstrapFunction =
35+ | GenericFunction < [ CommandKit ] >
36+ | AsyncFunction < [ CommandKit ] > ;
37+
38+ const bootstrapHooks = new Set < BootstrapFunction > ( ) ;
39+ const onApplicationBootstrapHooks = new Set < BootstrapFunction > ( ) ;
40+
41+ /**
42+ * Registers a bootstrap hook that will be called when the CommandKit instance is created.
43+ * This is useful for plugins that need to run some code after the CommandKit instance is fully initialized.
44+ * Note that not all commandkit dependiencs are available at this point. It is recommended to use the `onApplicationBootstrap` hook instead,
45+ * if you need access to the commandkit dependencies.
46+ * @param fn The bootstrap function to register.
47+ * @example ```ts
48+ * import { onBootstrap } from 'commandkit';
49+ *
50+ * onBootstrap(async (commandkit) => {
51+ * // Do something with the commandkit instance
52+ * })
53+ * ```
54+ */
55+ export function onBootstrap < F extends BootstrapFunction > ( fn : F ) : void {
56+ bootstrapHooks . add ( fn ) ;
57+ }
58+
59+ /**
60+ * Registers a bootstrap hook that will be called when the CommandKit instance is created.
61+ * This is useful for plugins that need to run some code after the CommandKit instance is fully initialized.
62+ * @param fn The bootstrap function to register.
63+ * @example ```ts
64+ * import { onApplicationBootstrap } from 'commandkit';
65+ *
66+ * onApplicationBootstrap(async (commandkit) => {
67+ * // Do something with the commandkit instance
68+ * })
69+ * ```
70+ */
71+ export function onApplicationBootstrap < F extends BootstrapFunction > (
72+ fn : F ,
73+ ) : void {
74+ onApplicationBootstrapHooks . add ( fn ) ;
75+ }
76+
3277export class CommandKit extends EventEmitter {
3378 #started = false ;
3479 public eventInterceptor ! : EventInterceptor ;
@@ -90,6 +135,37 @@ export class CommandKit extends EventEmitter {
90135
91136 // @ts -ignore
92137 commandkit = CommandKit . instance ;
138+
139+ this . #bootstrapHooks( ) ;
140+ }
141+
142+ async #bootstrapHooks( ) {
143+ for ( const hook of bootstrapHooks ) {
144+ try {
145+ await hook ( this ) ;
146+ } catch ( e ) {
147+ Logger . error ( 'Error while executing bootstrap hook: ' , e ) ;
148+ } finally {
149+ bootstrapHooks . delete ( hook ) ;
150+ }
151+ }
152+
153+ // force clear just in case we missed something
154+ bootstrapHooks . clear ( ) ;
155+ }
156+
157+ async #applicationBootstrapHooks( ) {
158+ for ( const hook of onApplicationBootstrapHooks ) {
159+ try {
160+ await hook ( this ) ;
161+ } catch ( e ) {
162+ Logger . error ( 'Error while executing application bootstrap hook: ' , e ) ;
163+ } finally {
164+ onApplicationBootstrapHooks . delete ( hook ) ;
165+ }
166+ }
167+ // force clear just in case we missed something
168+ onApplicationBootstrapHooks . clear ( ) ;
93169 }
94170
95171 /**
@@ -151,6 +227,8 @@ export class CommandKit extends EventEmitter {
151227 }
152228
153229 this . #started = true ;
230+
231+ await this . #applicationBootstrapHooks( ) ;
154232 }
155233
156234 /**
0 commit comments