@heyputer/puter.js 1.0.1 → 2.0.1

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 (74) hide show
  1. package/README.md +14 -43
  2. package/index.d.ts +479 -0
  3. package/package.json +13 -3
  4. package/APACHE_LICENSE.txt +0 -201
  5. package/doc/devlog.md +0 -49
  6. package/src/bg.png +0 -0
  7. package/src/bg.webp +0 -0
  8. package/src/lib/APICallLogger.js +0 -110
  9. package/src/lib/EventListener.js +0 -51
  10. package/src/lib/RequestError.js +0 -6
  11. package/src/lib/filesystem/APIFS.js +0 -73
  12. package/src/lib/filesystem/CacheFS.js +0 -243
  13. package/src/lib/filesystem/PostMessageFS.js +0 -40
  14. package/src/lib/filesystem/definitions.js +0 -39
  15. package/src/lib/path.js +0 -509
  16. package/src/lib/polyfills/localStorage.js +0 -92
  17. package/src/lib/polyfills/xhrshim.js +0 -233
  18. package/src/lib/socket.io/socket.io.esm.min.js +0 -7
  19. package/src/lib/socket.io/socket.io.esm.min.js.map +0 -1
  20. package/src/lib/socket.io/socket.io.js +0 -4385
  21. package/src/lib/socket.io/socket.io.js.map +0 -1
  22. package/src/lib/socket.io/socket.io.min.js +0 -7
  23. package/src/lib/socket.io/socket.io.min.js.map +0 -1
  24. package/src/lib/socket.io/socket.io.msgpack.min.js +0 -7
  25. package/src/lib/socket.io/socket.io.msgpack.min.js.map +0 -1
  26. package/src/lib/utils.js +0 -620
  27. package/src/lib/xdrpc.js +0 -104
  28. package/src/modules/AI.js +0 -680
  29. package/src/modules/Apps.js +0 -215
  30. package/src/modules/Auth.js +0 -171
  31. package/src/modules/Debug.js +0 -39
  32. package/src/modules/Drivers.js +0 -278
  33. package/src/modules/FSItem.js +0 -139
  34. package/src/modules/FileSystem/index.js +0 -187
  35. package/src/modules/FileSystem/operations/copy.js +0 -64
  36. package/src/modules/FileSystem/operations/deleteFSEntry.js +0 -59
  37. package/src/modules/FileSystem/operations/getReadUrl.js +0 -42
  38. package/src/modules/FileSystem/operations/mkdir.js +0 -62
  39. package/src/modules/FileSystem/operations/move.js +0 -75
  40. package/src/modules/FileSystem/operations/read.js +0 -46
  41. package/src/modules/FileSystem/operations/readdir.js +0 -102
  42. package/src/modules/FileSystem/operations/rename.js +0 -58
  43. package/src/modules/FileSystem/operations/sign.js +0 -103
  44. package/src/modules/FileSystem/operations/space.js +0 -40
  45. package/src/modules/FileSystem/operations/stat.js +0 -95
  46. package/src/modules/FileSystem/operations/symlink.js +0 -55
  47. package/src/modules/FileSystem/operations/upload.js +0 -440
  48. package/src/modules/FileSystem/operations/write.js +0 -65
  49. package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +0 -21
  50. package/src/modules/Hosting.js +0 -138
  51. package/src/modules/KV.js +0 -301
  52. package/src/modules/OS.js +0 -95
  53. package/src/modules/Perms.js +0 -109
  54. package/src/modules/PuterDialog.js +0 -481
  55. package/src/modules/Threads.js +0 -75
  56. package/src/modules/UI.js +0 -1555
  57. package/src/modules/Util.js +0 -38
  58. package/src/modules/Workers.js +0 -120
  59. package/src/modules/networking/PSocket.js +0 -87
  60. package/src/modules/networking/PTLS.js +0 -100
  61. package/src/modules/networking/PWispHandler.js +0 -89
  62. package/src/modules/networking/parsers.js +0 -157
  63. package/src/modules/networking/requests.js +0 -282
  64. package/src/services/APIAccess.js +0 -46
  65. package/src/services/FSRelay.js +0 -20
  66. package/src/services/Filesystem.js +0 -122
  67. package/src/services/NoPuterYet.js +0 -20
  68. package/src/services/XDIncoming.js +0 -44
  69. package/test/ai.test.js +0 -214
  70. package/test/fs.test.js +0 -798
  71. package/test/index.html +0 -1183
  72. package/test/kv.test.js +0 -548
  73. package/test/txt2speech.test.js +0 -178
  74. package/webpack.config.js +0 -25
