@@ -81,23 +81,25 @@ class DriverService extends BaseService {
81
81
return this . interface_to_implementation [ interface_name ] ;
82
82
}
83
83
84
+ return ;
84
85
this . log . noticeme ( 'HERE IT IS' ) ;
85
86
const options = this . services . get_implementors ( interface_name ) ;
86
87
this . log . info ( 'test' , { options } ) ;
87
88
if ( options . length < 1 ) return ;
88
89
return options [ 0 ] ;
89
90
}
90
91
91
- async call ( ... a ) {
92
+ async call ( o ) {
92
93
try {
93
- return await this . _call ( ... a ) ;
94
+ return await this . _call ( o ) ;
94
95
} catch ( e ) {
96
+ console . error ( e ) ;
95
97
return this . _driver_response_from_error ( e ) ;
96
98
}
97
99
}
98
100
99
- async _call ( interface_name , method , args ) {
100
- const processed_args = await this . _process_args ( interface_name , method , args ) ;
101
+ async _call ( { driver , iface , method, args } ) {
102
+ const processed_args = await this . _process_args ( iface , method , args ) ;
101
103
if ( Context . get ( 'test_mode' ) ) {
102
104
processed_args . test_mode = true ;
103
105
}
@@ -110,18 +112,44 @@ class DriverService extends BaseService {
110
112
const services = Context . get ( 'services' ) ;
111
113
const svc_permission = services . get ( 'permission' ) ;
112
114
113
- const reading = await svc_permission . scan ( actor , `driver:${ interface_name } :${ method } ` ) ;
115
+
116
+ const svc_registry = this . services . get ( 'registry' ) ;
117
+ const c_interfaces = svc_registry . get ( 'interfaces' ) ;
118
+
119
+ driver = driver ?? iface ;
120
+
121
+ const driver_service_exists = ( ( ) => {
122
+ return this . services . has ( driver ) &&
123
+ this . services . get ( driver ) . list_traits ( )
124
+ . includes ( iface ) ;
125
+ } ) ( ) ;
126
+ if ( driver_service_exists ) {
127
+ const service = this . services . get ( driver ) ;
128
+ const reading = await svc_permission . scan (
129
+ actor ,
130
+ PermissionUtil . join ( 'driver' , driver , 'ii' , iface ) ,
131
+ ) ;
132
+ const options = PermissionUtil . reading_to_options ( reading ) ;
133
+ if ( options . length > 0 ) {
134
+ return await this . call_new_ ( {
135
+ service_name : driver ,
136
+ service,
137
+ method,
138
+ args : processed_args ,
139
+ iface,
140
+ } ) ;
141
+ }
142
+ }
143
+
144
+ const reading = await svc_permission . scan ( actor , `driver:${ iface } :${ method } ` ) ;
114
145
const options = PermissionUtil . reading_to_options ( reading ) ;
115
146
if ( ! ( options . length > 0 ) ) {
116
147
throw APIError . create ( 'permission_denied' ) ;
117
148
}
118
149
119
- const svc_registry = this . services . get ( 'registry' ) ;
120
- const c_interfaces = svc_registry . get ( 'interfaces' ) ;
121
-
122
- const instance = this . get_default_implementation ( interface_name ) ;
150
+ const instance = this . get_default_implementation ( iface ) ;
123
151
if ( ! instance ) {
124
- throw APIError . create ( 'no_implementation_available' , null , { interface_name } )
152
+ throw APIError . create ( 'no_implementation_available' , null , { iface } )
125
153
}
126
154
const meta = await ( async ( ) => {
127
155
if ( instance instanceof Driver ) {
@@ -142,7 +170,7 @@ class DriverService extends BaseService {
142
170
result = await instance . impl [ method ] ( processed_args ) ;
143
171
}
144
172
if ( result instanceof TypedValue ) {
145
- const interface_ = c_interfaces . get ( interface_name ) ;
173
+ const interface_ = c_interfaces . get ( iface ) ;
146
174
let desired_type = interface_ . methods [ method ]
147
175
. result_choices [ 0 ] . type ;
148
176
const svc_coercion = services . get ( 'coercion' ) ;
@@ -151,8 +179,9 @@ class DriverService extends BaseService {
151
179
}
152
180
return { success : true , ...meta , result } ;
153
181
} catch ( e ) {
182
+ console . error ( e ) ;
154
183
let for_user = ( e instanceof APIError ) || ( e instanceof DriverError ) ;
155
- if ( ! for_user ) this . errors . report ( `driver:${ interface_name } :${ method } ` , {
184
+ if ( ! for_user ) this . errors . report ( `driver:${ iface } :${ method } ` , {
156
185
source : e ,
157
186
trace : true ,
158
187
// TODO: alarm will not be suitable for all errors.
@@ -164,6 +193,35 @@ class DriverService extends BaseService {
164
193
return this . _driver_response_from_error ( e , meta ) ;
165
194
}
166
195
}
196
+
197
+ async call_new_ ( {
198
+ service_name,
199
+ service, method, args,
200
+ iface,
201
+ } ) {
202
+ const svc_registry = this . services . get ( 'registry' ) ;
203
+ const c_interfaces = svc_registry . get ( 'interfaces' ) ;
204
+ let result = await service . as ( iface ) [ method ] ( args ) ;
205
+ if ( result instanceof TypedValue ) {
206
+ const interface_ = c_interfaces . get ( iface ) ;
207
+ let desired_type = interface_ . methods [ method ]
208
+ . result_choices [ 0 ] . type ;
209
+ const svc_coercion = services . get ( 'coercion' ) ;
210
+ result = await svc_coercion . coerce ( desired_type , result ) ;
211
+ }
212
+ const service_meta = { } ;
213
+ if ( service . list_traits ( ) . includes ( 'version' ) ) {
214
+ service_meta . version = service . as ( 'version' ) . get_version ( ) ;
215
+ }
216
+ return {
217
+ success : true ,
218
+ service : {
219
+ ...service_meta ,
220
+ name : service_name ,
221
+ } ,
222
+ result
223
+ } ;
224
+ }
167
225
168
226
async _driver_response_from_error ( e , meta ) {
169
227
let serializable = ( e instanceof APIError ) || ( e instanceof DriverError ) ;
0 commit comments