|
@@ -21,6 +21,7 @@ const APIError = require("../../api/APIError");
|
|
|
const { DriverError } = require("./DriverError");
|
|
|
const { TypedValue } = require("./meta/Runtime");
|
|
|
const BaseService = require("../BaseService");
|
|
|
+const { Driver } = require("../../definitions/Driver");
|
|
|
|
|
|
/**
|
|
|
* DriverService provides the functionality of Puter drivers.
|
|
@@ -31,10 +32,30 @@ class DriverService extends BaseService {
|
|
|
}
|
|
|
|
|
|
_construct () {
|
|
|
- this.interfaces = require('./interfaces');
|
|
|
+ this.drivers = {};
|
|
|
this.interface_to_implementation = {};
|
|
|
}
|
|
|
|
|
|
+ async ['__on_registry.collections'] (_, { svc_registry }) {
|
|
|
+ svc_registry.register_collection('interfaces');
|
|
|
+ svc_registry.register_collection('drivers');
|
|
|
+ }
|
|
|
+ async ['__on_registry.entries'] (_, { svc_registry }) {
|
|
|
+ const services = this.services;
|
|
|
+ const col_interfaces = svc_registry.get('interfaces');
|
|
|
+ const col_drivers = svc_registry.get('drivers');
|
|
|
+ {
|
|
|
+ const default_interfaces = require('./interfaces');
|
|
|
+ for ( const k in default_interfaces ) {
|
|
|
+ col_interfaces.set(k, default_interfaces[k]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ await services.emit('driver.register.interfaces',
|
|
|
+ { col_interfaces });
|
|
|
+ await services.emit('driver.register.drivers',
|
|
|
+ { col_drivers });
|
|
|
+ }
|
|
|
+
|
|
|
_init () {
|
|
|
const svc_registry = this.services.get('registry');
|
|
|
svc_registry.register_collection('');
|
|
@@ -43,9 +64,27 @@ class DriverService extends BaseService {
|
|
|
register_driver (interface_name, implementation) {
|
|
|
this.interface_to_implementation[interface_name] = implementation;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
get_interface (interface_name) {
|
|
|
- return this.interfaces[interface_name];
|
|
|
+ const o = {};
|
|
|
+ const col_interfaces = svc_registry.get('interfaces');
|
|
|
+ const keys = col_interfaces.keys();
|
|
|
+ for ( const k of keys ) o[k] = col_interfaces.get(k);
|
|
|
+ return col_interfaces.get(interface_name);
|
|
|
+ }
|
|
|
+
|
|
|
+ get_default_implementation (interface_name) {
|
|
|
+ // If there's a hardcoded implementation, use that
|
|
|
+ // (^ temporary, until all are migrated)
|
|
|
+ if (this.interface_to_implementation.hasOwnProperty(interface_name)) {
|
|
|
+ return this.interface_to_implementation[interface_name];
|
|
|
+ }
|
|
|
+
|
|
|
+ this.log.noticeme('HERE IT IS');
|
|
|
+ const options = this.services.get_implementors(interface_name);
|
|
|
+ this.log.info('test', { options });
|
|
|
+ if ( options.length < 1 ) return;
|
|
|
+ return options[0];
|
|
|
}
|
|
|
|
|
|
async call (...a) {
|
|
@@ -76,16 +115,33 @@ class DriverService extends BaseService {
|
|
|
throw APIError.create('permission_denied');
|
|
|
}
|
|
|
|
|
|
- const instance = this.interface_to_implementation[interface_name];
|
|
|
+ const svc_registry = this.services.get('registry');
|
|
|
+ const c_interfaces = svc_registry.get('interfaces');
|
|
|
+
|
|
|
+ const instance = this.get_default_implementation(interface_name);
|
|
|
if ( ! instance ) {
|
|
|
throw APIError.create('no_implementation_available', null, { interface_name })
|
|
|
}
|
|
|
- const meta = await instance.get_response_meta();
|
|
|
- const sla_override = await this.maybe_get_sla(interface_name, method);
|
|
|
+ const meta = await (async () => {
|
|
|
+ if ( instance instanceof Driver ) {
|
|
|
+ return await instance.get_response_meta();
|
|
|
+ }
|
|
|
+ if ( ! instance.instance.as('driver-metadata') ) return;
|
|
|
+ const t = instance.instance.as('driver-metadata');
|
|
|
+ return t.get_response_meta();
|
|
|
+ })();
|
|
|
try {
|
|
|
- let result = await instance.call(method, processed_args, sla_override);
|
|
|
+ let result;
|
|
|
+ if ( instance instanceof Driver ) {
|
|
|
+ result = await instance.call(
|
|
|
+ method, processed_args);
|
|
|
+ } else {
|
|
|
+ // TODO: SLA and monthly limits do not apply do drivers
|
|
|
+ // from service traits (yet)
|
|
|
+ result = await instance.impl[method](processed_args);
|
|
|
+ }
|
|
|
if ( result instanceof TypedValue ) {
|
|
|
- const interface_ = this.interfaces[interface_name];
|
|
|
+ const interface_ = c_interfaces.get(interface_name);
|
|
|
let desired_type = interface_.methods[method]
|
|
|
.result_choices[0].type;
|
|
|
const svc_coercion = services.get('coercion');
|
|
@@ -127,16 +183,12 @@ class DriverService extends BaseService {
|
|
|
return this.interfaces;
|
|
|
}
|
|
|
|
|
|
- async maybe_get_sla (interface_name, method) {
|
|
|
- const services = this.services;
|
|
|
- const fs = services.get('filesystem');
|
|
|
-
|
|
|
- return false;
|
|
|
- }
|
|
|
-
|
|
|
async _process_args (interface_name, method_name, args) {
|
|
|
+ const svc_registry = this.services.get('registry');
|
|
|
+ const c_interfaces = svc_registry.get('interfaces');
|
|
|
+
|
|
|
// Note: 'interface' is a strict mode reserved word.
|
|
|
- const interface_ = this.interfaces[interface_name];
|
|
|
+ const interface_ = c_interfaces.get(interface_name);
|
|
|
if ( ! interface_ ) {
|
|
|
throw APIError.create('interface_not_found', null, { interface_name });
|
|
|
}
|