mirror of
https://github.com/HeyPuter/puter.git
synced 2025-01-23 22:40:20 +08:00
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'.
This commit is contained in:
parent
6e5d5c2021
commit
480d996279
@ -13,7 +13,7 @@ import path from './lib/path.js';
|
||||
import Util from './modules/Util.js';
|
||||
import Drivers from './modules/Drivers.js';
|
||||
import putility from '@heyputer/putility';
|
||||
import { FSHostService } from './services/FSHost.js';
|
||||
import { FSRelayService } from './services/FSRelay.js';
|
||||
import { FilesystemService } from './services/Filesystem.js';
|
||||
import { APIAccessService } from './services/APIAccess.js';
|
||||
import { XDIncomingService } from './services/XDIncoming.js';
|
||||
@ -69,8 +69,10 @@ window.puter = (function() {
|
||||
// "modules" in puter.js are external interfaces for the developer
|
||||
this.modules_ = [];
|
||||
// "services" in puter.js are used by modules and may interact with each other
|
||||
const context = new putility.libs.context.Context();
|
||||
const context = new putility.libs.context.Context()
|
||||
.follow(this, ['env', 'util']);
|
||||
this.services = new putility.system.ServiceManager({ context });
|
||||
this.context = context;
|
||||
context.services = this.services;
|
||||
|
||||
// Holds the query parameters found in the current URL
|
||||
@ -148,12 +150,12 @@ window.puter = (function() {
|
||||
this.APIOrigin = 'https://api.' + URLParams.get('puter.domain');
|
||||
}
|
||||
|
||||
this.services.register('no-puter-yet', NoPuterYetService);
|
||||
this.services.register('filesystem', FilesystemService);
|
||||
this.services.register('api-access', APIAccessService);
|
||||
this.services.register('xd-incoming', XDIncomingService);
|
||||
if ( this.env !== 'app' ) {
|
||||
this.services.register('no-puter-yet', NoPuterYetService);
|
||||
this.services.register('filesystem', FilesystemService);
|
||||
this.services.register('api-access', APIAccessService);
|
||||
this.services.register('xd-incoming', XDIncomingService);
|
||||
// this.services.register('fs-host', FSHostService);
|
||||
this.services.register('fs-relay', FSRelayService);
|
||||
}
|
||||
|
||||
// When api-access is initialized, bind `.authToken` and
|
||||
@ -162,15 +164,18 @@ window.puter = (function() {
|
||||
await this.services.wait_for_init(['api-access']);
|
||||
const svc_apiAccess = this.services.get('api-access');
|
||||
|
||||
svc_apiAccess.authToken = this.authToken;
|
||||
svc_apiAccess.APIOrigin = this.APIOrigin;
|
||||
['authToken', 'APIOrigin'].forEach(key => {
|
||||
Object.defineProperty(this, key, {
|
||||
svc_apiAccess.auth_token = this.authToken;
|
||||
svc_apiAccess.api_origin = this.APIOrigin;
|
||||
[
|
||||
['authToken','auth_token'],
|
||||
['APIOrigin','api_origin'],
|
||||
].forEach(([k1,k2]) => {
|
||||
Object.defineProperty(this, k1, {
|
||||
get () {
|
||||
return svc_apiAccess[key];
|
||||
return svc_apiAccess[k2];
|
||||
},
|
||||
set (v) {
|
||||
svc_apiAccess[key] = v;
|
||||
svc_apiAccess[k2] = v;
|
||||
return true;
|
||||
}
|
||||
});
|
||||
@ -243,7 +248,7 @@ window.puter = (function() {
|
||||
new OS(this.authToken, this.APIOrigin, this.appID, this.env));
|
||||
// FileSystem
|
||||
this.registerModule('fs',
|
||||
new PuterJSFileSystemModule(this.authToken, this.APIOrigin, this.appID, this.env));
|
||||
new PuterJSFileSystemModule(this.authToken, this.APIOrigin, this.appID, this.context));
|
||||
// UI
|
||||
this.registerModule('ui',
|
||||
new UI(this.appInstanceID, this.parentInstanceID, this.appID, this.env, this.util));
|
||||
|
@ -1,7 +1,7 @@
|
||||
import * as utils from '../../lib/utils.js';
|
||||
import * as utils from '../utils.js';
|
||||
import putility from "@heyputer/putility";
|
||||
import { TeePromise } from "@heyputer/putility/src/libs/promise";
|
||||
import getAbsolutePathForApp from './utils/getAbsolutePathForApp.js';
|
||||
import getAbsolutePathForApp from '../../modules/FileSystem/utils/getAbsolutePathForApp.js';
|
||||
import { TFilesystem } from './definitions.js';
|
||||
|
||||
export class PuterAPIFilesystem extends putility.AdvancedBase {
|
@ -1,7 +1,7 @@
|
||||
import putility from "@heyputer/putility";
|
||||
import { RWLock } from "@heyputer/putility/src/libs/promise";
|
||||
import { ProxyFilesystem, TFilesystem } from "./definitions";
|
||||
import { uuidv4 } from "../../lib/utils";
|
||||
import { uuidv4 } from "../utils";
|
||||
|
||||
export const ROOT_UUID = '00000000-0000-0000-0000-000000000000';
|
||||
const TTL = 5 * 1000;
|
40
src/puter-js/src/lib/filesystem/PostMessageFS.js
Normal file
40
src/puter-js/src/lib/filesystem/PostMessageFS.js
Normal file
@ -0,0 +1,40 @@
|
||||
import putility from "@heyputer/putility";
|
||||
import { TFilesystem } from "./definitions";
|
||||
|
||||
const example = {
|
||||
"id": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
|
||||
"uid": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
|
||||
"is_dir": true,
|
||||
"immutable": true,
|
||||
"name": "Test",
|
||||
};
|
||||
|
||||
export class PostMessageFilesystem extends putility.AdvancedBase {
|
||||
constructor ({ rpc, messageTarget }) {
|
||||
super();
|
||||
this.rpc = rpc;
|
||||
this.messageTarget = messageTarget;
|
||||
}
|
||||
static IMPLEMENTS = {
|
||||
[TFilesystem]: {
|
||||
stat: async function (o) {
|
||||
return example;
|
||||
},
|
||||
readdir: async function (o) {
|
||||
const tp = new putility.libs.promise.TeePromise();
|
||||
const $callback = this.rpc.registerCallback((result) => {
|
||||
tp.resolve(result);
|
||||
});
|
||||
// return [example];
|
||||
this.messageTarget.postMessage({
|
||||
$: 'puter-fs',
|
||||
$callback,
|
||||
op: 'readdir',
|
||||
args: o,
|
||||
}, '*');
|
||||
|
||||
return await tp;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -13,10 +13,10 @@ import sign from "./operations/sign.js";
|
||||
// Why is this called deleteFSEntry instead of just delete? because delete is
|
||||
// a reserved keyword in javascript
|
||||
import deleteFSEntry from "./operations/deleteFSEntry.js";
|
||||
import { ProxyFilesystem, TFilesystem } from './definitions.js';
|
||||
import { ProxyFilesystem, TFilesystem } from '../../lib/filesystem/definitions.js';
|
||||
import { AdvancedBase } from '../../../../putility/index.js';
|
||||
import { CachedFilesystem } from './CacheFS.js';
|
||||
import { PuterAPIFilesystem } from './APIFS.js';
|
||||
import { CachedFilesystem } from '../../lib/filesystem/CacheFS.js';
|
||||
import { PuterAPIFilesystem } from '../../lib/filesystem/APIFS.js';
|
||||
|
||||
export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
|
||||
@ -38,14 +38,16 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
positional: ['path'],
|
||||
firstarg_options: true,
|
||||
async fn (parameters) {
|
||||
return this.filesystem.stat(parameters);
|
||||
const svc_fs = await this.context.services.aget('filesystem');
|
||||
return svc_fs.filesystem.stat(parameters);
|
||||
}
|
||||
},
|
||||
readdir: {
|
||||
positional: ['path'],
|
||||
firstarg_options: true,
|
||||
fn (parameters) {
|
||||
return this.filesystem.readdir(parameters);
|
||||
async fn (parameters) {
|
||||
const svc_fs = await this.context.services.aget('filesystem');
|
||||
return svc_fs.filesystem.readdir(parameters);
|
||||
}
|
||||
},
|
||||
}
|
||||
@ -59,11 +61,12 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
* @param {string} APIOrigin - Origin of the API server. Used to build the API endpoint URLs.
|
||||
* @param {string} appID - ID of the app to use.
|
||||
*/
|
||||
constructor (authToken, APIOrigin, appID) {
|
||||
constructor (authToken, APIOrigin, appID, context) {
|
||||
super();
|
||||
this.authToken = authToken;
|
||||
this.APIOrigin = APIOrigin;
|
||||
this.appID = appID;
|
||||
this.context = context;
|
||||
// Connect socket.
|
||||
this.initializeSocket();
|
||||
|
||||
@ -76,21 +79,6 @@ export class PuterJSFileSystemModule extends AdvancedBase {
|
||||
Object.defineProperty(api_info, 'APIOrigin', {
|
||||
get: () => this.APIOrigin,
|
||||
});
|
||||
|
||||
// Construct the decorator chain for the client-side filesystem.
|
||||
this.fs_nocache_ = new PuterAPIFilesystem({ api_info }).as(TFilesystem);
|
||||
this.fs_cache_ = new CachedFilesystem({ delegate: this.fs_nocache_ }).as(TFilesystem);
|
||||
// this.filesystem = this.fs_nocache;
|
||||
this.fs_proxy_ = new ProxyFilesystem({ delegate: this.fs_nocache_ });
|
||||
this.filesystem = this.fs_proxy_.as(TFilesystem);
|
||||
// this.fs_proxy_.delegate = this.fs_cache_;
|
||||
}
|
||||
|
||||
cache_on () {
|
||||
this.fs_proxy_.delegate = this.fs_cache_;
|
||||
}
|
||||
cache_off () {
|
||||
this.fs_proxy_.delegate = this.fs_nocache_;
|
||||
}
|
||||
|
||||
|
||||
|
@ -11,7 +11,7 @@ export class APIAccessService extends putility.concepts.Service {
|
||||
|
||||
static PROPERTIES = {
|
||||
auth_token: {
|
||||
post_set () {
|
||||
post_set (v) {
|
||||
this.as(TTopics).pub('update');
|
||||
}
|
||||
},
|
||||
@ -21,4 +21,24 @@ export class APIAccessService extends putility.concepts.Service {
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: inconsistent! Update all dependents.
|
||||
get_api_info () {
|
||||
const self = this;
|
||||
const o = {};
|
||||
[
|
||||
['authToken','auth_token'],
|
||||
['APIOrigin','api_origin'],
|
||||
].forEach(([k1,k2]) => {
|
||||
Object.defineProperty(o, k1, {
|
||||
get () {
|
||||
return self[k2];
|
||||
},
|
||||
set (v) {
|
||||
return self;
|
||||
}
|
||||
});
|
||||
});
|
||||
return o;
|
||||
}
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
import putility from '@heyputer/putility';
|
||||
|
||||
export class FSHostService extends putility.concepts.Service {
|
||||
async _init () {
|
||||
//
|
||||
}
|
||||
}
|
20
src/puter-js/src/services/FSRelay.js
Normal file
20
src/puter-js/src/services/FSRelay.js
Normal file
@ -0,0 +1,20 @@
|
||||
import putility from '@heyputer/putility';
|
||||
|
||||
const example = {
|
||||
"id": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
|
||||
"uid": "f485f1ba-de07-422c-8c4b-c2da057d4a44",
|
||||
"is_dir": true,
|
||||
"immutable": true,
|
||||
"name": "FromParentWindow",
|
||||
};
|
||||
|
||||
export class FSRelayService extends putility.concepts.Service {
|
||||
async _init () {
|
||||
const services = this._.context.services;
|
||||
const util = this._.context.util;
|
||||
const svc_xdIncoming = services.get('xd-incoming');
|
||||
svc_xdIncoming.register_tagged_listener('puter-fs', event => {
|
||||
util.rpc.send(event.source, event.data.$callback, [example]);
|
||||
});
|
||||
}
|
||||
}
|
@ -1,4 +1,9 @@
|
||||
import putility from "@heyputer/putility";
|
||||
import { PuterAPIFilesystem } from "../lib/filesystem/APIFS";
|
||||
import { CachedFilesystem } from "../lib/filesystem/CacheFS";
|
||||
import { ProxyFilesystem, TFilesystem } from "../lib/filesystem/definitions";
|
||||
import io from '../lib/socket.io/socket.io.esm.min.js';
|
||||
import { PostMessageFilesystem } from "../lib/filesystem/PostMessageFS.js";
|
||||
|
||||
export class FilesystemService extends putility.concepts.Service {
|
||||
static PROPERTIES = {
|
||||
@ -23,9 +28,44 @@ export class FilesystemService extends putility.concepts.Service {
|
||||
|
||||
_init () {
|
||||
console.log('does this init get called');
|
||||
|
||||
const env = this._.context.env;
|
||||
|
||||
if ( env === 'app' ) {
|
||||
// TODO: uncomment when relay is ready
|
||||
// this.init_app_fs_();
|
||||
|
||||
this.init_top_fs_();
|
||||
} else {
|
||||
this.init_top_fs_();
|
||||
}
|
||||
|
||||
this.initializeSocket();
|
||||
}
|
||||
|
||||
init_app_fs_ () {
|
||||
this.fs_nocache_ = new PostMessageFilesystem({
|
||||
messageTarget: window.parent,
|
||||
rpc: this._.context.util.rpc,
|
||||
}).as(TFilesystem);
|
||||
this.filesystem = this.fs_nocache_;
|
||||
}
|
||||
init_top_fs_ () {
|
||||
const api_info = this._.context.services.get('api-access').get_api_info();
|
||||
this.fs_nocache_ = new PuterAPIFilesystem({ api_info }).as(TFilesystem);
|
||||
this.fs_cache_ = new CachedFilesystem({ delegate: this.fs_nocache_ }).as(TFilesystem);
|
||||
// this.filesystem = this.fs_nocache;
|
||||
this.fs_proxy_ = new ProxyFilesystem({ delegate: this.fs_nocache_ });
|
||||
this.filesystem = this.fs_proxy_.as(TFilesystem);
|
||||
}
|
||||
|
||||
cache_on () {
|
||||
this.fs_proxy_.delegate = this.fs_cache_;
|
||||
}
|
||||
cache_off () {
|
||||
this.fs_proxy_.delegate = this.fs_nocache_;
|
||||
}
|
||||
|
||||
initializeSocket () {
|
||||
console.log('THIS IS RUNNING');
|
||||
if (this.socket) {
|
||||
|
@ -18,10 +18,27 @@ export class XDIncomingService extends putility.concepts.Service {
|
||||
fn(event, tp);
|
||||
if ( await tp ) return;
|
||||
}
|
||||
|
||||
const data = event.data;
|
||||
|
||||
const tag = data.$;
|
||||
if ( ! tag ) return;
|
||||
if ( ! this.tagged_listeners_[tag] ) return;
|
||||
|
||||
for ( const fn of this.tagged_listeners_[tag] ) {
|
||||
fn({ data, source: event.source });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
register_filter_listener (fn) {
|
||||
this.filter_listeners_.push(fn);
|
||||
}
|
||||
|
||||
register_tagged_listener (tag, fn) {
|
||||
if ( ! this.tagged_listeners_[tag] ) {
|
||||
this.tagged_listeners_[tag] = [];
|
||||
}
|
||||
this.tagged_listeners_[tag].push(fn);
|
||||
}
|
||||
}
|
||||
|
@ -77,6 +77,10 @@ class ServiceManager extends AdvancedBase {
|
||||
}
|
||||
return info.instance;
|
||||
}
|
||||
async aget (name) {
|
||||
await this.wait_for_init([name]);
|
||||
return this.get(name);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the specified list of services to be initialized.
|
||||
|
Loading…
Reference in New Issue
Block a user