hfs 0.29.1 → 0.30.0

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{c as SF}from"./index-cbb42a0e.js";function OF(iF,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 iF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(iF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(iF,Symbol.toStringTag,{value:"Module"}))}var EF={},UF={get exports(){return EF},set exports(iF){EF=iF}};/*
1
+ import{c as SF}from"./index-b557b421.js";function OF(iF,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 iF)){const lF=Object.getOwnPropertyDescriptor(tF,w);lF&&Object.defineProperty(iF,w,lF.get?lF:{enumerable:!0,get:()=>tF[w]})}}}return Object.freeze(Object.defineProperty(iF,Symbol.toStringTag,{value:"Module"}))}var EF={},UF={get exports(){return EF},set exports(iF){EF=iF}};/*
2
2
  * [js-sha512]{@link https://github.com/emn178/js-sha512}
3
3
  *
4
4
  * @version 0.8.0
@@ -6,8 +6,8 @@
6
6
  <link href="/fontello.css" rel="stylesheet" />
7
7
  <script>SESSION = _HFS_SESSION_</script>
8
8
  <title>File Server</title>
9
- <script type="module" crossorigin src="/assets/index-72e96bb2.js"></script>
10
- <link rel="stylesheet" href="/assets/index-cbcc6ac5.css">
9
+ <script type="module" crossorigin src="/assets/index-b557b421.js"></script>
10
+ <link rel="stylesheet" href="/assets/index-35d3e75f.css">
11
11
  </head>
12
12
  <body>
13
13
  <div hidden>_HFS_PLUGINS_</div>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hfs",
3
- "version": "0.29.1",
3
+ "version": "0.30.0",
4
4
  "description": "HTTP File Server",
5
5
  "keywords": [
6
6
  "file server",
@@ -96,6 +96,7 @@
96
96
  "@types/unzipper": "^0.10.5",
97
97
  "axios": "^0.24.0",
98
98
  "axios-cookiejar-support": "^4.0.1",
99
+ "cross-env": "^7.0.3",
99
100
  "koa-better-http-proxy": "^0.2.9",
100
101
  "mocha": "^9.1.3",
101
102
  "nm-prune": "^5.0.0",
package/src/adminApis.js CHANGED
@@ -150,8 +150,14 @@ exports.adminApis = {
150
150
  },
151
151
  };
152
152
  for (const [k, was] of Object.entries(exports.adminApis))
153
- exports.adminApis[k] = (params, ctx) => ctxAdminAccess(ctx) ? was(params, ctx)
154
- : new apiMiddleware_1.ApiError(const_1.HTTP_UNAUTHORIZED, { any: (0, perm_1.anyAccountCanLoginAdmin)() });
153
+ exports.adminApis[k] = (params, ctx) => {
154
+ if (ctxAdminAccess(ctx))
155
+ return was(params, ctx);
156
+ const props = { any: (0, perm_1.anyAccountCanLoginAdmin)() };
157
+ return ctx.headers.accept === 'text/event-stream'
158
+ ? new apiMiddleware_1.SendListReadable({ doAtStart: x => x.error(const_1.HTTP_UNAUTHORIZED, true, props) })
159
+ : new apiMiddleware_1.ApiError(const_1.HTTP_UNAUTHORIZED, props);
160
+ };
155
161
  exports.localhostAdmin = (0, config_1.defineConfig)('localhost_admin', true);
156
162
  function ctxAdminAccess(ctx) {
157
163
  return !ctx.state.proxiedFor // we consider localhost_admin only if no proxy is detected
@@ -31,13 +31,15 @@ const apis = {
31
31
  get_admins() {
32
32
  return { list: lodash_1.default.filter(perm_1.accountsConfig.get(), perm_1.accountCanLoginAdmin).map(ac => ac.username) };
33
33
  },
34
- set_account({ username, changes }) {
34
+ set_account({ username, changes }, ctx) {
35
35
  const { admin } = changes;
36
36
  if (admin === null)
37
37
  changes.admin = undefined;
38
38
  else if (admin !== undefined && typeof admin !== 'boolean')
39
39
  return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, "invalid admin");
40
40
  const acc = (0, perm_1.setAccount)(username, changes);
41
+ if (changes.username && ctx.session)
42
+ ctx.session.username = changes.username;
41
43
  return acc ? lodash_1.default.pick(acc, 'username') : new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST);
42
44
  },
43
45
  add_account({ username, ...rest }) {
package/src/api.vfs.js CHANGED
@@ -84,13 +84,15 @@ const apis = {
84
84
  errors: await Promise.all(uris.map(async (uri) => {
85
85
  if (typeof uri !== 'string')
86
86
  return const_1.HTTP_BAD_REQUEST;
87
+ if (uri === '/')
88
+ return const_1.HTTP_NOT_ACCEPTABLE;
87
89
  const node = await urlToNodeOriginal(uri);
88
90
  if (!node)
89
91
  return const_1.HTTP_NOT_FOUND;
90
92
  const parent = (0, path_1.dirname)(uri);
91
93
  const parentNode = await urlToNodeOriginal(parent);
92
- if (!parentNode)
93
- return const_1.HTTP_NOT_ACCEPTABLE;
94
+ if (!parentNode) // shouldn't happen
95
+ return const_1.HTTP_SERVER_ERROR;
94
96
  const { children } = parentNode;
95
97
  if (!children) // shouldn't happen
96
98
  return const_1.HTTP_SERVER_ERROR;
@@ -102,8 +102,8 @@ class SendListReadable extends stream_1.Readable {
102
102
  props(props) {
103
103
  this._push({ props });
104
104
  }
105
- error(msg, close = false) {
106
- this._push({ error: msg });
105
+ error(msg, close = false, props) {
106
+ this._push({ error: msg, ...props });
107
107
  this.lastError = msg;
108
108
  if (close)
109
109
  this.close();
package/src/const.js CHANGED
@@ -38,7 +38,7 @@ 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-01-27T14:53:53.543Z";
41
+ exports.BUILD_TIMESTAMP = "2023-02-04T16:32:19.926Z";
42
42
  const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
43
43
  exports.VERSION = pkg.version;
44
44
  exports.DAY = 86400000;
package/src/index.js CHANGED
@@ -23,7 +23,6 @@ const config_1 = require("./config");
23
23
  const assert_1 = require("assert");
24
24
  const lodash_1 = __importDefault(require("lodash"));
25
25
  const misc_1 = require("./misc");
26
- //import body from 'koa-better-body'
27
26
  (0, assert_1.ok)(lodash_1.default.intersection(Object.keys(frontEndApis_1.frontEndApis), Object.keys(adminApis_1.adminApis)).length === 0); // they share same endpoints
28
27
  const keys = ((_a = process.env.COOKIE_SIGN_KEYS) === null || _a === void 0 ? void 0 : _a.split(',')) || [(0, misc_1.randomId)(30)];
29
28
  exports.app = new koa_1.default({ keys });
@@ -36,7 +35,6 @@ exports.app.use(middlewares_1.someSecurity)
36
35
  .use(middlewares_1.gzipper)
37
36
  .use((0, plugins_1.pluginsMiddleware)())
38
37
  .use((0, koa_mount_1.default)(const_1.API_URI, (0, apiMiddleware_1.apiMiddleware)({ ...frontEndApis_1.frontEndApis, ...adminApis_1.adminApis })))
39
- //.use(body({ multipart: false }))
40
38
  .use(middlewares_1.serveGuiAndSharedFiles)
41
39
  .on('error', errorHandler);
42
40
  function errorHandler(err) {
@@ -59,9 +59,21 @@ const sessions = (app) => (0, koa_session_1.default)({
59
59
  exports.sessions = sessions;
60
60
  const serveFrontendFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.FRONTEND_PROXY, const_2.FRONTEND_URI);
61
61
  const serveFrontendPrefixed = (0, koa_mount_1.default)(const_2.FRONTEND_URI.slice(0, -1), serveFrontendFiles);
62
- const serveAdminPrefixed = (0, koa_mount_1.default)(const_1.ADMIN_URI.slice(0, -1), (0, serveGuiFiles_1.serveGuiFiles)(process.env.ADMIN_PROXY, const_1.ADMIN_URI));
62
+ const serveAdminFiles = (0, serveGuiFiles_1.serveGuiFiles)(process.env.ADMIN_PROXY, const_1.ADMIN_URI);
63
+ const serveAdminPrefixed = (0, koa_mount_1.default)(const_1.ADMIN_URI.slice(0, -1), serveAdminFiles);
63
64
  const serveGuiAndSharedFiles = async (ctx, next) => {
64
65
  const { path } = ctx;
66
+ // dynamic import on frontend|admin (used for non-https login) while developing (vite4) is not producing a relative path
67
+ if (const_1.DEV && path.startsWith('/node_modules/')) {
68
+ let { referer } = ctx.headers;
69
+ referer && (referer = new URL(referer).pathname);
70
+ if (referer) {
71
+ if (referer.startsWith(const_1.ADMIN_URI))
72
+ return serveAdminFiles(ctx, next);
73
+ if (referer.startsWith(const_2.FRONTEND_URI))
74
+ return serveFrontendFiles(ctx, next);
75
+ }
76
+ }
65
77
  if (ctx.body)
66
78
  return next();
67
79
  if (path.startsWith(const_2.FRONTEND_URI))
package/src/watchLoad.js CHANGED
@@ -12,10 +12,10 @@ const misc_1 = require("./misc");
12
12
  function watchLoad(path, parser, { failedOnFirstAttempt } = {}) {
13
13
  let doing = false;
14
14
  let watcher;
15
- const debounced = (0, misc_1.debounceAsync)(load, 500, { leading: true });
15
+ const debounced = (0, misc_1.debounceAsync)(load, 500, { maxWait: 1000 });
16
16
  let retry;
17
17
  let saving;
18
- let lastStats;
18
+ let last;
19
19
  init().then(ok => ok || (failedOnFirstAttempt === null || failedOnFirstAttempt === void 0 ? void 0 : failedOnFirstAttempt()));
20
20
  return {
21
21
  unwatch() {
@@ -46,24 +46,18 @@ function watchLoad(path, parser, { failedOnFirstAttempt } = {}) {
46
46
  if (doing)
47
47
  return;
48
48
  doing = true;
49
- let data;
50
49
  try {
51
- try { // I've seen watch() firing 'change' without any change, so we'll check if any change is detectable before going on
52
- const stats = await promises_1.default.stat(path);
53
- if (stats.mtimeMs === (lastStats === null || lastStats === void 0 ? void 0 : lastStats.mtimeMs))
54
- return;
55
- lastStats = stats;
56
- data = await (0, misc_1.readFileBusy)(path);
57
- console.debug('loaded', path);
58
- }
59
- catch (e) {
60
- if (e.code === 'EPERM')
61
- console.error("missing permissions on file", path); // warn user, who could be clueless about this problem
62
- return; // ignore read errors
63
- }
64
- if (path.endsWith('.yaml'))
65
- data = yaml_1.default.parse(data);
66
- await parser(data);
50
+ const text = await (0, misc_1.readFileBusy)(path);
51
+ if (text === last)
52
+ return;
53
+ last = text;
54
+ console.debug('loaded', path);
55
+ const parsed = path.endsWith('.yaml') ? yaml_1.default.parse(text) : text;
56
+ await parser(parsed);
57
+ }
58
+ catch (e) { // ignore read errors
59
+ if (e.code === 'EPERM')
60
+ console.error("missing permissions on file", path); // warn user, who could be clueless about this problem
67
61
  }
68
62
  finally {
69
63
  doing = false;