imported code from webfuse-example

master
Falk Werner 4 years ago
parent 824234d708
commit 8e27567857

1
dist/webfuse.js vendored

@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.webfuse=t():e.webfuse=t()}(window,(function(){return function(e){var t={};function r(n){if(t[n])return t[n].exports;var s=t[n]={i:n,l:!1,exports:{}};return e[n].call(s.exports,s,s.exports,r),s.l=!0,s.exports}return r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var s in e)r.d(n,s,function(t){return e[t]}.bind(null,s));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t,r){"use strict";r.r(t),r.d(t,"BadState",(function(){return n})),r.d(t,"Provider",(function(){return s})),r.d(t,"FileMode",(function(){return i})),r.d(t,"Client",(function(){return o}));class n extends Error{static get BAD(){return 1}static get NOT_IMPLEMENTED(){return 2}static get TIMEOUT(){return 3}static get FORMAT(){return 4}static get NO_ENTRY(){return 101}static get NO_ACCESS(){return 102}constructor(e){super("Bad State"),this.code=e}}class s{async lookup(e,t){throw new n(n.NOT_IMPLEMENTED)}async getattr(e){throw new n(n.NOT_IMPLEMENTED)}async readdir(e){throw new n(n.NOT_IMPLEMENTED)}async open(e,t){throw new n(n.NOT_IMPLEMENTED)}close(e,t,r){}async read(e,t,r,s){throw new n(n.NOT_IMPLEMENTED)}}class i{static get ACCESS_MODE(){return 3}static get READONLY(){return 0}static get WRITEONLY(){return 1}static get READWRITE(){return 2}static get CREATE(){return 64}static get EXCLUSIVE(){return 128}static get TRUNKATE(){return 512}static get APPEND(){return 1024}}class o{static get _PROTOCOL(){return"webfuse-adapter-server"}constructor(e){this._provider={},this._pendingRequests={},this._id=0,this._ws=null,this.onopen=()=>{},this.onclose=()=>{},this.onerror=()=>{}}connectTo(e){this.disconnect(),this._ws=new WebSocket(e,o._PROTOCOL),this._ws.onopen=this.onopen,this._ws.onclose=this.onclose,this._ws.onerror=this.onerror,this._ws.onmessage=e=>{this._onmessage(e)}}_invokeRequest(e,t){this._id+=1;const r=this._id,n={method:e,params:t,id:r};return new Promise((e,t)=>{this._pendingRequests[r]={resolve:e,reject:t},this._ws.send(JSON.stringify(n))})}authenticate(e,t){return this._invokeRequest("authenticate",[e,t])}addProvider(e,t){this._provider[e]=t;const r={method:"add_filesystem",params:[e],id:23};this._ws.send(JSON.stringify(r))}disconnect(){this._ws&&(this._ws.close(),this._ws=null)}isConnected(){return this._ws&&this._ws.readyState===WebSocket.OPEN}_isRequest(e){return"string"==typeof e.method&&"params"in e}_isResponse(e){return"number"==typeof e.id&&("result"in e||"error"in e)}_removePendingRequest(e){let t=null;return e in this._pendingRequests&&(t=this._pendingRequests[e],Reflect.deleteProperty(this._pendingRequests,e)),t}_onmessage(e){try{const t=JSON.parse(e.data);if(this._isRequest(t)){const e=t.method,r=t.id,n=t.params;"number"==typeof r?this._invoke(e,n,r):this._notify(e,n)}else if(this._isResponse(t)){const e=t.id,r=t.result,n=t.error,s=this._removePendingRequest(e);s&&(r?s.resolve(r):s.reject(n))}}catch(e){}}_invoke(e,t,r){this._invokeAsync(e,t).then(e=>{const t={result:e,id:r};this._ws.send(JSON.stringify(t))}).catch(e=>{const t={error:{code:e.code||n.BAD},id:r};this._ws.send(JSON.stringify(t))})}async _invokeAsync(e,t){switch(e){case"lookup":return this._lookup(t);case"getattr":return this._getattr(t);case"readdir":return this._readdir(t);case"open":return this._open(t);case"read":return this._read(t);default:throw new n(n.NOT_IMPLEMENTED)}}_notify(e,t){switch(e){case"close":this._close(t);break;default:throw new Error(`Invalid method: "${e}"`)}}_getProvider(e){if(e in this._provider)return this._provider[e];throw new Error("Unknown provider")}async _lookup([e,t,r]){return this._getProvider(e).lookup(t,r)}async _getattr([e,t]){return this._getProvider(e).getattr(t)}async _readdir([e,t]){return this._getProvider(e).readdir(t)}async _open([e,t,r]){return this._getProvider(e).open(t,r)}_close([e,t,r,n]){this._getProvider(e).close(t,r,n)}async _read([e,t,r,s,i]){const o=this._getProvider(e),u=await o.read(t,r,s,i);if("string"==typeof u)return{data:btoa(u),format:"base64",count:u.length};throw new n(n.BAD)}}}])}));

