@@ -55,16 +55,32 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
5555 this . logger . error ( invalidPackageError . message , invalidPackageError . stack ) ;
5656 throw invalidPackageError ;
5757 }
58- for ( const name of this . getServiceNames ( grpcPkg ) ) {
58+ // Take all of the services defined in grpcPkg and assign them to
59+ // method handlers defined in Controllers
60+ for ( const definition of this . getServiceNames ( grpcPkg ) ) {
5961 this . grpcClient . addService (
60- grpcPkg [ name ] . service ,
61- await this . createService ( grpcPkg [ name ] , name ) ,
62+ // First parameter requires exact service definition from proto
63+ definition . service . service ,
64+ // Here full proto definition required along with namespaced pattern name
65+ await this . createService ( definition . service , definition . name )
6266 ) ;
6367 }
6468 }
6569
66- public getServiceNames ( grpcPkg : any ) {
67- return Object . keys ( grpcPkg ) . filter ( name => grpcPkg [ name ] . service ) ;
70+ /**
71+ * Will return all of the services along with their fully namespaced
72+ * names as an array of objects.
73+ *
74+ * This method initiates recursive scan of grpcPkg object
75+ *
76+ * @param grpcPkg
77+ */
78+ public getServiceNames ( grpcPkg : any ) : { name : string , service : any } [ ] {
79+ // Define accumulator to collect all of the services available to load
80+ const services : { name : string , service : any } [ ] = [ ] ;
81+ // Initiate recursive services collector starting with empty name
82+ this . _getServiceNamesCollector ( '' , grpcPkg , services ) ;
83+ return services ;
6884 }
6985
7086 public async createService ( grpcService : any , name : string ) {
@@ -177,4 +193,58 @@ export class ServerGrpc extends Server implements CustomTransportStrategy {
177193 throw invalidProtoError ;
178194 }
179195 }
196+
197+ /**
198+ * Recursively fetch all of the service methods available on loaded
199+ * protobuf descriptor object, and collect those as an objects with
200+ * dot-syntax full-path names.
201+ *
202+ * Example:
203+ * for proto package Bundle.FirstService with service Events { rpc...
204+ * will be resolved to object of (while loaded for Bundle package):
205+ * {
206+ * name: "FirstService.Events",
207+ * service: {Object}
208+ * }
209+ *
210+ * @param name
211+ * @param grpcDefinition
212+ * @param accumulator
213+ * @private
214+ */
215+ private _getServiceNamesCollector ( name , grpcDefinition , accumulator ) {
216+ // Confirm that next definition to unwrap is an object
217+ if ( typeof grpcDefinition !== 'object' )
218+ // Exit for non objects
219+ return ;
220+ // Collect keys for traverse
221+ const keys = Object . keys ( grpcDefinition ) ;
222+ // Traverse definitions or namespace extensions
223+ for ( const key of keys ) {
224+ // Define name extension variable
225+ let nameExtended = '' ;
226+ // If depth is zero then just add key
227+ if ( name . length === 0 )
228+ nameExtended = key ;
229+ // If depth non-zero then add next through dot syntax
230+ else
231+ nameExtended = name + '.' + key ;
232+ // Take nested object
233+ const nested = grpcDefinition [ key ] ;
234+ // Check if it's in depth with service definition available
235+ const requirement1 = typeof nested . service !== 'undefined' ;
236+ // Check if first requirement passable and service isn't a boolean value
237+ const requirement2 = requirement1 ? nested . service !== false : false ;
238+ // Check if both requirements satisfied
239+ if ( requirement1 && requirement2 ) {
240+ // Add new service object to accumulator
241+ accumulator . push ( {
242+ name : nameExtended ,
243+ service : nested
244+ } ) ;
245+ } else
246+ // Continue recursion until objects end or service definition found
247+ this . _getServiceNamesCollector ( nameExtended , nested , accumulator ) ;
248+ }
249+ }
180250}
0 commit comments