@@ -75,90 +75,113 @@ export class AppCommandRunner {
75
75
env . variables . set ( 'execHandlerKind' , executionMode ) ;
76
76
env . variables . set ( 'customHandler' , options ?. handler ?? null ) ;
77
77
78
- const middlewareCtx = new MiddlewareContext ( commandkit , {
79
- command : prepared . command ,
80
- environment : env ,
81
- executionMode,
82
- interaction : ! ( source instanceof Message )
83
- ? ( source as ChatInputCommandInteraction )
84
- : ( null as never ) ,
85
- message : source instanceof Message ? source : ( null as never ) ,
86
- forwarded : false ,
87
- customArgs : {
88
- setCommandRunner : ( fn : RunCommand ) => {
89
- runCommand = fn ;
78
+ try {
79
+ const middlewareCtx = new MiddlewareContext ( commandkit , {
80
+ command : prepared . command ,
81
+ environment : env ,
82
+ executionMode,
83
+ interaction : ! ( source instanceof Message )
84
+ ? ( source as ChatInputCommandInteraction )
85
+ : ( null as never ) ,
86
+ message : source instanceof Message ? source : ( null as never ) ,
87
+ forwarded : false ,
88
+ customArgs : {
89
+ setCommandRunner : ( fn : RunCommand ) => {
90
+ runCommand = fn ;
91
+ } ,
90
92
} ,
91
- } ,
92
- messageCommandParser : prepared . messageCommandParser ,
93
- } ) ;
94
-
95
- const beforeMiddlewares = prepared . middlewares . filter (
96
- ( m ) => m . data . beforeExecute ,
97
- ) ;
98
-
99
- let beforeMiddlewaresStopped = false ;
93
+ messageCommandParser : prepared . messageCommandParser ,
94
+ } ) ;
100
95
101
- // Run middleware before command execution
102
- if ( beforeMiddlewares . length ) {
103
- await provideContext ( env , async ( ) => {
104
- for ( const middleware of beforeMiddlewares ) {
105
- try {
106
- await middleware . data . beforeExecute ( middlewareCtx ) ;
107
- } catch ( e ) {
108
- if ( isErrorType ( e , CommandKitErrorCodes . StopMiddlewares ) ) {
109
- beforeMiddlewaresStopped = true ;
110
- Logger . debug (
111
- `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called inside a beforeExecute function at "${ middleware . middleware . relativePath } "` ,
112
- ) ;
113
- break ; // Stop the middleware loop if `stopMiddlewares()` is called.
114
- }
96
+ const beforeMiddlewares = prepared . middlewares . filter (
97
+ ( m ) => m . data . beforeExecute ,
98
+ ) ;
99
+
100
+ let beforeMiddlewaresStopped = false ;
101
+
102
+ // Run middleware before command execution
103
+ if ( beforeMiddlewares . length ) {
104
+ await provideContext ( env , async ( ) => {
105
+ for ( const middleware of beforeMiddlewares ) {
106
+ try {
107
+ await middleware . data . beforeExecute ( middlewareCtx ) ;
108
+ } catch ( e ) {
109
+ if ( isErrorType ( e , CommandKitErrorCodes . StopMiddlewares ) ) {
110
+ beforeMiddlewaresStopped = true ;
111
+ Logger . debug (
112
+ `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called inside a beforeExecute function at "${ middleware . middleware . relativePath } "` ,
113
+ ) ;
114
+ break ; // Stop the middleware loop if `stopMiddlewares()` is called.
115
+ }
116
+
117
+ if (
118
+ isErrorType ( e , [
119
+ CommandKitErrorCodes . ForwardedCommand ,
120
+ CommandKitErrorCodes . InvalidCommandPrefix ,
121
+ ] )
122
+ ) {
123
+ continue ;
124
+ }
115
125
116
- if (
117
- isErrorType ( e , [
118
- CommandKitErrorCodes . ForwardedCommand ,
119
- CommandKitErrorCodes . InvalidCommandPrefix ,
120
- ] )
121
- ) {
122
- continue ;
126
+ throw e ;
123
127
}
124
-
125
- throw e ;
126
128
}
127
- }
128
- } ) ;
129
- }
129
+ } ) ;
130
+ }
130
131
131
- let result : any ;
132
+ let result : any ;
132
133
133
- let stopMiddlewaresCalledInCmd = false ;
134
+ let stopMiddlewaresCalledInCmd = false ;
134
135
135
- // If no `stopMiddlewares()` was called in a `beforeExecute` middleware, try to run the command
136
- if ( ! beforeMiddlewaresStopped ) {
137
- const targetData = prepared . command . data ;
138
- const fn = targetData [ options ?. handler || executionMode ] ;
136
+ // If no `stopMiddlewares()` was called in a `beforeExecute` middleware, try to run the command
137
+ if ( ! beforeMiddlewaresStopped ) {
138
+ const targetData = prepared . command . data ;
139
+ const fn = targetData [ options ?. handler || executionMode ] ;
139
140
140
- if ( ! fn ) {
141
- Logger . warn (
142
- `Command ${ prepared . command . command . name } has no handler for ${ executionMode } ` ,
143
- ) ;
144
- }
141
+ if ( ! fn ) {
142
+ Logger . warn (
143
+ `Command ${ prepared . command . command . name } has no handler for ${ executionMode } ` ,
144
+ ) ;
145
+ }
146
+
147
+ const analytics = commandkit . analytics ;
145
148
146
- const analytics = commandkit . analytics ;
147
-
148
- if ( fn ) {
149
- try {
150
- const _executeCommand = makeContextAwareFunction (
151
- env ,
152
- async ( ) => {
153
- env . registerDeferredFunction ( async ( env ) => {
154
- env . markEnd ( ) ;
155
- const error = env . getExecutionError ( ) ;
156
- const marker = env . getMarker ( ) ;
157
- const time = `${ env . getExecutionTime ( ) . toFixed ( 2 ) } ms` ;
158
-
159
- if ( error ) {
160
- Logger . error (
161
- `[${ marker } - ${ time } ] Error executing command: ${ error . stack || error } ` ,
149
+ if ( fn ) {
150
+ try {
151
+ const _executeCommand = makeContextAwareFunction (
152
+ env ,
153
+ async ( ) => {
154
+ env . registerDeferredFunction ( async ( env ) => {
155
+ env . markEnd ( ) ;
156
+ const error = env . getExecutionError ( ) ;
157
+ const marker = env . getMarker ( ) ;
158
+ const time = `${ env . getExecutionTime ( ) . toFixed ( 2 ) } ms` ;
159
+
160
+ if ( error ) {
161
+ Logger . error (
162
+ `[${ marker } - ${ time } ] Error executing command: ${ error . stack || error } ` ,
163
+ ) ;
164
+
165
+ const commandName =
166
+ prepared . command ?. data ?. command ?. name ??
167
+ prepared . command . command . name ;
168
+
169
+ await analytics . track ( {
170
+ name : AnalyticsEvents . COMMAND_EXECUTION ,
171
+ id : commandName ,
172
+ data : {
173
+ error : true ,
174
+ executionTime : env . getExecutionTime ( ) . toFixed ( 2 ) ,
175
+ type : executionMode ,
176
+ command : commandName ,
177
+ } ,
178
+ } ) ;
179
+
180
+ return ;
181
+ }
182
+
183
+ Logger . info (
184
+ `[${ marker } - ${ time } ] Command executed successfully` ,
162
185
) ;
163
186
164
187
const commandName =
@@ -169,130 +192,115 @@ export class AppCommandRunner {
169
192
name : AnalyticsEvents . COMMAND_EXECUTION ,
170
193
id : commandName ,
171
194
data : {
172
- error : true ,
195
+ error : false ,
173
196
executionTime : env . getExecutionTime ( ) . toFixed ( 2 ) ,
174
197
type : executionMode ,
175
198
command : commandName ,
176
199
} ,
177
200
} ) ;
178
-
179
- return ;
180
- }
181
-
182
- Logger . info (
183
- `[${ marker } - ${ time } ] Command executed successfully` ,
184
- ) ;
185
-
186
- const commandName =
187
- prepared . command ?. data ?. command ?. name ??
188
- prepared . command . command . name ;
189
-
190
- await analytics . track ( {
191
- name : AnalyticsEvents . COMMAND_EXECUTION ,
192
- id : commandName ,
193
- data : {
194
- error : false ,
195
- executionTime : env . getExecutionTime ( ) . toFixed ( 2 ) ,
196
- type : executionMode ,
197
- command : commandName ,
198
- } ,
199
201
} ) ;
200
- } ) ;
201
202
202
- return fn ( middlewareCtx . clone ( ) ) ;
203
- } ,
204
- this . #finalizer. bind ( this ) ,
205
- ) ;
206
-
207
- const executeCommand =
208
- runCommand != null
209
- ? ( runCommand as RunCommand ) ( _executeCommand )
210
- : _executeCommand ;
211
-
212
- env . markStart ( prepared . command . data . command . name ) ;
213
-
214
- const res = await commandkit . plugins . execute ( async ( ctx , plugin ) => {
215
- return plugin . executeCommand (
216
- ctx ,
217
- env ,
218
- source ,
219
- prepared ,
220
- executeCommand ,
203
+ return fn ( middlewareCtx . clone ( ) ) ;
204
+ } ,
205
+ this . #finalizer. bind ( this ) ,
221
206
) ;
222
- } ) ;
223
207
224
- if ( ! res ) {
225
- result = await executeCommand ( ) ;
226
- }
227
- } catch ( e ) {
228
- if ( isErrorType ( e , CommandKitErrorCodes . StopMiddlewares ) ) {
229
- stopMiddlewaresCalledInCmd = true ;
230
- Logger . debug (
231
- `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called by the command itself` ,
208
+ const executeCommand =
209
+ runCommand != null
210
+ ? ( runCommand as RunCommand ) ( _executeCommand )
211
+ : _executeCommand ;
212
+
213
+ env . markStart ( prepared . command . data . command . name ) ;
214
+
215
+ const res = await commandkit . plugins . execute (
216
+ async ( ctx , plugin ) => {
217
+ return plugin . executeCommand (
218
+ ctx ,
219
+ env ,
220
+ source ,
221
+ prepared ,
222
+ executeCommand ,
223
+ ) ;
224
+ } ,
232
225
) ;
233
- } else if ( ! isErrorType ( e , CommandKitErrorCodes . ForwardedCommand ) ) {
234
- if ( shouldThrowOnError ) {
235
- throw e ;
236
- }
237
- Logger . error ( e ) ;
238
- }
239
- }
240
- }
241
- } else {
242
- result = {
243
- error : true ,
244
- message :
245
- 'Command execution was cancelled by a beforeExecute middleware.' ,
246
- } ;
247
- }
248
226
249
- const afterMiddlewares = prepared . middlewares . filter (
250
- ( m ) => m . data . afterExecute ,
251
- ) ;
252
-
253
- // Run middleware after command execution only if `stopMiddlewares()` wasn't
254
- // called in either `beforeExecute` middleware or in the command itself.
255
- if (
256
- ! beforeMiddlewaresStopped &&
257
- ! stopMiddlewaresCalledInCmd &&
258
- afterMiddlewares . length
259
- ) {
260
- await provideContext ( env , async ( ) => {
261
- for ( const middleware of afterMiddlewares ) {
262
- try {
263
- await middleware . data . afterExecute ( middlewareCtx ) ;
227
+ if ( ! res ) {
228
+ result = await executeCommand ( ) ;
229
+ }
264
230
} catch ( e ) {
265
231
if ( isErrorType ( e , CommandKitErrorCodes . StopMiddlewares ) ) {
232
+ stopMiddlewaresCalledInCmd = true ;
266
233
Logger . debug (
267
- `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called inside an afterExecute function at " ${ middleware . middleware . relativePath } " ` ,
234
+ `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called by the command itself ` ,
268
235
) ;
269
- break ; // Stop the afterExecute middleware loop if `stopMiddlewares()` is called.
236
+ } else if ( ! isErrorType ( e , CommandKitErrorCodes . ForwardedCommand ) ) {
237
+ if ( shouldThrowOnError ) {
238
+ throw e ;
239
+ }
240
+ Logger . error ( e ) ;
270
241
}
271
- throw e ;
272
242
}
273
243
}
274
- } ) ;
275
- }
244
+ } else {
245
+ result = {
246
+ error : true ,
247
+ message :
248
+ 'Command execution was cancelled by a beforeExecute middleware.' ,
249
+ } ;
250
+ }
276
251
277
- return result ;
252
+ const afterMiddlewares = prepared . middlewares . filter (
253
+ ( m ) => m . data . afterExecute ,
254
+ ) ;
255
+
256
+ // Run middleware after command execution only if `stopMiddlewares()` wasn't
257
+ // called in either `beforeExecute` middleware or in the command itself.
258
+ if (
259
+ ! beforeMiddlewaresStopped &&
260
+ ! stopMiddlewaresCalledInCmd &&
261
+ afterMiddlewares . length
262
+ ) {
263
+ await provideContext ( env , async ( ) => {
264
+ for ( const middleware of afterMiddlewares ) {
265
+ try {
266
+ await middleware . data . afterExecute ( middlewareCtx ) ;
267
+ } catch ( e ) {
268
+ if ( isErrorType ( e , CommandKitErrorCodes . StopMiddlewares ) ) {
269
+ Logger . debug (
270
+ `Middleware propagation stopped for command "${ middlewareCtx . commandName } ". stopMiddlewares() was called inside an afterExecute function at "${ middleware . middleware . relativePath } "` ,
271
+ ) ;
272
+ break ; // Stop the afterExecute middleware loop if `stopMiddlewares()` is called.
273
+ }
274
+ throw e ;
275
+ }
276
+ }
277
+ } ) ;
278
+ }
279
+
280
+ return result ;
281
+ } finally {
282
+ await this . #finalizer( env , false ) ;
283
+ }
278
284
}
279
285
280
286
/**
281
287
* @private
282
288
* @internal
283
289
* Finalizes command execution by running deferred functions and plugin cleanup.
284
290
*/
285
- async #finalizer( ) {
286
- const env = useEnvironment ( ) ;
291
+ async #finalizer( env ?: CommandKitEnvironment , runPlugins = true ) {
292
+ env ?? = useEnvironment ( ) ;
287
293
288
294
await env . runDeferredFunctions ( ) ;
289
295
290
296
env . clearAllDeferredFunctions ( ) ;
291
297
292
298
// plugins may have their own deferred function, useful for cleanup or post-command analytics
293
- await this . handler . commandkit . plugins . execute ( async ( ctx , plugin ) => {
294
- await plugin . onAfterCommand ( ctx , env ) ;
295
- } ) ;
299
+ if ( runPlugins ) {
300
+ await this . handler . commandkit . plugins . execute ( async ( ctx , plugin ) => {
301
+ await plugin . onAfterCommand ( ctx , env ) ;
302
+ } ) ;
303
+ }
296
304
}
297
305
298
306
/**
0 commit comments