1
dist/webufse.js vendored

@ -1 +0,0 @@
!function(e){var t={};function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}r.m=e,r.c=t,r.d=function(e,t,n){r.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},r.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},r.t=function(e,t){if(1&t&&(e=r(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(r.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)r.d(n,o,function(t){return e[t]}.bind(null,o));return n},r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,"a",t),t},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},r.p="",r(r.s=0)}([function(e,t){e.exports={}}]);

@ -1,17 +1,17 @@
{
"name": "webfuse",
"version": "0.0.1",
"version": "0.1.0",
"description": "Webfuse JavaScript Provider",
"main": "dist/webfuse.js",
"scripts": {
"build": "webpack --config webpack.config.js",
"test": "echo \"Error: no test specified\" && exit 1"
"test": "mocha test/**/*.js"
},
"repository": {
"type": "git",
"url": "git+https://github.com/falk-werner/webfuse-js.git"
},
"keywords": [],
"keywords": ["websockets", "libfuse", "fuse", "ws", "wss", "filesystem"],
"author": "Falk Werner",
"license": "MIT",
"bugs": {
@ -19,7 +19,12 @@
},
"homepage": "https://github.com/falk-werner/webfuse-js#readme",
"devDependencies": {
"chai": "^4.2.0",
"jsdom": "16.2.2",
"jsdom-global": "3.0.2",
"mocha": "^7.1.1",
"webpack": "^4.42.1",
"webpack-cli": "^3.3.11"
}
},
"dependencies": {}
}

@ -0,0 +1,15 @@
export class BadState extends Error {
static get BAD() { return 1; }
static get NOT_IMPLEMENTED() { return 2; }
static get TIMEOUT() { return 3; }
static get FORMAT() { return 4; }
static get NO_ENTRY() { return 101; }
static get NO_ACCESS() { return 102; }
constructor(code) {
super("Bad State");
this.code = code;
}
}

