@heyputer/puter.js 2.0.1 → 2.0.3

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 (68) hide show
  1. package/dist/puter.js +4 -0
  2. package/package.json +4 -4
  3. package/src/bg.png +0 -0
  4. package/src/bg.webp +0 -0
  5. package/src/index.js +165 -165
  6. package/src/lib/APICallLogger.js +110 -0
  7. package/src/lib/EventListener.js +51 -0
  8. package/src/lib/RequestError.js +6 -0
  9. package/src/lib/filesystem/APIFS.js +73 -0
  10. package/src/lib/filesystem/CacheFS.js +243 -0
  11. package/src/lib/filesystem/PostMessageFS.js +40 -0
  12. package/src/lib/filesystem/definitions.js +39 -0
  13. package/src/lib/path.js +509 -0
  14. package/src/lib/polyfills/localStorage.js +92 -0
  15. package/src/lib/polyfills/xhrshim.js +233 -0
  16. package/src/lib/socket.io/socket.io.esm.min.js +7 -0
  17. package/src/lib/socket.io/socket.io.esm.min.js.map +1 -0
  18. package/src/lib/socket.io/socket.io.js +4385 -0
  19. package/src/lib/socket.io/socket.io.js.map +1 -0
  20. package/src/lib/socket.io/socket.io.min.js +7 -0
  21. package/src/lib/socket.io/socket.io.min.js.map +1 -0
  22. package/src/lib/socket.io/socket.io.msgpack.min.js +7 -0
  23. package/src/lib/socket.io/socket.io.msgpack.min.js.map +1 -0
  24. package/src/lib/utils.js +620 -0
  25. package/src/lib/xdrpc.js +104 -0
  26. package/src/modules/AI.js +680 -0
  27. package/src/modules/Apps.js +215 -0
  28. package/src/modules/Auth.js +171 -0
  29. package/src/modules/Debug.js +39 -0
  30. package/src/modules/Drivers.js +278 -0
  31. package/src/modules/FSItem.js +139 -0
  32. package/src/modules/FileSystem/index.js +187 -0
  33. package/src/modules/FileSystem/operations/copy.js +64 -0
  34. package/src/modules/FileSystem/operations/deleteFSEntry.js +59 -0
  35. package/src/modules/FileSystem/operations/getReadUrl.js +42 -0
  36. package/src/modules/FileSystem/operations/mkdir.js +62 -0
  37. package/src/modules/FileSystem/operations/move.js +75 -0
  38. package/src/modules/FileSystem/operations/read.js +46 -0
  39. package/src/modules/FileSystem/operations/readdir.js +102 -0
  40. package/src/modules/FileSystem/operations/rename.js +58 -0
  41. package/src/modules/FileSystem/operations/sign.js +103 -0
  42. package/src/modules/FileSystem/operations/space.js +40 -0
  43. package/src/modules/FileSystem/operations/stat.js +95 -0
  44. package/src/modules/FileSystem/operations/symlink.js +55 -0
  45. package/src/modules/FileSystem/operations/upload.js +440 -0
  46. package/src/modules/FileSystem/operations/write.js +65 -0
  47. package/src/modules/FileSystem/utils/getAbsolutePathForApp.js +21 -0
  48. package/src/modules/Hosting.js +138 -0
  49. package/src/modules/KV.js +301 -0
  50. package/src/modules/OS.js +95 -0
  51. package/src/modules/Perms.js +109 -0
  52. package/src/modules/PuterDialog.js +481 -0
  53. package/src/modules/Threads.js +75 -0
  54. package/src/modules/UI.js +1555 -0
  55. package/src/modules/Util.js +38 -0
  56. package/src/modules/Workers.js +120 -0
  57. package/src/modules/networking/PSocket.js +87 -0
  58. package/src/modules/networking/PTLS.js +100 -0
  59. package/src/modules/networking/PWispHandler.js +89 -0
  60. package/src/modules/networking/parsers.js +157 -0
  61. package/src/modules/networking/requests.js +282 -0
  62. package/src/safeLoadPuter.cjs +29 -0
  63. package/src/services/APIAccess.js +46 -0
  64. package/src/services/FSRelay.js +20 -0
  65. package/src/services/Filesystem.js +122 -0
  66. package/src/services/NoPuterYet.js +20 -0
  67. package/src/services/XDIncoming.js +44 -0
  68. package/index.d.ts +0 -479
package/src/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  import putility from '@heyputer/putility';
2
2
 
3
+ import kvjs from '@heyputer/kv.js';
3
4
  import APICallLogger from './lib/APICallLogger.js';
4
5
  import path from './lib/path.js';
5
- import localStorageMemory from './lib/polyfills/localStorage.js'
6
- import xhrshim from './lib/polyfills/xhrshim.js'
6
+ import localStorageMemory from './lib/polyfills/localStorage.js';
7
+ import xhrshim from './lib/polyfills/xhrshim.js';
7
8
  import * as utils from './lib/utils.js';
8
9
  import AI from './modules/AI.js';
