hfs 0.45.0 → 0.46.0-alpha3

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.
@@ -0,0 +1 @@
1
+ @charset "UTF-8";:root{height:100dvh;--bg: #fff;--text: #555;--ghost-contrast: #8882;--ghost-contrast-alt: #eee;--faint-contrast: #8884;--mild-contrast: #8886;--good-contrast: #000a;--button-bg: #6080aa;--button-text: #eaeaea;--focus-color: #468;--separator: " – "}:root .highlightedText,:root .file-menu a:hover{color:#0006;text-shadow:0 0 3px rgba(0,0,0,.4)}:root .theme-dark{--bg: #000;--text: #999;--ghost-contrast-alt: #181818;--good-contrast: #fffa;--button-bg: #345;--button-text: #999;color-scheme:dark}:root .theme-dark .highlightedText,:root .theme-dark .file-menu a:hover,:root .file-menu .theme-dark a:hover{color:#fff;text-shadow:0 0 3px #fff}:root .theme-dark a{color:#8ac}:root .theme-dark .dialog-closer{background:#633}:root .theme-dark .dialog-icon{color:#ccc}:root .theme-dark .dialog-icon .icon{color:#aaa;margin-left:-1px;font-size:95%;margin-top:.4em}:root .theme-dark .dialog-backdrop{background:rgba(51,51,51,.7333333333)}:root .theme-dark .error-msg{color:#b88;background-color:#623}:root .theme-dark button.toggled{color:#eee}body{background-color:var(--bg);margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,button,select,input{font-size:12pt}#root>div{max-width:50em;margin:auto;min-height:100vh;display:flex;flex-direction:column}body,input{color:var(--text)}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}input:not([type=checkbox]),select{padding:.3em .4em;border-radius:.5em;background:var(--bg);border-color:var(--mild-contrast);color:var(--good-contrast);max-width:100%;box-sizing:border-box;width:100%}input[type=checkbox]{transform:scale(1.7);accent-color:var(--button-bg)}label input[type=checkbox]{margin-right:.8em}select{text-align:center}.hidden{display:none!important}.icon{font-size:1.2em;height:1.18em;width:1.4em}.emoji-icon,.file-icon{display:inline-block;width:1.4em;text-align:center}.file-icon{height:1em;background-size:contain;background-repeat:no-repeat;background-position:center;vertical-align:text-bottom}.icon.mirror:before{transform:scaleX(-1)}a{text-decoration:none;color:var(--button-bg)}button{background-color:var(--button-bg);color:var(--button-text);padding:.5em 1em;border:transparent;text-decoration:none;border-radius:.3em;vertical-align:middle;cursor:pointer}button:hover{outline:1px solid var(--mild-contrast)}button.toggled{color:#fff;text-shadow:0 0 3px #fff}button:focus-visible,.breadcrumb:focus-visible{outline:3px solid var(--focus-color)}a>button{width:100%}input:focus-visible,select:focus-visible,ul a:focus-visible{border-radius:.3em;border-color:transparent;outline:2px solid var(--focus-color)}.icon-button,ul.dir li .entry-panel .file-menu-button{font-size:.7em;padding:.2em .4em;margin-left:.4em;vertical-align:bottom}.error-msg{background-color:#faa;color:#833;padding:.5em 1em}.hide-back,.upload-toolbar,header{background-color:var(--bg)}header{position:sticky;top:0;padding:.2em .1em;z-index:3}.before-sliding{width:0!important;flex:0!important;margin:0!important;height:0!important;padding:0!important;overflow:hidden!important;transition:flex .5s}.show-sliding{transition:flex .5s;overflow:clip;flex:1;white-space:nowrap}.ani-working{animation:1s blink infinite}@keyframes blink{0%{opacity:1}50%{opacity:.2}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.spinner,.icon.spinner:before{animation:1.5s spin infinite linear;display:inline-flex;justify-content:center;align-items:center;width:min-content}.breadcrumb{padding:.1em .6em .2em;line-height:1.8em;border-radius:.7em;background-color:var(--button-bg);color:var(--button-text);border-top:1px solid #666;margin-right:-.1em}.breadcrumb:nth-child(-n+3) .icon{padding:0 .2em}#folder-stats,#filter-bar>span{font-size:90%}#folder-stats{margin:.5em 0 0 .5em;float:right}#folder-stats .icon{margin-right:.3em}#filter{flex:1;box-sizing:border-box}#filter-bar{display:flex;align-items:center;gap:.8em;margin:.2em 0 0;padding:2px 0 1px 11px;height:1.8em}#filter-bar input[type=checkbox]{margin-top:.5em}#filter-bar span:empty{display:none}ul.dir{flex:1;padding:0;margin:0;clear:both}ul.dir>p{text-align:center}ul.dir li{display:block;list-style-type:none;padding:.3em .3em .4em;border-bottom:1px solid var(--faint-contrast)}ul.dir li:nth-of-type(odd){background-color:var(--ghost-contrast)}ul.dir li input[type=checkbox]{margin:0 .8em}ul.dir li .link-wrapper:not(:hover) .popup-menu-button{display:none}ul.dir li .link-wrapper:hover{padding:1em;margin:-1em}ul.dir li .link-wrapper a:last-of-type{word-break:break-word;padding-right:.3em}ul.dir li .link-wrapper a .icon{margin-right:.3em;vertical-align:text-bottom}ul.dir li .link-wrapper a:hover{text-decoration:underline}ul.dir li .entry-panel{float:right;padding-top:.3em;display:flex;align-items:center}ul.dir li .entry-panel .file-menu-button{margin:-3px 0 -3px .4em}ul.dir li .entry-panel .entry-details{font-size:90%;margin-left:4px;font-variant-numeric:tabular-nums}ul.dir li .entry-panel .entry-details .entry-size-unit{margin-left:.3em}ul.dir li>div:last-of-type{clear:both}ul.dir li.page-separator{margin-top:1em;position:relative}ul.dir li.page-separator:before{content:attr(label);position:absolute;top:-1.8em;font-size:smaller;margin-left:calc(50% - 1em);opacity:.9}#menu-bar{display:flex;justify-content:space-evenly;flex-wrap:wrap}#menu-bar>*{flex:1;margin:.1em}#menu-bar>*:first-child{margin-left:0}#menu-bar>*:last-child{margin-right:0}#menu-bar button{padding-left:0;padding-right:0}#searched{margin:.2em}#user-panel{display:flex;flex-direction:column;gap:1em}#user-panel a>button{width:100%}button label{cursor:inherit;margin-left:.5em}.dialog-backdrop.working{font-size:5em;animation:1s fade-in}.dialog-content{padding:.2em}.dialog-alert .dialog-content{text-align:center}.dialog-alert .dialog-content p{text-align:left;display:inline-block}.dialog{min-width:11em;--color: var(--button-bg)}#paging{position:sticky;bottom:0;display:flex;gap:.1em;background-color:var(--bg);padding:0 .2em .2em}#paging>button{z-index:1}#paging button{box-shadow:0 0 .3em .3em #0003}#paging #paging-middle{padding:0 .5em;margin:0 -.3em;display:flex;gap:.5em;flex:1;overflow-x:auto}#paging #paging-middle>button{flex:1;padding-top:0;padding-bottom:0}#paging button{background:var(--button-bg);text-align:center;white-space:nowrap;padding:.5em}.upload-toolbar{position:sticky;top:-4px}.upload-progress:before{content:var(--separator)}.entry-size:after{content:var(--separator)}.upload-progress{min-width:4em;display:inline-block;margin-left:.5em}.upload-list td:nth-child(1){width:0}.upload-list td:nth-child(2){text-align:right;width:0;white-space:nowrap;padding-left:.5em}.upload-list td:nth-child(3){padding:.2em .5em;word-break:break-word}.dialog-login form{display:flex;flex-direction:column;gap:1.2em}.dialog-login label{display:block;margin-bottom:.5em;margin-left:.1em}.miss-perm{margin:.3em}.popup-menu-button{font-size:.8em;padding:.2em .3em;position:absolute;opacity:.8}.popup-menu-button:hover{opacity:1}.file-dialog .dialog-content{min-width:calc(100% - 1em)}.file-dialog .dialog{min-width:13em}.file-dialog-properties{word-break:break-word;line-height:1.5em;margin:0}.file-dialog-properties dt{font-weight:700}.file-dialog-properties dd{margin-left:1.5em}.file-menu{margin-top:1em;display:flex;flex-direction:column}.file-menu a{padding:.5em 0}.file-menu a:first-child{padding-top:1em;border-top:1px solid var(--faint-contrast)}.file-menu a .icon{margin-right:.5em}#root>.tiles-mode{max-width:none;margin:0 1em;--tile-size: 5;--name-lines: 3;--name-height: calc(4.7em + var(--tile-size) * .4em + 1.2em * var(--name-lines));--tile-width: calc(5em + 1em * var(--tile-size))}#root>.tiles-mode ul.dir{display:grid;grid-template-columns:repeat(auto-fill,minmax(var(--tile-width),1fr));grid-auto-rows:calc(var(--name-height) + 1.3em);gap:0 20px}#root>.tiles-mode ul.dir li{text-align:center;position:relative;display:flex;flex-direction:column;border-bottom:none;overflow-x:clip;padding:0}#root>.tiles-mode ul.dir li a{max-height:var(--name-height);display:block;display:-webkit-box;overflow:hidden;-webkit-line-clamp:calc(var(--name-lines) + 1);-webkit-box-orient:vertical}#root>.tiles-mode ul.dir li a:last-of-type{padding:0}#root>.tiles-mode ul.dir li a:hover{overflow:visible;display:block;z-index:1}#root>.tiles-mode ul.dir li a span{display:block}#root>.tiles-mode ul.dir li a .icon.icon{font-size:calc(1.18rem + .6rem * var(--tile-size))}#root>.tiles-mode ul.dir li a img.icon{width:auto}#root>.tiles-mode ul.dir li a .icon{font-size:4rem;display:block;margin:auto}#root>.tiles-mode ul.dir li a:hover .icon:before{text-decoration:none}#root>.tiles-mode ul.dir li .link-wrapper:hover{padding:0;margin:0}#root>.tiles-mode ul.dir li:nth-of-type(odd){background-color:var(--bg)}#root>.tiles-mode ul.dir li .entry-panel{justify-content:center;font-size:10pt}#root>.tiles-mode ul.dir li .entry-details{display:flex;flex-direction:column-reverse;font-size:80%}#root>.tiles-mode ul.dir li.page-separator:before{content:""}#root>.tiles-mode ul.dir li input[type=checkbox]{margin:0;position:absolute;top:.3em;right:1em}#root>.tiles-mode ul.dir li:hover{--bg: var(--ghost-contrast-alt);background:var(--bg)}#root>.tiles-mode ul.dir li:hover .link-wrapper,#root>.tiles-mode ul.dir li:hover .entry-panel{z-index:1;background:var(--bg)}#root>.tiles-mode ul.dir li:hover input[type=checkbox]{z-index:2}#root>.tiles-mode ul.dir li:hover .link-wrapper a{display:inline}#root>.tiles-mode ul.dir li:hover .entry-panel{padding-bottom:.3em}#root>.tiles-mode .entry-size:after{content:none}#root>.tiles-mode .entry-ts{display:none}#root>.tiles-mode .popup-menu-button{position:absolute;top:0;left:0}#root>.tiles-mode #filter-bar{margin-bottom:1em}@media (min-width: 42em){body{scrollbar-width:thin;scrollbar-color:var(--button-bg) var(--ghost-contrast)}body::-webkit-scrollbar{width:12px}body::-webkit-scrollbar-track{background:var(--ghost-contrast)}body::-webkit-scrollbar-thumb{background-color:var(--button-bg);border-radius:20px;border:1px solid var(--ghost-contrast)}}@media (max-width: 42em){:root{--ghost-contrast: #8883}body,button,select{font-size:14pt}#menu-bar button label,#filter-bar button label{display:none}#filter-bar{margin-top:.4em}#filter-bar button{width:17.6vw;height:2.3em}.breadcrumb{word-break:break-all}.breadcrumb .icon{font-size:24px}}.dialog-backdrop{position:fixed;inset:0;background:#8886;backdrop-filter:blur(2px);display:flex;justify-content:center;align-items:center;z-index:1000}.dialog{background:#fff;background:var(--bg);padding:max(.5em,1vw);border-radius:1em;position:relative;margin:0 3vw;overflow:hidden;max-height:calc(100vh - 2em);display:flex;flex-direction:column;justify-content:center}.dialog-icon{color:#fff;background-color:var(--color);position:absolute;top:0;width:2em;height:1.8em;text-align:center;border-radius:.8em 0}.dialog-title{font-size:120%;margin-top:-.4em;padding:0 .5em}.dialog-closer~.dialog-title{margin-right:2em}.dialog-type~.dialog-title{margin-left:2em}.dialog-icon~.dialog-title{text-align:center}.dialog-closer{border-radius:0 .8em;right:0;padding:0;background-color:#c88}.dialog-icon~.dialog-content{margin-top:1.5em}.dialog-type{left:0;top:0;overflow:hidden;line-height:1.8em;opacity:.8}.dialog-content{overflow:auto;max-height:calc(100vh - 4.5em)}.dialog-content p{white-space:pre-wrap;margin:.5em 0}.dialog-confirm .dialog-content button{margin-top:1em}.dialog-alert-info{--color: #282 }.dialog-alert-warning{--color: #c91 }.dialog-alert-error{--color: #822}@media (max-width: 42em){.dialog-icon{font-size:120%}.dialog-icon~.dialog-content{margin-top:2.5em}.dialog-title{margin-top:-.2em}}.dialog-prompt label{display:block;margin-bottom:.5em;margin-left:.1em}
@@ -1,4 +1,4 @@
1
- import{c as SF}from"./index-101f19c9.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-d7a9a422.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
@@ -5,9 +5,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
7
 
8
- <script>HFS={}</script>
9
- <script type="module" crossorigin src="/assets/index-5aeff3af.js"></script>
10
- <link rel="stylesheet" href="/assets/index-59572489.css">
8
+ <script type="module" crossorigin src="/assets/index-d7a9a422.js"></script>
9
+ <link rel="stylesheet" href="/assets/index-db36ef67.css">
11
10
  </head>
12
11
  <body>
13
12
  <noscript>You need to enable JavaScript to run this app.</noscript>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hfs",
3
- "version": "0.45.0",
3
+ "version": "0.46.0-alpha3",
4
4
  "description": "HTTP File Server",
5
5
  "keywords": [
6
6
  "file server",
@@ -26,13 +26,13 @@
26
26
  "dist": "npm run build-all && npm run dist-bin",
27
27
  "dist-bin": "npm run dist-modules && cd dist && pkg . --public -C gzip && mv -f hfs-win-x64.exe hfs.exe && zip hfs-windows.zip hfs.exe -r plugins && cp -f hfs-linux-x64 hfs && zip hfs-linux.zip hfs -r plugins && cp -f hfs-macos-x64 hfs && zip hfs-mac.zip hfs -r plugins && cp -f hfs-macos-arm64 hfs && zip hfs-mac-arm.zip hfs -r plugins && rm hfs",
28
28
  "dist-modules": "cp package*.json dist && cd dist && npm ci --omit=dev && npm run dist-crclib && rm package-lock.json && cd .. && node prune_modules",
29
- "dist-crclib": "npm i -f --no-save --omit=dev @node-rs/crc32-win32-x64-msvc @node-rs/crc32-darwin-arm64 @node-rs/crc32-darwin-x64 ",
29
+ "dist-crclib": "npm i -f --no-save --omit=dev @node-rs/crc32-win32-x64-msvc @node-rs/crc32-darwin-arm64 @node-rs/crc32-darwin-x64 @node-rs/crc32-linux-x64-gnu",
30
30
  "dist-win": "cp package*.json dist && cd dist && npm ci --omit=dev && npm i -f --no-save --omit=dev @node-rs/crc32-win32 && pkg . --public -C gzip -t node16-win-x64",
31
31
  "dist-mac": "cp package*.json dist && cd dist && npm ci --omit=dev && pkg . --public -C gzip -t node16-macos-arm64",
32
32
  "dist-node": "npm run dist-modules && cd dist && zip hfs-node.zip -r * -x *.zip *.exe hfs-* *.log logs"
33
33
  },
34
34
  "engines": {
35
- "node": ">=16.13.0"
35
+ "node": ">=18.12.0"
36
36
  },
37
37
  "files": [
38
38
  "src/*",
package/src/adminApis.js CHANGED
@@ -187,8 +187,13 @@ exports.ctxAdminAccess = ctxAdminAccess;
187
187
  const frpDebounced = (0, misc_1.debounceAsync)(async () => {
188
188
  if (!const_1.IS_WINDOWS)
189
189
  return false;
190
- const { stdout } = await (0, util_1.promisify)(child_process_1.execFile)('tasklist', ['/fi', 'imagename eq frpc.exe', '/nh']);
191
- return stdout.includes('frpc');
190
+ try { // guy with win11 reported missing tasklist, so don't take it for granted
191
+ const { stdout } = await (0, util_1.promisify)(child_process_1.execFile)('tasklist', ['/fi', 'imagename eq frpc.exe', '/nh']);
192
+ return stdout.includes('frpc');
193
+ }
194
+ catch (_a) {
195
+ return false;
196
+ }
192
197
  });
193
198
  function anyAccountCanLoginAdmin() {
194
199
  return Boolean(lodash_1.default.find(perm_1.accountsConfig.get(), perm_1.accountCanLoginAdmin));
@@ -116,14 +116,12 @@ const apis = {
116
116
  return typeof res === 'string' ? (0, plugins_1.getPluginInfo)(res) : res;
117
117
  },
118
118
  async update_plugin(pl) {
119
+ await (0, plugins_1.enablePlugin)(pl.id, false, true);
119
120
  await (0, github_1.downloadPlugin)(pl.id, pl.branch, true);
120
121
  return {};
121
122
  },
122
123
  async uninstall_plugin({ id }) {
123
- while ((0, plugins_1.isPluginRunning)(id)) {
124
- (0, plugins_1.enablePlugin)(id, false);
125
- await (0, misc_1.wait)(500);
126
- }
124
+ await (0, plugins_1.enablePlugin)(id, false, true);
127
125
  await (0, promises_1.rm)(plugins_1.PATH + '/' + id, { recursive: true, force: true });
128
126
  return {};
129
127
  }
package/src/commands.js CHANGED
@@ -111,6 +111,8 @@ const commands = {
111
111
  params: '',
112
112
  async cb() {
113
113
  const update = await (0, update_1.getUpdate)();
114
+ if (update.name === const_1.VERSION)
115
+ throw "you already have the latest version: " + const_1.VERSION;
114
116
  console.log("new version available", update.name);
115
117
  }
116
118
  },
package/src/const.js CHANGED
@@ -38,11 +38,11 @@ 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-05-21T10:24:51.009Z";
41
+ exports.BUILD_TIMESTAMP = "2023-05-31T20:07:45.208Z";
42
42
  const pkg = JSON.parse(fs.readFileSync(PKG_PATH, 'utf8'));
43
43
  exports.VERSION = pkg.version;
44
44
  exports.DAY = 86400000;
45
- exports.API_VERSION = 8.1; // entry.uri + script.plugin + absolute frontend_*
45
+ exports.API_VERSION = 8.21;
46
46
  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
47
  exports.HFS_REPO = 'rejetto/hfs';
48
48
  exports.SPECIAL_URI = '/~/';
package/src/github.js CHANGED
@@ -11,7 +11,7 @@ const plugins_1 = require("./plugins");
11
11
  const apiMiddleware_1 = require("./apiMiddleware");
12
12
  const lodash_1 = __importDefault(require("lodash"));
13
13
  const const_1 = require("./const");
14
- const DIST_ROOT = 'dist/';
14
+ const DIST_ROOT = 'dist';
15
15
  const downloading = {};
16
16
  function downloadProgress(id, status) {
17
17
  if (status === undefined)
@@ -24,24 +24,37 @@ async function downloadPlugin(repo, branch = '', overwrite) {
24
24
  if (downloading[repo])
25
25
  return new apiMiddleware_1.ApiError(const_1.HTTP_CONFLICT, "already downloading");
26
26
  downloadProgress(repo, true);
27
- const rec = await getRepoInfo(repo);
28
- if (!branch)
29
- branch = rec.default_branch;
30
- const short = repo.split('/')[1]; // second part, repo without the owner
31
- if (!short)
32
- return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, "bad repo");
33
- const folder2repo = getFolder2repo();
34
- const folder = overwrite ? lodash_1.default.findKey(folder2repo, x => x === repo) // use existing folder
35
- : short in folder2repo ? repo.replace('/', '-') // longer form only if another plugin is using short form
36
- : short;
37
- const installPath = plugins_1.PATH + '/' + folder;
38
- const GITHUB_ZIP_ROOT = short + '-' + branch; // GitHub puts everything within this folder
39
- const rootWithinZip = GITHUB_ZIP_ROOT + '/' + DIST_ROOT;
40
- const stream = await (0, misc_1.httpsStream)(`https://github.com/${repo}/archive/refs/heads/${branch}.zip`);
41
- await (0, misc_1.unzip)(stream, path => path.startsWith(rootWithinZip) && installPath + '/' + path.slice(rootWithinZip.length));
42
- downloadProgress(repo, undefined);
43
- await (0, plugins_1.rescan)(); // workaround: for some reason, operations are not triggering the rescan of the watched folder. Let's invoke it.
44
- return folder;
27
+ try {
28
+ const rec = await getRepoInfo(repo);
29
+ if (!branch)
30
+ branch = rec.default_branch;
31
+ const short = repo.split('/')[1]; // second part, repo without the owner
32
+ if (!short)
33
+ return new apiMiddleware_1.ApiError(const_1.HTTP_BAD_REQUEST, "bad repo");
34
+ const folder2repo = getFolder2repo();
35
+ const folder = overwrite ? lodash_1.default.findKey(folder2repo, x => x === repo) // use existing folder
36
+ : short in folder2repo ? repo.replace('/', '-') // longer form only if another plugin is using short form
37
+ : short;
38
+ const installPath = plugins_1.PATH + '/' + folder;
39
+ const GITHUB_ZIP_ROOT = short + '-' + branch; // GitHub puts everything within this folder
40
+ const rootWithinZip = GITHUB_ZIP_ROOT + '/' + DIST_ROOT;
41
+ const foldersToCopy = [
42
+ rootWithinZip + '-' + process.platform + '-' + process.arch,
43
+ rootWithinZip + '-' + process.platform,
44
+ rootWithinZip,
45
+ ].map(x => x + '/');
46
+ // this zip doesn't have content-length, so we cannot produce progress event
47
+ const stream = await (0, misc_1.httpsStream)(`https://github.com/${repo}/archive/refs/heads/${branch}.zip`);
48
+ await (0, misc_1.unzip)(stream, path => {
49
+ const folder = foldersToCopy.find(x => path.startsWith(x));
50
+ return folder ? installPath + '/' + path.slice(folder.length) : false;
51
+ });
52
+ await (0, plugins_1.rescan)(); // workaround: for some reason, operations are not triggering the rescan of the watched folder. Let's invoke it.
53
+ return folder;
54
+ }
55
+ finally {
56
+ downloadProgress(repo, undefined);
57
+ }
45
58
  }
46
59
  exports.downloadPlugin = downloadPlugin;
47
60
  function getRepoInfo(id) {
@@ -54,7 +67,7 @@ function readGithubFile(uri) {
54
67
  }
55
68
  exports.readGithubFile = readGithubFile;
56
69
  async function readOnlinePlugin(repoInfo, branch = '') {
57
- const res = await readGithubFile(`${repoInfo.full_name}/${branch || repoInfo.default_branch}/${DIST_ROOT}plugin.js`);
70
+ const res = await readGithubFile(`${repoInfo.full_name}/${branch || repoInfo.default_branch}/${DIST_ROOT}/plugin.js`);
58
71
  const pl = (0, plugins_1.parsePluginSource)(repoInfo.full_name, res); // use 'repo' as 'id' client-side
59
72
  pl.branch = branch || undefined;
60
73
  return pl;
@@ -67,15 +80,22 @@ function getFolder2repo() {
67
80
  }
68
81
  exports.getFolder2repo = getFolder2repo;
69
82
  async function apiGithub(uri) {
70
- const res = await (0, misc_1.httpsString)('https://api.github.com/' + uri, {
71
- headers: {
72
- 'User-Agent': 'HFS',
73
- Accept: 'application/vnd.github.v3+json',
74
- }
75
- });
76
- if (!res.ok)
77
- throw res.statusCode;
78
- return JSON.parse(res.body);
83
+ try {
84
+ const res = await (0, misc_1.httpsString)('https://api.github.com/' + uri, {
85
+ headers: {
86
+ 'User-Agent': 'HFS',
87
+ Accept: 'application/vnd.github.v3+json',
88
+ }
89
+ });
90
+ if (!res.ok)
91
+ throw res.statusCode;
92
+ return JSON.parse(res.body);
93
+ }
94
+ catch (e) {
95
+ // https://docs.github.com/en/rest/overview/resources-in-the-rest-api?apiVersion=2022-11-28#rate-limiting
96
+ throw e.message === '403' ? Error('github_quota')
97
+ : e;
98
+ }
79
99
  }
80
100
  async function* searchPlugins(text = '') {
81
101
  var _a, _b;
package/src/plugins.js CHANGED
@@ -47,13 +47,17 @@ exports.DISABLING_POSTFIX = '-disabled';
47
47
  const plugins = {};
48
48
  function isPluginRunning(id) {
49
49
  var _a;
50
- return (_a = plugins[id]) === null || _a === void 0 ? void 0 : _a.started;
50
+ return Boolean((_a = plugins[id]) === null || _a === void 0 ? void 0 : _a.started);
51
51
  }
52
52
  exports.isPluginRunning = isPluginRunning;
53
- function enablePlugin(id, state = true) {
53
+ async function enablePlugin(id, state = true, waitForIt = false) {
54
54
  exports.enablePlugins.set(arr => arr.includes(id) === state ? arr
55
55
  : state ? [...arr, id]
56
56
  : arr.filter((x) => x !== id));
57
+ if (!waitForIt)
58
+ return;
59
+ while (isPluginRunning(id) !== state)
60
+ await (0, misc_1.wait)(500);
57
61
  }
58
62
  exports.enablePlugin = enablePlugin;
59
63
  // nullish values are equivalent to defaultValues
@@ -271,14 +275,17 @@ function loadPlugin(id, path) {
271
275
  console.log("plugin", id, data.badApi);
272
276
  await (alreadyRunning === null || alreadyRunning === void 0 ? void 0 : alreadyRunning.unload(true));
273
277
  console.debug("starting plugin", id);
278
+ const storageDir = (0, path_1.resolve)(module, '..', 'storage') + (const_1.IS_WINDOWS ? '\\' : '/');
279
+ await (0, promises_1.mkdir)(storageDir, { recursive: true });
274
280
  const res = await (init === null || init === void 0 ? void 0 : init.call(null, {
275
281
  srcDir: __dirname,
282
+ storageDir,
276
283
  const: Const,
277
284
  require,
278
285
  getConnections: connections_1.getConnections,
279
286
  events: events_1.default,
280
287
  log(...args) {
281
- console.log('plugin', id, ':', ...args);
288
+ console.log('plugin', id + ':', ...args);
282
289
  },
283
290
  getConfig: (cfgKey) => { var _a, _b, _c, _d, _e; return (_c = (_b = (_a = exports.pluginsConfig.get()) === null || _a === void 0 ? void 0 : _a[id]) === null || _b === void 0 ? void 0 : _b[cfgKey]) !== null && _c !== void 0 ? _c : (_e = (_d = data.config) === null || _d === void 0 ? void 0 : _d[cfgKey]) === null || _e === void 0 ? void 0 : _e.defaultValue; },
284
291
  setConfig: (cfgKey, value) => setPluginConfig(id, { [cfgKey]: value }),
@@ -120,13 +120,6 @@ async function treatIndex(ctx, filesUri, body) {
120
120
  }, null, 4)
121
121
  .replace(/<(\/script)/g, '<"+"$1') /*avoid breaking our script container*/}
122
122
  document.documentElement.setAttribute('ver', '${const_1.VERSION.split('-')[0] /*for style selectors*/}')
123
- function getScriptAttr(k) {
124
- return document.currentScript?.getAttribute(k)
125
- || console.error("this function must be called at the very top of your file")
126
- }
127
- HFS.getPluginKey = () => getScriptAttr('plugin')
128
- HFS.getPluginConfig = () => HFS.plugins[HFS.getPluginKey()]
129
- HFS.getPluginPublic = () => getScriptAttr('src')?.match(/^.*\\//)[0]
130
123
  </script>
131
124
  <style>
132
125
  :root {
package/src/update.js CHANGED
@@ -15,10 +15,7 @@ const plugins_1 = require("./plugins");
15
15
  const promises_1 = require("fs/promises");
16
16
  const open_1 = __importDefault(require("open"));
17
17
  async function getUpdate() {
18
- const [latest] = await (0, github_1.getRepoInfo)(const_1.HFS_REPO + '/releases?per_page=1');
19
- if (latest.name === const_1.VERSION)
20
- throw "you already have the latest version: " + const_1.VERSION;
21
- return latest;
18
+ return (await (0, github_1.getRepoInfo)(const_1.HFS_REPO + '/releases?per_page=1'))[0];
22
19
  }
23
20
  exports.getUpdate = getUpdate;
24
21
  const LOCAL_UPDATE = 'hfs-update.zip'; // update from file takes precedence over net
package/src/util-files.js CHANGED
@@ -126,8 +126,13 @@ async function unzip(stream, cb) {
126
126
  await pending; // don't overlap writings
127
127
  console.debug('unzip', dest);
128
128
  await prepareFolder(dest);
129
- const thisFile = entry.pipe((0, fs_1.createWriteStream)(dest));
130
- pending = (0, stream_1.once)(thisFile, 'finish');
129
+ try {
130
+ const out = (0, fs_1.createWriteStream)(dest);
131
+ out.on('error', () => { });
132
+ const thisFile = entry.pipe(out);
133
+ pending = (0, stream_1.once)(thisFile, 'finish');
134
+ }
135
+ catch (_a) { }
131
136
  }));
132
137
  }
133
138
  exports.unzip = unzip;
package/src/vfs.js CHANGED
@@ -267,20 +267,14 @@ function masksCouldGivePermission(masks, perm) {
267
267
  }
268
268
  exports.masksCouldGivePermission = masksCouldGivePermission;
269
269
  function parentMaskApplier(parent) {
270
- const matchers = Object.entries(parent.masks || {}).map(([k, v]) => {
270
+ const matchers = (0, misc_1.onlyTruthy)(Object.entries(parent.masks || {}).map(([k, { maskOnly, ...mods }]) => {
271
271
  k = k.startsWith('**/') ? k.slice(3) : !k.includes('/') ? k : '';
272
- if (!k)
273
- return;
274
- const m = (0, misc_1.makeMatcher)(k);
275
- return [m, v];
276
- });
277
- return (item, virtualBasename) => {
278
- if (virtualBasename === undefined)
279
- virtualBasename = getNodeName(item);
280
- for (const entry of matchers) {
281
- if (!entry)
272
+ return k && { mods, maskOnly, matcher: (0, misc_1.makeMatcher)(k) };
273
+ }));
274
+ return (item, virtualBasename = getNodeName(item)) => {
275
+ for (const { matcher, mods, maskOnly } of matchers) {
276
+ if (maskOnly === 'folders' && !item.isFolder || maskOnly === 'files' && item.isFolder)
282
277
  continue;
283
- const [matcher, mods] = entry;
284
278
  if (!matcher(virtualBasename))
285
279
  continue;
286
280
  if (item.masks)
@@ -1 +0,0 @@
1
- @charset "UTF-8";:root{height:100dvh;--bg: #fff;--text: #555;--ghost-contrast: #8882;--faint-contrast: #8884;--mild-contrast: #8886;--good-contrast: #000a;--button-bg: #68a;--button-text: #eaeaea;--focus-color: #468;--separator: " – "}:root .highlightedText,:root .file-menu a:hover{color:#0006;text-shadow:0 0 3px rgba(0,0,0,.4)}:root .theme-dark{--bg: #000;--text: #999;--good-contrast: #fffa;--button-bg: #345;--button-text: #999;color-scheme:dark}:root .theme-dark .highlightedText,:root .theme-dark .file-menu a:hover,:root .file-menu .theme-dark a:hover{color:#fff;text-shadow:0 0 3px #fff}:root .theme-dark a{color:#8ac}:root .theme-dark .dialog-closer{background:#633}:root .theme-dark .dialog-icon{color:#ccc}:root .theme-dark .dialog-icon .icon{color:#aaa;margin-left:-1px;font-size:95%}:root .theme-dark .dialog-backdrop{background:rgba(51,51,51,.7333333333)}:root .theme-dark .error-msg{color:#b88;background-color:#623}:root .theme-dark button.toggled{color:#eee}body{background-color:var(--bg);margin:0;font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}body,button,select,input{font-size:12pt}#root{max-width:50em;margin:auto;min-height:100vh;display:flex;flex-direction:column}body,input{color:var(--text)}code{font-family:source-code-pro,Menlo,Monaco,Consolas,Courier New,monospace}input:not([type=checkbox]),select{padding:.3em .4em;border-radius:.5em;background:var(--bg);border-color:var(--mild-contrast);color:var(--good-contrast);max-width:100%;box-sizing:border-box;width:100%}input[type=checkbox]{transform:scale(1.7);accent-color:var(--button-bg)}label input[type=checkbox]{margin-right:.8em}select{text-align:center}.hidden{display:none!important}.icon{font-size:1.2em;height:1.18em;min-width:1.4em}.emoji-icon,.file-icon{display:inline-block;width:1.4em;text-align:center}.file-icon{height:1em;background-size:contain;background-repeat:no-repeat;background-position:center;vertical-align:text-bottom}.icon.mirror:before{transform:scaleX(-1)}a{text-decoration:none;color:#57a}button{background-color:var(--button-bg);color:var(--button-text);padding:.5em 1em;border:transparent;text-decoration:none;border-radius:.3em;vertical-align:middle;cursor:pointer}button:hover{outline:1px solid var(--mild-contrast)}button.toggled{color:#fff;text-shadow:0 0 3px #fff}button:focus-visible,.breadcrumb:focus-visible{outline:3px solid var(--focus-color)}a>button{width:100%}input:focus-visible,select:focus-visible,ul a:focus-visible{border-radius:.3em;border-color:transparent;outline:2px solid var(--focus-color)}.icon-button,ul.dir li .entry-panel .file-menu-button{font-size:.7em;padding:.2em .4em;margin-left:.4em;vertical-align:bottom}.error-msg{background-color:#faa;color:#833;padding:.5em 1em}.hide-back,.upload-toolbar,header{background-color:var(--bg)}header{position:sticky;top:0;padding:.2em;z-index:1}.before-sliding{width:0!important;flex:0!important;margin:0!important;height:0!important;padding:0!important;overflow:hidden!important;transition:flex .5s}.show-sliding{transition:flex .5s;overflow:clip;flex:1;white-space:nowrap}.ani-working{animation:1s blink infinite}@keyframes blink{0%{opacity:1}50%{opacity:.2}}@keyframes spin{to{transform:rotate(360deg)}}@keyframes fade-in{0%{opacity:0}to{opacity:1}}.spinner,.icon.spinner:before{animation:1.5s spin infinite linear;display:inline-flex;justify-content:center;align-items:center;width:min-content}.breadcrumb{padding:.1em .6em .2em;line-height:1.8em;border-radius:.7em;background-color:var(--button-bg);color:var(--button-text);border-top:1px solid #666;margin-right:-.1em}.breadcrumb:nth-child(-n+3) .icon{padding:0 .2em}#folder-stats,#filter-bar>span{font-size:90%}#folder-stats{margin:.5em 0 0 .5em;float:right}#folder-stats .icon{margin-right:.3em}#filter{flex:1;box-sizing:border-box}#filter-bar{display:flex;align-items:center;gap:.8em;margin:.2em 0 0;padding:2px 0 1px 11px;height:1.8em}#filter-bar input[type=checkbox]{margin-top:.5em}#filter-bar span:empty{display:none}ul.dir{flex:1;padding:0;margin:0;clear:both}ul.dir>p{text-align:center}ul.dir li{display:block;list-style-type:none;padding:.3em .3em .4em;border-bottom:1px solid var(--faint-contrast)}ul.dir li:nth-of-type(odd){background-color:var(--ghost-contrast)}ul.dir li input[type=checkbox]{margin:0 .8em}ul.dir li .link-and-menu:not(:hover) .popup-menu-button{display:none}ul.dir li .link-and-menu:hover{padding:1em;margin:-1em}ul.dir li a:last-of-type{word-break:break-word;padding-right:.3em}ul.dir li a .icon{margin-right:.3em;vertical-align:text-bottom}ul.dir li a:hover{text-decoration:underline}ul.dir li .entry-panel{float:right;margin-top:.3em;display:flex;align-items:center}ul.dir li .entry-panel .file-menu-button{margin:-3px 0 -3px .4em}ul.dir li .entry-panel .entry-details{font-size:90%;margin-left:4px;font-variant-numeric:tabular-nums}ul.dir li .entry-panel .entry-details .entry-size-unit{margin-left:.3em}ul.dir li>div:last-of-type{clear:both}ul.dir li.page-separator{margin-top:1em;position:relative}ul.dir li.page-separator:before{content:attr(label);position:absolute;top:-1.8em;font-size:smaller;margin-left:calc(50% - 1em);opacity:.9}#menu-bar{display:flex;justify-content:space-evenly;flex-wrap:wrap}#menu-bar>*{flex:1;margin:.1em}#menu-bar button{padding-left:0;padding-right:0}#searched{margin:.2em}#user-panel{display:flex;flex-direction:column;gap:1em}#user-panel a>button{width:100%}button label{cursor:inherit;margin-left:.5em}.dialog-backdrop.working{font-size:5em;animation:1s fade-in}.dialog-content{padding:.2em}.dialog-alert .dialog-content{text-align:center}.dialog-alert .dialog-content p{text-align:left;display:inline-block}.dialog{min-width:11em;--color: var(--button-bg)}#paging{position:sticky;bottom:0;display:flex;gap:.1em;background-color:var(--bg);padding:0 .2em .2em}#paging>button{z-index:1}#paging button{box-shadow:0 0 .3em .3em #0003}#paging #paging-middle{padding:0 .5em;margin:0 -.3em;display:flex;gap:.5em;flex:1;overflow-x:auto}#paging #paging-middle>button{flex:1;padding-top:0;padding-bottom:0}#paging button{background:var(--button-bg);text-align:center;white-space:nowrap;padding:.5em}.upload-toolbar{position:sticky;top:-4px}.upload-progress:before{content:var(--separator)}.entry-size:after{content:var(--separator)}.upload-progress{min-width:4em;display:inline-block;margin-left:.5em}.upload-list td:nth-child(1){width:0}.upload-list td:nth-child(2){text-align:right;width:0;white-space:nowrap;padding-left:.5em}.upload-list td:nth-child(3){padding:.2em .5em;word-break:break-word}.dialog-login form{display:flex;flex-direction:column;gap:1.2em}.dialog-login label{display:block;margin-bottom:.5em;margin-left:.1em}.miss-perm{margin:.3em}.popup-menu-button{font-size:.8em;padding:.2em .3em;position:absolute;opacity:.8}.popup-menu-button:hover{opacity:1}.file-dialog .dialog-content{min-width:calc(100% - 1em)}.file-dialog .dialog{min-width:13em}.file-dialog-properties{word-break:break-word;line-height:1.5em}.file-dialog-properties dt{font-weight:700}.file-dialog-properties dd{margin-left:1.5em}.file-menu{margin-top:1em;display:flex;flex-direction:column}.file-menu a{padding:.5em 0}.file-menu a:first-child{padding-top:1em;border-top:1px solid var(--faint-contrast)}.file-menu a .icon{margin-right:.5em}@media (min-width: 42em){body{scrollbar-width:thin;scrollbar-color:var(--button-bg) var(--ghost-contrast)}body::-webkit-scrollbar{width:12px}body::-webkit-scrollbar-track{background:var(--ghost-contrast)}body::-webkit-scrollbar-thumb{background-color:var(--button-bg);border-radius:20px;border:1px solid var(--ghost-contrast)}}@media (max-width: 42em){:root{--ghost-contrast: #8883}body,button,select{font-size:14pt}#menu-bar button label,#filter-bar button label{display:none}#filter-bar{margin-top:.4em}#filter-bar button{width:17.6vw;height:2.3em}.breadcrumb{word-break:break-all}.breadcrumb .icon{font-size:24px}}.dialog-backdrop{position:fixed;inset:0;background:#8886;backdrop-filter:blur(2px);display:flex;justify-content:center;align-items:center;z-index:1000}.dialog{background:#fff;background:var(--bg);padding:max(.5em,1vw);border-radius:1em;position:relative;margin:0 3vw;overflow:hidden;max-height:calc(100vh - 2em);display:flex;flex-direction:column;justify-content:center}.dialog-icon{color:#fff;background-color:var(--color);position:absolute;top:0;width:2em;height:1.8em;text-align:center;border-radius:.8em 0}.dialog-title{font-size:120%;margin-top:-.4em;padding:0 .5em}.dialog-closer~.dialog-title{margin-right:2em}.dialog-type~.dialog-title{margin-left:2em}.dialog-icon~.dialog-title{text-align:center}.dialog-closer{border-radius:0 .8em;right:0;padding:0;background-color:#c88}.dialog-icon~.dialog-content{margin-top:2em}.dialog-type{left:0;top:0;overflow:hidden;line-height:1.8em;opacity:.8}.dialog-content{overflow:auto;max-height:calc(100vh - 4.5em)}.dialog-content p{white-space:pre-wrap;margin:.5em 0}.dialog-confirm .dialog-content button{margin-top:1em}.dialog-alert-info{--color: #282 }.dialog-alert-warning{--color: #c91 }.dialog-alert-error{--color: #822}@media (max-width: 42em){.dialog-icon{font-size:120%}.dialog-icon~.dialog-content{margin-top:2.5em}.dialog-title{margin-top:-.2em}}.dialog-prompt label{display:block;margin-bottom:.5em;margin-left:.1em}