hfs 0.46.1 → 0.47.0-alpha6

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.
Files changed (50) hide show
  1. package/README.md +4 -4
  2. package/admin/assets/{index-35f6e3dc.css → index-20dd43f3.css} +1 -1
  3. package/admin/assets/index-d55dfed9.js +518 -0
  4. package/{frontend/assets/sha512-d9635c9d.js → admin/assets/sha512-9867267f.js} +1 -1
  5. package/admin/index.html +2 -2
  6. package/frontend/assets/index-3a32a9b9.css +1 -0
  7. package/frontend/assets/index-ad78cbad.js +116 -0
  8. package/{admin/assets/sha512-3412b98f.js → frontend/assets/sha512-4c1cbf45.js} +1 -1
  9. package/frontend/fontello.css +5 -2
  10. package/frontend/fontello.woff2 +0 -0
  11. package/frontend/index.html +2 -3
  12. package/package.json +2 -2
  13. package/plugins/download-counter/plugin.js +15 -7
  14. package/plugins/download-counter/public/main.js +1 -1
  15. package/plugins/list-uploader/plugin.js +1 -1
  16. package/plugins/list-uploader/public/main.js +9 -10
  17. package/plugins/vhosting/plugin.js +5 -2
  18. package/src/QuickZipStream.js +3 -0
  19. package/src/adminApis.js +20 -5
  20. package/src/api.auth.js +0 -3
  21. package/src/api.file_list.js +3 -2
  22. package/src/api.monitor.js +36 -33
  23. package/src/api.vfs.js +37 -34
  24. package/src/apiMiddleware.js +44 -15
  25. package/src/commands.js +2 -2
  26. package/src/config.js +16 -13
  27. package/src/connections.js +3 -4
  28. package/src/consoleLog.js +17 -0
  29. package/src/const.js +4 -3
  30. package/src/frontEndApis.js +17 -10
  31. package/src/github.js +1 -1
  32. package/src/index.js +3 -1
  33. package/src/langs/embedded.js +3 -1
  34. package/src/langs/hfs-lang-es.json +118 -0
  35. package/src/langs/hfs-lang-it.json +7 -5
  36. package/src/langs/hfs-lang-nl.json +118 -0
  37. package/src/langs/hfs-lang-ru.json +3 -3
  38. package/src/langs/hfs-lang-zh.json +25 -5
  39. package/src/log.js +5 -3
  40. package/src/middlewares.js +2 -2
  41. package/src/misc.js +5 -1
  42. package/src/perm.js +1 -1
  43. package/src/serveFile.js +3 -1
  44. package/src/throttler.js +2 -1
  45. package/src/update.js +45 -7
  46. package/src/util-http.js +8 -3
  47. package/src/vfs.js +36 -12
  48. package/admin/assets/index-7f1741ba.js +0 -517
  49. package/frontend/assets/index-b49b8a16.js +0 -94
  50. package/frontend/assets/index-f2f8fd6b.css +0 -1