9
10
  import Apps from './modules/Apps.js';
@@ -15,7 +16,7 @@ import FSItem from './modules/FSItem.js';
15
16
  import Hosting from './modules/Hosting.js';
16
17
  import KV from './modules/KV.js';
17
18
  import { PSocket } from './modules/networking/PSocket.js';
18
- import { PTLSSocket } from "./modules/networking/PTLS.js"
19
+ import { PTLSSocket } from './modules/networking/PTLS.js';
19
20
  import { pFetch } from './modules/networking/requests.js';
20
21
  import OS from './modules/OS.js';
21
22
  import Perms from './modules/Perms.js';
@@ -28,14 +29,13 @@ import { FilesystemService } from './services/Filesystem.js';
28
29
  import { FSRelayService } from './services/FSRelay.js';
29
30
  import { NoPuterYetService } from './services/NoPuterYet.js';
30
31
  import { XDIncomingService } from './services/XDIncoming.js';
31
- import kvjs from '@heyputer/kv.js';
32
32
 
33
33
  // TODO: This is for a safe-guard below; we should check if we can
34
34
  // generalize this behavior rather than hard-coding it.
35
35
  // (using defaultGUIOrigin breaks locally-hosted apps)
36
36
  const PROD_ORIGIN = 'https://puter.com';
37
37
 
