@heyputer/puter.js 2.1.4 → 2.1.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. package/dist/puter.cjs +2 -2
  2. package/index.d.ts +41 -15
  3. package/package.json +1 -1
  4. package/src/index.js +116 -79
  5. package/src/lib/APICallLogger.js +20 -21
  6. package/src/lib/EventListener.js +10 -10
  7. package/src/lib/filesystem/APIFS.js +11 -19
  8. package/src/lib/filesystem/CacheFS.js +25 -25
  9. package/src/lib/filesystem/PostMessageFS.js +11 -11
  10. package/src/lib/filesystem/definitions.js +11 -10
  11. package/src/lib/path.js +505 -446
  12. package/src/lib/polyfills/fileReaderPoly.js +40 -0
  13. package/src/lib/polyfills/localStorage.js +30 -33
  14. package/src/lib/polyfills/xhrshim.js +206 -207
  15. package/src/lib/utils.js +160 -151
  16. package/src/lib/xdrpc.js +9 -9
  17. package/src/modules/AI.js +473 -292
  18. package/src/modules/Apps.js +56 -56
  19. package/src/modules/Auth.js +17 -17
  20. package/src/modules/Debug.js +1 -1
  21. package/src/modules/Drivers.js +41 -41
  22. package/src/modules/FSItem.js +64 -62
  23. package/src/modules/FileSystem/index.js +22 -23
  24. package/src/modules/FileSystem/operations/copy.js +7 -7
  25. package/src/modules/FileSystem/operations/deleteFSEntry.js +14 -12
  26. package/src/modules/FileSystem/operations/getReadUrl.js +16 -14
  27. package/src/modules/FileSystem/operations/mkdir.js +11 -11
  28. package/src/modules/FileSystem/operations/move.js +12 -12
  29. package/src/modules/FileSystem/operations/read.js +10 -10
  30. package/src/modules/FileSystem/operations/readdir.js +28 -28
  31. package/src/modules/FileSystem/operations/rename.js +11 -11
  32. package/src/modules/FileSystem/operations/sign.js +33 -30
  33. package/src/modules/FileSystem/operations/space.js +7 -7
  34. package/src/modules/FileSystem/operations/stat.js +25 -25
  35. package/src/modules/FileSystem/operations/symlink.js +15 -17
  36. package/src/modules/FileSystem/operations/upload.js +151 -122
  37. package/src/modules/FileSystem/operations/write.js +16 -12
  38. package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +10 -6
  39. package/src/modules/Hosting.js +29 -29
  40. package/src/modules/KV.js +23 -23
  41. package/src/modules/OS.js +15 -15
  42. package/src/modules/Perms.js +19 -21
  43. package/src/modules/PuterDialog.js +46 -48
  44. package/src/modules/Threads.js +17 -20
  45. package/src/modules/UI.js +156 -156
  46. package/src/modules/Util.js +3 -3
  47. package/src/modules/Workers.js +52 -49
  48. package/src/modules/networking/PSocket.js +38 -38
  49. package/src/modules/networking/PTLS.js +54 -47
  50. package/src/modules/networking/PWispHandler.js +49 -47
  51. package/src/modules/networking/parsers.js +110 -108
  52. package/src/modules/networking/requests.js +67 -78
  53. package/src/services/APIAccess.js +9 -9
  54. package/src/services/FSRelay.js +6 -6
  55. package/src/services/Filesystem.js +8 -8
  56. package/src/services/NoPuterYet.js +2 -2
  57. package/src/services/XDIncoming.js +1 -1
@@ -1,6 +1,6 @@
1
- import * as utils from '../lib/utils.js'
1
+ import * as utils from '../lib/utils.js';
2
2
 