package/src/serveFile.js CHANGED
@@ -68,9 +68,10 @@ async function serveFile(ctx, source, mime, content) {
68
68
  return ctx.body = content;
69
69
  const { size } = stats;
70
70
  const range = getRange(ctx, size);
71
- ctx.body = (0, fs_1.createReadStream)(source, range);
71
+ ctx.body = (0, fs_1.createReadStream)(source, range).on('end', () => (0, connections_1.updateConnection)(ctx.state.connection, { opProgress: 1 }));
72
72
  if (ctx.vfsNode)
73
73
  (0, connections_1.updateConnection)(ctx.state.connection, {
74
+ ctx,
74
75
  op: 'download',
75
76
  opTotal: stats.size,
76
77
  opOffset: range && (range.start / size),
@@ -106,6 +107,7 @@ function getRange(ctx, totalSize) {
106
107
  ctx.body = 'Requested Range Not Satisfiable';
107
108
  return;
108
109
  }
110
+ ctx.state.includesLastByte = end === max;
109
111
  ctx.status = const_1.HTTP_PARTIAL_CONTENT;
110
112
  ctx.set('Content-Range', `bytes ${start}-${isNaN(end) ? '' : end}/${isNaN(totalSize) ? '*' : totalSize}`);
111
113
  ctx.response.length = end - start + 1;
package/src/throttler.js CHANGED
@@ -44,7 +44,7 @@ const throttler = async (ctx, next) => {
44
44
  (0, connections_1.updateConnection)(conn, {
45
45
  outSpeed,
46
46
  sent: conn.socket.bytesWritten,
47
- opProgress: (conn.opOffset || 0) + ts.getBytesSent() / conn.opTotal,
47
+ opProgress: conn.opTotal && ((conn.opOffset || 0) + (ts.getBytesSent() - offset) / conn.opTotal),
48
48
  });
49
49
  /* in case this stream stands still for a while (before the end), we'll have neither 'sent' or 'close' events,
50
50
  * so who will take care to updateConnection? This artificial next-call will ensure just that */
@@ -67,6 +67,7 @@ const throttler = async (ctx, next) => {
67
67
  delete ip2group[ctx.ip];
68
68
  });
69
69
  const downloadTotal = ctx.response.length;
70
+ ctx.state.originalStream = ctx.body;
70
71
  ctx.body = ctx.body.pipe(ts);
71
72
  if (downloadTotal) // preserve this info
72
73
  ctx.response.length = downloadTotal;
package/src/update.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.update = exports.updateSupported = exports.localUpdateAvailable = exports.getUpdate = void 0;
7
+ exports.update = exports.updateSupported = exports.localUpdateAvailable = exports.getUpdates = void 0;
8
8
  const github_1 = require("./github");
9
9
  const const_1 = require("./const");
10
10
  const path_1 = require("path");
@@ -14,10 +14,45 @@ const fs_1 = require("fs");
14
14
  const plugins_1 = require("./plugins");
15
15
  const promises_1 = require("fs/promises");
16
16
  const open_1 = __importDefault(require("open"));
17
- async function getUpdate() {
18
- return (await (0, github_1.getRepoInfo)(const_1.HFS_REPO + '/releases?per_page=1'))[0];
17
+ const config_1 = require("./config");
18
+ const updateToBeta = (0, config_1.defineConfig)('update_to_beta', false);
19
+ async function getUpdates() {
20
+ const stable = await (0, github_1.getRepoInfo)(const_1.HFS_REPO + '/releases/latest');
21
+ const verStable = ver(stable);
22
+ const ret = await getBetas();
23
+ if (stable && (config_1.currentVersion.olderThan(stable.tag_name) || const_1.RUNNING_BETA)) // if we are running a beta, also offer the latest stable
24
+ ret.push(stable);
25
+ return ret;
26
+ function ver(x) {
27
+ return (0, config_1.versionToScalar)(x.name);
28
+ }
29
+ async function getBetas() {
30
+ if (!updateToBeta.get() && !const_1.RUNNING_BETA)
31
+ return [];
32
+ let page = 1;
33
+ const ret = [];
34
+ while (1) {
35
+ const per = 100;
36
+ const res = await (0, github_1.getRepoInfo)(const_1.HFS_REPO + `/releases?per_page=${per}&page=${page++}`);
37
+ if (!res.length)
38
+ break;
39
+ const curV = config_1.currentVersion.getScalar();
40
+ for (const x of res) {
41
+ if (!x.prerelease)
42
+ continue; // prerelease are all the end
43
+ const v = ver(x);
44
+ if (v <= verStable) // prerelease-s are locally ordered, so as soon as we reach verStable we are done
45
+ return ret;
46
+ if (v === curV)
47
+ continue; // skip current
48
+ x.isNewer = v > curV; // make easy to know what's newer
49
+ ret.push(x);
50
+ }
51
+ }
52
+ return ret;
53
+ }
19
54
  }
20
- exports.getUpdate = getUpdate;
55
+ exports.getUpdates = getUpdates;
21
56
  const LOCAL_UPDATE = 'hfs-update.zip'; // update from file takes precedence over net
22
57
  function localUpdateAvailable() {
23
58
  return (0, promises_1.access)(LOCAL_UPDATE).then(() => true, () => false);
@@ -27,12 +62,15 @@ function updateSupported() {
27
62
  return const_1.IS_BINARY;
28
63
  }
29
64
  exports.updateSupported = updateSupported;
30
- async function update() {
65
+ async function update(tag) {
31
66
  if (!updateSupported())
32
67
  throw "only binary versions are supported for now";
33
68
  let updateSource = await localUpdateAvailable() && (0, fs_1.createReadStream)(LOCAL_UPDATE);
34
69
  if (!updateSource) {
35
- const update = await getUpdate();
70
+ const update = !tag ? (await getUpdates())[0]
71
+ : await (0, github_1.getRepoInfo)(const_1.HFS_REPO + '/releases/tags/' + tag);
72
+ if (!update)
73
+ throw "no update found";
36
74
  const assetSearch = { win32: 'windows', darwin: 'mac', linux: 'linux' }[process.platform];
37
75
  if (!assetSearch)
38
76
  throw "this feature doesn't support your platform: " + process.platform;
@@ -45,7 +83,7 @@ async function update() {
45
83
  }
46
84
  const bin = process.execPath;
47
85
  const binPath = (0, path_1.dirname)(bin);
48
- const binFile = (0, path_1.basename)(bin);
86
+ const binFile = 'hfs' + (const_1.IS_WINDOWS ? '.exe' : ''); // currently running bin could have been renamed
49
87
  const newBinFile = 'new-' + binFile;
50
88
  plugins_1.pluginsWatcher.pause();
51
89
  try {
package/src/util-http.js CHANGED
@@ -7,7 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  exports.httpsStream = exports.httpsString = void 0;
8
8
  const node_https_1 = __importDefault(require("node:https"));
9
9
  const const_1 = require("./const");
10
- function httpsString(url, options = {}) {
10
+ function httpsString(url, options) {
11
11
  return httpsStream(url, options).then(res => new Promise(resolve => {
12
12
  let buf = '';
13
13
  res.on('data', chunk => buf += chunk.toString());
@@ -18,8 +18,10 @@ function httpsString(url, options = {}) {
18
18
  }));
19
19
  }
20
20
  exports.httpsString = httpsString;
21
- function httpsStream(url, options = {}) {
21
+ function httpsStream(url, { body, ...options } = {}) {
22
22
  return new Promise((resolve, reject) => {
23
+ if (body)
24
+ options.method || (options.method = 'POST');
23
25
  const req = node_https_1.default.request(url, options, res => {
24
26
  if (!res.statusCode || res.statusCode >= 400)
25
27
  return reject(new Error(String(res.statusCode), { cause: res }));
@@ -28,7 +30,10 @@ function httpsStream(url, options = {}) {
28
30
  resolve(res);
29
31
  }).on('error', e => {
30
32
  reject(req.res || e);
31
- }).end();
33
+ });
34
+ if (body)
35
+ req.write(body);
36
+ req.end();
32
37
  });
33
38
  }
34
39
  exports.httpsStream = httpsStream;
package/src/vfs.js CHANGED
@@ -26,22 +26,33 @@ exports.defaultPerms = {
26
26
  exports.PERM_KEYS = (0, misc_1.typedKeys)(exports.defaultPerms);
27
27
  exports.MIME_AUTO = 'auto';
28
28
  function inheritFromParent(parent, child) {
29
- var _a, _b, _c, _d;
29
+ var _a, _b, _c;
30
30
  for (const k of (0, misc_1.typedKeys)(exports.defaultPerms)) {
31
- let dueParent = parent;
32
- while (((_a = dueParent === null || dueParent === void 0 ? void 0 : dueParent.propagate) === null || _a === void 0 ? void 0 : _a[k]) === false)
33
- dueParent = dueParent.parent;
34
- const v = dueParent === null || dueParent === void 0 ? void 0 : dueParent[k];
35
- if (v !== undefined) // small optimization: don't expand the object
36
- (_b = child[k]) !== null && _b !== void 0 ? _b : (child[k] = v);
31
+ let p = parent;
32
+ let inheritedPerm;
33
+ while (p) {
34
+ inheritedPerm = p[k];
35
+ // // in case of object without children, parent is skipped in favor of the parent's parent
36
+ if (!isWhoObject(inheritedPerm))
37
+ break;
38
+ inheritedPerm = inheritedPerm.children;
39
+ if (inheritedPerm !== undefined)
40
+ break;
41
+ p = p.parent;
42
+ }
43
+ if (inheritedPerm !== undefined) // small optimization: don't expand the object
44
+ (_a = child[k]) !== null && _a !== void 0 ? _a : (child[k] = inheritedPerm);
37
45
  }
38
46
  if (typeof parent.mime === 'object' && typeof child.mime === 'object')
39
47
  lodash_1.default.defaults(child.mime, parent.mime);
40
48
  else
41
- (_c = child.mime) !== null && _c !== void 0 ? _c : (child.mime = parent.mime);
42
- (_d = child.accept) !== null && _d !== void 0 ? _d : (child.accept = parent.accept);
49
+ (_b = child.mime) !== null && _b !== void 0 ? _b : (child.mime = parent.mime);
50
+ (_c = child.accept) !== null && _c !== void 0 ? _c : (child.accept = parent.accept);
43
51
  return child;
44
52
  }
53
+ function isWhoObject(v) {
54
+ return v !== null && typeof v === 'object' && !Array.isArray(v);
55
+ }
45
56
  function isSameFilenameAs(name) {
46
57
  const lc = name.toLowerCase();
47
58
  return (other) => lc === (typeof other === 'string' ? other : getNodeName(other)).toLowerCase();
@@ -114,7 +125,18 @@ async function urlToNode(url, ctx, parent = exports.vfs, getRest) {
114
125
  }
115
126
  exports.urlToNode = urlToNode;
116
127
  exports.vfs = {};
117
- (0, config_1.defineConfig)('vfs', {}).sub(data => exports.vfs = data);
128
+ (0, config_1.defineConfig)('vfs', {}).sub(data => exports.vfs = (function recur(node) {
129
+ if (node.propagate) { // legacy pre-0.47
130
+ for (const [k, v] of (0, misc_1.typedEntries)(node.propagate))
131
+ if (v === false)
132
+ node[k] = { this: node[k] };
133
+ delete node.propagate;
134
+ }
135
+ if (node.children)
136
+ for (const c of node.children)
137
+ recur(c);
138
+ return node;
139
+ })(data));
118
140
  function saveVfs() {
119
141
  return (0, config_1.setConfig)({ vfs: lodash_1.default.cloneDeep(exports.vfs) }, true);
120
142
  }
@@ -157,14 +179,16 @@ function statusCodeForMissingPerm(node, perm, ctx, assign = true) {
157
179
  ctx.status = ret;
158
180
  return ret;
159
181
  function getCode() {
160
- var _a;
161
182
  if (!node.source && perm === 'can_upload') // Upload possible only if we know where to store. First check node.source because is supposedly faster.
162
183
  return const_1.HTTP_FORBIDDEN;
163
184
  // calculate value of permission resolving references to other permissions, avoiding infinite loop
164
185
  let who;
165
186
  let max = exports.PERM_KEYS.length;
166
187
  do {
167
- who = (_a = node[perm]) !== null && _a !== void 0 ? _a : exports.defaultPerms[perm];
188
+ who = node[perm];
189
+ if (isWhoObject(who))
190
+ who = who.this;
191
+ who !== null && who !== void 0 ? who : (who = exports.defaultPerms[perm]);
168
192
  if (!max-- || typeof who !== 'string' || who === exports.WHO_ANY_ACCOUNT)
169
193
  break;
170
194
  perm = who;