@@ -1,215 +0,0 @@
1
- import * as utils from '../lib/utils.js'
2
-
3
- class Apps{
4
- /**
5
- * Creates a new instance with the given authentication token, API origin, and app ID,
6
- *
7
- * @class
8
- * @param {string} authToken - Token used to authenticate the user.
9
- * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
10
- * @param {string} appID - ID of the app to use.
11
- */
12
- constructor (context) {
13
- this.authToken = context.authToken;
14
- this.APIOrigin = context.APIOrigin;
15
- this.appID = context.appID;
16
- }
17
-
18
- /**
19
- * Sets a new authentication token.
20
- *
21
- * @param {string} authToken - The new authentication token.
22
- * @memberof [Apps]
23
- * @returns {void}
24
- */
25
- setAuthToken (authToken) {
26
- this.authToken = authToken;
27
- }
28
-
29
- /**
30
- * Sets the API origin.
31
- *
32
- * @param {string} APIOrigin - The new API origin.
33
- * @memberof [Apps]
34
- * @returns {void}
35
- */
36
- setAPIOrigin (APIOrigin) {
37
- this.APIOrigin = APIOrigin;
38
- }
39
-
40
- list = async (...args) => {
41
- let options = {};
42
-
43
- // if args is a single object, assume it is the options object
44
- if (typeof args[0] === 'object' && args[0] !== null) {
45
- options.params = args[0];
46
- }
47
-
48
- options.predicate = ['user-can-edit'];
49
-
50
- return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'select').call(this, options);
51
- }
52
-
53
- create = async (...args) => {
54
- let options = {};
55
- // * allows for: puter.apps.new('example-app') *
56
- if (typeof args[0] === 'string') {
57
- let indexURL = args[1];
58
- let title = args[2] ?? args[0];
59
-
60
- options = {
61
- object: {
62
- name: args[0],
63
- index_url: indexURL,
64
- title: title
65
- }
66
- };
67
- }
68
-
69
- // * allows for: puter.apps.new({name: 'example-app', indexURL: 'https://example.com'}) *
70
- else if (typeof args[0] === 'object' && args[0] !== null) {
71
- let options_raw = args[0];
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.
78
- // If title is provided, use it. If not, use name.
79
- title: options_raw.title ?? options_raw.name,
80
- description: options_raw.description,
81
- icon: options_raw.icon,
82
- maximize_on_start: options_raw.maximizeOnStart,
83
- background: options_raw.background,
84
- filetype_associations: options_raw.filetypeAssociations,
85
- metadata: options_raw.metadata,
86
- },
87
- options: {
88
- dedupe_name: options_raw.dedupeName ?? false,
89
- }
90
- };
91
- }
92
-
93
- // name and indexURL are required
94
- if(!options.object.name){
95
- throw {
96
- success: false,
97
- error: {
98
- code: 'invalid_request',
99
- message: 'Name is required'
100
- }
101
- };
102
- }
103
- if(!options.object.index_url){
104
- throw {
105
- success: false,
106
- error: {
107
- code: 'invalid_request',
108
- message: 'Index URL is required'
109
- }
110
- };
111
- }
112
-
113
- // Call the original chat.complete method
114
- return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'create').call(this, options);
115
- }
116
-
117
- update = async(...args) => {
118
- let options = {};
119
-
120
- // if there is one string argument, assume it is the app name
121
- // * allows for: puter.apps.update('example-app') *
122
- if (Array.isArray(args) && typeof args[0] === 'string') {
123
- let object_raw = args[1];
124
- let object = {
125
- name: object_raw.name,
126
- index_url: object_raw.indexURL,
127
- title: object_raw.title,
128
- description: object_raw.description,
129
- icon: object_raw.icon,
130
- maximize_on_start: object_raw.maximizeOnStart,
131
- background: object_raw.background,
132
- filetype_associations: object_raw.filetypeAssociations,
133
- metadata: object_raw.metadata,
134
- };
135
-
136
- options = { id: { name: args[0]}, object: object};
137
- }
138
-
139
- // Call the original chat.complete method
140
- return await utils.make_driver_method(['object'], 'puter-apps', undefined, 'update').call(this, options);
141
- }
142
-
143
- get = async(...args) => {
144
- let options = {};
145
-
146
- // if there is one string argument, assume it is the app name
147
- // * allows for: puter.apps.get('example-app') *
148
- if (Array.isArray(args) && typeof args[0] === 'string') {
149
- // if second argument is an object, assume it is the options object
150
- if (typeof args[1] === 'object' && args[1] !== null) {
151
- options.params = args[1];
152
- }
153
- // name
154
- options.id = {name: args[0]};
155
- }
156
-
157
- // if first argument is an object, assume it is the options object
158
- if (typeof args[0] === 'object' && args[0] !== null) {
159
- options.params = args[0];
160
- }
161
-
162
- return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'read').call(this, options);
163
- }
164
-
165
- delete = async(...args) => {
166
- let options = {};
167
- // if there is one string argument, assume it is the app name
168
- // * allows for: puter.apps.get('example-app') *
169
- if (Array.isArray(args) && typeof args[0] === 'string') {
170
- options = { id: {name: args[0]}};
171
- }
172
- return utils.make_driver_method(['uid'], 'puter-apps', undefined, 'delete').call(this, options);
173
- }
174
-
175
- getDeveloperProfile = function(...args){
176
- let options;
177
-
178
- // If first argument is an object, it's the options
179
- if (typeof args[0] === 'object' && args[0] !== null) {
180
- options = args[0];
181
- } else {
182
- // Otherwise, we assume separate arguments are provided
183
- options = {
184
- success: args[0],
185
- error: args[1],
186
- };
187
- }
188
-
189
- return new Promise((resolve, reject) => {
190
- let options;
191
-
192
- // If first argument is an object, it's the options
193
- if (typeof args[0] === 'object' && args[0] !== null) {
194
- options = args[0];
195
- } else {
196
- // Otherwise, we assume separate arguments are provided
197
- options = {
198
- success: args[0],
199
- error: args[1],
200
- };
201
- }
202
-
203
- return new Promise((resolve, reject) => {
204
- const xhr = utils.initXhr('/get-dev-profile', puter.APIOrigin, puter.authToken, 'get');
205
-
206
- // set up event handlers for load and error events
207
- utils.setupXhrEventHandlers(xhr, options.success, options.error, resolve, reject);
208
-
209
- xhr.send();
210
- })
211
- });
212
- }
213
- }
214
-
215
- export default Apps;
@@ -1,171 +0,0 @@
1
- import * as utils from '../lib/utils.js'
2
-
3
- class Auth{
4
- // Used to generate a unique message id for each message sent to the host environment
5
- // we start from 1 because 0 is falsy and we want to avoid that for the message id
6
- #messageID = 1;
7
-
8
-
9
- /**
10
- * Creates a new instance with the given authentication token, API origin, and app ID,
11
- *
12
- * @class
13
- * @param {string} authToken - Token used to authenticate the user.
14
- * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
15
- * @param {string} appID - ID of the app to use.
16
- */
17
- constructor (context) {
18
- this.authToken = context.authToken;
19
- this.APIOrigin = context.APIOrigin;
20
- this.appID = context.appID;
21
- }
22
-
23
- /**
24
- * Sets a new authentication token.
25
- *
26
- * @param {string} authToken - The new authentication token.
27
- * @memberof [Auth]
28
- * @returns {void}
29
- */
30
- setAuthToken (authToken) {
31
- this.authToken = authToken;
32
- }
33
-
34
- /**
35
- * Sets the API origin.
36
- *
37
- * @param {string} APIOrigin - The new API origin.
38
- * @memberof [Auth]
39
- * @returns {void}
40
- */
41
- setAPIOrigin (APIOrigin) {
42
- this.APIOrigin = APIOrigin;
43
- }
44
-
45
- signIn = (options) =>{
46
- options = options || {};
47
-
48
- return new Promise((resolve, reject) => {
49
- let msg_id = this.#messageID++;
50
- let w = 600;
51
- let h = 600;
52
- let title = 'Puter';
53
- var left = (screen.width/2)-(w/2);
54
- var top = (screen.height/2)-(h/2);
55
-
56
- // Store reference to the popup window
57
- const popup = window.open(puter.defaultGUIOrigin + '/action/sign-in?embedded_in_popup=true&msg_id=' + msg_id + (window.crossOriginIsolated ? '&cross_origin_isolated=true' : '') +(options.attempt_temp_user_creation ? '&attempt_temp_user_creation=true' : ''),
58
- title,
59
- 'toolbar=no, location=no, directories=no, status=no, menubar=no, scrollbars=no, resizable=no, copyhistory=no, width='+w+', height='+h+', top='+top+', left='+left);
60
-
61
- // Set up interval to check if popup was closed
62
- const checkClosed = setInterval(() => {
63
- if (popup.closed) {
64
- clearInterval(checkClosed);
65
- // Remove the message listener
66
- window.removeEventListener('message', messageHandler);
67
- reject({ error: 'auth_window_closed', msg: 'Authentication window was closed by the user without completing the process.' });
68
- }
69
- }, 100);
70
-
71
- function messageHandler(e) {
72
- if(e.data.msg_id == msg_id){
73
- // Clear the interval since we got a response
74
- clearInterval(checkClosed);
75
-
76
- // remove redundant attributes
77
- delete e.data.msg_id;
78
- delete e.data.msg;
79
-
80
- if(e.data.success){
81
- // set the auth token
82
- puter.setAuthToken(e.data.token);
83
-
84
- resolve(e.data);
85
- }else
86
- reject(e.data);
87
-
88
- // delete the listener
89
- window.removeEventListener('message', messageHandler);
90
- }
91
- }
92
-
93
- window.addEventListener('message', messageHandler);
94
- });
95
- }
96
-
97
- isSignedIn = () =>{
98
- if(puter.authToken)
99
- return true;
100
- else
101
- return false;
102
- }
103
-
104
- getUser = function(...args){
105
- let options;
106
-
107
- // If first argument is an object, it's the options
108
- if (typeof args[0] === 'object' && args[0] !== null) {
109
- options = args[0];
110
- } else {
111
- // Otherwise, we assume separate arguments are provided
112
- options = {
113
- success: args[0],
114
- error: args[1],
115
- };
116
- }
117
-
118
- return new Promise((resolve, reject) => {
119
- const xhr = utils.initXhr('/whoami', puter.APIOrigin, puter.authToken, 'get');
120
-
121
- // set up event handlers for load and error events
122
- utils.setupXhrEventHandlers(xhr, options.success, options.error, resolve, reject);
123
-
124
- xhr.send();
125
- })
126
- }
127
-
128
- signOut = () =>{
129
- puter.resetAuthToken();
130
- }
131
-
132
- async whoami () {
133
- try {
134
- const resp = await fetch(this.APIOrigin + '/whoami', {
135
- headers: {
136
- Authorization: `Bearer ${this.authToken}`
137
- }
138
- });
139
-
140
- const result = await resp.json();
141
-
142
- // Log the response
143
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
144
- globalThis.puter.apiCallLogger.logRequest({
145
- service: 'auth',
146
- operation: 'whoami',
147
- params: {},
148
- result: result
149
- });
150
- }
151
-
152
- return result;
153
- } catch (error) {
154
- // Log the error
155
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
156
- globalThis.puter.apiCallLogger.logRequest({
157
- service: 'auth',
158
- operation: 'whoami',
159
- params: {},
160
- error: {
161
- message: error.message || error.toString(),
162
- stack: error.stack
163
- }
164
- });
165
- }
166
- throw error;
167
- }
168
- }
169
- }
170
-
171
- export default Auth
@@ -1,39 +0,0 @@
1
- export class Debug {
2
- constructor (context, parameters) {
3
- this.context = context;
4
- this.parameters = parameters;
5
-
6
- this._init();
7
- }
8
-
9
- _init () {
10
- // Check query parameter 'enabled_logs'
11
- const url = new URL(location.href);
12
- let enabled_logs = url.searchParams.get('enabled_logs');
13
- if ( ! enabled_logs ) enabled_logs = '';
14
- enabled_logs = enabled_logs.split(';');
15
- for ( const category of enabled_logs ) {
16
- if ( category === '' ) continue;
17
- this.context.puter.logger.on(category);
18
- }
19
-
20
- globalThis.addEventListener('message', async e => {
21
- // Ensure message is from parent window
22
- if ( e.source !== globalThis.parent ) return;
23
- // (parent window is allowed to be anything)
24
-
25
- // Check if it's a debug message
26
- if ( ! e.data.$ ) return;
27
- if ( e.data.$ !== 'puterjs-debug' ) return;
28
-
29
- // It's okay to log this; it will only show if a
30
- // developer does something in the console.
31
- console.log('Got a puter.js debug event!', e.data);
32
-
33
- if ( e.data.cmd === 'log.on' ) {
34
- console.log('Got instruction to turn logs on!');
35
- this.context.puter.logger.on(e.data.category);
36
- }
37
- })
38
- }
39
- }
@@ -1,278 +0,0 @@
1
- class FetchDriverCallBackend {
2
- constructor ({ context }) {
3
- this.context = context;
4
- this.response_handlers = this.constructor.response_handlers;
5
- }
6
-
7
- static response_handlers = {
8
- 'application/x-ndjson': async resp => {
9
- const Stream = async function* Stream (readableStream) {
10
- const reader = readableStream.getReader();
11
- let value, done;
12
- while ( ! done ) {
13
- ({ value, done } = await reader.read());
14
- if ( done ) break;
15
- const parts = (new TextDecoder().decode(value).split('\n'));
16
- for ( const part of parts ) {
17
- if ( part.trim() === '' ) continue;
18
- yield JSON.parse(part);
19
- }
20
- }
21
- }
22
-
23
- return Stream(resp.body);
24
- },
25
- 'application/json': async resp => {
26
- return await resp.json();
27
- },
28
- 'application/octet-stream': async resp => {
29
- return await resp.blob();
30
- },
31
- }
32
-
33
- async call ({ driver, method_name, parameters }) {
34
- try {
35
- const resp = await fetch(`${this.context.APIOrigin}/drivers/call`, {
36
- headers: {
37
- 'Content-Type': 'text/plain;actually=json',
38
- },
39
- method: 'POST',
40
- body: JSON.stringify({
41
- 'interface': driver.iface_name,
42
- ...(driver.service_name
43
- ? { service: driver.service_name }
44
- : {}),
45
- method: method_name,
46
- args: parameters,
47
- auth_token: this.context.authToken
48
- }),
49
- });
50
-
51
- const content_type = resp.headers.get('content-type')
52
- .split(';')[0].trim(); // TODO: parser for Content-Type
53
- const handler = this.response_handlers[content_type];
54
- if ( ! handler ) {
55
- const msg = `unrecognized content type: ${content_type}`;
56
- console.error(msg);
57
- console.error('creating blob so dev tools shows response...');
58
- await resp.blob();
59
-
60
- // Log the error
61
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
62
- globalThis.puter.apiCallLogger.logRequest({
63
- service: 'drivers',
64
- operation: `${driver.iface_name}::${method_name}`,
65
- params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
66
- error: { message: msg }
67
- });
68
- }
69
-
70
- throw new Error(msg);
71
- }
72
-
73
- const result = await handler(resp);
74
-
75
- // Log the successful response
76
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
77
- globalThis.puter.apiCallLogger.logRequest({
78
- service: 'drivers',
79
- operation: `${driver.iface_name}::${method_name}`,
80
- params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
81
- result: result
82
- });
83
- }
84
-
85
- return result;
86
- } catch (error) {
87
- // Log unexpected errors
88
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
89
- globalThis.puter.apiCallLogger.logRequest({
90
- service: 'drivers',
91
- operation: `${driver.iface_name}::${method_name}`,
92
- params: { interface: driver.iface_name, driver: driver.service_name || driver.iface_name, method: method_name, args: parameters },
93
- error: {
94
- message: error.message || error.toString(),
95
- stack: error.stack
96
- }
97
- });
98
- }
99
- throw error;
100
- }
101
- }
102
- }
103
-
104
- class Driver {
105
- constructor ({
106
- iface,
107
- iface_name,
108
- service_name,
109
- call_backend,
110
- }) {
111
- this.iface = iface;
112
- this.iface_name = iface_name;
113
- this.service_name = service_name;
114
- this.call_backend = call_backend;
115
- }
116
- async call (method_name, parameters) {
117
- return await this.call_backend.call({
118
- driver: this,
119
- method_name,
120
- parameters,
121
- });
122
- }
123
- }
124
-
125
- class Drivers {
126
- /**
127
- * Creates a new instance with the given authentication token, API origin, and app ID,
128
- *
129
- * @class
130
- * @param {string} authToken - Token used to authenticate the user.
131
- * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
132
- * @param {string} appID - ID of the app to use.
133
- */
134
- constructor (context) {
135
- this.authToken = context.authToken;
136
- this.APIOrigin = context.APIOrigin;
137
- this.appID = context.appID;
138
-
139
- // Driver-specific
140
- this.drivers_ = {};
141
-
142
- // TODO: replace with `context` from constructor and test site login
143
- this.context = {};
144
- Object.defineProperty(this.context, 'authToken', {
145
- get: () => this.authToken,
146
- });
147
- Object.defineProperty(this.context, 'APIOrigin', {
148
- get: () => this.APIOrigin,
149
- });
150
- }
151
-
152
- _init ({ puter }) {
153
- puter.call = this.call.bind(this);
154
- }
155
-
156
- /**
157
- * Sets a new authentication token and resets the socket connection with the updated token, if applicable.
158
- *
159
- * @param {string} authToken - The new authentication token.
160
- * @memberof [AI]
161
- * @returns {void}
162
- */
163
- setAuthToken (authToken) {
164
- this.authToken = authToken;
165
- }
166
-
167
- /**
168
- * Sets the API origin.
169
- *
170
- * @param {string} APIOrigin - The new API origin.
171
- * @memberof [AI]
172
- * @returns {void}
173
- */
174
- setAPIOrigin (APIOrigin) {
175
- this.APIOrigin = APIOrigin;
176
- }
177
-
178
- async list () {
179
- try {
180
- const resp = await fetch(`${this.APIOrigin}/lsmod`, {
181
- headers: {
182
- Authorization: 'Bearer ' + this.authToken,
183
- },
184
- method: 'POST'
185
- });
186
-
187
- const list = await resp.json();
188
-
189
- // Log the response
190
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
191
- globalThis.puter.apiCallLogger.logRequest({
192
- service: 'drivers',
193
- operation: 'list',
194
- params: {},
195
- result: list.interfaces
196
- });
197
- }
198
-
199
- return list.interfaces;
200
- } catch (error) {
201
- // Log the error
202
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
203
- globalThis.puter.apiCallLogger.logRequest({
204
- service: 'drivers',
205
- operation: 'list',
206
- params: {},
207
- error: {
208
- message: error.message || error.toString(),
209
- stack: error.stack
210
- }
211
- });
212
- }
213
- throw error;
214
- }
215
- }
216
-
217
- async get (iface_name, service_name) {
218
- if ( ! service_name ) service_name = iface_name;
219
- const key = `${iface_name}:${service_name}`;
220
- if ( this.drivers_[key] ) return this.drivers_[key];
221
-
222
- // const interfaces = await this.list();
223
- // if ( ! interfaces[iface_name] ) {
224
- // throw new Error(`Interface ${iface_name} not found`);
225
- // }
226
-
227
- return this.drivers_[key] = new Driver ({
228
- call_backend: new FetchDriverCallBackend({
229
- context: this.context,
230
- }),
231
- // iface: interfaces[iface_name],
232
- iface_name,
233
- service_name,
234
- });
235
- }
236
-
237
- async call (...a) {
238
- let iface_name, service_name, method_name, parameters;
239
-
240
- // Services with the same name as an interface they implement
241
- // are considered the default implementation for that interface.
242
- //
243
- // A method with the same name as the interface and service it is
244
- // called on can be left unspecified in a driver call through puter.js.
245
- //
246
- // For example:
247
- // puter.drivers.call('ipgeo', { ip: '1.2.3.4' });
248
- //
249
- // Is the same as:
250
- // puter.drivers.call('ipgeo', 'ipgeo', 'ipgeo', { ip: '1.2.3.4' })
251
- //
252
- // This is commonly the case when an interface only exists to
253
- // connect a particular service to the drivers API. In this case,
254
- // the interface might not specify the structure of the response
255
- // because it is only intended for that specific integration
256
- // (and that integration alone is responsible for avoiding regressions)
257
-
258
- // interface name, service name, method name, parameters
259
- if ( a.length === 4 ) {
260
- ([iface_name, service_name, method_name, parameters] = a);
261
- }
262
- // interface name, method name, parameters
263
- else if ( a.length === 3 ) {
264
- ([iface_name, method_name, parameters] = a);
265
- }
266
- // interface name, parameters
267
- else if ( a.length === 2 ) {
268
- ([iface_name, parameters] = a);
269
- method_name = iface_name;
270
- }
271
-
272
- const driver = await this.get(iface_name, service_name);
273
- return await driver.call(method_name, parameters);
274
- }
275
-
276
- }
277
-
278
- export default Drivers;