@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
package/src/lib/utils.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { FileReaderPoly } from "./polyfills/fileReaderPoly.js";
2
+
1
3
  /**
2
4
  * Parses a given response text into a JSON object. If the parsing fails due to invalid JSON format,
3
5
  * the original response text is returned.
@@ -12,7 +14,7 @@
12
14
  * // returns "Invalid JSON"
13
15
  * parseResponse('Invalid JSON');
14
16
  */
15
- async function parseResponse(target) {
17
+ async function parseResponse (target) {
16
18
  if ( target.responseType === 'blob' ) {
17
19
  // Get content type of the blob
18
20
  const contentType = target.getResponseHeader('content-type');
@@ -21,10 +23,10 @@ async function parseResponse(target) {
21
23
  const text = await target.response.text();
22
24
  try {
23
25
  return JSON.parse(text);
24
- } catch (error) {
26
+ } catch ( error ) {
25
27
  return text;
26
28
  }
27
- }else if ( contentType.startsWith('application/octet-stream') ) {
29
+ } else if ( contentType.startsWith('application/octet-stream') ) {
28
30
  // If the blob is an octet stream, return the blob
29
31
  return target.response;
30
32
  }
@@ -38,33 +40,31 @@ async function parseResponse(target) {
38
40
  const responseText = target.responseText;
39
41
  try {
40
42
  return JSON.parse(responseText);
41
- } catch (error) {
43
+ } catch ( error ) {
42
44
  return responseText;
43
45
  }
44
46
  }
45
47
 
46
48
  /**
47
- * A function that generates a UUID (Universally Unique Identifier) using the version 4 format,
49
+ * A function that generates a UUID (Universally Unique Identifier) using the version 4 format,
48
50
  * which are random UUIDs. It uses the cryptographic number generator available in modern browsers.
49
51
  *
50
- * The generated UUID is a 36 character string (32 alphanumeric characters separated by 4 hyphens).
51
- * It follows the pattern: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where x is any hexadecimal digit
52
+ * The generated UUID is a 36 character string (32 alphanumeric characters separated by 4 hyphens).
53
+ * It follows the pattern: xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx, where x is any hexadecimal digit
52
54
  * and y is one of 8, 9, A, or B.
53
55
  *
54
56
  * @returns {string} Returns a new UUID v4 string.
55
57
  *
56
58
  * @example
57
- *
59
+ *
58
60
  * let id = this.#uuidv4(); // Generate a new UUID
59
- *
61
+ *
60
62
  */
61
- function uuidv4(){
63
+ function uuidv4 () {
62
64
  return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
63
- (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
64
- );
65
+ (c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16));
65
66
  }
66
67
 
67
-
68
68
  /**
69
69
  * Initializes and returns an XMLHttpRequest object configured for a specific API endpoint, method, and headers.
70
70
  *
@@ -77,30 +77,32 @@ function uuidv4(){
77
77
  *
78
78
  * @returns {XMLHttpRequest} The initialized XMLHttpRequest object.
79
79
  */
80
- function initXhr(endpoint, APIOrigin, authToken, method= "post", contentType = "text/plain;actually=json", responseType = undefined) {
80
+ function initXhr (endpoint, APIOrigin, authToken, method = 'post', contentType = 'text/plain;actually=json', responseType = undefined) {
81
81
  const xhr = new XMLHttpRequest();
82
82
  xhr.open(method, APIOrigin + endpoint, true);
83
- if (authToken)
84
- xhr.setRequestHeader("Authorization", "Bearer " + authToken);
85
- xhr.setRequestHeader("Content-Type", contentType);
83
+ if ( authToken )
84
+ {
85
+ xhr.setRequestHeader('Authorization', `Bearer ${ authToken}`);
86
+ }
87
+ xhr.setRequestHeader('Content-Type', contentType);
86
88
  xhr.responseType = responseType ?? '';
87
-
89
+
88
90
  // Add API call logging if available
89
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
91
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
90
92
  xhr._puterRequestId = {
91
93
  method,
92
94
  service: 'xhr',
93
95
  operation: endpoint.replace(/^\//, ''),
94
- params: { endpoint, contentType, responseType }
96
+ params: { endpoint, contentType, responseType },
95
97
  };
96
98
  }
97
-
99
+
98
100
  return xhr;
99
101
  }
100
102
 
101
103
  /**
102
104
  * Handles an HTTP response by invoking appropriate callback functions and resolving or rejecting a promise.
103
- *
105
+ *
104
106
  * @param {Function} success_cb - An optional callback function for successful responses. It should take a response object
105
107
  * as its only argument.
106
108
  * @param {Function} error_cb - An optional callback function for error handling. It should take an error object
@@ -111,41 +113,47 @@ function initXhr(endpoint, APIOrigin, authToken, method= "post", contentType = "
111
113
  * as its only argument.
112
114
  * @param {Object} response - The HTTP response object from the request. Expected to have 'status' and 'responseText'
113
115
  * properties.
114
- *
116
+ *
115
117
  * @returns {void} The function does not return a value but will either resolve or reject a promise based on the
116
118
  * response status.
117
119
  */
118
- async function handle_resp(success_cb, error_cb, resolve_func, reject_func, response){
120
+ async function handle_resp (success_cb, error_cb, resolve_func, reject_func, response) {
119
121
  const resp = await parseResponse(response);
120
122
  // error - unauthorized
121
- if(response.status === 401){
123
+ if ( response.status === 401 ) {
122
124
  // if error callback is provided, call it
123
- if(error_cb && typeof error_cb === 'function')
124
- error_cb({status: 401, message: 'Unauthorized'})
125
+ if ( error_cb && typeof error_cb === 'function' )
126
+ {
127
+ error_cb({ status: 401, message: 'Unauthorized' });
128
+ }
125
129
  // reject promise
126
- return reject_func({status: 401, message: 'Unauthorized'})
130
+ return reject_func({ status: 401, message: 'Unauthorized' });
127
131
  }
128
132
  // error - other
129
- else if(response.status !== 200){
133
+ else if ( response.status !== 200 ) {
130
134
  // if error callback is provided, call it
131
- if(error_cb && typeof error_cb === 'function')
132
- error_cb(resp)
135
+ if ( error_cb && typeof error_cb === 'function' )
136
+ {
137
+ error_cb(resp);
138
+ }
133
139
  // reject promise
134
- return reject_func(resp)
140
+ return reject_func(resp);
135
141
  }
136
142
  // success
137
- else{
143
+ else {
138
144
  // This is a driver error
139
- if(resp.success === false && resp.error?.code === 'permission_denied'){
140
- let perm = await puter.ui.requestPermission({permission: 'driver:puter-image-generation:generate'});
145
+ if ( resp.success === false && resp.error?.code === 'permission_denied' ) {
146
+ let perm = await puter.ui.requestPermission({ permission: 'driver:puter-image-generation:generate' });
141
147
  // try sending again if permission was granted
142
- if(perm.granted){
148
+ if ( perm.granted ) {
143
149
  // todo repeat request
144
150
  }
145
151
  }
146
152
  // if success callback is provided, call it
147
- if(success_cb && typeof success_cb === 'function')
153
+ if ( success_cb && typeof success_cb === 'function' )
154
+ {
148
155
  success_cb(resp);
156
+ }
149
157
  // resolve with success
150
158
  return resolve_func(resp);
151
159
  }
@@ -153,59 +161,62 @@ async function handle_resp(success_cb, error_cb, resolve_func, reject_func, resp
153
161
 
154
162
  /**
155
163
  * Handles an error by invoking a specified error callback and then rejecting a promise.
156
- *
164
+ *
157
165
  * @param {Function} error_cb - An optional callback function that is called if it's provided.
158
166
  * This function should take an error object as its only argument.
159
167
  * @param {Function} reject_func - A function used to reject a promise. It should take an error object
160
168
  * as its only argument.
161
169
  * @param {Object} error - The error object that is passed to both the error callback and the reject function.
162
- *
170
+ *
163
171
  * @returns {void} The function does not return a value but will call the reject function with the error.
164
172
  */
165
- function handle_error(error_cb, reject_func, error){
173
+ function handle_error (error_cb, reject_func, error) {
166
174
  // if error callback is provided, call it
167
- if(error_cb && typeof error_cb === 'function')
168
- error_cb(error)
175
+ if ( error_cb && typeof error_cb === 'function' )
176
+ {
177
+ error_cb(error);
178
+ }
169
179
  // reject promise
170
- return reject_func(error)
180
+ return reject_func(error);
171
181
  }
172
182
 
173
- function setupXhrEventHandlers(xhr, success_cb, error_cb, resolve_func, reject_func) {
183
+ function setupXhrEventHandlers (xhr, success_cb, error_cb, resolve_func, reject_func) {
174
184
  // load: success or error
175
- xhr.addEventListener('load', async function(e){
185
+ xhr.addEventListener('load', async function (e) {
176
186
  // Log the response if API logging is enabled
177
- if (globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId) {
187
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId ) {
178
188
  const response = await parseResponse(this).catch(() => null);
179
189
  globalThis.puter.apiCallLogger.logRequest({
180
190
  service: this._puterRequestId.service,
181
191
  operation: this._puterRequestId.operation,
182
192
  params: this._puterRequestId.params,
183
193
  result: this.status >= 400 ? null : response,
184
- error: this.status >= 400 ? { message: this.statusText, status: this.status } : null
194
+ error: this.status >= 400 ? { message: this.statusText, status: this.status } : null,
185
195
  });
186
196
  }
187
197
  return handle_resp(success_cb, error_cb, resolve_func, reject_func, this, xhr);
188
198
  });
189
199
 
190
200
  // error
191
- xhr.addEventListener('error', function(e){
201
+ xhr.addEventListener('error', function (e) {
192
202
  // Log the error if API logging is enabled
193
- if (globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId) {
203
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() && this._puterRequestId ) {
194
204
  globalThis.puter.apiCallLogger.logRequest({
195
205
  service: this._puterRequestId.service,
196
206
  operation: this._puterRequestId.operation,
197
207
  params: this._puterRequestId.params,
198
208
  error: {
199
209
  message: 'Network error occurred',
200
- event: e.type
201
- }
210
+ event: e.type,
211
+ },
202
212
  });
203
213
  }
204
214
  return handle_error(error_cb, reject_func, this);
205
- })
215
+ });
206
216
  }
207
217
 
208
- const NOOP = () => {};
218
+ const NOOP = () => {
219
+ };
209
220
  class Valid {
210
221
  static callback (cb) {
211
222
  return (cb && typeof cb === 'function') ? cb : undefined;
@@ -219,13 +230,13 @@ class Valid {
219
230
  * @param {string} driverName - name of the driver
220
231
  * @param {string} driverMethod - name of the method
221
232
  */
222
- function make_driver_method(arg_defs, driverInterface, driverName, driverMethod, settings = {}) {
233
+ function make_driver_method (arg_defs, driverInterface, driverName, driverMethod, settings = {}) {
223
234
  return async function (...args) {
224
235
  let driverArgs = {};
225
236
  let options = {};
226
237
 
227
238
  // Check if the first argument is an object and use it as named parameters
228
- if (args.length === 1 && typeof args[0] === 'object' && !Array.isArray(args[0])) {
239
+ if ( args.length === 1 && typeof args[0] === 'object' && !Array.isArray(args[0]) ) {
229
240
  driverArgs = { ...args[0] };
230
241
  options = {
231
242
  success: driverArgs.success,
@@ -246,7 +257,7 @@ function make_driver_method(arg_defs, driverInterface, driverName, driverMethod,
246
257
  }
247
258
 
248
259
  // preprocess
249
- if(settings.preprocess && typeof settings.preprocess === 'function'){
260
+ if ( settings.preprocess && typeof settings.preprocess === 'function' ) {
250
261
  driverArgs = settings.preprocess(driverArgs);
251
262
  }
252
263
 
@@ -257,24 +268,22 @@ function make_driver_method(arg_defs, driverInterface, driverName, driverMethod,
257
268
  async function driverCall (options, driverInterface, driverName, driverMethod, driverArgs, settings) {
258
269
  const tp = new TeePromise();
259
270
 
260
- driverCall_(
261
- options,
262
- tp.resolve.bind(tp),
263
- tp.reject.bind(tp),
264
- driverInterface,
265
- driverName,
266
- driverMethod,
267
- driverArgs,
268
- undefined,
269
- undefined,
270
- settings,
271
- );
271
+ driverCall_(options,
272
+ tp.resolve.bind(tp),
273
+ tp.reject.bind(tp),
274
+ driverInterface,
275
+ driverName,
276
+ driverMethod,
277
+ driverArgs,
278
+ undefined,
279
+ undefined,
280
+ settings);
272
281
 
273
282
  return await tp;
274
283
  }
275
284
 
276
285
  // This function encapsulates the logic for sending a driver call request
277
- async function driverCall_(
286
+ async function driverCall_ (
278
287
  options = {},
279
288
  resolve_func, reject_func,
280
289
  driverInterface, driverName, driverMethod, driverArgs,
@@ -285,34 +294,34 @@ async function driverCall_(
285
294
  // Generate request ID for logging
286
295
  // Store request info for logging
287
296
  let requestInfo = null;
288
- if (globalThis.puter?.apiCallLogger?.isEnabled()) {
297
+ if ( globalThis.puter?.apiCallLogger?.isEnabled() ) {
289
298
  requestInfo = {
290
299
  interface: driverInterface,
291
300
  driver: driverName,
292
301
  method: driverMethod,
293
- args: driverArgs
302
+ args: driverArgs,
294
303
  };
295
304
  }
296
305
 
297
306
  // If there is no authToken and the environment is web, try authenticating with Puter
298
- if(!puter.authToken && puter.env === 'web'){
299
- try{
307
+ if ( !puter.authToken && puter.env === 'web' ) {
308
+ try {
300
309
  await puter.ui.authenticateWithPuter();
301
- }catch(e){
310
+ } catch (e) {
302
311
  // Log authentication error
303
- if (requestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
312
+ if ( requestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
304
313
  globalThis.puter.apiCallLogger.logRequest({
305
314
  service: 'drivers',
306
315
  operation: `${driverInterface}::${driverMethod}`,
307
316
  params: { interface: driverInterface, driver: driverName, method: driverMethod, args: driverArgs },
308
- error: { code: 'auth_canceled', message: 'Authentication canceled' }
317
+ error: { code: 'auth_canceled', message: 'Authentication canceled' },
309
318
  });
310
319
  }
311
320
  return reject_func({
312
321
  error: {
313
- code: 'auth_canceled', message: 'Authentication canceled'
314
- }
315
- })
322
+ code: 'auth_canceled', message: 'Authentication canceled',
323
+ },
324
+ });
316
325
  }
317
326
  }
318
327
 
@@ -322,14 +331,14 @@ async function driverCall_(
322
331
  const xhr = initXhr('/drivers/call', puter.APIOrigin, undefined, 'POST', contentType);
323
332
 
324
333
  // Store request info for later logging
325
- if (requestInfo) {
334
+ if ( requestInfo ) {
326
335
  xhr._puterDriverRequestInfo = requestInfo;
327
336
  }
328
337
 
329
338
  if ( settings.responseType ) {
330
339
  xhr.responseType = settings.responseType;
331
340
  }
332
-
341
+
333
342
  // ===============================================
334
343
  // TO UNDERSTAND THIS CODE, YOU MUST FIRST
335
344
  // UNDERSTAND THE FOLLOWING TEXT:
@@ -338,14 +347,14 @@ async function driverCall_(
338
347
  // "=== END OF STREAMING ===" is ONLY for handling
339
348
  // requests with content type "application/x-ndjson"
340
349
  // ===============================================
341
-
350
+
342
351
  let is_stream = false;
343
352
  let signal_stream_update = null;
344
353
  let lastLength = 0;
345
354
  let response_complete = false;
346
-
355
+
347
356
  let buffer = '';
348
-
357
+
349
358
  // NOTE: linked-list technically would perform better,
350
359
  // but in practice there are at most 2-3 lines
351
360
  // buffered so this does not matter.
@@ -353,12 +362,12 @@ async function driverCall_(
353
362
 
354
363
  xhr.onreadystatechange = () => {
355
364
  if ( xhr.readyState === 2 ) {
356
- if ( xhr.getResponseHeader("Content-Type") !==
365
+ if ( xhr.getResponseHeader('Content-Type') !==
357
366
  'application/x-ndjson'
358
367
  ) return;
359
368
  is_stream = true;
360
369
  const Stream = async function* Stream () {
361
- while ( ! response_complete ) {
370
+ while ( !response_complete ) {
362
371
  const tp = new TeePromise();
363
372
  signal_stream_update = tp.resolve.bind(tp);
364
373
  await tp;
@@ -367,7 +376,7 @@ async function driverCall_(
367
376
  const line = lines_received.shift();
368
377
  if ( line.trim() === '' ) continue;
369
378
  const lineObject = (JSON.parse(line));
370
- if (typeof (lineObject.text) === 'string') {
379
+ if ( typeof (lineObject.text) === 'string' ) {
371
380
  Object.defineProperty(lineObject, 'toString', {
372
381
  enumerable: false,
373
382
  value: () => lineObject.text,
@@ -376,20 +385,20 @@ async function driverCall_(
376
385
  yield lineObject;
377
386
  }
378
387
  }
379
- }
388
+ };
380
389
 
381
390
  const startedStream = Stream();
382
391
  Object.defineProperty(startedStream, 'start', {
383
392
  enumerable: false,
384
- value: async(controller) => {
393
+ value: async (controller) => {
385
394
  const texten = new TextEncoder();
386
- for await (const part of startedStream) {
387
- controller.enqueue(texten.encode(part))
395
+ for await ( const part of startedStream ) {
396
+ controller.enqueue(texten.encode(part));
388
397
  }
389
398
  controller.close();
390
- }
391
- })
392
-
399
+ },
400
+ });
401
+
393
402
  return resolve_func(startedStream);
394
403
  }
395
404
  if ( xhr.readyState === 4 ) {
@@ -400,12 +409,12 @@ async function driverCall_(
400
409
  }
401
410
  };
402
411
 
403
- xhr.onprogress = function() {
412
+ xhr.onprogress = function () {
404
413
  if ( ! signal_stream_update ) return;
405
414
 
406
415
  const newText = xhr.responseText.slice(lastLength);
407
416
  lastLength = xhr.responseText.length; // Update lastLength to the current length
408
-
417
+
409
418
  let hasUpdates = false;
410
419
  for ( let i = 0; i < newText.length; i++ ) {
411
420
  buffer += newText[i];
@@ -415,83 +424,85 @@ async function driverCall_(
415
424
  buffer = '';
416
425
  }
417
426
  }
418
-
427
+
419
428
  if ( hasUpdates ) {
420
429
  signal_stream_update();
421
430
  }
422
431
  };
423
-
432
+
424
433
  // ========================
425
434
  // === END OF STREAMING ===
426
435
  // ========================
427
436
 
428
437
  // load: success or error
429
- xhr.addEventListener('load', async function(response){
438
+ xhr.addEventListener('load', async function (response) {
430
439
  if ( is_stream ) {
431
440
  return;
432
441
  }
433
442
  const resp = await parseResponse(response.target);
434
-
443
+
435
444
  // Log driver call response
436
- if (this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
445
+ if ( this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
437
446
  globalThis.puter.apiCallLogger.logRequest({
438
447
  service: 'drivers',
439
448
  operation: `${this._puterDriverRequestInfo.interface}::${this._puterDriverRequestInfo.method}`,
440
449
  params: { interface: this._puterDriverRequestInfo.interface, driver: this._puterDriverRequestInfo.driver, method: this._puterDriverRequestInfo.method, args: this._puterDriverRequestInfo.args },
441
450
  result: response.status >= 400 || resp?.success === false ? null : resp,
442
- error: response.status >= 400 || resp?.success === false ? resp : null
451
+ error: response.status >= 400 || resp?.success === false ? resp : null,
443
452
  });
444
453
  }
445
-
454
+
446
455
  // HTTP Error - unauthorized
447
- if(response.status === 401 || resp?.code === "token_auth_failed"){
448
- if(resp?.code === "token_auth_failed" && puter.env === 'web'){
449
- try{
456
+ if ( response.status === 401 || resp?.code === 'token_auth_failed' ) {
457
+ if ( resp?.code === 'token_auth_failed' && puter.env === 'web' ) {
458
+ try {
450
459
  puter.resetAuthToken();
451
460
  await puter.ui.authenticateWithPuter();
452
- }catch(e){
461
+ } catch (e) {
453
462
  return reject_func({
454
463
  error: {
455
- code: 'auth_canceled', message: 'Authentication canceled'
456
- }
457
- })
464
+ code: 'auth_canceled', message: 'Authentication canceled',
465
+ },
466
+ });
458
467
  }
459
468
  }
460
469
  // if error callback is provided, call it
461
- if(error_cb && typeof error_cb === 'function')
462
- error_cb({status: 401, message: 'Unauthorized'})
470
+ if ( error_cb && typeof error_cb === 'function' )
471
+ {
472
+ error_cb({ status: 401, message: 'Unauthorized' });
473
+ }
463
474
  // reject promise
464
- return reject_func({status: 401, message: 'Unauthorized'})
475
+ return reject_func({ status: 401, message: 'Unauthorized' });
465
476
  }
466
477
  // HTTP Error - other
467
- else if(response.status && response.status !== 200){
478
+ else if ( response.status && response.status !== 200 ) {
468
479
  // if error callback is provided, call it
469
- error_cb(resp)
480
+ error_cb(resp);
470
481
  // reject promise
471
- return reject_func(resp)
482
+ return reject_func(resp);
472
483
  }
473
484
  // HTTP Success
474
- else{
485
+ else {
475
486
  // Driver Error: permission denied
476
- if(resp.success === false && resp.error?.code === 'permission_denied'){
477
- let perm = await puter.ui.requestPermission({permission: 'driver:' + driverInterface + ':' + driverMethod});
487
+ if ( resp.success === false && resp.error?.code === 'permission_denied' ) {
488
+ let perm = await puter.ui.requestPermission({ permission: `driver:${ driverInterface }:${ driverMethod}` });
478
489
  // try sending again if permission was granted
479
- if(perm.granted){
490
+ if ( perm.granted ) {
480
491
  // repeat request with permission granted
481
492
  return driverCall_(options, resolve_func, reject_func, driverInterface, driverMethod, driverArgs, method, contentType, settings);
482
- }else{
493
+ } else {
483
494
  // if error callback is provided, call it
484
- error_cb(resp)
495
+ error_cb(resp);
485
496
  // reject promise
486
- return reject_func(resp)
497
+ return reject_func(resp);
487
498
  }
488
499
  }
489
500
  // Driver Error: other
490
- else if(resp.success === false){
501
+ else if ( resp.success === false ) {
491
502
  // if error callback is provided, call it
492
- error_cb(resp)
503
+ error_cb(resp);
493
504
  // reject promise
494
- return reject_func(resp)
505
+ return reject_func(resp);
495
506
  }
496
507
 
497
508
  let result = resp.result !== undefined ? resp.result : resp;
@@ -500,35 +511,37 @@ async function driverCall_(
500
511
  }
501
512
 
502
513
  // Success: if callback is provided, call it
503
- if(resolve_func.success)
514
+ if ( resolve_func.success )
515
+ {
504
516
  success_cb(result);
517
+ }
505
518
  // Success: resolve with the result
506
519
  return resolve_func(result);
507
520
  }
508
521
  });
509
522
 
510
523
  // error
511
- xhr.addEventListener('error', function(e){
524
+ xhr.addEventListener('error', function (e) {
512
525
  // Log driver call error
513
- if (this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled()) {
526
+ if ( this._puterDriverRequestInfo && globalThis.puter?.apiCallLogger?.isEnabled() ) {
514
527
  globalThis.puter.apiCallLogger.logRequest({
515
528
  service: 'drivers',
516
529
  operation: `${this._puterDriverRequestInfo.interface}::${this._puterDriverRequestInfo.method}`,
517
530
  params: { interface: this._puterDriverRequestInfo.interface, driver: this._puterDriverRequestInfo.driver, method: this._puterDriverRequestInfo.method, args: this._puterDriverRequestInfo.args },
518
- error: { message: 'Network error occurred', event: e.type }
531
+ error: { message: 'Network error occurred', event: e.type },
519
532
  });
520
533
  }
521
534
  return handle_error(error_cb, reject_func, this);
522
- })
535
+ });
523
536
 
524
537
  // send request
525
538
  xhr.send(JSON.stringify({
526
539
  interface: driverInterface,
527
540
  driver: driverName,
528
- test_mode: settings?.test_mode,
541
+ test_mode: settings?.test_mode,
529
542
  method: driverMethod,
530
543
  args: driverArgs,
531
- auth_token: puter.authToken
544
+ auth_token: puter.authToken,
532
545
  }));
533
546
  }
534
547
 
@@ -567,54 +580,50 @@ class TeePromise {
567
580
  this.status_ = this.constructor.STATUS_DONE;
568
581
  this.doneReject(err);
569
582
  }
570
-
583
+
571
584
  /**
572
585
  * @deprecated use then() instead
573
586
  */
574
- onComplete(fn) {
587
+ onComplete (fn) {
575
588
  return this.then(fn);
576
589
  }
577
590
  }
578
591
 
579
592
  async function blob_to_url (blob) {
580
593
  const tp = new TeePromise();
581
- const reader = new FileReader();
594
+ const reader = new (globalThis.FileReader || FileReaderPoly)();
582
595
  reader.onloadend = () => tp.resolve(reader.result);
583
596
  reader.readAsDataURL(blob);
584
597
  return await tp;
585
598
  }
586
599
 
587
- function blobToDataUri(blob) {
600
+ function blobToDataUri (blob) {
588
601
  return new Promise((resolve, reject) => {
589
- const reader = new FileReader();
590
- reader.onload = function(event) {
602
+ const reader = new (globalThis.FileReader || FileReaderPoly)();
603
+ reader.onload = function (event) {
591
604
  resolve(event.target.result);
592
605
  };
593
- reader.onerror = function(error) {
606
+ reader.onerror = function (error) {
594
607
  reject(error);
595
608
  };
596
609
  reader.readAsDataURL(blob);
597
610
  });
598
611
  }
599
612
 
600
- function arrayBufferToDataUri(arrayBuffer) {
613
+ function arrayBufferToDataUri (arrayBuffer) {
601
614
  return new Promise((resolve, reject) => {
602
615
  const blob = new Blob([arrayBuffer]);
603
- const reader = new FileReader();
604
- reader.onload = function(event) {
616
+ const reader = new (globalThis.FileReader || FileReaderPoly)();
617
+ reader.onload = function (event) {
605
618
  resolve(event.target.result);
606
619
  };
607
- reader.onerror = function(error) {
620
+ reader.onerror = function (error) {
608
621
  reject(error);
609
622
  };
610
623
  reader.readAsDataURL(blob);
611
624
  });
612
625
  }
613
626
 
614
- export {parseResponse, uuidv4, handle_resp, handle_error, initXhr, setupXhrEventHandlers, driverCall,
615
- TeePromise,
616
- make_driver_method,
617
- blob_to_url,
618
- arrayBufferToDataUri,
619
- blobToDataUri,
620
- };
627
+ export {
628
+ arrayBufferToDataUri, blob_to_url, blobToDataUri, driverCall, handle_error, handle_resp, initXhr, make_driver_method, parseResponse, setupXhrEventHandlers, TeePromise, uuidv4
629
+ };