@@ -8,7 +8,8 @@ import { AppsScriptEventType, ParamSource } from "../domain/enums";
88import { InjectTokenDefinition , Newable , ParamDefinition } from "../domain/types" ;
99import { getInjectionTokens } from "../repository" ;
1010import { Resolver } from "../service" ;
11- import { isFunctionLike } from "apps-script-utils" ;
11+ import { isFunctionLike , isRegExp } from "apps-script-utils" ;
12+ import { isChangeEvent , isEditEvent , isFormSubmitEvent , isRecord } from "../shared/utils" ;
1213
1314/**
1415 * Service for dispatching events to controllers.
@@ -39,7 +40,9 @@ export class EventDispatcher {
3940 const propertyNames = Object . getOwnPropertyNames ( prototype ) ;
4041
4142 for ( const propertyName of propertyNames ) {
42- if ( propertyName === "constructor" ) continue ;
43+ if ( propertyName === "constructor" ) {
44+ continue ;
45+ }
4346
4447 const methodHandler = prototype [ propertyName ] ;
4548
@@ -50,12 +53,15 @@ export class EventDispatcher {
5053 if ( eventMetadata === eventType && this . checkFilters ( eventType , event , options ) ) {
5154 const instance = this . resolver . resolve ( controller ) ;
5255
53- const args = this . buildMethodParams ( instance as object , propertyName , event ) ;
56+ if ( ! isRecord ( instance ) ) continue ;
57+
58+ const args = this . buildMethodParams ( instance , propertyName , event ) ;
5459
55- const handler = ( instance as Record < string | symbol , unknown > ) [ propertyName ] as (
56- ...args : unknown [ ]
57- ) => unknown ;
58- await handler . apply ( instance , args ) ;
60+ const handler = instance [ propertyName ] ;
61+
62+ if ( isFunctionLike ( handler ) ) {
63+ await Reflect . apply ( handler , instance , args ) ;
64+ }
5965 }
6066 }
6167 }
@@ -70,7 +76,9 @@ export class EventDispatcher {
7076 */
7177 public async dispatchByName ( methodName : string , event : unknown ) : Promise < void > {
7278 for ( const controller of this . controllers . keys ( ) ) {
73- const instance = this . resolver . resolve ( controller ) as Record < string , any > ;
79+ const instance = this . resolver . resolve ( controller ) ;
80+
81+ if ( ! isRecord ( instance ) ) continue ;
7482
7583 const prototype = Object . getPrototypeOf ( instance ) ;
7684
@@ -91,9 +99,9 @@ export class EventDispatcher {
9199 continue ;
92100 }
93101
94- const handler = instance [ methodName ] . bind ( instance ) ;
102+ const method = instance [ methodName ] ;
95103
96- if ( ! isFunctionLike ( handler ) ) {
104+ if ( ! isFunctionLike ( method ) ) {
97105 console . warn (
98106 "Method '%s' in controller '%s' is not a callable function and was skipped during event handling." ,
99107 methodName ,
@@ -103,10 +111,10 @@ export class EventDispatcher {
103111 continue ;
104112 }
105113
106- const args = this . buildMethodParams ( instance as object , methodName , event ) ;
114+ const args = this . buildMethodParams ( instance , methodName , event ) ;
107115
108116 try {
109- await handler ( ... args ) ;
117+ await Reflect . apply ( method , instance , args ) ;
110118 } catch ( err : unknown ) {
111119 console . error ( "Error:" , err instanceof Error ? err . stack : String ( err ) ) ;
112120 }
@@ -136,9 +144,10 @@ export class EventDispatcher {
136144 propertyKey
137145 ) ;
138146
139- const metadata : ( ParamDefinition | InjectTokenDefinition ) [ ] = (
140- Object . values ( rawMetadata ) as ( ParamDefinition | InjectTokenDefinition ) [ ]
141- ) . concat ( Object . values ( rawInjectMetadata ) as ( ParamDefinition | InjectTokenDefinition ) [ ] ) ;
147+ const metadata : ( ParamDefinition | InjectTokenDefinition ) [ ] = [
148+ ...Object . values ( rawMetadata ) ,
149+ ...Object . values ( rawInjectMetadata )
150+ ] ;
142151
143152 metadata . sort ( ( a , b ) => a . index - b . index ) ;
144153
@@ -150,10 +159,7 @@ export class EventDispatcher {
150159 for ( const param of metadata ) {
151160 switch ( param . type ) {
152161 case ParamSource . EVENT :
153- args [ param . index ] =
154- param . key && typeof event === "object" && event !== null
155- ? ( event as Record < string , unknown > ) [ param . key ]
156- : event ;
162+ args [ param . index ] = param . key && isRecord ( event ) ? event [ param . key ] : event ;
157163 break ;
158164
159165 case ParamSource . INJECT :
@@ -188,36 +194,40 @@ export class EventDispatcher {
188194 event : unknown ,
189195 options : Record < string , unknown > | undefined
190196 ) : boolean {
191- if ( ! options ) return true ;
197+ if ( ! options ) {
198+ return true ;
199+ }
192200
193201 switch ( eventType ) {
194202 case AppsScriptEventType . EDIT :
195203 if ( options . range ) {
196- const editEvent = event as GoogleAppsScript . Events . SheetsOnEdit ;
197- const eventRangeA1 =
198- typeof editEvent . range ?. getA1Notation === "function"
199- ? editEvent . range . getA1Notation ( )
200- : null ;
204+ if ( ! isEditEvent ( event ) ) {
205+ return false ;
206+ }
207+
208+ const eventRangeA1 = isFunctionLike ( event . range ?. getA1Notation )
209+ ? event . range . getA1Notation ( )
210+ : null ;
201211
202212 if ( ! eventRangeA1 ) {
203213 return false ;
204214 }
205215
206216 const ranges = Array . isArray ( options . range ) ? options . range : [ options . range ] ;
207217
208- // TODO: isRegExp
209218 return ranges . some ( ( r : string | RegExp ) =>
210- r instanceof RegExp ? r . test ( eventRangeA1 ) : eventRangeA1 === r
219+ isRegExp ( r ) ? r . test ( eventRangeA1 ) : eventRangeA1 === r
211220 ) ;
212221 }
213222 break ;
214223
215224 case AppsScriptEventType . FORM_SUBMIT :
216225 if ( options . formId ) {
217- const submitEvent = event as GoogleAppsScript . Events . FormsOnFormSubmit ;
218- const eventFormId = (
219- submitEvent . source as unknown as { getId ?: ( ) => string }
220- ) ?. getId ?.( ) ;
226+ if ( ! isFormSubmitEvent ( event ) ) {
227+ return false ;
228+ }
229+
230+ const eventFormId = isFunctionLike ( event . source ?. getId ) ? event . source . getId ( ) : null ;
221231
222232 if ( ! eventFormId ) {
223233 return false ;
@@ -231,8 +241,11 @@ export class EventDispatcher {
231241
232242 case AppsScriptEventType . CHANGE :
233243 if ( options . changeType ) {
234- const changeEvent = event as GoogleAppsScript . Events . SheetsOnChange ;
235- const eventChangeType = changeEvent . changeType ;
244+ if ( ! isChangeEvent ( event ) ) {
245+ return false ;
246+ }
247+
248+ const eventChangeType = event . changeType ;
236249
237250 if ( ! eventChangeType ) {
238251 return false ;
0 commit comments