diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..810c656
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,3 @@
+/www/node_modules
+/www/package-lock.json
+/www/dist
\ No newline at end of file
diff --git a/Dockerfile b/Dockerfile
index dce2c25..fbf4fe2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -19,8 +19,6 @@ RUN set -x \
libconfig-dev \
libpam0g-dev
-COPY www /var/www
-
ARG PARALLELMFLAGS=-j2
ARG DUMB_INIT_VERSION=1.2.2
@@ -124,6 +122,25 @@ RUN set -x \
COPY webfused.conf /etc
+ARG NPM_VERSION=">=6.14.0 <7.0.0"
+ARG NODEJS_VERSION=12
+RUN set -x \
+ && apt update \
+ && apt upgrade -y \
+ && apt install --yes --no-install-recommends \
+ nodejs \
+ npm \
+ && npm install -g npm@"${NPM_VERSION}" \
+ && npm install -g n \
+ && n "${NODEJS_VERSION}"
+
+COPY www /usr/local/src/www
+RUN set -x \
+ && cd /usr/local/src/www \
+ && npm run build \
+ && mkdir -p /var/www \
+ && cp -r ./dist/. /var/www/
+
ARG USERID=1000
RUN set -x \
&& useradd -u "$USERID" -ms /bin/bash user
diff --git a/www/index.html b/www/index.html
deleted file mode 100644
index 0cb0918..0000000
--- a/www/index.html
+++ /dev/null
@@ -1,18 +0,0 @@
-
-
- WebFuse Example
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/www/js/package.json b/www/js/package.json
deleted file mode 100644
index 6c553ef..0000000
--- a/www/js/package.json
+++ /dev/null
@@ -1,11 +0,0 @@
-{
- "name": "webfuse-provider",
- "version": "0.2.0",
- "description": "Provider for websocket filesystem (webfuse)",
- "main": "startup.js",
- "scripts": {
- "test": "echo \"Error: no test specified\" && exit 1"
- },
- "author": "Falk Werner",
- "license": "LGPL-3.0"
-}
diff --git a/www/js/webfuse/bad_state.js b/www/js/webfuse/bad_state.js
deleted file mode 100644
index fdb05d9..0000000
--- a/www/js/webfuse/bad_state.js
+++ /dev/null
@@ -1,15 +0,0 @@
-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;
- }
-}
\ No newline at end of file
diff --git a/www/js/webfuse/client.js b/www/js/webfuse/client.js
deleted file mode 100644
index b046b3f..0000000
--- a/www/js/webfuse/client.js
+++ /dev/null
@@ -1,223 +0,0 @@
-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);
- }
- }
-}
\ No newline at end of file
diff --git a/www/js/webfuse/file_mode.js b/www/js/webfuse/file_mode.js
deleted file mode 100644
index b81a1ea..0000000
--- a/www/js/webfuse/file_mode.js
+++ /dev/null
@@ -1,10 +0,0 @@
-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; }
-}
\ No newline at end of file
diff --git a/www/js/webfuse/provider.js b/www/js/webfuse/provider.js
deleted file mode 100644
index b9c5dc2..0000000
--- a/www/js/webfuse/provider.js
+++ /dev/null
@@ -1,30 +0,0 @@
-/* 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);
- }
-}
diff --git a/www/package.json b/www/package.json
new file mode 100644
index 0000000..30a1097
--- /dev/null
+++ b/www/package.json
@@ -0,0 +1,34 @@
+{
+ "name": "webfuse-example",
+ "version": "0.1.0",
+ "description": "Example to demonstate webfuse",
+ "private": true,
+ "main": "./dist/webfuse-example.js",
+ "scripts": {
+ "build": "webpack --config webpack.config.js",
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/falk-werner/webfuse-example.git"
+ },
+ "keywords": [
+ "webfuse",
+ "websockets",
+ "libfuse",
+ "fuse",
+ "example"
+ ],
+ "author": "Falk Werner",
+ "license": "MIT",
+ "homepage": "https://github.com/falk-werner/webfuse-example#readme",
+ "devDependencies": {
+ "copy-webpack-plugin": "^5.1.1",
+ "html-webpack-plugin": "^4.2.0",
+ "webpack": "^4.42.1",
+ "webpack-cli": "^3.3.11"
+ },
+ "dependencies": {
+ "webfuse": "^0.1.0"
+ }
+}
diff --git a/www/js/.eslintrc.js b/www/src/.eslintrc.js
similarity index 100%
rename from www/js/.eslintrc.js
rename to www/src/.eslintrc.js
diff --git a/www/js/connection_view.js b/www/src/connection_view.js
similarity index 100%
rename from www/js/connection_view.js
rename to www/src/connection_view.js
diff --git a/www/js/filesystem_provider.js b/www/src/filesystem_provider.js
similarity index 95%
rename from www/js/filesystem_provider.js
rename to www/src/filesystem_provider.js
index 85ad287..f06a2e1 100644
--- a/www/js/filesystem_provider.js
+++ b/www/src/filesystem_provider.js
@@ -1,8 +1,6 @@
/* eslint no-unused-vars: ["error", { "argsIgnorePattern": "^_" }] */
-import { BadState } from "./webfuse/bad_state.js";
-import { FileMode } from "./webfuse/file_mode.js";
-import { Provider } from "./webfuse/provider.js";
+import { BadState, FileMode, Provider } from "webfuse";
export class FileSystemProvider extends Provider {
constructor(root) {
diff --git a/www/src/index.html b/www/src/index.html
new file mode 100644
index 0000000..ce665e3
--- /dev/null
+++ b/www/src/index.html
@@ -0,0 +1,20 @@
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+ <%= htmlWebpackPlugin.tags.headTags %>
+
+
+
+
+
+<%= htmlWebpackPlugin.tags.bodyTage %>
+
+
+
\ No newline at end of file
diff --git a/www/js/startup.js b/www/src/index.js
similarity index 94%
rename from www/js/startup.js
rename to www/src/index.js
index 284d229..0632653 100644
--- a/www/js/startup.js
+++ b/www/src/index.js
@@ -1,4 +1,4 @@
-import { Client } from "./webfuse/client.js";
+import { Client } from "webfuse";
import { ConnectionView } from "./connection_view.js";
import { FileSystemProvider } from "./filesystem_provider.js";
diff --git a/www/style/main.css b/www/src/style/main.css
similarity index 100%
rename from www/style/main.css
rename to www/src/style/main.css
diff --git a/www/webpack.config.js b/www/webpack.config.js
new file mode 100644
index 0000000..bb7234f
--- /dev/null
+++ b/www/webpack.config.js
@@ -0,0 +1,29 @@
+const path = require('path');
+const HtmlWebpackPlugin = require('html-webpack-plugin');
+const CopyWebpackPlugin = require('copy-webpack-plugin');
+
+module.exports = {
+ mode: 'production',
+ entry: './src/index.js',
+ output: {
+ filename: 'webfuse-example.js',
+ library: 'webfuse',
+ libraryTarget: 'umd',
+ path: path.resolve(__dirname, './dist')
+ },
+ plugins: [
+ new HtmlWebpackPlugin({
+ title: "Webfuse Example",
+ filename: "index.html",
+ template: "./src/index.html"
+ }),
+ new CopyWebpackPlugin([
+ { from: './src/style', to: 'style' }
+ ])
+ ],
+ resolve: {
+ alias: {
+ webfuse: "webfuse/src/index.js"
+ }
+ }
+};