hfs 0.46.1 → 0.47.0-alpha5

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,4 +1,4 @@
1
- import{g as OF,c as UF}from"./index-7f1741ba.js";function gF(sF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in sF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(sF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(sF,Symbol.toStringTag,{value:"Module"}))}var dF={exports:{}};/*
1
+ import{g as OF,c as UF}from"./index-0e105986.js";function gF(sF,hF){for(var eF=0;eF<hF.length;eF++){const tF=hF[eF];if(typeof tF!="string"&&!Array.isArray(tF)){for(const w in tF)if(w!=="default"&&!(w in sF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(sF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(sF,Symbol.toStringTag,{value:"Module"}))}var dF={exports:{}};/*
2
2
  * [js-sha512]{@link https://github.com/emn178/js-sha512}
3
3
  *
4
4
  * @version 0.8.0
@@ -4,9 +4,8 @@
4
4
  <meta charset="utf-8" />
5
5
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1.0, user-scalable=0" />
6
6
  <link href="/fontello.css" rel="stylesheet" />
7
- <script>HFS={}</script>
8
7
 
9
- <script type="module" crossorigin src="/assets/index-b49b8a16.js"></script>
8
+ <script type="module" crossorigin src="/assets/index-0e105986.js"></script>
10
9
  <link rel="stylesheet" href="/assets/index-f2f8fd6b.css">
11
10
  </head>
12
11
  <body>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hfs",
3
- "version": "0.46.1",
3
+ "version": "0.47.0-alpha5",
4
4
  "description": "HTTP File Server",
5
5
  "keywords": [
6
6
  "file server",
@@ -68,7 +68,7 @@
68
68
  "fast-glob": "^3.2.7",
69
69
  "find-process": "^1.4.7",
70
70
  "formidable": "^2.1.1",
71
- "fs-x-attributes": "^1.0.0",
71
+ "fs-x-attributes": "^1.0.2",
72
72
  "koa": "^2.13.4",
73
73
  "koa-compress": "^5.1.0",
74
74
  "koa-mount": "^4.0.0",
@@ -1,6 +1,6 @@
1
1
  exports.version = 1.0
2
2
  exports.description = "Show uploader info in list"
3
- exports.apiRequired = 8.23
3
+ exports.apiRequired = 8.3 // useBatch
4
4
  exports.frontend_js = "main.js"
5
5
 
6
6
  exports.configDialog = {
@@ -1,27 +1,26 @@
1
1
  "use strict";{
2
+ const { React } = HFS
2
3
  const { display } = HFS.getPluginConfig()
3
4
 
4
5
  HFS.onEvent('additionalEntryDetails', ({ entry }) =>
5
6
  HFS.h(Uploader, entry))
6
7
 
7
- const cache = {}
8
-
9
8
  function Uploader({ uri }) {
10
- const fullUri = location.pathname + uri
11
- const cachedData = cache[fullUri]
12
- const [freshData, error] = HFS.useApi(!cachedData && 'get_file_details', { uri: fullUri })
13
- if (!cachedData)
14
- cache[fullUri] = freshData || Boolean(error)
15
- const data = freshData || cachedData
16
- const text = HFS.React.useMemo(() => {
9
+ const { data } = HFS.useBatch(getDetails, uri)
10
+ const text = React.useMemo(() => {
17
11
  if (!data || data === true) return ''
18
12
  const { upload: x } = data
19
13
  return !x ? ''
20
14
  : display === 'user' ? x.username
21
15
  : display === 'ip' || !x.username ? x.ip
22
16
  : x.ip + ' (' + x.username + ')'
23
- })
17
+ }, [data])
24
18
  return text && HFS.h('span', { className: 'uploader', title: HFS.t`Uploader` },
25
19
  HFS.hIcon('upload'), ' ', text, ' – ')
26
20
  }
21
+
22
+ function getDetails(batched) {
23
+ return batched.length && HFS.apiCall('get_file_details', { uris: batched }).then(x => x.details)
24
+ }
25
+
27
26
  }
package/src/adminApis.js CHANGED
@@ -51,6 +51,7 @@ const util_1 = require("util");
51
51
  const customHtml_1 = require("./customHtml");
52
52
  const lodash_1 = __importDefault(require("lodash"));
53
53
  const update_1 = require("./update");
54
+ const consoleLog_1 = require("./consoleLog");
54
55
  exports.adminApis = {
55
56
  ...api_vfs_1.default,
56
57
  ...api_accounts_1.default,
@@ -73,8 +74,12 @@ exports.adminApis = {
73
74
  return {};
74
75
  },
75
76
  get_config: config_1.getWholeConfig,
76
- update: update_1.update,
77
- check_update: () => (0, update_1.getUpdate)().then(x => lodash_1.default.pick(x, 'name')),
77
+ update({ tag }) {
78
+ return (0, update_1.update)(tag);
79
+ },
80
+ async check_update() {
81
+ return { options: await (0, update_1.getUpdates)() };
82
+ },
78
83
  get_custom_html() {
79
84
  return {
80
85
  sections: Object.fromEntries([
@@ -101,7 +106,7 @@ exports.adminApis = {
101
106
  ...await (0, listen_1.getServerStatus)(),
102
107
  urls: (0, listen_1.getUrls)(),
103
108
  baseUrl: middlewares_1.baseUrl.get(),
104
- update: !(0, update_1.updateSupported)() ? false : await (0, update_1.localUpdateAvailable)() ? 'local' : true,
109
+ updatePossible: !(0, update_1.updateSupported)() ? false : await (0, update_1.localUpdateAvailable)() ? 'local' : true,
105
110
  proxyDetected: (0, middlewares_1.getProxyDetected)(),
106
111
  frpDetected: exports.localhostAdmin.get() && !(0, middlewares_1.getProxyDetected)()
107
112
  && (0, connections_1.getConnections)().every(misc_1.isLocalHost)
@@ -116,10 +121,20 @@ exports.adminApis = {
116
121
  await (0, promises_1.writeFile)(files.cert, cert);
117
122
  return files;
118
123
  },
119
- async get_log({ file = 'log' }, ctx) {
124
+ get_log({ file = 'log' }, ctx) {
120
125
  return new apiMiddleware_1.SendListReadable({
121
126
  bufferTime: 10,
122
- doAtStart(list) {
127
+ async doAtStart(list) {
128
+ if (file === 'console') {
129
+ for (const chunk of lodash_1.default.chunk(consoleLog_1.consoleLog, 1000)) { // avoid occupying the thread too long
130
+ for (const x of chunk)
131
+ list.add(x);
132
+ await (0, misc_1.wait)(0);
133
+ }
134
+ list.ready();
135
+ events_1.default.on('console', x => list.add(x));
136
+ return;
137
+ }
123
138
  const logger = log_1.loggers.find(l => l.name === file);
124
139
  if (!logger)
125
140
  return list.error(const_1.HTTP_NOT_FOUND, true);
@@ -39,7 +39,7 @@ const file_list = async ({ uri, offset, limit, search, c, sse }, ctx) => {
39
39
  return { ...props, list: await (0, misc_1.asyncGeneratorToArray)(produceEntries()) };
40
40
  setTimeout(async () => {
41
41
  if (can_upload || can_delete)
42
- list.custom({ props });
42
+ list.props(props);
43
43
  for await (const entry of produceEntries())
44
44
  list.add(entry);
45
45
  list.close();
@@ -103,12 +103,13 @@ async function nodeToDirEntry(ctx, node) {
103
103
  const pr = node.can_read === vfs_1.WHO_NO_ONE && !(folder && filesInsideCould()) ? 'r'
104
104
  : !(0, vfs_1.hasPermission)(node, 'can_read', ctx) ? 'R'
105
105
  : '';
106
+ const pd = (0, vfs_1.hasPermission)(node, 'can_delete', ctx) ? 'd' : '';
106
107
  return {
107
108
  n: name + (folder ? '/' : ''),
108
109
  c: ctime,
109
110
  m: Math.abs(+mtime - +ctime) < 1000 ? undefined : mtime,
110
111
  s: folder ? undefined : st.size,
111
- p: (pr + pl) || undefined
112
+ p: (pr + pl + pd) || undefined
112
113
  };
113
114
  }
114
115
  catch (_a) {
@@ -26,47 +26,47 @@ const apis = {
26
26
  return { result: Boolean(c) };
27
27
  },
28
28
  get_connections({}, ctx) {
29
- const list = new apiMiddleware_1.SendListReadable({ addAtStart: (0, connections_1.getConnections)().map(c => serializeConnection(c)) });
30
- const throttledUpdate = lodash_1.default.throttle(update, 1000 / 20); // try to avoid clogging with updates
31
- const state = Symbol('state'); // undefined=added, Timeout=add-pending, false=removed
29
+ const sent = Symbol('sent');
30
+ const list = new apiMiddleware_1.SendListReadable({
31
+ addAtStart: (0, connections_1.getConnections)().map(c => !ignore(c) && (c[sent] = serializeConnection(c))).filter(Boolean),
32
+ onEnd() {
33
+ for (const c of (0, connections_1.getConnections)())
34
+ delete c[sent];
35
+ }
36
+ });
32
37
  list.props({ you: ctx.ip });
33
38
  return list.events(ctx, {
34
39
  connection(conn) {
35
- conn[state] = setTimeout(() => add(conn), 100);
40
+ if (ignore(conn))
41
+ return;
42
+ list.add(conn[sent] = serializeConnection(conn));
36
43
  },
37
44
  connectionClosed(conn) {
38
- if (cancel(conn))
45
+ if (ignore(conn))
39
46
  return;
40
47
  list.remove(getConnAddress(conn));
41
- conn[state] = false;
48
+ delete conn[sent];
42
49
  },
43
50
  connectionUpdated(conn, change) {
44
- if (!change.ctx)
45
- return throttledUpdate(conn, change);
46
- Object.assign(change, fromCtx(change.ctx));
47
- change.ctx = undefined;
48
- if (!add(conn))
49
- throttledUpdate(conn, change);
51
+ if (ignore(conn) || ignore(change) || !conn[sent])
52
+ return;
53
+ if (change.ctx) {
54
+ Object.assign(change, fromCtx(change.ctx));
55
+ change.ctx = undefined;
56
+ }
57
+ if (change.opProgress)
58
+ change.opProgress = lodash_1.default.round(change.opProgress, 3);
59
+ // avoid sending non-changes
60
+ const last = conn[sent];
61
+ for (const [k, v] of (0, misc_1.typedEntries)(change))
62
+ if (v === last[k])
63
+ delete change[k];
64
+ if (lodash_1.default.isEmpty(change))
65
+ return;
66
+ Object.assign(last, change);
67
+ list.update(getConnAddress(conn), change);
50
68
  },
51
69
  });
52
- function add(conn) {
53
- if (!cancel(conn))
54
- return;
55
- list.add(serializeConnection(conn));
56
- return true;
57
- }
58
- function cancel(conn) {
59
- if (!conn[state])
60
- return;
61
- clearTimeout(conn[state]);
62
- conn[state] = undefined;
63
- return true;
64
- }
65
- function update(conn, change) {
66
- if (conn[state] === false)
67
- return;
68
- list.update(getConnAddress(conn), change);
69
- }
70
70
  function serializeConnection(conn) {
71
71
  var _a;
72
72
  const { socket, started, secure } = conn;
@@ -99,13 +99,16 @@ const apis = {
99
99
  inSpeed: throttler_1.totalInSpeed,
100
100
  got: throttler_1.totalGot,
101
101
  sent: throttler_1.totalSent,
102
- connections: (0, connections_1.getConnections)().length
102
+ connections: lodash_1.default.sumBy((0, connections_1.getConnections)(), x => ignore(x) ? 0 : 1),
103
103
  };
104
104
  await (0, misc_1.wait)(1000);
105
105
  }
106
106
  },
107
107
  };
108
108
  exports.default = apis;
109
+ function ignore(conn) {
110
+ return false; //conn.socket && isLocalHost(conn)
111
+ }
109
112
  function getConnAddress(conn) {
110
113
  return {
111
114
  ip: conn.ip,
package/src/api.vfs.js CHANGED
@@ -78,7 +78,7 @@ const apis = {
78
78
  const n = await urlToNodeOriginal(uri);
79
79
  if (!n)
80
80
  return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND, 'path not found');
81
- props = pickProps(props, ['name', 'source', 'masks', 'default', 'accept', 'propagate', ...vfs_1.PERM_KEYS]); // sanitize
81
+ props = pickProps(props, ['name', 'source', 'masks', 'default', 'accept', ...vfs_1.PERM_KEYS]); // sanitize
82
82
  if (props.name && props.name !== (0, vfs_1.getNodeName)(n)) {
83
83
  const parent = await urlToNodeOriginal((0, path_1.dirname)(uri));
84
84
  if ((_a = parent === null || parent === void 0 ? void 0 : parent.children) === null || _a === void 0 ? void 0 : _a.find(x => (0, vfs_1.getNodeName)(x) === props.name))
@@ -151,44 +151,47 @@ const apis = {
151
151
  path = (0, path_1.dirname)(path);
152
152
  return { path };
153
153
  },
154
- async *ls({ path, files = true, fileMask }, ctx) {
155
- if (!path && const_1.IS_WINDOWS) {
156
- try {
157
- for (const n of await (0, util_os_1.getDrives)())
158
- yield { add: { n, k: 'd' } };
159
- }
160
- catch (error) {
161
- console.debug(error);
162
- }
163
- return;
164
- }
165
- try {
166
- const matching = (0, misc_1.makeMatcher)(fileMask);
167
- path = (0, misc_1.isWindowsDrive)(path) ? path + '\\' : (0, path_1.resolve)(path || '/');
168
- for await (const [name, isDir] of (0, misc_1.dirStream)(path)) {
169
- if (ctx.req.aborted)
154
+ ls({ path, files = true, fileMask }, ctx) {
155
+ return new apiMiddleware_1.SendListReadable({
156
+ async doAtStart(list) {
157
+ if (!path && const_1.IS_WINDOWS) {
158
+ try {
159
+ for (const n of await (0, util_os_1.getDrives)())
160
+ list.add({ n, k: 'd' });
161
+ }
162
+ catch (error) {
163
+ console.debug(error);
164
+ }
170
165
  return;
166
+ }
171
167
  try {
172
- if (!isDir)
173
- if (!files || fileMask && !matching(name))
174
- continue;
175
- const stats = await (0, promises_1.stat)((0, path_1.join)(path, name));
176
- yield {
177
- add: {
178
- n: name,
179
- s: stats.size,
180
- c: stats.ctime,
181
- m: stats.mtime,
182
- k: isDir ? 'd' : undefined,
168
+ const matching = (0, misc_1.makeMatcher)(fileMask);
169
+ path = (0, misc_1.isWindowsDrive)(path) ? path + '\\' : (0, path_1.resolve)(path || '/');
170
+ for await (const [name, isDir] of (0, misc_1.dirStream)(path)) {
171
+ if (ctx.req.aborted)
172
+ return;
173
+ if (!isDir)
174
+ if (!files || fileMask && !matching(name))
175
+ continue;
176
+ try {
177
+ const stats = await (0, promises_1.stat)((0, path_1.join)(path, name));
178
+ list.add({
179
+ n: name,
180
+ s: stats.size,
181
+ c: stats.ctime,
182
+ m: stats.mtime,
183
+ k: isDir ? 'd' : undefined,
184
+ });
183
185
  }
184
- };
186
+ catch (_a) { } // just ignore entries we can't stat
187
+ }
188
+ list.close();
189
+ }
190
+ catch (e) {
191
+ list.error(e.code || e.message || String(e), true);
185
192
  }
186
- catch (_a) { } // just ignore entries we can't stat
187
193
  }
188
- }
189
- catch (e) {
190
- yield { error: e.code || e.message || String(e) };
191
- }
194
+ });
192
195
  }
193
196
  };
194
197
  exports.default = apis;
@@ -36,10 +36,16 @@ function apiMiddleware(apis) {
36
36
  let res;
37
37
  try {
38
38
  for (const [k, v] of Object.entries(params))
39
- if (k.startsWith('uri') && typeof v === 'string')
40
- params[k] = (0, misc_1.removeStarting)(ctx.state.revProxyPath, v);
39
+ if (k.startsWith('uri'))
40
+ if (typeof v === 'string')
41
+ fixUri(params, k);
42
+ else if (typeof (v === null || v === void 0 ? void 0 : v[0]) === 'string')
43
+ v.forEach((x, i) => fixUri(v, i));
41
44
  res = csrf && csrf !== params.csrf ? new ApiError(const_1.HTTP_UNAUTHORIZED, 'csrf')
42
45
  : await apiFun(params || {}, ctx);
46
+ function fixUri(o, k) {
47
+ o[k] = (0, misc_1.removeStarting)(ctx.state.revProxyPath, o[k]);
48
+ }
43
49
  }
44
50
  catch (e) {
45
51
  res = e;
@@ -69,18 +75,20 @@ function isAsyncGenerator(x) {
69
75
  return typeof (x === null || x === void 0 ? void 0 : x.next) === 'function';
70
76
  }
71
77
  class SendListReadable extends stream_1.Readable {
72
- constructor({ addAtStart, doAtStart, bufferTime } = {}) {
78
+ constructor({ addAtStart, doAtStart, bufferTime, onEnd } = {}) {
73
79
  super({ objectMode: true, read() { } });
74
80
  this.buffer = [];
75
81
  if (!bufferTime)
76
- bufferTime = 100;
82
+ bufferTime = 200;
77
83
  this.processBuffer = lodash_1.default.debounce(() => {
78
84
  this.push(this.buffer);
79
85
  this.buffer = [];
80
86
  }, bufferTime, { maxWait: bufferTime });
81
- this.on('end', () => this.destroy());
82
- if (doAtStart)
83
- setTimeout(() => doAtStart(this)); // work later, when list object has been received by Koa
87
+ this.on('end', () => {
88
+ onEnd === null || onEnd === void 0 ? void 0 : onEnd(this);
89
+ this.destroy();
90
+ });
91
+ setTimeout(() => doAtStart === null || doAtStart === void 0 ? void 0 : doAtStart(this)); // work later, when list object has been received by Koa
84
92
  if (addAtStart) {
85
93
  for (const x of addAtStart)
86
94
  this.add(x);
@@ -95,25 +103,45 @@ class SendListReadable extends stream_1.Readable {
95
103
  this.processBuffer();
96
104
  }
97
105
  add(rec) {
98
- this._push({ add: rec });
106
+ this._push(['add', rec]);
99
107
  }
100
- remove(key) {
101
- this._push({ remove: [key] });
108
+ remove(search) {
109
+ const match = lodash_1.default.matches(search);
110
+ const idx = lodash_1.default.findIndex(this.buffer, x => match(x[1]));
111
+ const found = this.buffer[idx];
112
+ const op = found === null || found === void 0 ? void 0 : found[0];
113
+ if (op === 'remove')
114
+ return;
115
+ if (found) {
116
+ this.buffer.splice(idx, 1);
117
+ if (op === 'add')
118
+ return;
119
+ }
120
+ this._push(['remove', search]);
102
121
  }
103
122
  update(search, change) {
104
- this._push({ update: [{ search, change }] });
123
+ if (lodash_1.default.isEmpty(change))
124
+ return;
125
+ const match = lodash_1.default.matches(search);
126
+ const found = lodash_1.default.find(this.buffer, x => match(x[1]));
127
+ const op = found === null || found === void 0 ? void 0 : found[0];
128
+ if (op === 'remove')
129
+ return;
130
+ if (op === 'add' || op === 'update')
131
+ return Object.assign(found[op === 'add' ? 1 : 2], change);
132
+ return this._push(['update', search, change]);
105
133
  }
106
134
  ready() {
107
- this._push('ready');
135
+ this._push(['ready']);
108
136
  }
109
137
  custom(data) {
110
138
  this._push(data);
111
139
  }
112
140
  props(props) {
113
- this._push({ props });
141
+ this._push(['props', props]);
114
142
  }
115
143
  error(msg, close = false, props) {
116
- this._push({ error: msg, ...props });
144
+ this._push(['error', msg, props]);
117
145
  this.lastError = msg;
118
146
  if (close)
119
147
  this.close();
package/src/commands.js CHANGED
@@ -111,8 +111,8 @@ const commands = {
111
111
  'check-update': {
112
112
  params: '',
113
113
  async cb() {
114
- const update = await (0, update_1.getUpdate)();
115
- if (update.name === const_1.VERSION)
114
+ const [update] = await (0, update_1.getUpdates)();
115
+ if (!update)
116
116
  throw "you already have the latest version: " + const_1.VERSION;
117
117
  console.log("new version available", update.name);
118
118
  }
package/src/config.js CHANGED
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  return (mod && mod.__esModule) ? mod : { "default": mod };
5
5
  };
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.saveConfigAsap = exports.setConfig = exports.getWholeConfig = exports.getConfig = exports.configKeyExists = exports.defineConfig = void 0;
7
+ exports.saveConfigAsap = exports.setConfig = exports.getWholeConfig = exports.getConfig = exports.configKeyExists = exports.defineConfig = exports.currentVersion = exports.versionToScalar = void 0;
8
8
  const events_1 = __importDefault(require("events"));
9
9
  const const_1 = require("./const");
10
10
  const watchLoad_1 = require("./watchLoad");
@@ -48,27 +48,30 @@ if (!(0, fs_1.existsSync)(filePath) && (0, fs_1.existsSync)(legacyPosition))
48
48
  catch (_b) { }
49
49
  }
50
50
  // takes a semver like 1.2.3-alpha1, but alpha and beta numbers must share the number progression
51
- const versionToScalar = lodash_1.default.memoize((ver) => {
52
- var _a;
53
- const [official, beta] = ver.split('-');
54
- const numbers = official.split('.').map(Number);
55
- if (numbers.length !== 3)
51
+ exports.versionToScalar = lodash_1.default.memoize((ver) => {
52
+ // this regexp is supposed to be resistant to optional leading "v" and an optional custom name after a space
53
+ const res = /^v?(\d+)\.(\d+)\.(\d+)(?:-\w+(\d+))?/.exec(ver);
54
+ if (!res)
56
55
  return NaN;
57
- const officialScalar = numbers.reduce((acc, x, i) => acc + x * 1000 ** (2 - i), 0); // 1000 gives 3 digits for each number
58
- const betaScalar = 1 / (beta && Number((_a = /\d+/.exec(beta)) === null || _a === void 0 ? void 0 : _a[0]) || Infinity); // beta tends to 0, while non-beta is 0
56
+ const [, a, b, c, beta] = res.map(Number);
57
+ const officialScalar = c + b * 1E3 + a * 1E6; // gives 3 digits for each number
58
+ const betaScalar = 1 / (1 + beta || Infinity); // beta tends to 0, while non-beta is 0. +1 to make it work even in case of alpha0
59
59
  return officialScalar - betaScalar;
60
60
  });
61
61
  class Version extends String {
62
62
  olderThan(otherVersion) {
63
- return versionToScalar(this.valueOf()) < versionToScalar(otherVersion);
63
+ return (0, exports.versionToScalar)(this.valueOf()) < (0, exports.versionToScalar)(otherVersion);
64
+ }
65
+ getScalar() {
66
+ return (0, exports.versionToScalar)(this.valueOf());
64
67
  }
65
68
  }
66
69
  const CONFIG_CHANGE_EVENT_PREFIX = 'new.';
67
- const currentVersion = new Version(const_1.VERSION);
70
+ exports.currentVersion = new Version(const_1.VERSION);
68
71
  const configVersion = defineConfig('version', const_1.VERSION, v => new Version(v));
69
72
  function defineConfig(k, defaultValue, compiler) {
70
73
  configProps[k] = { defaultValue };
71
- let compiled = compiler === null || compiler === void 0 ? void 0 : compiler(defaultValue, { version: currentVersion, defaultValue });
74
+ let compiled = compiler === null || compiler === void 0 ? void 0 : compiler(defaultValue, { version: exports.currentVersion, defaultValue });
72
75
  const ret = {
73
76
  key() {
74
77
  return k;
@@ -162,7 +165,7 @@ function setConfig(newCfg, save) {
162
165
  if (version !== const_1.VERSION) // be sure to save version
163
166
  (0, exports.saveConfigAsap)();
164
167
  function apply(k, newV, isDefault = false) {
165
- return setConfig1(k, newV, save === undefined, argCfg && k in argCfg || isDefault ? currentVersion : version);
168
+ return setConfig1(k, newV, save === undefined, argCfg && k in argCfg || isDefault ? exports.currentVersion : version);
166
169
  }
167
170
  }
168
171
  exports.setConfig = setConfig;
@@ -6,7 +6,6 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.updateConnection = exports.socket2connection = exports.getConnections = exports.newConnection = exports.normalizeIp = exports.Connection = void 0;
8
8
  const events_1 = __importDefault(require("./events"));
9
- const lodash_1 = __importDefault(require("lodash"));
10
9
  class Connection {
11
10
  constructor(socket) {
12
11
  this.socket = socket;
@@ -49,9 +48,9 @@ function socket2connection(socket) {
49
48
  }
50
49
  exports.socket2connection = socket2connection;
51
50
  function updateConnection(conn, change) {
52
- // if no change is detected, skip update. ctx is a special case
53
- if (!change.ctx && Object.entries(change).every(([k, v]) => lodash_1.default.isEqual(v, conn[k])))
54
- return;
51
+ var _a;
52
+ if (change.op)
53
+ (_a = change.opProgress) !== null && _a !== void 0 ? _a : (change.opProgress = change.opOffset || 0);
55
54
  Object.assign(conn, change);
56
55
  events_1.default.emit('connectionUpdated', conn, change);
57
56
  }
@@ -0,0 +1,17 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.consoleLog = void 0;
7
+ const events_1 = __importDefault(require("./events"));
8
+ exports.consoleLog = [];
9
+ for (const k of ['log', 'warn', 'error']) {
10
+ const original = console[k];
11
+ console[k] = (...args) => {
12
+ const rec = { ts: new Date(), k, msg: args.join(' ') };
13
+ exports.consoleLog.push(rec);
14
+ events_1.default.emit('console', rec);
15
+ return original(...args);
16
+ };
17
+ }
package/src/const.js CHANGED
@@ -27,7 +27,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
27
27
  return (mod && mod.__esModule) ? mod : { "default": mod };
28
28
  };
29
29
  Object.defineProperty(exports, "__esModule", { value: true });
30
- exports.APP_PATH = exports.IS_BINARY = exports.IS_WINDOWS = exports.HTTP_SERVER_ERROR = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_OK = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = exports.HFS_REPO = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.DAY = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.argv = void 0;
30
+ exports.APP_PATH = exports.IS_BINARY = exports.IS_WINDOWS = exports.HTTP_SERVER_ERROR = exports.HTTP_FAILED_DEPENDENCY = exports.HTTP_FOOL = exports.HTTP_RANGE_NOT_SATISFIABLE = exports.HTTP_PAYLOAD_TOO_LARGE = exports.HTTP_CONFLICT = exports.HTTP_NOT_ACCEPTABLE = exports.HTTP_METHOD_NOT_ALLOWED = exports.HTTP_NOT_FOUND = exports.HTTP_FORBIDDEN = exports.HTTP_UNAUTHORIZED = exports.HTTP_BAD_REQUEST = exports.HTTP_NOT_MODIFIED = exports.HTTP_TEMPORARY_REDIRECT = exports.HTTP_PARTIAL_CONTENT = exports.HTTP_NO_CONTENT = exports.HTTP_OK = exports.PLUGINS_PUB_URI = exports.API_URI = exports.ADMIN_URI = exports.FRONTEND_URI = exports.SPECIAL_URI = exports.HFS_REPO = exports.COMPATIBLE_API_VERSION = exports.API_VERSION = exports.DAY = exports.RUNNING_BETA = exports.VERSION = exports.BUILD_TIMESTAMP = exports.HFS_STARTED = exports.ORIGINAL_CWD = exports.DEV = exports.argv = void 0;
31
31
  const minimist_1 = __importDefault(require("minimist"));
32
32
  const fs = __importStar(require("fs"));
33
33
  const os_1 = require("os");
@@ -38,11 +38,12 @@ exports.DEV = process.env.DEV || exports.argv.dev ? 'DEV' : '';
38
38
  exports.ORIGINAL_CWD = process.cwd();
39
39
  exports.HFS_STARTED = new Date();
40
40
  const PKG_PATH = (0, path_1.join)(__dirname, '..', 'package.json');
41
- exports.BUILD_TIMESTAMP = "2023-07-08T18:00:25.802Z";
41
+ exports.BUILD_TIMESTAMP = "2023-07-23T12:24:58.087Z";
42
42
  const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
43
43
  exports.VERSION = pkg.version;
44
+ exports.RUNNING_BETA = exports.VERSION.includes('-');
44
45
  exports.DAY = 86400000;
45
- exports.API_VERSION = 8.23;
46
+ exports.API_VERSION = 8.3;
46
47
  exports.COMPATIBLE_API_VERSION = 1; // while changes in the api are not breaking, this number stays the same, otherwise it is made equal to API_VERSION
47
48
  exports.HFS_REPO = 'rejetto/hfs';
48
49
  exports.SPECIAL_URI = '/~/';
@@ -53,13 +53,19 @@ exports.frontEndApis = {
53
53
  }
54
54
  });
55
55
  },
56
- async get_file_details({ uri }, ctx) {
57
- apiAssertTypes({ string: { uri } });
58
- const node = await (0, vfs_1.urlToNode)(uri, ctx);
59
- if (!node)
60
- return new apiMiddleware_1.ApiError(const_1.HTTP_NOT_FOUND);
56
+ async get_file_details({ uris }, ctx) {
57
+ if (typeof (uris === null || uris === void 0 ? void 0 : uris[0]) !== 'string')
58
+ return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad uris');
61
59
  return {
62
- upload: node.source && await (0, upload_1.getUploadMeta)(node.source).catch(() => undefined)
60
+ details: Promise.all(uris.map(async (uri) => {
61
+ if (typeof uri !== 'string')
62
+ return false; // false means error
63
+ const node = await (0, vfs_1.urlToNode)(uri, ctx);
64
+ if (!node)
65
+ return false;
66
+ const upload = node.source && await (0, upload_1.getUploadMeta)(node.source).catch(() => undefined);
67
+ return upload && { upload };
68
+ }))
63
69
  };
64
70
  },
65
71
  async create_folder({ uri, name }, ctx) {
@@ -127,8 +133,9 @@ function notifyClient(ctx, name, data) {
127
133
  exports.notifyClient = notifyClient;
128
134
  const NOTIFICATION_PREFIX = 'notificationChannel:';
129
135
  function apiAssertTypes(paramsByType) {
130
- for (const [type, params] of Object.entries(paramsByType))
131
- for (const [name, val] of Object.entries(params))
132
- if (typeof val !== type)
133
- throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad ' + name);
136
+ for (const [types, params] of Object.entries(paramsByType))
137
+ for (const type of types.split('_'))
138
+ for (const [name, val] of Object.entries(params))
139
+ if (typeof val !== type)
140
+ throw new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, 'bad ' + name);
134
141
  }