38
- export default globalThis.puter = (function() {
38
+ const puterInit = (function() {
39
39
  'use strict';
40
40
 
41
41
  class Puter{
@@ -58,7 +58,7 @@ export default globalThis.puter = (function() {
58
58
  puterAuthState = {
59
59
  isPromptOpen: false,
60
60
  authGranted: null,
61
- resolver: null
61
+ resolver: null,
62
62
  };
63
63
 
64
64
  // Holds the unique app instance ID that is provided by the host environment
@@ -78,12 +78,12 @@ export default globalThis.puter = (function() {
78
78
 
79
79
  /**
80
80
  * Puter.js Modules
81
- *
81
+ *
82
82
  * These are the modules you see on docs.puter.com; for example:
83
83
  * - puter.fs
84
84
  * - puter.kv
85
85
  * - puter.ui
86
- *
86
+ *
87
87
  * initSubmodules is called from the constructor of this class.
88
88
  */
89
89
  initSubmodules = function(){
@@ -108,14 +108,13 @@ export default globalThis.puter = (function() {
108
108
 
109
109
  // Path
110
110
  this.path = path;
111
- }
111
+ };
112
112
 
113
113
  // --------------------------------------------
114
114
  // Constructor
115
115
  // --------------------------------------------
116
- constructor(options) {
117
- options = options ?? {};
118
-
116
+ constructor() {
117
+
119
118
  // Initialize the cache using kv.js
120
119
  this._cache = new kvjs();
121
120
 
@@ -131,57 +130,57 @@ export default globalThis.puter = (function() {
131
130
  this.context = context;
132
131
  context.services = this.services;
133
132
 
134
-
135
133
  // Holds the query parameters found in the current URL
136
134
  let URLParams = new URLSearchParams(globalThis.location?.search);
137
135
 
138
136
  // Figure out the environment in which the SDK is running
139
- if (URLParams.has('puter.app_instance_id')) {
137
+ if ( URLParams.has('puter.app_instance_id') ) {
140
138
  this.env = 'app';
141
- } else if(globalThis.puter_gui_enabled === true)
139
+ } else if ( globalThis.puter_gui_enabled === true )
140
+ {
142
141
  this.env = 'gui';
143
- else if (globalThis.WorkerGlobalScope) {
144
- if (globalThis.ServiceWorkerGlobalScope) {
145
- this.env = 'service-worker'
146
- if (!globalThis.XMLHttpRequest) {
147
- globalThis.XMLHttpRequest = xhrshim
142
+ }
143
+ else if ( globalThis.WorkerGlobalScope ) {
144
+ if ( globalThis.ServiceWorkerGlobalScope ) {
145
+ this.env = 'service-worker';
146
+ if ( !globalThis.XMLHttpRequest ) {
147
+ globalThis.XMLHttpRequest = xhrshim;
148
148
  }
149
- if (!globalThis.location) {
150
- globalThis.location = new URL("https://puter.site/");
149
+ if ( !globalThis.location ) {
150
+ globalThis.location = new URL('https://puter.site/');
151
151
  }
152
152
  // XHRShimGlobalize here
153
153
  } else {
154
- this.env = 'web-worker'
154
+ this.env = 'web-worker';
155
155
  }
156
- if (!globalThis.localStorage) {
156
+ if ( !globalThis.localStorage ) {
157
157
  globalThis.localStorage = localStorageMemory;
158
158
  }
159
- } else if (globalThis.process) {
159
+ } else if ( globalThis.process ) {
160
160
  this.env = 'nodejs';
161
- if (!globalThis.localStorage) {
161
+ if ( !globalThis.localStorage ) {
162
162
  globalThis.localStorage = localStorageMemory;
163
163
  }
164
- if (!globalThis.XMLHttpRequest) {
165
- globalThis.XMLHttpRequest = xhrshim
164
+ if ( !globalThis.XMLHttpRequest ) {
165
+ globalThis.XMLHttpRequest = xhrshim;
166
166
  }
167
- if (!globalThis.location) {
168
- globalThis.location = new URL("https://nodejs.puter.site/");
167
+ if ( !globalThis.location ) {
168
+ globalThis.location = new URL('https://nodejs.puter.site/');
169
169
  }
170
- if (!globalThis.addEventListener) {
171
- globalThis.addEventListener = () => {} // API Stub
170
+ if ( !globalThis.addEventListener ) {
171
+ globalThis.addEventListener = () => {
172
+ }; // API Stub
172
173
  }
173
174
  } else {
174
175
  this.env = 'web';
175
176
  }
176
-
177
-
178
177
 
179
178
  // There are some specific situations where puter is definitely loaded in GUI mode
180
179
  // we're going to check for those situations here so that we don't break anything unintentionally
181
180
  // if navigator URL's hostname is 'puter.com'
182
- if(this.env !== 'gui'){
181
+ if ( this.env !== 'gui' ){
183
182
  // Retrieve the hostname from the URL: Remove the trailing dot if it exists. This is to handle the case where the URL is, for example, `https://puter.com.` (note the trailing dot).
184
- // This is necessary because the trailing dot can cause the hostname to not match the expected value.
183
+ // This is necessary because the trailing dot can cause the hostname to not match the expected value.
185
184
  let hostname = location.hostname.replace(/\.$/, '');
186
185
 
187
186
  // Create a new URL object with the URL string
@@ -191,45 +190,45 @@ export default globalThis.puter = (function() {
191
190
  const gui_hostname = url.hostname;
192
191
 
193
192
  // If the hostname matches the GUI hostname, then the SDK is running in the GUI environment
194
- if(hostname === gui_hostname){
193
+ if ( hostname === gui_hostname ){
195
194
  this.env = 'gui';
196
195
  }
197
196
  }
198
197
 
199
198
  // Get the 'args' from the URL. This is used to pass arguments to the app.
200
- if(URLParams.has('puter.args')){
199
+ if ( URLParams.has('puter.args') ){
201
200
  this.args = JSON.parse(decodeURIComponent(URLParams.get('puter.args')));
202
- }else{
201
+ } else {
203
202
  this.args = {};
204
203
  }
205
204
 
206
205
  // Try to extract appInstanceID from the URL. appInstanceID is included in every messaage
207
206
  // sent to the host environment. This is used to help host environment identify the app
208
207
  // instance that sent the message and communicate back to it.
209
- if(URLParams.has('puter.app_instance_id')){
208
+ if ( URLParams.has('puter.app_instance_id') ){
210
209
  this.appInstanceID = decodeURIComponent(URLParams.get('puter.app_instance_id'));
211
210
  }
212
211
 
213
212
  // Try to extract parentInstanceID from the URL. If another app launched this app instance, parentInstanceID
214
213
  // holds its instance ID, and is used to communicate with that parent app.
215
- if(URLParams.has('puter.parent_instance_id')){
214
+ if ( URLParams.has('puter.parent_instance_id') ){
216
215
  this.parentInstanceID = decodeURIComponent(URLParams.get('puter.parent_instance_id'));
217
216
  }
218
217
 
219
218
  // Try to extract `puter.app.id` from the URL. `puter.app.id` is the unique ID of the app.
220
219
  // App ID is useful for identifying the app when communicating with the Puter API, among other things.
221
- if(URLParams.has('puter.app.id')){
220
+ if ( URLParams.has('puter.app.id') ){
222
221
  this.appID = decodeURIComponent(URLParams.get('puter.app.id'));
223
222
  }
224
-
223
+
225
224
  // Extract app name (added later)
226
- if(URLParams.has('puter.app.name')){
225
+ if ( URLParams.has('puter.app.name') ){
227
226
  this.appName = decodeURIComponent(URLParams.get('puter.app.name'));
228
227
  }
229
228
 
230
229
  // Construct this App's AppData path based on the appID. AppData path is used to store files that are specific to this app.
231
230
  // The default AppData path is `~/AppData/<appID>`.
232
- if(this.appID){
231
+ if ( this.appID ){
233
232
  this.appDataPath = `~/AppData/${this.appID}`;
234
233
  }
235
234
 
@@ -239,9 +238,9 @@ export default globalThis.puter = (function() {
239
238
  // is constructed as `https://api.<puter.domain>`.
240
239
  // This should only be done when the SDK is running in 'app' mode.
241
240
  this.APIOrigin = this.defaultAPIOrigin;
242
- if(URLParams.has('puter.api_origin') && this.env === 'app'){
241
+ if ( URLParams.has('puter.api_origin') && this.env === 'app' ){
243
242
  this.APIOrigin = decodeURIComponent(URLParams.get('puter.api_origin'));
244
- }else if(URLParams.has('puter.domain') && this.env === 'app'){
243
+ } else if ( URLParams.has('puter.domain') && this.env === 'app' ){
245
244
  this.APIOrigin = 'https://api.' + URLParams.get('puter.domain');
246
245
  }
247
246
 
@@ -251,10 +250,9 @@ export default globalThis.puter = (function() {
251
250
  let logger = new putility.libs.log.ConsoleLogger();
252
251
 
253
252
  // logs can be toggled based on categories
254
- logger = new putility.libs.log.CategorizedToggleLogger(
255
- { delegate: logger });
253
+ logger = new putility.libs.log.CategorizedToggleLogger({ delegate: logger });
256
254
  const cat_logger = logger;
257
-
255
+
258
256
  // create facade for easy logging
259
257
  this.logger = new putility.libs.log.LoggerFacade({
260
258
  impl: logger,
@@ -263,7 +261,7 @@ export default globalThis.puter = (function() {
263
261
 
264
262
  // Initialize API call logger
265
263
  this.apiCallLogger = new APICallLogger({
266
- enabled: false // Disabled by default
264
+ enabled: false, // Disabled by default
267
265
  });
268
266
 
269
267
  // === START :: Services === //
@@ -285,17 +283,16 @@ export default globalThis.puter = (function() {
285
283
  svc_apiAccess.auth_token = this.authToken;
286
284
  svc_apiAccess.api_origin = this.APIOrigin;
287
285
  [
288
- ['authToken','auth_token'],
289
- ['APIOrigin','api_origin'],
290
- ].forEach(([k1,k2]) => {
286
+ ['authToken', 'auth_token'],
287
+ ['APIOrigin', 'api_origin'],
288
+ ].forEach(([k1, k2]) => {
291
289
  Object.defineProperty(this, k1, {
292
- get () {
290
+ get() {
293
291
  return svc_apiAccess[k2];
294
292
  },
295
- set (v) {
293
+ set(v) {
296
294
  svc_apiAccess[k2] = v;
297
- return true;
298
- }
295
+ },
299
296
  });
300
297
  });
301
298
  })();
@@ -303,27 +300,27 @@ export default globalThis.puter = (function() {
303
300
  // === Start :: Modules === //
304
301
 
305
302
  // The SDK is running in the Puter GUI (i.e. 'gui')
306
- if(this.env === 'gui'){
303
+ if ( this.env === 'gui' ){
307
304
  this.authToken = window.auth_token;
308
305
  // initialize submodules
309
306
  this.initSubmodules();
310
307
  }
311
308
  // Loaded in an iframe in the Puter GUI (i.e. 'app')
312
309
  // When SDK is loaded in App mode the initiation process should start when the DOM is ready
313
- else if (this.env === 'app') {
310
+ else if ( this.env === 'app' ) {
314
311
  this.authToken = decodeURIComponent(URLParams.get('puter.auth.token'));
315
312
  // initialize submodules
316
313
  this.initSubmodules();
317
314
  // If the authToken is already set in localStorage, then we don't need to show the dialog
318
315
  try {
319
- if(localStorage.getItem('puter.auth.token')){
316
+ if ( localStorage.getItem('puter.auth.token') ){
320
317
  this.setAuthToken(localStorage.getItem('puter.auth.token'));
321
318
  }
322
319
  // if appID is already set in localStorage, then we don't need to show the dialog
323
- if(localStorage.getItem('puter.app.id')){
320
+ if ( localStorage.getItem('puter.app.id') ){
324
321
  this.setAppID(localStorage.getItem('puter.app.id'));
325
322
  }
326
- } catch (error) {
323
+ } catch( error ) {
327
324
  // Handle the error here
328
325
  console.error('Error accessing localStorage:', error);
329
326
  }
@@ -331,23 +328,23 @@ export default globalThis.puter = (function() {
331
328
  // SDK was loaded in a 3rd-party website.
332
329
  // When SDK is loaded in GUI the initiation process should start when the DOM is ready. This is because
333
330
  // the SDK needs to show a dialog to the user to ask for permission to access their Puter account.
334
- else if(this.env === 'web') {
331
+ else if ( this.env === 'web' ) {
335
332
  // initialize submodules
336
333
  this.initSubmodules();
337
- try{
334
+ try {
338
335
  // If the authToken is already set in localStorage, then we don't need to show the dialog
339
- if(localStorage.getItem('puter.auth.token')){
336
+ if ( localStorage.getItem('puter.auth.token') ){
340
337
  this.setAuthToken(localStorage.getItem('puter.auth.token'));
341
338
  }
342
339
  // if appID is already set in localStorage, then we don't need to show the dialog
343
- if(localStorage.getItem('puter.app.id')){
340
+ if ( localStorage.getItem('puter.app.id') ){
344
341
  this.setAppID(localStorage.getItem('puter.app.id'));
345
342
  }
346
- } catch (error) {
343
+ } catch( error ) {
347
344
  // Handle the error here
348
345
  console.error('Error accessing localStorage:', error);
349
346
  }
350
- } else if (this.env === 'web-worker' || this.env === 'service-worker' || this.env === 'nodejs') {
347
+ } else if ( this.env === 'web-worker' || this.env === 'service-worker' || this.env === 'nodejs' ) {
351
348
  this.initSubmodules();
352
349
  }
353
350
 
@@ -364,7 +361,7 @@ export default globalThis.puter = (function() {
364
361
 
365
362
  this.logger.impl = logger;
366
363
  })();
367
-
364
+
368
365
  // Lock to prevent multiple requests to `/rao`
369
366
  this.lock_rao_ = new putility.libs.promise.Lock();
370
367
  // Promise that resolves when it's okay to request `/rao`
@@ -388,14 +385,14 @@ export default globalThis.puter = (function() {
388
385
  },
389
386
  body: JSON.stringify({}),
390
387
  })).json());
391
- return `${wispServer}/${wispToken}/`
388
+ return `${wispServer}/${wispToken}/`;
392
389
  },
393
390
  Socket: PSocket,
394
391
  tls: {
395
- TLSSocket: PTLSSocket
392
+ TLSSocket: PTLSSocket,
396
393
  },
397
- fetch: pFetch
398
- }
394
+ fetch: pFetch,
395
+ };
399
396
 
400
397
  this.workers = new WorkersHandler(this.authToken);
401
398
 
@@ -408,13 +405,13 @@ export default globalThis.puter = (function() {
408
405
  * Makes a request to `/rao`. This method aquires a lock to prevent
409
406
  * multiple requests, and is effectively idempotent.
410
407
  */
411
- async request_rao_ () {
408
+ async request_rao_() {
412
409
  await this.p_can_request_rao_;
413
-
410
+
414
411
  if ( this.env === 'gui' ) {
415
412
  return;
416
413
  }
417
-
414
+
418
415
  // setAuthToken is called more than once when auth completes, which
419
416
  // causes multiple requests to /rao. This lock prevents that.
420
417
  await this.lock_rao_.acquire();
@@ -429,11 +426,11 @@ export default globalThis.puter = (function() {
429
426
  method: 'POST',
430
427
  headers: {
431
428
  Authorization: `Bearer ${this.authToken}`,
432
- Origin: location.origin // This is ignored in the browser but needed for workers and nodejs
433
- }
429
+ Origin: location.origin, // This is ignored in the browser but needed for workers and nodejs
430
+ },
434
431
  });
435
432
  return await resp.json();
436
- } catch (e) {
433
+ } catch( e ) {
437
434
  had_error = true;
438
435
  console.error(e);
439
436
  } finally {
@@ -443,8 +440,8 @@ export default globalThis.puter = (function() {
443
440
  this.rao_requested_ = true;
444
441
  }
445
442
  }
446
-
447
- registerModule (name, cls, parameters = {}) {
443
+
444
+ registerModule(name, cls, parameters = {}) {
448
445
  const instance = new cls(this.context, parameters);
449
446
  this.modules_.push(name);
450
447
  this[name] = instance;
@@ -460,24 +457,24 @@ export default globalThis.puter = (function() {
460
457
  }
461
458
  }
462
459
 
463
- setAppID = function (appID) {
460
+ setAppID = function(appID) {
464
461
  // save to localStorage
465
- try{
462
+ try {
466
463
  localStorage.setItem('puter.app.id', appID);
467
- } catch (error) {
464
+ } catch( error ) {
468
465
  // Handle the error here
469
466
  console.error('Error accessing localStorage:', error);
470
467
  }
471
468
  this.appID = appID;
472
- }
469
+ };
473
470
 
474
- setAuthToken = function (authToken) {
471
+ setAuthToken = function(authToken) {
475
472
  this.authToken = authToken;
476
473
  // If the SDK is running on a 3rd-party site or an app, then save the authToken in localStorage
477
- if(this.env === 'web' || this.env === 'app'){
478
- try{
474
+ if ( this.env === 'web' || this.env === 'app' ){
475
+ try {
479
476
  localStorage.setItem('puter.auth.token', authToken);
480
- } catch (error) {
477
+ } catch( error ) {
481
478
  // Handle the error here
482
479
  console.error('Error accessing localStorage:', error);
483
480
  }
@@ -486,41 +483,41 @@ export default globalThis.puter = (function() {
486
483
  this.updateSubmodules();
487
484
  // rao
488
485
  this.request_rao_();
489
- }
486
+ };
490
487
 
491
- setAPIOrigin = function (APIOrigin) {
488
+ setAPIOrigin = function(APIOrigin) {
492
489
  this.APIOrigin = APIOrigin;
493
490
  // reinitialize submodules
494
491
  this.updateSubmodules();
495
- }
492
+ };
496
493
 
497
- resetAuthToken = function () {
494
+ resetAuthToken = function() {
498
495
  this.authToken = null;
499
496
  // If the SDK is running on a 3rd-party site or an app, then save the authToken in localStorage
500
- if(this.env === 'web' || this.env === 'app'){
501
- try{
497
+ if ( this.env === 'web' || this.env === 'app' ){
498
+ try {
502
499
  localStorage.removeItem('puter.auth.token');
503
- } catch (error) {
500
+ } catch( error ) {
504
501
  // Handle the error here
505
502
  console.error('Error accessing localStorage:', error);
506
503
  }
507
504
  }
508
505
  // reinitialize submodules
509
506
  this.updateSubmodules();
510
- }
507
+ };
511
508
 
512
509
  exit = function(statusCode = 0) {
513
- if (statusCode && (typeof statusCode !== 'number')) {
510
+ if ( statusCode && (typeof statusCode !== 'number') ) {
514
511
  console.warn('puter.exit() requires status code to be a number. Treating it as 1');
515
512
  statusCode = 1;
516
513
  }
517
514
 
518
515
  globalThis.parent.postMessage({
519
- msg: "exit",
516
+ msg: 'exit',
520
517
  appInstanceID: this.appInstanceID,
521
518
  statusCode,
522
519
  }, '*');
523
- }
520
+ };
524
521
 
525
522
  /**
526
523
  * A function that generates a domain-safe name by combining a random adjective, a random noun, and a random number (between 0 and 9999).
@@ -532,29 +529,29 @@ export default globalThis.puter = (function() {
532
529
  *
533
530
  */
534
531
  randName = function(separateWith = '-'){
535
- const first_adj = ['helpful','sensible', 'loyal', 'honest', 'clever', 'capable','calm', 'smart', 'genius', 'bright', 'charming', 'creative', 'diligent', 'elegant', 'fancy',
536
- 'colorful', 'avid', 'active', 'gentle', 'happy', 'intelligent', 'jolly', 'kind', 'lively', 'merry', 'nice', 'optimistic', 'polite',
537
- 'quiet', 'relaxed', 'silly', 'victorious', 'witty', 'young', 'zealous', 'strong', 'brave', 'agile', 'bold'];
538
-
539
- const nouns = ['street', 'roof', 'floor', 'tv', 'idea', 'morning', 'game', 'wheel', 'shoe', 'bag', 'clock', 'pencil', 'pen',
540
- 'magnet', 'chair', 'table', 'house', 'dog', 'room', 'book', 'car', 'cat', 'tree',
541
- 'flower', 'bird', 'fish', 'sun', 'moon', 'star', 'cloud', 'rain', 'snow', 'wind', 'mountain',
542
- 'river', 'lake', 'sea', 'ocean', 'island', 'bridge', 'road', 'train', 'plane', 'ship', 'bicycle',
543
- 'horse', 'elephant', 'lion', 'tiger', 'bear', 'zebra', 'giraffe', 'monkey', 'snake', 'rabbit', 'duck',
544
- 'goose', 'penguin', 'frog', 'crab', 'shrimp', 'whale', 'octopus', 'spider', 'ant', 'bee', 'butterfly', 'dragonfly',
545
- 'ladybug', 'snail', 'camel', 'kangaroo', 'koala', 'panda', 'piglet', 'sheep', 'wolf', 'fox', 'deer', 'mouse', 'seal',
546
- 'chicken', 'cow', 'dinosaur', 'puppy', 'kitten', 'circle', 'square', 'garden', 'otter', 'bunny', 'meerkat', 'harp']
532
+ const first_adj = ['helpful', 'sensible', 'loyal', 'honest', 'clever', 'capable', 'calm', 'smart', 'genius', 'bright', 'charming', 'creative', 'diligent', 'elegant', 'fancy',
533
+ 'colorful', 'avid', 'active', 'gentle', 'happy', 'intelligent', 'jolly', 'kind', 'lively', 'merry', 'nice', 'optimistic', 'polite',
534
+ 'quiet', 'relaxed', 'silly', 'victorious', 'witty', 'young', 'zealous', 'strong', 'brave', 'agile', 'bold'];
535
+
536
+ const nouns = ['street', 'roof', 'floor', 'tv', 'idea', 'morning', 'game', 'wheel', 'shoe', 'bag', 'clock', 'pencil', 'pen',
537
+ 'magnet', 'chair', 'table', 'house', 'dog', 'room', 'book', 'car', 'cat', 'tree',
538
+ 'flower', 'bird', 'fish', 'sun', 'moon', 'star', 'cloud', 'rain', 'snow', 'wind', 'mountain',
539
+ 'river', 'lake', 'sea', 'ocean', 'island', 'bridge', 'road', 'train', 'plane', 'ship', 'bicycle',
540
+ 'horse', 'elephant', 'lion', 'tiger', 'bear', 'zebra', 'giraffe', 'monkey', 'snake', 'rabbit', 'duck',
541
+ 'goose', 'penguin', 'frog', 'crab', 'shrimp', 'whale', 'octopus', 'spider', 'ant', 'bee', 'butterfly', 'dragonfly',
542
+ 'ladybug', 'snail', 'camel', 'kangaroo', 'koala', 'panda', 'piglet', 'sheep', 'wolf', 'fox', 'deer', 'mouse', 'seal',
543
+ 'chicken', 'cow', 'dinosaur', 'puppy', 'kitten', 'circle', 'square', 'garden', 'otter', 'bunny', 'meerkat', 'harp'];
547
544
 
548
545
  // return a random combination of first_adj + noun + number (between 0 and 9999)
549
546
  // e.g. clever-idea-123
550
547
  return first_adj[Math.floor(Math.random() * first_adj.length)] + separateWith + nouns[Math.floor(Math.random() * nouns.length)] + separateWith + Math.floor(Math.random() * 10000);
551
- }
548
+ };
552
549
 
553
550
  getUser = function(...args){
554
551
  let options;
555
-
552
+
556
553
  // If first argument is an object, it's the options
557
- if (typeof args[0] === 'object' && args[0] !== null) {
554
+ if ( typeof args[0] === 'object' && args[0] !== null ) {
558
555
  options = args[0];
559
556
  } else {
560
557
  // Otherwise, we assume separate arguments are provided
@@ -563,43 +560,43 @@ export default globalThis.puter = (function() {
563
560
  error: args[1],
564
561
  };
565
562
  }
566
-
563
+
567
564
  return new Promise((resolve, reject) => {
568
565
  const xhr = utils.initXhr('/whoami', this.APIOrigin, this.authToken, 'get');
569
566
  // set up event handlers for load and error events
570
567
  utils.setupXhrEventHandlers(xhr, options.success, options.error, resolve, reject);
571
-
568
+
572
569
  xhr.send();
573
- })
574
- }
570
+ });
571
+ };
575
572
 
576
573
  print = function(...args){
577
574
  // Check if the last argument is an options object with escapeHTML or code property
578
575
  let options = {};
579
- if(args.length > 0 && typeof args[args.length - 1] === 'object' && args[args.length - 1] !== null &&
580
- ('escapeHTML' in args[args.length - 1] || 'code' in args[args.length - 1])) {
576
+ if ( args.length > 0 && typeof args[args.length - 1] === 'object' && args[args.length - 1] !== null &&
577
+ ('escapeHTML' in args[args.length - 1] || 'code' in args[args.length - 1]) ) {
581
578
  options = args.pop();
582
579
  }
583
-
584
- for(let arg of args){
580
+
581
+ for ( let arg of args ){
585
582
  // Escape HTML if the option is set to true or if code option is true
586
- if((options.escapeHTML === true || options.code === true) && typeof arg === 'string') {
583
+ if ( (options.escapeHTML === true || options.code === true) && typeof arg === 'string' ) {
587
584
  arg = arg.replace(/&/g, '&amp;')
588
- .replace(/</g, '&lt;')
589
- .replace(/>/g, '&gt;')
590
- .replace(/"/g, '&quot;')
591
- .replace(/'/g, '&#039;');
585
+ .replace(/</g, '&lt;')
586
+ .replace(/>/g, '&gt;')
587
+ .replace(/"/g, '&quot;')
588
+ .replace(/'/g, '&#039;');
592
589
  }
593
-
590
+
594
591
  // Wrap in code/pre tags if code option is true
595
- if(options.code === true) {
592
+ if ( options.code === true ) {
596
593
  arg = `<code><pre>${arg}</pre></code>`;
597
594
  }
598
-
595
+
599
596
  document.body.innerHTML += arg;
600
597
  }
601
- }
602
-
598
+ };
599
+
603
600
  /**
604
601
  * Configures API call logging settings
605
602
  * @param {Object} config - Configuration options for API call logging
@@ -607,32 +604,32 @@ export default globalThis.puter = (function() {
607
604
  * @param {boolean} config.enabled - Enable/disable API call logging
608
605
  */
609
606
  configureAPILogging = function(config = {}){
610
- if (this.apiCallLogger) {
607
+ if ( this.apiCallLogger ) {
611
608
  this.apiCallLogger.updateConfig(config);
612
609
  }
613
610
  return this;
614
- }
615
-
611
+ };
612
+
616
613
  /**
617
614
  * Enables API call logging with optional configuration
618
615
  * @param {Object} config - Optional configuration to apply when enabling
619
616
  */
620
617
  enableAPILogging = function(config = {}) {
621
- if (this.apiCallLogger) {
618
+ if ( this.apiCallLogger ) {
622
619
  this.apiCallLogger.updateConfig({ ...config, enabled: true });
623
620
  }
624
621
  return this;
625
- }
626
-
622
+ };
623
+
627
624
  /**
628
625
  * Disables API call logging
629
626
  */
630
627
  disableAPILogging = function() {
631
- if (this.apiCallLogger) {
628
+ if ( this.apiCallLogger ) {
632
629
  this.apiCallLogger.disable();
633
630
  }
634
631
  return this;
635
- }
632
+ };
636
633
 
637
634
  /**
638
635
  * Initializes network connectivity monitoring to purge cache when connection is lost
@@ -640,8 +637,8 @@ export default globalThis.puter = (function() {
640
637
  */
641
638
  initNetworkMonitoring = function() {
642
639
  // Only initialize in environments that support navigator.onLine and window events
643
- if (typeof globalThis.navigator === 'undefined' ||
644
- typeof globalThis.addEventListener !== 'function') {
640
+ if ( typeof globalThis.navigator === 'undefined' ||
641
+ typeof globalThis.addEventListener !== 'function' ) {
645
642
  return;
646
643
  }
647
644
 
@@ -651,13 +648,13 @@ export default globalThis.puter = (function() {
651
648
  // Function to handle network state changes
652
649
  const handleNetworkChange = () => {
653
650
  const isOnline = navigator.onLine;
654
-
651
+
655
652
  // If we went from online to offline, purge the cache
656
- if (wasOnline && !isOnline) {
653
+ if ( wasOnline && !isOnline ) {
657
654
  console.log('Network connection lost - purging cache');
658
655
  this.purgeCache();
659
656
  }
660
-
657
+
661
658
  // Update the previous state
662
659
  wasOnline = isOnline;
663
660
  };
@@ -668,13 +665,13 @@ export default globalThis.puter = (function() {
668
665
 
669
666
  // Also listen for visibility change as an additional indicator
670
667
  // (some browsers don't fire offline events reliably)
671
- if (typeof document !== 'undefined') {
668
+ if ( typeof document !== 'undefined' ) {
672
669
  document.addEventListener('visibilitychange', () => {
673
670
  // Small delay to allow network state to update
674
671
  setTimeout(handleNetworkChange, 100);
675
672
  });
676
673
  }
677
- }
674
+ };
678
675
 
679
676
  /**
680
677
  * Purges all cached data
@@ -682,17 +679,17 @@ export default globalThis.puter = (function() {
682
679
  */
683
680
  purgeCache = function() {
684
681
  try {
685
- if (this._cache && typeof this._cache.flushall === 'function') {
682
+ if ( this._cache && typeof this._cache.flushall === 'function' ) {
686
683
  this._cache.flushall();
687
684
  console.log('Cache purged successfully');
688
685
  } else {
689
686
  console.warn('Cache purge failed: cache instance not available');
690
687
  }
691
- } catch (error) {
688
+ } catch( error ) {
692
689
  console.error('Error purging cache:', error);
693
690
  }
694
- }
695
-
691
+ };
692
+
696
693
  }
697
694
 
698
695
  // Create a new Puter object and return it
@@ -700,18 +697,21 @@ export default globalThis.puter = (function() {
700
697
 
701
698
  // Return the Puter object
702
699
  return puterobj;
703
- }());
700
+ });
701
+
702
+ export const puter = puterInit();
703
+ export default puter;
704
704
 
705
- globalThis.addEventListener('message', async (event) => {
705
+ globalThis.addEventListener && globalThis.addEventListener('message', async (event) => {
706
706
  // if the message is not from Puter, then ignore it
707
- if(event.origin !== puter.defaultGUIOrigin) return;
707
+ if ( event.origin !== puter.defaultGUIOrigin ) return;
708
708
 
709
- if(event.data.msg && event.data.msg === 'requestOrigin'){
709
+ if ( event.data.msg && event.data.msg === 'requestOrigin' ){
710
710
  event.source.postMessage({
711
- msg: "originResponse",
712
- }, '*');
711
+ msg: 'originResponse',
712
+ }, '*');
713
713
  }
714
- else if (event.data.msg === 'puter.token') {
714
+ else if ( event.data.msg === 'puter.token' ) {
715
715
  // puterDialog.close();
716
716
  // Set the authToken property
717
717
  puter.setAuthToken(event.data.token);
@@ -725,16 +725,16 @@ globalThis.addEventListener('message', async (event) => {
725
725
  // resolve();
726
726
 
727
727
  // Call onAuth callback
728
- if(puter.onAuth && typeof puter.onAuth === 'function'){
728
+ if ( puter.onAuth && typeof puter.onAuth === 'function' ){
729
729
  puter.getUser().then((user) => {
730
- puter.onAuth(user)
730
+ puter.onAuth(user);
731
731
  });
732
732
  }
733
733
 
734
734
  puter.puterAuthState.isPromptOpen = false;
735
735
  // Resolve or reject any waiting promises.
736
- if (puter.puterAuthState.resolver) {
737
- if (puter.puterAuthState.authGranted) {
736
+ if ( puter.puterAuthState.resolver ) {
737
+ if ( puter.puterAuthState.authGranted ) {
738
738
  puter.puterAuthState.resolver.resolve();
739
739
  } else {
740
740
  puter.puterAuthState.resolver.reject();
@@ -742,4 +742,4 @@ globalThis.addEventListener('message', async (event) => {
742
742
  puter.puterAuthState.resolver = null;
743
743
  };
744
744
  }
745
- })
745
+ });