@heyputer/puter.js 2.1.15 → 2.2.2

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.
@@ -1,6 +1,6 @@
1
1
  export class Debug {
2
- constructor (context, parameters) {
3
- this.context = context;
2
+ constructor (puter, parameters) {
3
+ this.puter = puter;
4
4
  this.parameters = parameters;
5
5
 
6
6
  this._init();
@@ -14,7 +14,7 @@ export class Debug {
14
14
  enabled_logs = enabled_logs.split(';');
15
15
  for ( const category of enabled_logs ) {
16
16
  if ( category === '' ) continue;
17
- this.context.puter.logger.on(category);
17
+ this.puter.logger.on(category);
18
18
  }
19
19
 
20
20
  globalThis.addEventListener('message', async e => {
@@ -32,7 +32,7 @@ export class Debug {
32
32
 
33
33
  if ( e.data.cmd === 'log.on' ) {
34
34
  console.log('Got instruction to turn logs on!');
35
- this.context.puter.logger.on(e.data.category);
35
+ this.puter.logger.on(e.data.category);
36
36
  }
37
37
  });
38
38
  }
@@ -1,6 +1,7 @@
1
1
  class FetchDriverCallBackend {
2
- constructor ({ context }) {
3
- this.context = context;
2
+ constructor ({ getAPIOrigin, getAuthToken }) {
3
+ this.getAPIOrigin = getAPIOrigin;
4
+ this.getAuthToken = getAuthToken;
4
5
  this.response_handlers = this.constructor.response_handlers;
5
6
  }
6
7
 
@@ -32,7 +33,7 @@ class FetchDriverCallBackend {
32
33
 
33
34
  async call ({ driver, method_name, parameters }) {
34
35
  try {
35
- const resp = await fetch(`${this.context.APIOrigin}/drivers/call`, {
36
+ const resp = await fetch(`${this.getAPIOrigin()}/drivers/call`, {
36
37
  headers: {
37
38
  'Content-Type': 'text/plain;actually=json',
38
39
  },
@@ -44,7 +45,7 @@ class FetchDriverCallBackend {
44
45
  : {}),
45
46
  method: method_name,
46
47
  args: parameters,
47
- auth_token: this.context.authToken,
48
+ auth_token: this.getAuthToken(),
48
49
  }),
49
50
  });
50
51
 
@@ -131,22 +132,15 @@ class Drivers {
131
132
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
132
133
  * @param {string} appID - ID of the app to use.
133
134
  */
134
- constructor (context) {
135
- this.authToken = context.authToken;
136
- this.APIOrigin = context.APIOrigin;
137
- this.appID = context.appID;
135
+ constructor (puter) {
136
+ this.puter = puter;
137
+ this.authToken = puter.authToken;
138
+ this.APIOrigin = puter.APIOrigin;
139
+ this.appID = puter.appID;
138
140
 
139
141
  // Driver-specific
140
142
  this.drivers_ = {};
141
143
 
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
144
  }
151
145
 
152
146
  _init ({ puter }) {
@@ -226,7 +220,8 @@ class Drivers {
226
220
 
227
221
  return this.drivers_[key] = new Driver ({
228
222
  call_backend: new FetchDriverCallBackend({
229
- context: this.context,
223
+ getAPIOrigin: () => this.APIOrigin,
224
+ getAuthToken: () => this.authToken,
230
225
  }),
231
226
  // iface: interfaces[iface_name],
232
227
  iface_name,
@@ -20,14 +20,11 @@ import stat from './operations/stat.js';
20
20
  import symlink from './operations/symlink.js';
21
21
  import upload from './operations/upload.js';
22
22
  import write from './operations/write.js';
23
- // Why is this called deleteFSEntry instead of just delete? because delete is
24
- // a reserved keyword in javascript
25
- import { AdvancedBase } from '../../../../putility/index.js';
26
23
  import FSItem from '../FSItem.js';
27
24
  import deleteFSEntry from './operations/deleteFSEntry.js';
28
25
  import getReadURL from './operations/getReadUrl.js';
29
26
 
30
- export class PuterJSFileSystemModule extends AdvancedBase {
27
+ export class PuterJSFileSystemModule {
31
28
 
32
29
  space = space;
33
30
  mkdir = mkdir;
@@ -48,16 +45,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
48
45
 
49
46
  FSItem = FSItem;
50
47
 
51
- static NARI_METHODS = {
52
- // stat: {
53
- // positional: ['path'],
54
- // firstarg_options: true,
55
- // async fn (parameters) {
56
- // const svc_fs = await this.context.services.aget('filesystem');
57
- // return svc_fs.filesystem.stat(parameters);
58
- // }
59
- // },
60
- };
48
+ static NARI_METHODS = {};
61
49
 
62
50
  /**
63
51
  * Creates a new instance with the given authentication token, API origin, and app ID,
@@ -68,12 +56,11 @@ export class PuterJSFileSystemModule extends AdvancedBase {
68
56
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
69
57
  * @param {string} appID - ID of the app to use.
70
58
  */
71
- constructor (context) {
72
- super();
73
- this.authToken = context.authToken;
74
- this.APIOrigin = context.APIOrigin;
75
- this.appID = context.appID;
76
- this.context = context;
59
+ constructor (puter) {
60
+ this.puter = puter;
61
+ this.authToken = puter.authToken;
62
+ this.APIOrigin = puter.APIOrigin;
63
+ this.appID = puter.appID;
77
64
  this.cacheUpdateTimer = null;
78
65
  // Connect socket.
79
66
  this.initializeSocket();
@@ -107,7 +94,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
107
94
  auth: {
108
95
  auth_token: this.authToken,
109
96
  },
110
- autoUnref: this.context.env === 'nodejs',
97
+ autoUnref: this.puter.env === 'nodejs',
111
98
  });
112
99
 
113
100
  this.bindSocketEvents();
@@ -212,7 +199,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
212
199
  this.authToken = authToken;
213
200
 
214
201
  // Check cache timestamp and purge if needed (only in GUI environment)
215
- if ( this.context.env === 'gui' ) {
202
+ if ( this.puter.env === 'gui' ) {
216
203
  this.checkCacheAndPurge();
217
204
  // Start background task to update LAST_VALID_TS every 1 second
218
205
  this.startCacheUpdateTimer();
@@ -305,7 +292,7 @@ export class PuterJSFileSystemModule extends AdvancedBase {
305
292
  * @returns {void}
306
293
  */
307
294
  startCacheUpdateTimer () {
308
- if ( this.context.env !== 'gui' ) {
295
+ if ( this.puter.env !== 'gui' ) {
309
296
  return;
310
297
  }
311
298
 
@@ -10,10 +10,11 @@ class Hosting {
10
10
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
11
11
  * @param {string} appID - ID of the app to use.
12
12
  */
13
- constructor (context) {
14
- this.authToken = context.authToken;
15
- this.APIOrigin = context.APIOrigin;
16
- this.appID = context.appID;
13
+ constructor (puter) {
14
+ this.puter = puter;
15
+ this.authToken = puter.authToken;
16
+ this.APIOrigin = puter.APIOrigin;
17
+ this.appID = puter.appID;
17
18
  }
18
19
 
19
20
  /**
package/src/modules/KV.js CHANGED
@@ -1,6 +1,15 @@
1
- import { TeePromise } from '@heyputer/putility/src/libs/promise.js';
2
1
  import * as utils from '../lib/utils.js';
3
2
 
3
+ const createDeferred = () => {
4
+ let resolve;
5
+ let reject;
6
+ const promise = new Promise((res, rej) => {
7
+ resolve = res;
8
+ reject = rej;
9
+ });
10
+ return { promise, resolve, reject };
11
+ };
12
+
4
13
  const gui_cache_keys = [
5
14
  'has_set_default_app_user_permissions',
6
15
  'window_sidebar_width',
@@ -29,15 +38,16 @@ class KV {
29
38
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
30
39
  * @param {string} appID - ID of the app to use.
31
40
  */
32
- constructor (context) {
33
- this.authToken = context.authToken;
34
- this.APIOrigin = context.APIOrigin;
35
- this.appID = context.appID;
36
-
37
- this.gui_cached = new TeePromise();
38
- this.gui_cache_init = new TeePromise();
41
+ constructor (puter) {
42
+ this.puter = puter;
43
+ this.authToken = puter.authToken;
44
+ this.APIOrigin = puter.APIOrigin;
45
+ this.appID = puter.appID;
46
+
47
+ this.gui_cached = createDeferred();
48
+ this.gui_cache_init = createDeferred();
39
49
  (async () => {
40
- await this.gui_cache_init;
50
+ await this.gui_cache_init.promise;
41
51
  this.gui_cache_init = null;
42
52
  const resp = await fetch(`${this.APIOrigin}/drivers/call`, {
43
53
  method: 'POST',
@@ -142,7 +152,7 @@ class KV {
142
152
  this.gui_cached !== null
143
153
  ) {
144
154
  this.gui_cache_init && this.gui_cache_init.resolve();
145
- const cache = await this.gui_cached;
155
+ const cache = await this.gui_cached.promise;
146
156
  return cache[args[0]];
147
157
  }
148
158
 
@@ -323,4 +333,4 @@ function globMatch (pattern, str) {
323
333
  return re.test(str);
324
334
  }
325
335
 
326
- export default KV;
336
+ export default KV;
package/src/modules/OS.js CHANGED
@@ -9,10 +9,11 @@ class OS {
9
9
  * @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
10
10
  * @param {string} appID - ID of the app to use.
11
11
  */
12
- constructor (context) {
13
- this.authToken = context.authToken;
14
- this.APIOrigin = context.APIOrigin;
15
- this.appID = context.appID;
12
+ constructor (puter) {
13
+ this.puter = puter;
14
+ this.authToken = puter.authToken;
15
+ this.APIOrigin = puter.APIOrigin;
16
+ this.appID = puter.appID;
16
17
  }
17
18
 
18
19
  /**
@@ -92,4 +93,4 @@ class OS {
92
93
  };
93
94
  }
94
95
 
95
- export default OS;
96
+ export default OS;
@@ -1,7 +1,8 @@
1
1
  export default class Perms {
2
- constructor (context) {
3
- this.authToken = context.authToken;
4
- this.APIOrigin = context.APIOrigin;
2
+ constructor (puter) {
3
+ this.puter = puter;
4
+ this.authToken = puter.authToken;
5
+ this.APIOrigin = puter.APIOrigin;
5
6
  }
6
7
  setAuthToken (authToken) {
7
8
  this.authToken = authToken;
@@ -1,9 +1,10 @@
1
1
  import { RequestError } from '../lib/RequestError.js';
2
2
 
3
3
  export default class Threads {
4
- constructor (context) {
5
- this.authToken = context.authToken;
6
- this.APIOrigin = context.APIOrigin;
4
+ constructor (puter) {
5
+ this.puter = puter;
6
+ this.authToken = puter.authToken;
7
+ this.APIOrigin = puter.APIOrigin;
7
8
  }
8
9
  setAuthToken (authToken) {
9
10
  this.authToken = authToken;
package/src/modules/UI.js CHANGED
@@ -1,8 +1,17 @@
1
- import putility from '@heyputer/putility';
2
1
  import EventListener from '../lib/EventListener.js';
3
2
  import FSItem from './FSItem.js';
4
3
  import PuterDialog from './PuterDialog.js';
5
4
 
5
+ const createDeferred = () => {
6
+ let resolve;
7
+ let reject;
8
+ const promise = new Promise((res, rej) => {
9
+ resolve = res;
10
+ reject = rej;
11
+ });
12
+ return { promise, resolve, reject };
13
+ };
14
+
6
15
  const FILE_SAVE_CANCELLED = Symbol('FILE_SAVE_CANCELLED');
7
16
  const FILE_OPEN_CANCELLED = Symbol('FILE_OPEN_CANCELLED');
8
17
 
@@ -22,10 +31,12 @@ class AppConnection extends EventListener {
22
31
  // (Closing and close events will still function.)
23
32
  #usesSDK;
24
33
 
25
- static from (values, context) {
26
- const connection = new AppConnection(context, {
34
+ static from (values, puter, { messageTarget, appInstanceID }) {
35
+ const connection = new AppConnection(puter, {
27
36
  target: values.appInstanceID,
28
37
  usesSDK: values.usesSDK,
38
+ messageTarget,
39
+ appInstanceID,
29
40
  });
30
41
 
31
42
  // When a connection is established the app is able to
@@ -35,23 +46,23 @@ class AppConnection extends EventListener {
35
46
  return connection;
36
47
  }
37
48
 
38
- constructor (context, { target, usesSDK }) {
49
+ constructor (puter, { target, usesSDK, messageTarget, appInstanceID }) {
39
50
  super([
40
51
  'message', // The target sent us something with postMessage()
41
52
  'close', // The target app was closed
42
53
  ]);
43
- this.messageTarget = context.messageTarget;
44
- this.appInstanceID = context.appInstanceID;
54
+ this.messageTarget = messageTarget;
55
+ this.appInstanceID = appInstanceID;
45
56
  this.targetAppInstanceID = target;
46
57
  this.#isOpen = true;
47
58
  this.#usesSDK = usesSDK;
48
59
 
49
- this.log = context.puter.logger.fields({
60
+ this.log = puter.logger.fields({
50
61
  category: 'ipc',
51
62
  });
52
63
  this.log.fields({
53
- cons_source: context.appInstanceID,
54
- source: context.puter.appInstanceID,
64
+ cons_source: appInstanceID,
65
+ source: puter.appInstanceID,
55
66
  target,
56
67
  }).info(`AppConnection created to ${target}`, this);
57
68
 
@@ -232,7 +243,7 @@ class UI extends EventListener {
232
243
  return ret;
233
244
  };
234
245
 
235
- constructor (context, { appInstanceID, parentInstanceID }) {
246
+ constructor (puter, { appInstanceID, parentInstanceID }) {
236
247
  const eventNames = [
237
248
  'localeChanged',
238
249
  'themeChanged',
@@ -240,12 +251,12 @@ class UI extends EventListener {
240
251
  ];
241
252
  super(eventNames);
242
253
  this.#eventNames = eventNames;
243
- this.context = context;
254
+ this.puter = puter;
244
255
  this.appInstanceID = appInstanceID;
245
256
  this.parentInstanceID = parentInstanceID;
246
- this.appID = context.appID;
247
- this.env = context.env;
248
- this.util = context.util;
257
+ this.appID = puter.appID;
258
+ this.env = puter.env;
259
+ this.util = puter.util;
249
260
 
250
261
  if ( this.env === 'app' ) {
251
262
  this.messageTarget = window.parent;
@@ -254,16 +265,12 @@ class UI extends EventListener {
254
265
  return;
255
266
  }
256
267
 
257
- // Context to pass to AppConnection instances
258
- this.context = this.context.sub({
259
- appInstanceID: this.appInstanceID,
260
- messageTarget: this.messageTarget,
261
- });
262
-
263
268
  if ( this.parentInstanceID ) {
264
- this.#parentAppConnection = new AppConnection(this.context, {
269
+ this.#parentAppConnection = new AppConnection(this.puter, {
265
270
  target: this.parentInstanceID,
266
271
  usesSDK: true,
272
+ messageTarget: this.messageTarget,
273
+ appInstanceID: this.appInstanceID,
267
274
  });
268
275
  }
269
276
 
@@ -535,7 +542,10 @@ class UI extends EventListener {
535
542
  }
536
543
  else if ( e.data.msg === 'connection' ) {
537
544
  e.data.usesSDK = true; // we can safely assume this
538
- const conn = AppConnection.from(e.data, this.context);
545
+ const conn = AppConnection.from(e.data, this.puter, {
546
+ messageTarget: this.messageTarget,
547
+ appInstanceID: this.appInstanceID,
548
+ });
539
549
  const accept = value => {
540
550
  this.messageTarget?.postMessage({
541
551
  $: 'connection-resp',
@@ -743,7 +753,7 @@ class UI extends EventListener {
743
753
  };
744
754
 
745
755
  showOpenFilePicker (options, callback) {
746
- const undefinedOnCancel = new putility.libs.promise.TeePromise();
756
+ const undefinedOnCancel = createDeferred();
747
757
  const resolveOnlyPromise = new Promise((resolve, reject) => {
748
758
  if ( ! globalThis.open ) {
749
759
  return reject('This API is not compatible in Web Workers.');
@@ -779,7 +789,7 @@ class UI extends EventListener {
779
789
  resolve(maybe_result);
780
790
  };
781
791
  });
782
- resolveOnlyPromise.undefinedOnCancel = undefinedOnCancel;
792
+ resolveOnlyPromise.undefinedOnCancel = undefinedOnCancel.promise;
783
793
  return resolveOnlyPromise;
784
794
  };
785
795
 
@@ -802,7 +812,7 @@ class UI extends EventListener {
802
812
  };
803
813
 
804
814
  showSaveFilePicker (content, suggestedName, type) {
805
- const undefinedOnCancel = new putility.libs.promise.TeePromise();
815
+ const undefinedOnCancel = createDeferred();
806
816
  const resolveOnlyPromise = new Promise((resolve, reject) => {
807
817
  if ( ! globalThis.open ) {
808
818
  return reject('This API is not compatible in Web Workers.');
@@ -870,7 +880,7 @@ class UI extends EventListener {
870
880
  };
871
881
  });
872
882
 
873
- resolveOnlyPromise.undefinedOnCancel = undefinedOnCancel;
883
+ resolveOnlyPromise.undefinedOnCancel = undefinedOnCancel.promise;
874
884
 
875
885
  return resolveOnlyPromise;
876
886
  };
@@ -1203,7 +1213,10 @@ class UI extends EventListener {
1203
1213
  },
1204
1214
  });
1205
1215
 
1206
- return AppConnection.from(app_info, this.context);
1216
+ return AppConnection.from(app_info, this.puter, {
1217
+ messageTarget: this.messageTarget,
1218
+ appInstanceID: this.appInstanceID,
1219
+ });
1207
1220
  };
1208
1221
 
1209
1222
  connectToInstance = async function connectToInstance (app_name) {
@@ -1214,7 +1227,10 @@ class UI extends EventListener {
1214
1227
  },
1215
1228
  });
1216
1229
 
1217
- return AppConnection.from(app_info, this.context);
1230
+ return AppConnection.from(app_info, this.puter, {
1231
+ messageTarget: this.messageTarget,
1232
+ appInstanceID: this.appInstanceID,
1233
+ });
1218
1234
  };
1219
1235
 
1220
1236
  parentApp () {
@@ -1,65 +0,0 @@
1
- import * as utils from '../utils.js';
2
- import putility from '@heyputer/putility';
3
- import { TeePromise } from '@heyputer/putility/src/libs/promise.js';
4
- import getAbsolutePathForApp from '../../modules/FileSystem/utils/getAbsolutePathForApp.js';
5
- import { TFilesystem } from './definitions.js';
6
-
7
- export class PuterAPIFilesystem extends putility.AdvancedBase {
8
- constructor ({ api_info }) {
9
- super();
10
- this.api_info = api_info;
11
- }
12
-
13
- static IMPLEMENTS = {
14
- [TFilesystem]: {
15
- stat: async function (options) {
16
- this.ensure_auth_();
17
- const tp = new TeePromise();
18
-
19
- const xhr = new utils.initXhr('/stat', this.api_info.APIOrigin, undefined, 'post', 'text/plain;actually=json');
20
- utils.setupXhrEventHandlers(xhr, undefined, undefined, tp.resolve.bind(tp), tp.reject.bind(tp));
21
-
22
- let dataToSend = {};
23
- if ( options.uid !== undefined ) {
24
- dataToSend.uid = options.uid;
25
- } else if ( options.path !== undefined ) {
26
- // If dirPath is not provided or it's not starting with a slash, it means it's a relative path
27
- // in that case, we need to prepend the app's root directory to it
28
- dataToSend.path = getAbsolutePathForApp(options.path);
29
- }
30
-
31
- dataToSend.return_subdomains = options.returnSubdomains;
32
- dataToSend.return_permissions = options.returnPermissions;
33
- dataToSend.return_versions = options.returnVersions;
34
- dataToSend.return_size = options.returnSize;
35
- dataToSend.auth_token = this.api_info.authToken;
36
-
37
- xhr.send(JSON.stringify(dataToSend));
38
-
39
- return await tp;
40
- },
41
- readdir: async function (options) {
42
- this.ensure_auth_();
43
- const tp = new TeePromise();
44
-
45
- const xhr = new utils.initXhr('/readdir', this.api_info.APIOrigin, undefined, 'post', 'text/plain;actually=json');
46
- utils.setupXhrEventHandlers(xhr, undefined, undefined, tp.resolve.bind(tp), tp.reject.bind(tp));
47
-
48
- xhr.send(JSON.stringify({ path: getAbsolutePathForApp(options.path), auth_token: this.api_info.authToken }));
49
-
50
- return await tp;
51
- },
52
- },
53
- };
54
-
55
- ensure_auth_ () {
56
- // TODO: remove reference to global 'puter'; get 'env' via context
57
- if ( !this.api_info.authToken && puter.env === 'web' ) {
58
- try {
59
- this.ui.authenticateWithPuter();
60
- } catch (e) {
61
- throw new Error('Authentication failed.');
62
- }
63
- }
64
- }
65
- }