Skip to content

Commit 480d996

Browse files
committed
dev: proof-of-concept for fs postMessage relay
Adds a filesystem relay service to GUI-side which currently reports an exmaple fsentry for /stat and /readdir. Added filesystem services for both sides. Moved filesystem implementations from src/modules to src/lib since they're being called by services now rather than modules. This functionality is effectively disabled unless src/puter-js/src/services/Filesystem.js is updated to use init_app_fs_() when the environment is 'app'.
1 parent 6e5d5c2 commit 480d996

File tree

12 files changed

+174
-47
lines changed

12 files changed

+174
-47
lines changed

src/puter-js/src/index.js

+19-14
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import path from './lib/path.js';
1313
import Util from './modules/Util.js';
1414
import Drivers from './modules/Drivers.js';
1515
import putility from '@heyputer/putility';
16-
import { FSHostService } from './services/FSHost.js';
16+
import { FSRelayService } from './services/FSRelay.js';
1717
import { FilesystemService } from './services/Filesystem.js';
1818
import { APIAccessService } from './services/APIAccess.js';
1919
import { XDIncomingService } from './services/XDIncoming.js';
@@ -69,8 +69,10 @@ window.puter = (function() {
6969
// "modules" in puter.js are external interfaces for the developer
7070
this.modules_ = [];
7171
// "services" in puter.js are used by modules and may interact with each other
72-
const context = new putility.libs.context.Context();
72+
const context = new putility.libs.context.Context()
73+
.follow(this, ['env', 'util']);
7374
this.services = new putility.system.ServiceManager({ context });
75+
this.context = context;
7476
context.services = this.services;
7577

7678
// Holds the query parameters found in the current URL
@@ -148,12 +150,12 @@ window.puter = (function() {
148150
this.APIOrigin = 'https://api.' + URLParams.get('puter.domain');
149151
}
150152

153+
this.services.register('no-puter-yet', NoPuterYetService);
154+
this.services.register('filesystem', FilesystemService);
155+
this.services.register('api-access', APIAccessService);
156+
this.services.register('xd-incoming', XDIncomingService);
151157
if ( this.env !== 'app' ) {
152-
this.services.register('no-puter-yet', NoPuterYetService);
153-
this.services.register('filesystem', FilesystemService);
154-
this.services.register('api-access', APIAccessService);
155-
this.services.register('xd-incoming', XDIncomingService);
156-
// this.services.register('fs-host', FSHostService);
158+
this.services.register('fs-relay', FSRelayService);
157159
}
158160

159161
// When api-access is initialized, bind `.authToken` and
@@ -162,15 +164,18 @@ window.puter = (function() {
162164
await this.services.wait_for_init(['api-access']);
163165
const svc_apiAccess = this.services.get('api-access');
164166

165-
svc_apiAccess.authToken = this.authToken;
166-
svc_apiAccess.APIOrigin = this.APIOrigin;
167-
['authToken', 'APIOrigin'].forEach(key => {
168-
Object.defineProperty(this, key, {
167+
svc_apiAccess.auth_token = this.authToken;
168+
svc_apiAccess.api_origin = this.APIOrigin;
169+
[
170+
['authToken','auth_token'],
171+
['APIOrigin','api_origin'],
172+
].forEach(([k1,k2]) => {
173+
Object.defineProperty(this, k1, {
169174
get () {
170-
return svc_apiAccess[key];
175+
return svc_apiAccess[k2];
171176
},
172177
set (v) {
173-
svc_apiAccess[key] = v;
178+
svc_apiAccess[k2] = v;
174179
return true;
175180
}
176181
});
@@ -243,7 +248,7 @@ window.puter = (function() {
243248
new OS(this.authToken, this.APIOrigin, this.appID, this.env));
244249
// FileSystem
245250
this.registerModule('fs',
246-
new PuterJSFileSystemModule(this.authToken, this.APIOrigin, this.appID, this.env));
251+
new PuterJSFileSystemModule(this.authToken, this.APIOrigin, this.appID, this.context));
247252
// UI
248253
this.registerModule('ui',
249254
new UI(this.appInstanceID, this.parentInstanceID, this.appID, this.env, this.util));

src/puter-js/src/modules/FileSystem/APIFS.js renamed to src/puter-js/src/lib/filesystem/APIFS.js

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import * as utils from '../../lib/utils.js';
1+
import * as utils from '../utils.js';
22
import putility from "@heyputer/putility";
33
import { TeePromise } from "@heyputer/putility/src/libs/promise";
4-
import getAbsolutePathForApp from './utils/getAbsolutePathForApp.js';
4+
import getAbsolutePathForApp from '../../modules/FileSystem/utils/getAbsolutePathForApp.js';
55
import { TFilesystem } from './definitions.js';
66

77
export class PuterAPIFilesystem extends putility.AdvancedBase {

src/puter-js/src/modules/FileSystem/CacheFS.js renamed to src/puter-js/src/lib/filesystem/CacheFS.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import putility from "@heyputer/putility";
22
import { RWLock } from "@heyputer/putility/src/libs/promise";
33
import { ProxyFilesystem, TFilesystem } from "./definitions";
4-
import { uuidv4 } from "../../lib/utils";
4+
import { uuidv4 } from "../utils";
55

66
export const ROOT_UUID = '00000000-0000-0000-0000-000000000000';
77
const TTL = 5 * 1000;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import putility from "@heyputer/putility";
2+
import { TFilesystem } from "./definitions";
3+
4+
const example = {
5+
"id": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
6+
"uid": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
7+
"is_dir": true,
8+
"immutable": true,
9+
"name": "Test",
10+
};
11+
12+
export class PostMessageFilesystem extends putility.AdvancedBase {
13+
constructor ({ rpc, messageTarget }) {
14+
super();
15+
this.rpc = rpc;
16+
this.messageTarget = messageTarget;
17+
}
18+
static IMPLEMENTS = {
19+
[TFilesystem]: {
20+
stat: async function (o) {
21+
return example;
22+
},
23+
readdir: async function (o) {
24+
const tp = new putility.libs.promise.TeePromise();
25+
const $callback = this.rpc.registerCallback((result) => {
26+
tp.resolve(result);
27+
});
28+
// return [example];
29+
this.messageTarget.postMessage({
30+
$: 'puter-fs',
31+
$callback,
32+
op: 'readdir',
33+
args: o,
34+
}, '*');
35+
36+
return await tp;
37+
}
38+
}
39+
}
40+
}

src/puter-js/src/modules/FileSystem/index.js

+10-22
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,10 @@ import sign from "./operations/sign.js";
1313
// Why is this called deleteFSEntry instead of just delete? because delete is
1414
// a reserved keyword in javascript
1515
import deleteFSEntry from "./operations/deleteFSEntry.js";
16-
import { ProxyFilesystem, TFilesystem } from './definitions.js';
16+
import { ProxyFilesystem, TFilesystem } from '../../lib/filesystem/definitions.js';
1717
import { AdvancedBase } from '../../../../putility/index.js';
18-
import { CachedFilesystem } from './CacheFS.js';
19-
import { PuterAPIFilesystem } from './APIFS.js';
18+
import { CachedFilesystem } from '../../lib/filesystem/CacheFS.js';
19+
import { PuterAPIFilesystem } from '../../lib/filesystem/APIFS.js';
2020

2121
export class PuterJSFileSystemModule extends AdvancedBase {
2222

@@ -38,14 +38,16 @@ export class PuterJSFileSystemModule extends AdvancedBase {
3838
positional: ['path'],
3939
firstarg_options: true,
4040
async fn (parameters) {
41-
return this.filesystem.stat(parameters);
41+
const svc_fs = await this.context.services.aget('filesystem');
42+
return svc_fs.filesystem.stat(parameters);
4243
}
4344
},
4445
readdir: {
4546
positional: ['path'],
4647
firstarg_options: true,
47-
fn (parameters) {
48-
return this.filesystem.readdir(parameters);
48+
async fn (parameters) {
49+
const svc_fs = await this.context.services.aget('filesystem');
50+
return svc_fs.filesystem.readdir(parameters);
4951
}
5052
},
5153
}
@@ -59,11 +61,12 @@ export class PuterJSFileSystemModule extends AdvancedBase {
5961
* @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
6062
* @param {string} appID - ID of the app to use.
6163
*/
62-
constructor (authToken, APIOrigin, appID) {
64+
constructor (authToken, APIOrigin, appID, context) {
6365
super();
6466
this.authToken = authToken;
6567
this.APIOrigin = APIOrigin;
6668
this.appID = appID;
69+
this.context = context;
6770
// Connect socket.
6871
this.initializeSocket();
6972

@@ -76,21 +79,6 @@ export class PuterJSFileSystemModule extends AdvancedBase {
7679
Object.defineProperty(api_info, 'APIOrigin', {
7780
get: () => this.APIOrigin,
7881
});
79-
80-
// Construct the decorator chain for the client-side filesystem.
81-
this.fs_nocache_ = new PuterAPIFilesystem({ api_info }).as(TFilesystem);
82-
this.fs_cache_ = new CachedFilesystem({ delegate: this.fs_nocache_ }).as(TFilesystem);
83-
// this.filesystem = this.fs_nocache;
84-
this.fs_proxy_ = new ProxyFilesystem({ delegate: this.fs_nocache_ });
85-
this.filesystem = this.fs_proxy_.as(TFilesystem);
86-
// this.fs_proxy_.delegate = this.fs_cache_;
87-
}
88-
89-
cache_on () {
90-
this.fs_proxy_.delegate = this.fs_cache_;
91-
}
92-
cache_off () {
93-
this.fs_proxy_.delegate = this.fs_nocache_;
9482
}
9583

9684

src/puter-js/src/services/APIAccess.js

+21-1
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ export class APIAccessService extends putility.concepts.Service {
1111

1212
static PROPERTIES = {
1313
auth_token: {
14-
post_set () {
14+
post_set (v) {
1515
this.as(TTopics).pub('update');
1616
}
1717
},
@@ -21,4 +21,24 @@ export class APIAccessService extends putility.concepts.Service {
2121
}
2222
},
2323
};
24+
25+
// TODO: inconsistent! Update all dependents.
26+
get_api_info () {
27+
const self = this;
28+
const o = {};
29+
[
30+
['authToken','auth_token'],
31+
['APIOrigin','api_origin'],
32+
].forEach(([k1,k2]) => {
33+
Object.defineProperty(o, k1, {
34+
get () {
35+
return self[k2];
36+
},
37+
set (v) {
38+
return self;
39+
}
40+
});
41+
});
42+
return o;
43+
}
2444
}

src/puter-js/src/services/FSHost.js

-7
This file was deleted.

src/puter-js/src/services/FSRelay.js

+20
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
import putility from '@heyputer/putility';
2+
3+
const example = {
4+
"id": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
5+
"uid": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
6+
"is_dir": true,
7+
"immutable": true,
8+
"name": "FromParentWindow",
9+
};
10+
11+
export class FSRelayService extends putility.concepts.Service {
12+
async _init () {
13+
const services = this._.context.services;
14+
const util = this._.context.util;
15+
const svc_xdIncoming = services.get('xd-incoming');
16+
svc_xdIncoming.register_tagged_listener('puter-fs', event => {
17+
util.rpc.send(event.source, event.data.$callback, [example]);
18+
});
19+
}
20+
}

src/puter-js/src/services/Filesystem.js

+40
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,9 @@
11
import putility from "@heyputer/putility";
2+
import { PuterAPIFilesystem } from "../lib/filesystem/APIFS";
3+
import { CachedFilesystem } from "../lib/filesystem/CacheFS";
4+
import { ProxyFilesystem, TFilesystem } from "../lib/filesystem/definitions";
5+
import io from '../lib/socket.io/socket.io.esm.min.js';
6+
import { PostMessageFilesystem } from "../lib/filesystem/PostMessageFS.js";
27

38
export class FilesystemService extends putility.concepts.Service {
49
static PROPERTIES = {
@@ -23,9 +28,44 @@ export class FilesystemService extends putility.concepts.Service {
2328

2429
_init () {
2530
console.log('does this init get called');
31+
32+
const env = this._.context.env;
33+
34+
if ( env === 'app' ) {
35+
// TODO: uncomment when relay is ready
36+
// this.init_app_fs_();
37+
38+
this.init_top_fs_();
39+
} else {
40+
this.init_top_fs_();
41+
}
42+
2643
this.initializeSocket();
2744
}
2845

46+
init_app_fs_ () {
47+
this.fs_nocache_ = new PostMessageFilesystem({
48+
messageTarget: window.parent,
49+
rpc: this._.context.util.rpc,
50+
}).as(TFilesystem);
51+
this.filesystem = this.fs_nocache_;
52+
}
53+
init_top_fs_ () {
54+
const api_info = this._.context.services.get('api-access').get_api_info();
55+
this.fs_nocache_ = new PuterAPIFilesystem({ api_info }).as(TFilesystem);
56+
this.fs_cache_ = new CachedFilesystem({ delegate: this.fs_nocache_ }).as(TFilesystem);
57+
// this.filesystem = this.fs_nocache;
58+
this.fs_proxy_ = new ProxyFilesystem({ delegate: this.fs_nocache_ });
59+
this.filesystem = this.fs_proxy_.as(TFilesystem);
60+
}
61+
62+
cache_on () {
63+
this.fs_proxy_.delegate = this.fs_cache_;
64+
}
65+
cache_off () {
66+
this.fs_proxy_.delegate = this.fs_nocache_;
67+
}
68+
2969
initializeSocket () {
3070
console.log('THIS IS RUNNING');
3171
if (this.socket) {

src/puter-js/src/services/XDIncoming.js

+17
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,27 @@ export class XDIncomingService extends putility.concepts.Service {
1818
fn(event, tp);
1919
if ( await tp ) return;
2020
}
21+
22+
const data = event.data;
23+
24+
const tag = data.$;
25+
if ( ! tag ) return;
26+
if ( ! this.tagged_listeners_[tag] ) return;
27+
28+
for ( const fn of this.tagged_listeners_[tag] ) {
29+
fn({ data, source: event.source });
30+
}
2131
});
2232
}
2333

2434
register_filter_listener (fn) {
2535
this.filter_listeners_.push(fn);
2636
}
37+
38+
register_tagged_listener (tag, fn) {
39+
if ( ! this.tagged_listeners_[tag] ) {
40+
this.tagged_listeners_[tag] = [];
41+
}
42+
this.tagged_listeners_[tag].push(fn);
43+
}
2744
}

src/putility/src/system/ServiceManager.js

+4
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ class ServiceManager extends AdvancedBase {
7777
}
7878
return info.instance;
7979
}
80+
async aget (name) {
81+
await this.wait_for_init([name]);
82+
return this.get(name);
83+
}
8084

8185
/**
8286
* Wait for the specified list of services to be initialized.

0 commit comments

Comments
 (0)