3
- class Apps{
3
+ class Apps {
4
4
  /**
5
5
  * Creates a new instance with the given authentication token, API origin, and app ID,
6
6
  *
@@ -28,7 +28,7 @@ class Apps{
28
28
 
29
29
  /**
30
30
  * Sets the API origin.
31
- *
31
+ *
32
32
  * @param {string} APIOrigin - The new API origin.
33
33
  * @memberof [Apps]
34
34
  * @returns {void}
@@ -41,40 +41,40 @@ class Apps{
41
41
  let options = {};
42
42
 
43
43
  // if args is a single object, assume it is the options object
44
- if (typeof args[0] === 'object' && args[0] !== null) {
44
+ if ( typeof args[0] === 'object' && args[0] !== null ) {
45
45
  options.params = args[0];
46
46
  }
47
47
 
48
- options.predicate = ['user-can-edit'];
48
+ options.predicate = ['user-can-edit'];
49
49
 
50
50
  return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'select').call(this, options);
51
- }
51
+ };
52
52
 
53
53
  create = async (...args) => {
54
54
  let options = {};
55
55
  // * allows for: puter.apps.new('example-app') *
56
- if (typeof args[0] === 'string') {
56
+ if ( typeof args[0] === 'string' ) {
57
57
  let indexURL = args[1];
58
58
  let title = args[2] ?? args[0];
59
59
 
60
- options = {
61
- object: {
62
- name: args[0],
63
- index_url: indexURL,
64
- title: title
65
- }
60
+ options = {
61
+ object: {
62
+ name: args[0],
63
+ index_url: indexURL,
64
+ title: title,
65
+ },
66
66
  };
67
67
  }
68
68
 
69
69
  // * allows for: puter.apps.new({name: 'example-app', indexURL: 'https://example.com'}) *
70
- else if (typeof args[0] === 'object' && args[0] !== null) {
70
+ else if ( typeof args[0] === 'object' && args[0] !== null ) {
71
71
  let options_raw = args[0];
72
72
 
73
- options = {
74
- object: {
75
- name: options_raw.name,
76
- index_url: options_raw.indexURL,
77
- // title is optional only if name is provided.
73
+ options = {
74
+ object: {
75
+ name: options_raw.name,
76
+ index_url: options_raw.indexURL,
77
+ // title is optional only if name is provided.
78
78
  // If title is provided, use it. If not, use name.
79
79
  title: options_raw.title ?? options_raw.name,
80
80
  description: options_raw.description,
@@ -86,44 +86,44 @@ class Apps{
86
86
  },
87
87
  options: {
88
88
  dedupe_name: options_raw.dedupeName ?? false,
89
- }
89
+ },
90
90
  };
91
91
  }
92
92
 
93
93
  // name and indexURL are required
94
- if(!options.object.name){
94
+ if ( ! options.object.name ) {
95
95
  throw {
96
- success: false,
96
+ success: false,
97
97
  error: {
98
- code: 'invalid_request',
99
- message: 'Name is required'
100
- }
98
+ code: 'invalid_request',
99
+ message: 'Name is required',
100
+ },
101
101
  };
102
102
  }
103
- if(!options.object.index_url){
103
+ if ( ! options.object.index_url ) {
104
104
  throw {
105
- success: false,
105
+ success: false,
106
106
  error: {
107
- code: 'invalid_request',
108
- message: 'Index URL is required'
109
- }
107
+ code: 'invalid_request',
108
+ message: 'Index URL is required',
109
+ },
110
110
  };
111
111
  }
112
112
 
113
113
  // Call the original chat.complete method
114
114
  return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'create').call(this, options);
115
- }
115
+ };
116
116
 
117
- update = async(...args) => {
117
+ update = async (...args) => {
118
118
  let options = {};
119
119
 
120
120
  // if there is one string argument, assume it is the app name
121
121
  // * allows for: puter.apps.update('example-app') *
122
- if (Array.isArray(args) && typeof args[0] === 'string') {
122
+ if ( Array.isArray(args) && typeof args[0] === 'string' ) {
123
123
  let object_raw = args[1];
124
- let object = {
125
- name: object_raw.name,
126
- index_url: object_raw.indexURL,
124
+ let object = {
125
+ name: object_raw.name,
126
+ index_url: object_raw.indexURL,
127
127
  title: object_raw.title,
128
128
  description: object_raw.description,
129
129
  icon: object_raw.icon,
@@ -133,50 +133,50 @@ class Apps{
133
133
  metadata: object_raw.metadata,
134
134
  };
135
135
 
136
- options = { id: { name: args[0]}, object: object};
136
+ options = { id: { name: args[0] }, object: object };
137
137
  }
138
138
 
139
139
  // Call the original chat.complete method
140
140
  return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'update').call(this, options);
141
- }
141
+ };
142
142
 
143
- get = async(...args) => {
143
+ get = async (...args) => {
144
144
  let options = {};
145
145
 
146
146
  // if there is one string argument, assume it is the app name
147
147
  // * allows for: puter.apps.get('example-app') *
148
- if (Array.isArray(args) && typeof args[0] === 'string') {
148
+ if ( Array.isArray(args) && typeof args[0] === 'string' ) {
149
149
  // if second argument is an object, assume it is the options object
150
- if (typeof args[1] === 'object' && args[1] !== null) {
150
+ if ( typeof args[1] === 'object' && args[1] !== null ) {
151
151
  options.params = args[1];
152
152
  }
153
153
  // name
154
- options.id = {name: args[0]};
154
+ options.id = { name: args[0] };
155
155
  }
156
156
 
157
157
  // if first argument is an object, assume it is the options object
158
- if (typeof args[0] === 'object' && args[0] !== null) {
158
+ if ( typeof args[0] === 'object' && args[0] !== null ) {
159
159
  options.params = args[0];
160
160
  }
161
161
 
162
162
  return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'read').call(this, options);
163
- }
163
+ };
164
164
 
165
- delete = async(...args) => {
165
+ delete = async (...args) => {
166
166
  let options = {};
167
167
  // if there is one string argument, assume it is the app name
168
168
  // * allows for: puter.apps.get('example-app') *
169
- if (Array.isArray(args) && typeof args[0] === 'string') {
170
- options = { id: {name: args[0]}};
169
+ if ( Array.isArray(args) && typeof args[0] === 'string' ) {
170
+ options = { id: { name: args[0] } };
171
171
  }
172
172
  return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'delete').call(this, options);
173
- }
173
+ };
174
174
 
175
- getDeveloperProfile = function(...args){
175
+ getDeveloperProfile = function (...args) {
176
176
  let options;
177
177
 
178
178
  // If first argument is an object, it's the options
179
- if (typeof args[0] === 'object' && args[0] !== null) {
179
+ if ( typeof args[0] === 'object' && args[0] !== null ) {
180
180
  options = args[0];
181
181
  } else {
182
182
  // Otherwise, we assume separate arguments are provided
@@ -190,7 +190,7 @@ class Apps{
190
190
  let options;
191
191
 
192
192
  // If first argument is an object, it's the options
193
- if (typeof args[0] === 'object' && args[0] !== null) {
193
+ if ( typeof args[0] === 'object' && args[0] !== null ) {
194
194
  options = args[0];
195
195
  } else {
196
196
  // Otherwise, we assume separate arguments are provided
@@ -199,17 +199,17 @@ class Apps{
199
199
  error: args[1],
200
200
  };
201
201
  }
202
-
202
+
203
203
  return new Promise((resolve, reject) => {
204
204
  const xhr = utils.initXhr('/get-dev-profile', puter.APIOrigin, puter.authToken, 'get');
205
-
205
+
206
206
  // set up event handlers for load and error events
207
207
  utils.setupXhrEventHandlers(xhr, options.success, options.error, resolve, reject);
208
-
208
+
209
209
  xhr.send();
210
- })
210
+ });
211
211
  });
212
- }
212
+ };
213
213
  }
214
214
 
215
215
  export default Apps;
@@ -1,6 +1,6 @@
1
1
  import * as utils from '../lib/utils.js';
2
2
 
3
- class Auth{
3
+ class Auth {
4
4
  // Used to generate a unique message id for each message sent to the host environment
5
5
  // we start from 1 because 0 is falsy and we want to avoid that for the message id
6
6
  #messageID = 1;
@@ -13,7 +13,7 @@ class Auth{
13
13
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
14
14
  * @param {string} appID - ID of the app to use.
15
15
  */
16
- constructor(context) {
16
+ constructor (context) {
17
17
  this.authToken = context.authToken;
18
18
  this.APIOrigin = context.APIOrigin;
19
19
  this.appID = context.appID;
@@ -26,7 +26,7 @@ class Auth{
26
26
  * @memberof [Auth]
27
27
  * @returns {void}
28
28
  */
29
- setAuthToken(authToken) {
29
+ setAuthToken (authToken) {
30
30
  this.authToken = authToken;
31
31
  }
32
32
 
@@ -37,7 +37,7 @@ class Auth{
37
37
  * @memberof [Auth]
38
38
  * @returns {void}
39
39
  */
40
- setAPIOrigin(APIOrigin) {
40
+ setAPIOrigin (APIOrigin) {
41
41
  this.APIOrigin = APIOrigin;
42
42
  }
43
43
 
@@ -67,8 +67,8 @@ class Auth{
67
67
  }
68
68
  }, 100);
69
69
 
70
- function messageHandler(e) {
71
- if ( e.data.msg_id == msg_id ){
70
+ function messageHandler (e) {
71
+ if ( e.data.msg_id == msg_id ) {
72
72
  // Clear the interval since we got a response
73
73
  clearInterval(checkClosed);
74
74
 
@@ -76,7 +76,7 @@ class Auth{
76
76
  delete e.data.msg_id;
77
77
  delete e.data.msg;
78
78
 
79
- if ( e.data.success ){
79
+ if ( e.data.success ) {
80
80
  // set the auth token
81
81
  puter.setAuthToken(e.data.token);
82
82
 
@@ -106,7 +106,7 @@ class Auth{
106
106
  }
107
107
  };
108
108
 
109
- getUser = function(...args){
109
+ getUser = function (...args) {
110
110
  let options;
111
111
 
112
112
  // If first argument is an object, it's the options
@@ -134,7 +134,7 @@ class Auth{
134
134
  puter.resetAuthToken();
135
135
  };
136
136
 
137
- async whoami() {
137
+ async whoami () {
138
138
  try {
139
139
  const resp = await fetch(`${this.APIOrigin}/whoami`, {
140
140
  headers: {
@@ -155,7 +155,7 @@ class Auth{
155
155
  }
156
156
 
157
157
  return result;
158
- } catch( error ) {
158
+ } catch ( error ) {
159
159
  // Log the error
160
160
  if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
161
161
  globalThis.puter.apiCallLogger.logRequest({
@@ -172,7 +172,7 @@ class Auth{
172
172
  }
173
173
  }
174
174
 
175
- async getMonthlyUsage() {
175
+ async getMonthlyUsage () {
176
176
  try {
177
177
  const resp = await fetch(`${this.APIOrigin}/metering/usage`, {
178
178
  headers: {
@@ -193,7 +193,7 @@ class Auth{
193
193
  }
194
194
 
195
195
  return result;
196
- } catch( error ) {
196
+ } catch ( error ) {
197
197
  // Log the error
198
198
  if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
199
199
  globalThis.puter.apiCallLogger.logRequest({
@@ -210,8 +210,8 @@ class Auth{
210
210
  }
211
211
  }
212
212
 
213
- async getDetailedAppUsage(appId) {
214
- if ( !appId ) {
213
+ async getDetailedAppUsage (appId) {
214
+ if ( ! appId ) {
215
215
  throw new Error('appId is required');
216
216
  }
217
217
 
@@ -235,7 +235,7 @@ class Auth{
235
235
  }
236
236
 
237
237
  return result;
238
- } catch( error ) {
238
+ } catch ( error ) {
239
239
  // Log the error
240
240
  if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
241
241
  globalThis.puter.apiCallLogger.logRequest({
@@ -252,7 +252,7 @@ class Auth{
252
252
  }
253
253
  }
254
254
 
255
- async getGlobalUsage() {
255
+ async getGlobalUsage () {
256
256
  try {
257
257
  const resp = await fetch(`${this.APIOrigin}/metering/globalUsage`, {
258
258
  headers: {
@@ -273,7 +273,7 @@ class Auth{
273
273
  }
274
274
 
275
275
  return result;
276
- } catch( error ) {
276
+ } catch ( error ) {
277
277
  // Log the error
278
278
  if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
279
279
  globalThis.puter.apiCallLogger.logRequest({
@@ -34,6 +34,6 @@ export class Debug {
34
34
  console.log('Got instruction to turn logs on!');
35
35
  this.context.puter.logger.on(e.data.category);
36
36
  }
37
- })
37
+ });
38
38
  }
39
39
  }
@@ -3,13 +3,13 @@ class FetchDriverCallBackend {
3
3
  this.context = context;
4
4
  this.response_handlers = this.constructor.response_handlers;
5
5
  }
6
-
6
+
7
7
  static response_handlers = {
8
8
  'application/x-ndjson': async resp => {
9
9
  const Stream = async function* Stream (readableStream) {
10
10
  const reader = readableStream.getReader();
11
11
  let value, done;
12
- while ( ! done ) {
12
+ while ( !done ) {
13
13
  ({ value, done } = await reader.read());
14
14
  if ( done ) break;
15
15
  const parts = (new TextDecoder().decode(value).split('\n'));
@@ -18,8 +18,8 @@ class FetchDriverCallBackend {
18
18
  yield JSON.parse(part);
19
19
  }
20
20
  }
21
- }
22
-
21
+ };
22
+
23
23
  return Stream(resp.body);
24
24
  },
25
25
  'application/json': async resp => {
@@ -28,8 +28,8 @@ class FetchDriverCallBackend {
28
28
  'application/octet-stream': async resp => {
29
29
  return await resp.blob();
30
30
  },
31
- }
32
-
31
+ };
32
+
33
33
  async call ({ driver, method_name, parameters }) {
34
34
  try {
35
35
  const resp = await fetch(`${this.context.APIOrigin}/drivers/call`, {
@@ -44,10 +44,10 @@ class FetchDriverCallBackend {
44
44
  : {}),
45
45
  method: method_name,
46
46
  args: parameters,
47
- auth_token: this.context.authToken
47
+ auth_token: this.context.authToken,
48
48
  }),
49
49
  });
50
-
50
+
51
51
  const content_type = resp.headers.get('content-type')
52
52
  .split(';')[0].trim(); // TODO: parser for Content-Type
53
53
  const handler = this.response_handlers[content_type];
@@ -56,44 +56,44 @@ class FetchDriverCallBackend {
56
56
  console.error(msg);
57
57
  console.error('creating blob so dev tools shows response...');
58
58
  await resp.blob();
59
-
59
+
60
60
  // Log the error
61
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
61
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
62
62
  globalThis.puter.apiCallLogger.logRequest({
63
63
  service: 'drivers',
64
64
  operation: `${driver.iface_name}::${method_name}`,
65
65
  params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
66
- error: { message: msg }
66
+ error: { message: msg },
67
67
  });
68
68
  }
69
-
69
+
70
70
  throw new Error(msg);
71
71
  }
72
-
72
+
73
73
  const result = await handler(resp);
74
-
74
+
75
75
  // Log the successful response
76
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
76
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
77
77
  globalThis.puter.apiCallLogger.logRequest({
78
78
  service: 'drivers',
79
79
  operation: `${driver.iface_name}::${method_name}`,
80
80
  params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
81
- result: result
81
+ result: result,
82
82
  });
83
83
  }
84
-
84
+
85
85
  return result;
86
- } catch (error) {
86
+ } catch ( error ) {
87
87
  // Log unexpected errors
88
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
88
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
89
89
  globalThis.puter.apiCallLogger.logRequest({
90
90
  service: 'drivers',
91
91
  operation: `${driver.iface_name}::${method_name}`,
92
92
  params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
93
93
  error: {
94
94
  message: error.message || error.toString(),
95
- stack: error.stack
96
- }
95
+ stack: error.stack,
96
+ },
97
97
  });
98
98
  }
99
99
  throw error;
@@ -135,7 +135,7 @@ class Drivers {
135
135
  this.authToken = context.authToken;
136
136
  this.APIOrigin = context.APIOrigin;
137
137
  this.appID = context.appID;
138
-
138
+
139
139
  // Driver-specific
140
140
  this.drivers_ = {};
141
141
 
@@ -148,7 +148,7 @@ class Drivers {
148
148
  get: () => this.APIOrigin,
149
149
  });
150
150
  }
151
-
151
+
152
152
  _init ({ puter }) {
153
153
  puter.call = this.call.bind(this);
154
154
  }
@@ -166,7 +166,7 @@ class Drivers {
166
166
 
167
167
  /**
168
168
  * Sets the API origin.
169
- *
169
+ *
170
170
  * @param {string} APIOrigin - The new API origin.
171
171
  * @memberof [AI]
172
172
  * @returns {void}
@@ -174,46 +174,46 @@ class Drivers {
174
174
  setAPIOrigin (APIOrigin) {
175
175
  this.APIOrigin = APIOrigin;
176
176
  }
177
-
177
+
178
178
  async list () {
179
179
  try {
180
180
  const resp = await fetch(`${this.APIOrigin}/lsmod`, {
181
181
  headers: {
182
- Authorization: 'Bearer ' + this.authToken,
182
+ Authorization: `Bearer ${ this.authToken}`,
183
183
  },
184
- method: 'POST'
184
+ method: 'POST',
185
185
  });
186
-
186
+
187
187
  const list = await resp.json();
188
-
188
+
189
189
  // Log the response
190
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
190
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
191
191
  globalThis.puter.apiCallLogger.logRequest({
192
192
  service: 'drivers',
193
193
  operation: 'list',
194
194
  params: {},
195
- result: list.interfaces
195
+ result: list.interfaces,
196
196
  });
197
197
  }
198
-
198
+
199
199
  return list.interfaces;
200
- } catch (error) {
200
+ } catch ( error ) {
201
201
  // Log the error
202
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
202
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
203
203
  globalThis.puter.apiCallLogger.logRequest({
204
204
  service: 'drivers',
205
205
  operation: 'list',
206
206
  params: {},
207
207
  error: {
208
208
  message: error.message || error.toString(),
209
- stack: error.stack
210
- }
209
+ stack: error.stack,
210
+ },
211
211
  });
212
212
  }
213
213
  throw error;
214
214
  }
215
215
  }
216
-
216
+
217
217
  async get (iface_name, service_name) {
218
218
  if ( ! service_name ) service_name = iface_name;
219
219
  const key = `${iface_name}:${service_name}`;
@@ -233,10 +233,10 @@ class Drivers {
233
233
  service_name,
234
234
  });
235
235
  }
236
-
236
+
237
237
  async call (...a) {
238
238
  let iface_name, service_name, method_name, parameters;
239
-
239
+
240
240
  // Services with the same name as an interface they implement
241
241
  // are considered the default implementation for that interface.
242
242
  //
@@ -254,7 +254,7 @@ class Drivers {
254
254
  // the interface might not specify the structure of the response
255
255
  // because it is only intended for that specific integration
256
256
  // (and that integration alone is responsible for avoiding regressions)
257
-
257
+
258
258
  // interface name, service name, method name, parameters
259
259
  if ( a.length === 4 ) {
260
260
  ([iface_name, service_name, method_name, parameters] = a);
@@ -272,7 +272,7 @@ class Drivers {
272
272
  const driver = await this.get(iface_name, service_name);
273
273
  return await driver.call(method_name, parameters);
274
274
  }
275
-
275
+
276
276
  }
277
277
 
278
278
  export default Drivers;