@ -0,0 +1,223 @@
import { BadState } from "./bad_state.js";
export class Client {
static get _PROTOCOL() { return "webfuse-adapter-server"; }
constructor(provider) {
this._provider = { };
this._pendingRequests = {};
this._id = 0;
this._ws = null;
this.onopen = () => { };
this.onclose = () => { };
this.onerror = () => { };
}
connectTo(url) {
this.disconnect();
this._ws = new WebSocket(url, Client._PROTOCOL);
this._ws.onopen = this.onopen;
this._ws.onclose = this.onclose;
this._ws.onerror = this.onerror;
this._ws.onmessage = (message) => {
this._onmessage(message);
};
}
_invokeRequest(method, params) {
this._id += 1;
const id = this._id;
const request = {method, params, id};
return new Promise((resolve, reject) => {
this._pendingRequests[id] = {resolve, reject};
this._ws.send(JSON.stringify(request));
});
}
authenticate(type, credentials) {
return this._invokeRequest("authenticate", [type, credentials]);
}
addProvider(name, provider) {
this._provider[name] = provider;
const request = {
"method": "add_filesystem",
"params": [name],
"id": 23
};
this._ws.send(JSON.stringify(request));
}
disconnect() {
if (this._ws) {
this._ws.close();
this._ws = null;
}
}
isConnected() {
return ((this._ws) && (this._ws.readyState === WebSocket.OPEN));
}
_isRequest(request) {
const method = request.method;
return (("string" === typeof(method)) && ("params" in request));
}
_isResponse(response) {
const id = response.id;
return (("number" === typeof(id)) && (("result" in response) || ("error" in response)));
}
_removePendingRequest(id) {
let result = null;
if (id in this._pendingRequests) {
result = this._pendingRequests[id];
Reflect.deleteProperty(this._pendingRequests, id);
}
return result;
}
_onmessage(message) {
try {
const data = JSON.parse(message.data);
if (this._isRequest(data)) {
const method = data.method;
const id = data.id;
const params = data.params;
if ("number" === typeof(id)) {
this._invoke(method, params, id);
}
else {
this._notify(method, params);
}
}
else if (this._isResponse(data)) {
const id = data.id;
const result = data.result;
const error = data.error;
const request = this._removePendingRequest(id);
if (request) {
if (result) {
request.resolve(result);
}
else {
request.reject(error);
}
}
}
}
catch (ex) {
// swallow
}
}
_invoke(method, params, id) {
this._invokeAsync(method, params).
then((result) => {
const response = { result, id };
this._ws.send(JSON.stringify(response));
}).
catch((ex) => {
const code = ex.code || BadState.BAD;
const response = {error: {code}, id};
this._ws.send(JSON.stringify(response));
});
}
async _invokeAsync(method, params) {
switch(method)
{
case "lookup":
return this._lookup(params);
case "getattr":
return this._getattr(params);
case "readdir":
return this._readdir(params);
case "open":
return this._open(params);
case "read":
return this._read(params);
default:
throw new BadState(BadState.NOT_IMPLEMENTED);
}
}
_notify(method, params) {
switch(method) {
case 'close':
this._close(params);
break;
default:
throw new Error(`Invalid method: "${method}"`);
}
}
_getProvider(name) {
if (name in this._provider) {
return this._provider[name];
}
else {
throw new Error('Unknown provider');
}
}
async _lookup([providerName, parent, name]) {
const provider = this._getProvider(providerName);
return provider.lookup(parent, name);
}
async _getattr([providerName, inode]) {
const provider = this._getProvider(providerName);
return provider.getattr(inode);
}
async _readdir([providerName, inode]) {
const provider = this._getProvider(providerName);
return provider.readdir(inode);
}
async _open([providerName, inode, mode]) {
const provider = this._getProvider(providerName);
return provider.open(inode, mode);
}
_close([providerName, inode, handle, mode]) {
const provider = this._getProvider(providerName);
provider.close(inode, handle, mode);
}
async _read([providerName, inode, handle, offset, length]) {
const provider = this._getProvider(providerName);
const data = await provider.read(inode, handle, offset, length);
if ("string" === typeof(data)) {
return {
data: btoa(data),
format: "base64",
count: data.length
};
}
else {
throw new BadState(BadState.BAD);
}
}
}

@ -0,0 +1,10 @@
export class FileMode {
static get ACCESS_MODE() { return 0x003; }
static get READONLY() { return 0x000; }
static get WRITEONLY() { return 0x001; }
static get READWRITE() { return 0x002; }
static get CREATE() { return 0x040; }
static get EXCLUSIVE() { return 0x080; }
static get TRUNKATE() { return 0x200; }
static get APPEND() { return 0x400; }
}

@ -1,4 +1,8 @@
import { BadState } from './bad_state.js'
import { Provider } from './provider.js'
import { FileMode } from './file_mode.js'
import { Client } from './client.js'
module.exports = {
export {
BadState, Provider, FileMode, Client
};

@ -0,0 +1,30 @@
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
import { BadState } from "./bad_state.js";
export class Provider {
async lookup(_parent, _name) {
throw new BadState(BadState.NOT_IMPLEMENTED);
}
async getattr(_inode) {
throw new BadState(BadState.NOT_IMPLEMENTED);
}
async readdir(_inode) {
throw new BadState(BadState.NOT_IMPLEMENTED);
}
async open(_inode, _mode) {
throw new BadState(BadState.NOT_IMPLEMENTED);
}
close(_inode, _handle, _mode) {
// empty
}
async read(_inode, _handle, _offset, _length) {
throw new BadState(BadState.NOT_IMPLEMENTED);
}
}

@ -0,0 +1 @@
-r jsdom-global/register

@ -0,0 +1,20 @@
const webfuse = require('../dist/webfuse')
const chai = require('chai');
const assert = chai.assert;
describe('Provider', function() {
it('lookup should throw not implemented error', function() {
const provider = new webfuse.Provider();
return provider.lookup(1, 'root').then(
() => Promise.reject(new Error("reject expected")),
err => {
assert.instanceOf(err, webfuse.BadState);
assert.equal(webfuse.BadState.NOT_IMPLEMENTED, err.code);
}
);
});
});

@ -4,7 +4,9 @@ module.exports = {
mode: 'production',
entry: './src/index.js',
output: {
filename: 'webufse.js',
filename: 'webfuse.js',
library: 'webfuse',
libraryTarget: 'umd',
path: path.resolve(__dirname, './dist')
}
};

Loading…
Cancel
Save