hfs 3.3.1 → 3.3.3

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 (48) hide show
  1. package/admin/assets/{AccountsPage-Cvi9DSc1.js → AccountsPage-C_ayTmn7.js} +1 -1
  2. package/admin/assets/{ArrayField-ChS9pNra.js → ArrayField-B20NUH0C.js} +1 -1
  3. package/admin/assets/{ConfigFilePage-6jCYVkbr.js → ConfigFilePage-Dw0-gus3.js} +1 -1
  4. package/admin/assets/{CustomHtmlPage-DaEXsEcQ.js → CustomHtmlPage-CLGyZfZ8.js} +1 -1
  5. package/admin/assets/{DataTable-Cf5S5yWr.js → DataTable-BwyFEGxv.js} +1 -1
  6. package/admin/assets/{DateTimeField--mTsSB1l.js → DateTimeField-ZUy9IBhM.js} +1 -1
  7. package/admin/assets/{EventManager-BJWba-fL.js → EventManager-DomWgRty.js} +1 -1
  8. package/admin/assets/{FileField-B0WhrAuk.js → FileField-Bj3P7JUc.js} +1 -1
  9. package/admin/assets/{InternetPage-BICQDG_K.js → InternetPage-CGMQCcBM.js} +3 -3
  10. package/admin/assets/{LangPage-D42UPSxC.js → LangPage-DGFrOItT.js} +1 -1
  11. package/admin/assets/{LogsPage-DQTrf5GE.js → LogsPage-CvCYNhID.js} +1 -1
  12. package/admin/assets/{MenuButton-DDfB3119.js → MenuButton-BTRAUH7H.js} +1 -1
  13. package/admin/assets/{MonitorPage-CH06c8aW.js → MonitorPage-CVa2ILH2.js} +1 -1
  14. package/admin/assets/{OptionsPage-BvXLA_R0.js → OptionsPage-C3cprG9u.js} +1 -1
  15. package/admin/assets/PluginsPage-CIOnncph.js +1 -0
  16. package/admin/assets/{Tabs-CGfV3BK0.js → Tabs-zcHwsK2s.js} +1 -1
  17. package/admin/assets/{TextEditor-Df9LSzm6.js → TextEditor-CDOjRy40.js} +1 -1
  18. package/admin/assets/{VfsPathField-6Kyy5vuQ.js → VfsPathField-DHifSPJi.js} +1 -1
  19. package/admin/assets/{agentIcons-DwT9U-lh.js → agentIcons-DB1m4pGa.js} +1 -1
  20. package/admin/assets/{baseUrl-D7S0KsqZ.js → baseUrl-Bt9R8Da2.js} +2 -2
  21. package/admin/assets/{icons-DWkdo8hc.js → icons-DR_Rvxtn.js} +1 -1
  22. package/admin/assets/index-B3difDBD.js +477 -0
  23. package/admin/assets/{routing-CxxvyWME.js → routing-CBrDVeFB.js} +1 -1
  24. package/admin/index.html +1 -1
  25. package/central.json +3 -0
  26. package/frontend/assets/{dist-legacy-zQdkj0Z9.js → dist-legacy-CSuZ0eoA.js} +1 -1
  27. package/frontend/assets/index-legacy-tk5ZmBDE.js +1 -0
  28. package/frontend/assets/{lib-legacy-CRrFEEqm.js → lib-legacy-I77jyH6j.js} +1 -1
  29. package/frontend/assets/{sha512-legacy-BB7Mdt0y.js → sha512-legacy-DxvM1xc4.js} +1 -1
  30. package/frontend/index.html +1 -1
  31. package/npm-shrinkwrap.json +56 -56
  32. package/package.json +2 -2
  33. package/src/api.auth.js +4 -4
  34. package/src/api.net.js +2 -1
  35. package/src/api.vfs.js +10 -5
  36. package/src/auth.js +2 -2
  37. package/src/const.js +1 -1
  38. package/src/cross.js +1 -2
  39. package/src/middlewares.js +6 -2
  40. package/src/nat.js +10 -7
  41. package/src/outboundProxy.js +1 -1
  42. package/src/update.js +11 -2
  43. package/src/updateChangelog.js +31 -0
  44. package/src/upload.js +5 -2
  45. package/src/util-os.js +12 -4
  46. package/admin/assets/PluginsPage-CyaVJZkM.js +0 -1
  47. package/admin/assets/index-BDdPG215.js +0 -477
  48. package/frontend/assets/index-legacy-B8EvbIOB.js +0 -1
@@ -114,6 +114,7 @@ const prepareState = async (ctx, next) => {
114
114
  // calculate these once and for all
115
115
  ctx.state.connection = (0, connections_1.socket2connection)(ctx.socket);
116
116
  // explicit credentials and existing sessions must take precedence, so a matching IP cannot override a chosen account
117
+ let via;
117
118
  let a = await urlLogin() || await getHttpAccount() || !s?.username && autoLogin();
118
119
  const loggedInNotBySession = a;
119
120
  ctx.state.account = a ||= (0, perm_1.getAccount)(s?.username, false); // with least precedence, we consider session
@@ -123,12 +124,12 @@ const prepareState = async (ctx, next) => {
123
124
  else if (loggedInNotBySession) {
124
125
  try {
125
126
  if (a.username)
126
- await (0, auth_1.setLoggedIn)(ctx, a.username);
127
+ await (0, auth_1.setLoggedIn)(ctx, a.username, via);
127
128
  }
128
129
  catch (e) {
129
130
  events_1.default.emit('failedLogin', { ctx, username: a.username, via: ctx.query.login ? 'url' : ctx.get('authorization') ? 'header' : undefined });
130
131
  ctx.status = const_1.HTTP_UNAUTHORIZED;
131
- ctx.body = String(e);
132
+ ctx.body = e instanceof Error ? e.message : String(e);
132
133
  return;
133
134
  }
134
135
  ctx.headers['x-username'] = a.username; // give an easier way to determine if the login was successful
@@ -137,6 +138,7 @@ const prepareState = async (ctx, next) => {
137
138
  (0, connections_1.updateConnectionForCtx)(ctx);
138
139
  await next();
139
140
  function urlLogin() {
141
+ via = 'url';
140
142
  const { login } = ctx.query;
141
143
  if (!login)
142
144
  return;
@@ -145,6 +147,7 @@ const prepareState = async (ctx, next) => {
145
147
  return u && (0, auth_1.clearTextLogin)(ctx, u, p, 'url');
146
148
  }
147
149
  function getHttpAccount() {
150
+ via = 'header';
148
151
  const b64 = allowAuthorizationHeader.get() && ctx.get('authorization')?.split(' ')[1];
149
152
  if (!b64)
150
153
  return;
@@ -157,6 +160,7 @@ const prepareState = async (ctx, next) => {
157
160
  catch { }
158
161
  }
159
162
  function autoLogin() {
163
+ via = 'net';
160
164
  // keep the mask direct so group inheritance cannot make identity depend on account order
161
165
  return Object.values(perm_1.accounts.get()).find(a => (0, perm_1.accountCanLogin)(a) && a.auto_login_net && (0, misc_1.netMatches)(ctx.ip, a.auto_login_net, true));
162
166
  }
package/src/nat.js CHANGED
@@ -82,24 +82,25 @@ exports.getPublicIps = (0, debounceAsync_1.debounceAsync)(async () => {
82
82
  return ret;
83
83
  }, { retain: 10 * cross_1.MINUTE });
84
84
  exports.getNatInfo = (0, debounceAsync_1.debounceAsync)(async () => {
85
+ const MAPPINGS_TIMEOUT = 15_000; // routers enumerate rules sequentially; a few dozen mappings can take over 5 seconds
85
86
  const upnp = await exports.upnpEnabled.getWhenReady() ? getUpnpClient() : null;
86
87
  const gatewayIpPromise = findGateway().catch(() => undefined);
87
88
  const gw = upnp && await (0, cross_1.haveTimeout)(10_000, upnp.getGateway()).catch(() => null);
88
- const status = await (0, listen_1.getServerStatus)();
89
- let mappings = gw && await (0, cross_1.haveTimeout)(5_000, upnp.getMappings())?.catch(() => null);
90
- console.debug(gw ? "Mappings found:" : "Mappings not queried:", mappings?.map(x => x.description).join(', ') || (gw ? "none" : upnp ? "gateway not found" : "UPnP disabled"));
89
+ let mappings = gw && await (0, cross_1.haveTimeout)(MAPPINGS_TIMEOUT, upnp.getMappings())?.catch(() => null);
90
+ console.debug(gw ? "Mappings found:" : "Mappings not queried:", lodash_1.default.uniq(mappings?.map(x => x.description)).join(', ') || (gw ? "none" : upnp ? "gateway not found" : "UPnP disabled"));
91
91
  const localIps = await (0, listen_1.getIps)(false);
92
92
  const gatewayIp = await gatewayIpPromise;
93
93
  const localIp = gw?.address || (gatewayIp ? lodash_1.default.maxBy(localIps, x => (0, cross_1.inCommon)(x, gatewayIp)) : localIps[0]);
94
+ const status = await (0, listen_1.getServerStatus)();
94
95
  const internalPort = status?.https?.listening && status.https.port || status?.http?.listening && status.http.port || undefined;
95
96
  let mapped = lodash_1.default.find(mappings, x => x.private.host === localIp && x.private.port === internalPort);
96
97
  if (upnp && mappings && localIp && internalPort && !mapped && exports.mappedPort.get())
97
98
  // restore the HFS-created mapping after routers that forget UPnP state across reboots
98
99
  await (0, cross_1.haveTimeout)(5_000, upnp.createMapping(upnpMappingParam(internalPort, exports.mappedPort.get()))).then(async () => {
99
100
  // confirm router state after restore instead of trusting the AddPortMapping result
100
- mappings = await (0, cross_1.haveTimeout)(5_000, upnp.getMappings());
101
+ mappings = await (0, cross_1.haveTimeout)(MAPPINGS_TIMEOUT, upnp.getMappings());
101
102
  mapped = lodash_1.default.find(mappings, x => x.private.host === localIp && x.private.port === internalPort);
102
- }).catch(e => console.warn('UPnP mapping restore failed:', e?.message || String(e)));
103
+ }).catch(e => console.warn('UPnP mapping restore failed:', e?.message || e?.errorDescription || String(e)));
103
104
  const externalPort = mapped?.public.port;
104
105
  if (localIp)
105
106
  exports.defaultBaseUrl.localIp = localIp;
@@ -134,9 +135,11 @@ function getUpnpClient() {
134
135
  throw Error("UPnP disabled");
135
136
  if (!upnpClient) {
136
137
  upnpClient = new nat_upnp_1.Client({ timeout: 4_000 });
137
- const originalMethod = upnpClient.getGateway;
138
138
  // other client methods call getGateway too, so this will ensure they reuse this same result
139
- upnpClient.getGateway = (0, debounceAsync_1.debounceAsync)(() => originalMethod.apply(upnpClient), { retain: cross_1.HOUR, retainFailure: 30_000 });
139
+ (0, cross_1.patchKey)(upnpClient, 'getGateway', was => (0, debounceAsync_1.debounceAsync)(() => was.apply(upnpClient), { retain: cross_1.HOUR, retainFailure: 30_000 }));
140
+ const f = (0, cross_1.patchKey)(upnpClient, 'getMappings', was => (0, debounceAsync_1.debounceAsync)(() => was.apply(upnpClient), { retain: cross_1.MINUTE }));
141
+ for (const k of ['createMapping', 'removeMapping']) // these methods must invalidate the cache
142
+ (0, cross_1.patchKey)(upnpClient, k, (was) => (...args) => was.apply(upnpClient, args).finally(f.clearRetain));
140
143
  }
141
144
  return upnpClient;
142
145
  }
@@ -44,7 +44,7 @@ config_1.configReady.then(async (startedWithoutConfig) => {
44
44
  // it can be like "IP:PORT" or "http=IP:PORT;https=IP:PORT;ftp=IP:PORT"
45
45
  const url = (0, cross_1.prefix)('https://', /https=([\d:.]+)/.exec(out)?.[1]) // prefer https
46
46
  || (0, cross_1.prefix)('http://', /http=([\d:.]+)/.exec(out)?.[1])
47
- || !read.includes('=') && 'http://' + read; // simpler form
47
+ || !read.includes('=') && (read.includes('://') ? read : 'http://' + read); // simpler form
48
48
  if (!url)
49
49
  return;
50
50
  outboundProxy.set(url);
package/src/update.js CHANGED
@@ -28,6 +28,7 @@ const persistence_1 = require("./persistence");
28
28
  const lodash_1 = __importDefault(require("lodash"));
29
29
  const argv_1 = require("./argv");
30
30
  const promises_2 = require("stream/promises");
31
+ const updateChangelog_1 = require("./updateChangelog");
31
32
  const updateToBeta = (0, config_1.defineConfig)(misc_1.CFG.update_to_beta, false);
32
33
  const autoCheckUpdate = (0, config_1.defineConfig)(misc_1.CFG.auto_check_update, true);
33
34
  const lastCheckUpdate = persistence_1.storedMap.singleSync('lastCheckUpdate', 0);
@@ -69,14 +70,17 @@ function prepareRelease(r) {
69
70
  assets: r.assets.map((a) => lodash_1.default.pick(a, ReleaseAssetKeys))
70
71
  });
71
72
  }
72
- async function getVersions(filter, max = 30) {
73
+ async function getVersions(filter, max = 30, stopAtCurrent = false) {
73
74
  const ret = [];
74
75
  for await (const x of (0, github_1.apiGithubPaginated)(`repos/${const_1.HFS_REPO}/releases`)) {
75
76
  if (x.name.endsWith('-ignore'))
76
77
  continue;
77
78
  const rel = prepareRelease(x);
78
- if (rel.versionScalar === curV)
79
+ if (rel.versionScalar === curV) {
80
+ if (stopAtCurrent)
81
+ break; // stop at the installed release, not at older maintenance releases published more recently
79
82
  continue;
83
+ }
80
84
  if (!filter || filter(rel))
81
85
  ret.push(rel);
82
86
  if (ret.length >= max)
@@ -93,6 +97,11 @@ async function getUpdates(strict = false) {
93
97
  const betas = !includeBetas ? [] : await getVersions(x => x.prerelease && x.versionScalar > stable.versionScalar && (!strict || x.isNewer));
94
98
  if (stable.isNewer || const_1.RUNNING_BETA && !strict)
95
99
  betas.push(stable);
100
+ if (stable.isNewer && stable.body) {
101
+ const history = await getVersions(r => !r.prerelease && r.isNewer && r.versionScalar <= stable.versionScalar, Infinity, true)
102
+ .catch(() => []); // missing history must not prevent installing an available update
103
+ stable.body = (0, updateChangelog_1.updateChangelog)(stable, history, curV);
104
+ }
96
105
  return betas;
97
106
  }
98
107
  const LOCAL_UPDATE = 'hfs-update.zip'; // update from file takes precedence over net
@@ -0,0 +1,31 @@
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.updateChangelog = updateChangelog;
7
+ const lodash_1 = __importDefault(require("lodash"));
8
+ function updateChangelog(destination, releases, currentVersion) {
9
+ const newer = lodash_1.default.sortBy(lodash_1.default.uniqBy([destination, ...releases], 'tag_name')
10
+ .filter(r => !r.prerelease && r.versionScalar > currentVersion && r.versionScalar <= destination.versionScalar), r => -r.versionScalar);
11
+ const level = Math.max(...newer.map(releaseLevel));
12
+ const seen = new Set();
13
+ const sections = newer.filter(r => releaseLevel(r) === level).map(r => {
14
+ let body = r.body.trim();
15
+ if (level === 0) {
16
+ // deduplicate complete entries, preserving continuation lines and nested lists
17
+ body = body.replace(/\r\n/g, '\n').split(/\n{2,}|\n(?=[*+-] )/).filter(entry => {
18
+ const key = entry.trim().replace(/^[*+-] /, '');
19
+ if (!key || seen.has(key))
20
+ return false;
21
+ seen.add(key);
22
+ return true;
23
+ }).join('\n\n');
24
+ }
25
+ return { tag: r.tag_name, body };
26
+ }).filter(r => r.body);
27
+ return sections.map(r => r.tag === destination.tag_name ? r.body : `**${r.tag}**\n\n${r.body}`).join('\n\n') || destination.body;
28
+ function releaseLevel(r) {
29
+ return r.versionScalar % 1E6 === 0 ? 2 : r.versionScalar % 1E3 === 0 ? 1 : 0;
30
+ }
31
+ }
package/src/upload.js CHANGED
@@ -125,11 +125,14 @@ function uploadWriter(base, baseUri, filename, ctx) {
125
125
  if (firstCreated) {
126
126
  setUploadMeta(dir, ctx);
127
127
  // recursive mkdir returns the first created directory; existing ancestors must not receive ownership
128
- const existingParent = (0, path_1.dirname)((0, path_1.resolve)(firstCreated));
128
+ const firstCreatedPath = (0, path_1.toNamespacedPath)((0, path_1.resolve)(firstCreated)); // Node 24 mkdir can return a namespace-prefixed Windows path
129
129
  let source = (0, path_1.resolve)(dir);
130
130
  let uri = path_1.posix.dirname(vfsUri);
131
- while (source !== existingParent) {
131
+ while (true) {
132
132
  createdFolders.push({ uri, source });
133
+ // stop before the existing parent: namespaced drive and UNC roots can differ in their trailing separator
134
+ if ((0, path_1.toNamespacedPath)(source) === firstCreatedPath)
135
+ break;
133
136
  source = (0, path_1.dirname)(source);
134
137
  uri = path_1.posix.dirname(uri);
135
138
  }
package/src/util-os.js CHANGED
@@ -23,8 +23,12 @@ const const_1 = require("./const");
23
23
  const promises_1 = require("node:fs/promises");
24
24
  const DF_TIMEOUT = 2000;
25
25
  function getDiskSpaceSync(path) {
26
- while (path && !(0, misc_1.isWindowsDrive)(path) && !(0, fs_1.existsSync)(path))
27
- path = (0, path_1.dirname)(path);
26
+ while (path && !(0, misc_1.isWindowsDrive)(path) && !(0, fs_1.existsSync)(path)) {
27
+ const parent = (0, path_1.dirname)(path);
28
+ if (parent === path)
29
+ break; // an unavailable root has no other parent to try
30
+ path = parent;
31
+ }
28
32
  const res = (0, fs_1.statfsSync)(path);
29
33
  return { free: res.bavail * res.bsize, total: res.blocks * res.bsize, name: path };
30
34
  }
@@ -35,8 +39,12 @@ function cmdEscape(par) {
35
39
  return `"${par.replaceAll('"', '\\"')}"`;
36
40
  }
37
41
  async function getDiskSpace(path) {
38
- while (path && !(0, misc_1.isWindowsDrive)(path) && !await (0, misc_1.exists)(path))
39
- path = (0, path_1.dirname)(path);
42
+ while (path && !(0, misc_1.isWindowsDrive)(path) && !await (0, misc_1.exists)(path)) {
43
+ const parent = (0, path_1.dirname)(path);
44
+ if (parent === path)
45
+ break; // an unavailable root has no other parent to try; this test covers UNC as well
46
+ path = parent;
47
+ }
40
48
  const res = await (0, promises_1.statfs)(path);
41
49
  return { free: res.bavail * res.bsize, total: res.blocks * res.bsize, name: path };
42
50
  }
@@ -1 +0,0 @@
1
- import{i as e}from"./rolldown-runtime-CacB07dV.js";import{a as t,i as n,r,t as i}from"./DataTable-Cf5S5yWr.js";import{t as a}from"./DateTimeField--mTsSB1l.js";import{a as o,t as s}from"./Tabs-CGfV3BK0.js";import{t as c}from"./VfsPathField-6Kyy5vuQ.js";import{$i as l,Bn as u,Bt as d,C as f,Da as p,E as ee,Ea as m,H as te,K as h,L as ne,Ma as g,Mn as re,Pa as ie,Rr as ae,Rt as oe,S as _,Ta as v,Tn as se,U as ce,Ut as le,W as ue,Xt as de,Zn as fe,_ as pe,_n as me,_t as y,ai as b,ar as he,bt as ge,c as _e,ea as x,er as ve,fr as ye,ft as be,ga as S,gt as C,ha as w,ht as T,ia as xe,ir as E,it as Se,j as D,l as O,lr as k,ma as A,mn as j,mt as Ce,na as M,nn as we,o as N,oa as P,pr as Te,rr as F,s as Ee,tr as De,tt as Oe,u as ke,un as I,v as L,va as Ae,wi as je,xt as Me,y as R,zt as z}from"./index-BDdPG215.js";import{$ as Ne,K as Pe,R as Fe,a as Ie,et as Le,g as Re,i as ze,n as Be,o as Ve,r as He,rt as Ue,s as We,t as Ge}from"./icons-DWkdo8hc.js";import{t as B}from"./ArrayField-ChS9pNra.js";import{t as Ke}from"./routing-CxxvyWME.js";import{t as qe}from"./FileField-B0WhrAuk.js";function Je(e){return w(`MuiTable`,e)}A(`MuiTable`,[`root`,`stickyHeader`]);var V=e(ie(),1),H=Ae();p();var Ye=[`className`,`component`,`padding`,`size`,`stickyHeader`],Xe=e=>{let{classes:t,stickyHeader:n}=e;return P({root:[`root`,n&&`stickyHeader`]},Je,t)},Ze=M(`table`,{name:`MuiTable`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.stickyHeader&&t.stickyHeader]}})(x(({theme:e})=>({display:`table`,width:`100%`,borderCollapse:`collapse`,borderSpacing:0,"& caption":m(m({},e.typography.body2),{},{padding:e.spacing(2),color:(e.vars||e).palette.text.secondary,textAlign:`left`,captionSide:`bottom`}),variants:[{props:({ownerState:e})=>e.stickyHeader,style:{borderCollapse:`separate`}}]}))),U=`table`,Qe=V.forwardRef(function(e,n){let r=l({props:e,name:`MuiTable`}),{className:i,component:a=U,padding:o=`normal`,size:s=`medium`,stickyHeader:c=!1}=r,u=v(r,Ye),d=m(m({},r),{},{component:a,padding:o,size:s,stickyHeader:c}),f=Xe(d),p=V.useMemo(()=>({padding:o,size:s,stickyHeader:c}),[o,s,c]);return(0,H.jsx)(t.Provider,{value:p,children:(0,H.jsx)(Ze,m({as:a,role:a===U?null:`table`,ref:n,className:S(f.root,i),ownerState:d},u))})});function $e(e){return w(`MuiTableBody`,e)}A(`MuiTableBody`,[`root`]),p();var et=[`className`,`component`],tt=e=>{let{classes:t}=e;return P({root:[`root`]},$e,t)},nt=M(`tbody`,{name:`MuiTableBody`,slot:`Root`})({display:`table-row-group`}),rt={variant:`body`},W=`tbody`,it=V.forwardRef(function(e,t){let r=l({props:e,name:`MuiTableBody`}),{className:i,component:a=W}=r,o=v(r,et),s=m(m({},r),{},{component:a}),c=tt(s);return(0,H.jsx)(n.Provider,{value:rt,children:(0,H.jsx)(nt,m({className:S(c.root,i),as:a,ref:t,role:a===W?null:`rowgroup`,ownerState:s},o))})});function at(e){return w(`MuiTableRow`,e)}var G=A(`MuiTableRow`,[`root`,`selected`,`hover`,`head`,`footer`]);p();var ot=[`className`,`component`,`hover`,`selected`],st=e=>{let{classes:t,selected:n,hover:r,head:i,footer:a}=e;return P({root:[`root`,n&&`selected`,r&&`hover`,i&&`head`,a&&`footer`]},at,t)},ct=M(`tr`,{name:`MuiTableRow`,slot:`Root`,overridesResolver:(e,t)=>{let{ownerState:n}=e;return[t.root,n.head&&t.head,n.footer&&t.footer]}})(x(({theme:e})=>({color:`inherit`,display:`table-row`,verticalAlign:`middle`,outline:0,[`&.${G.hover}:hover`]:{backgroundColor:(e.vars||e).palette.action.hover},[`&.${G.selected}`]:{backgroundColor:e.alpha((e.vars||e).palette.primary.main,(e.vars||e).palette.action.selectedOpacity),"&:hover":{backgroundColor:e.alpha((e.vars||e).palette.primary.main,`${(e.vars||e).palette.action.selectedOpacity} + ${(e.vars||e).palette.action.hoverOpacity}`)}}}))),K=`tr`,lt=V.forwardRef(function(e,t){let r=l({props:e,name:`MuiTableRow`}),{className:i,component:a=K,hover:o=!1,selected:s=!1}=r,c=v(r,ot),u=V.useContext(n),d=m(m({},r),{},{component:a,hover:o,selected:s,head:u&&u.variant===`head`,footer:u&&u.variant===`footer`});return(0,H.jsx)(ct,m({as:a,ref:t,className:S(st(d).root,i),role:a===K?null:`row`,ownerState:d},c))}),q=e(ye());p();var ut=[`type`,`defaultValue`,`frontend`,`showIf`],dt=[`value`,`onChange`,`multiple`,`groups`];function ft(e,t){return J.apply(this,arguments)}function J(){return J=g(function*(e,t){let{id:n}=e,{config:r}=yield k(`get_plugin`,{id:n}),i=q.default.some(I(e.config,r),{type:`array`})?`min(100%, ${t})`:void 0,a=!!e.config,o=yield ue({title:a?`Options for ${n}`:`Log for ${n}`,form:(t,{submit:n})=>({before:e.description&&(0,V.createElement)(b,{sx:{mx:2,mb:2}},e.description),fields:Y(I(e.config,t)||{},t),save:a?{children:`Save and close`}:!1,barSx:{gap:1},onError:te,addToBar:[(0,V.createElement)(R,{variant:`outlined`,onClick:()=>n(s)},`Save`)]}),values:r,dialogProps:q.default.merge({maxWidth:`md`,sx:{m:`auto`}},e.configDialog,{maxWidth:!1,sx:{maxWidth:null}}),Wrapper({children:e}){let{list:r,setList:o}=L(`get_plugin_log`,{id:n},{map(e){e.ts=new Date(e.ts)}}),s;return(0,V.createElement)(_,{alignItems:`stretch`,justifyContent:`center`,flexWrap:`wrap`,flexDirection:a?void 0:`column`},(0,V.createElement)(b,{sx:{maxWidth:t,width:i,minWidth:`min-content`}},e),(0,V.createElement)(je,{elevation:1,sx:{position:`relative`,fontFamily:`monospace`,flex:1,minWidth:`min(40em, 90vw)`,minHeight:`20em`,px:.5}},(0,V.createElement)(b,{sx:{my:.5,pb:.5,borderBottom:`1px solid`,display:`flex`,alignItems:`center`,justifyContent:`space-between`}},`Output`,(0,V.createElement)(R,{size:`small`,sx:{p:0},onClick(){o([])}},`Clear`)),(0,V.createElement)(b,{ref:de(r),sx:{position:`absolute`,bottom:0,top:`31px`,left:0,right:0,overflowY:`auto`}},!r.length&&(0,V.createElement)(b,{sx:{p:1}},`Log is empty`),(0,V.createElement)(b,{sx:{textIndent:`-1em`,pl:`1em`,position:`absolute`,width:`calc(100% - 1.2em)`,ml:`2px`,pt:`.2em`}},r.map(e=>{j(e.ts);let t=j(e.ts);return(0,V.createElement)(V.Fragment,{key:e.id},t!==s&&(s=t),(0,V.createElement)(b,{},(0,V.createElement)(b,{title:t,sx:{display:`inline`,color:`text.secondary`,mr:1}},me(e.ts)),d(e.msg,/https?:\/\/\S+/,e=>(0,V.createElement)(ae,{href:e[0],target:`_blank`},e[0]))))})))))}});if(o&&!q.default.isEqual(r,o))return s(o);function s(e){return c.apply(this,arguments)}function c(){return c=g(function*(e){yield k(`set_plugin`,{id:n,config:e}),Object.assign(r,e),h(`Configuration saved`)}),c.apply(this,arguments)}}),J.apply(this,arguments)}function Y(e,t){return Object.entries(e).map(([e,n])=>{if(!n)return;let{type:r,defaultValue:i,frontend:a,showIf:o}=n,s=v(n,ut);try{if(s.getError=X(s.getError),typeof o==`string`&&(n.showIf=o=X(o)),o&&!o(t))return}catch(e){}s.helperText&&(s.helperText=z(s.helperText,{html:!1}));let c=Z[r];if(t===!1&&r===`date_time`&&(s.$type=`dateTime`),c===B){let{fields:e}=s;typeof e==`string`&&(e=X(e)),s.valuesForAdd=re(I(e,!1),e=>e.defaultValue),s.details!=null||(s.details=!1),s.fields=t=>q.default.map(Y(I(e,t),t),(e,t)=>e&&m(m({k:t},e),{},{defaultValue:void 0})).filter(Boolean)}return i!==void 0&&r===`boolean`&&(s.placeholder=`Default value is ${JSON.stringify(i)}`),m({k:e,comp:c},s)})}function X(e){return(0,eval)(e)}var Z={string:y,number:Ce,boolean:be,select:C,multiselect:T,array:B,real_path:qe,vfs_path:c,username:pt,color:mt,show_html:({html:e})=>(0,V.createElement)(oe,{},String(e)),date_time:a,net_mask:ee};Z.showHtml=Z.show_html;function pt(e){let{value:t,onChange:n,multiple:r,groups:i}=e,a=v(e,dt),{data:o,element:s,loading:c}=pe(`get_accounts`),l=(0,V.useMemo)(()=>o&&q.default.sortBy(o.list,[e=>!e.isGroup,e=>!e.adminActualAccess,`username`]),[o]);return(!c||!o)&&s||(0,V.createElement)(r?T:C,m({value:t,onChange:n,options:l==null?void 0:l.filter(e=>i===void 0||i===e.isGroup).map(e=>({value:e.username,label:e.username,a:e})),renderOption:e=>{if(!e.a)return(0,V.createElement)(`span`,{style:{textDecoration:`line-through`}},e.label);let t=e.a.isGroup&&(0,V.createElement)(Le)||e.a.adminActualAccess&&D(Ne,`Can login into Admin`);return t?(0,V.createElement)(`span`,{},(0,V.createElement)(`span`,{style:{marginLeft:-8,marginRight:8}},t),e.label):e.label}},a))}function mt(e){return(0,V.createElement)(y,m({inputProps:m({type:`color`,style:{marginRight:24}},!e.value&&{value:`#888888`,style:{zIndex:1,opacity:.1}}),InputProps:{endAdornment:e.value?(0,V.createElement)(R,{icon:He,size:`small`,sx:{position:`absolute`,right:0,bottom:3},title:`Clear`,onClick(t){e.onChange(null,{was:e.value,event:t})}}):(0,V.createElement)(b,{sx:{position:`absolute`,width:`100%`,bottom:2,pt:`3px`,textAlign:`center`,color:`#fff`,background:`repeating-linear-gradient(45deg, #333, #333 10px, #444 10px, #444 20px)`}},`default`)},typing:!0},e))}p();function Q({updates:e}){let{list:t,error:n,setList:a,initializing:o}=L(e?`get_plugin_updates`:`get_plugins`,{},{map(e){e.config&&(e.config=fe(e.config,e=>X(`()=>(`+e+`)`)()))}}),[s,c]=(0,V.useState)(0);(0,V.useEffect)(()=>{a(e=>q.default.sortBy(e,e=>{var t;return(e.error?0:e.started?1:e.badApi?2:3)+_e(((t=e.repo)==null?void 0:t.split(`/`).reverse().join(`/`))||e.id).toLowerCase()}))},[t.length,s]);let l=`small`,{pause:d,pauseButton:p}=ne(`plugins`,()=>ht(E.suspend_plugins).then(e=>!e),{onClick(){return g(function*(){yield k(`set_config`,{values:{[E.suspend_plugins]:!d}}),d&&(yield ve(2e3),c(Date.now()))})()}}),ee=xe();return(0,V.createElement)(i,{error:se(n)?F(n,N):q.default.map(n,(e,t)=>`Error ${t} for: ${e.join(`, `)}`).join(`; `),rows:t.length?t:[],fillFlex:!0,initializing:o,disableColumnSelector:!0,quickFilter:!e,actionsHeader:!e&&p,getRowHeight:e&&(({model:e})=>e.changelog?`auto`:50),noRows:e&&`No updates available. Only plugins available on "search online" are checked.`,columns:[{field:`id`,headerName:`name`,flex:.3,minWidth:150,renderCell:O,valueGetter(e,t){return t.repo||t.id},mergeRender:{[e?`changelog`:`description`]:{sx:{fontSize:`x-small`}}}},{field:`version`,width:70,hideUnder:`sm`,cellInnerProps:{className:he},mergeRender:{installedVersion:{sx:{fontSize:`x-small`}}}},_t,m(m({},gt),{},{flex:1,hideUnder:`sm`}),{field:`installedVersion`,hideUnder:!0,dialogHidden:!0,renderCell:({value:e})=>e&&`Yours ${e}`},{field:`changelog`,headerName:`Change log`,flex:2,hideUnder:!e||`sm`,sx:{flexDirection:`column`,alignItems:`flex-start`},renderCell({value:e,row:t}){return Array.isArray(e)?(0,V.createElement)(Qe,{sx:{td:{p:0}}},(0,V.createElement)(it,{},q.default.uniq(q.default.sortBy(e,`version`).filter(e=>q.default.isString(e.message)&&e.message&&e.version>t.installedVersion)).map((e,t)=>(0,V.createElement)(lt,{key:t},(0,V.createElement)(r,{sx:{whiteSpace:`pre`,verticalAlign:`top`}},`• ${e.version}: `),(0,V.createElement)(r,{},z(e.message,{html:!1})))))):null}}],actions:({row:t,id:n})=>e?[(0,V.createElement)(f,{icon:ze,title:t.downloading?`Downloading`:t.updated?`Already updated`:`Update`,disabled:t.updated,progress:t.downloading,size:l,onClick(){return g(function*(){yield k(`update_plugin`,{id:n},{timeout:!1}).catch(e=>{var t;throw e.code===424?Error(`Failed dependencies: `+((t=e.cause)==null?void 0:t.map(e=>u(`plugin "`,e.id||e.repo,`" `)+e.error).join(`; `))):e}),h(`Plugin updated`)})()}})]:[(0,V.createElement)(f,t.started?{icon:Ie,title:(0,V.createElement)(b,{"aria-hidden":!0},`Stop ${n}`,(0,V.createElement)(`br`),`Started `+new Date(t.started).toLocaleString()),"aria-label":`Stop ${n}`,size:l,color:`success`,doneAnimation:!0,onClick:()=>k(`stop_plugin`,{id:n})}:{icon:ge,title:`Start ${n}`,disabled:d&&`All plugins are paused – Click the Resume button below`,size:l,onClick:()=>ke(n)}),(0,V.createElement)(f,{icon:t.config||!t.started||!t.log?Te:Ve,title:t.config||!t.log?`Options`:`Log`,size:l,disabled:!t.started&&`Start plugin to access options`||!t.config&&!t.log&&`No options and no log for this plugin`,onClick(){var e;let n=t.configDialog,r=ee.breakpoints.values[n==null?void 0:n.maxWidth]||(n==null||(e=n.sx)==null?void 0:e.maxWidth)||F(n==null?void 0:n.maxWidth,{xs:0})||432;return typeof r==`number`&&(r+=`px`),ft(t,r)}}),(0,V.createElement)(f,{icon:Ue,title:`Uninstall`,size:l,onClick(){return g(function*(){let e=yield ce(`${n}: delete configuration too?`,{trueText:`Yes`,falseText:`No`,after:({onClick:e})=>(0,V.createElement)(R,{variant:`outlined`,onClick(){e(void 0)}},`Abort`)});e!==void 0&&(yield k(`uninstall_plugin`,{id:n,deleteConfig:e}),h(`Plugin uninstalled`))})()}})]})}function ht(e){return k(`get_config`,{only:[e]}).then(t=>t[e])}var gt={field:`description`,mergeRender:{isTheme:{}},mergeRenderSx:{float:`left`}},_t={field:`isTheme`,headerName:`is theme`,hideUnder:!0,dialogHidden:!0,type:`boolean`,renderCell({value:e}){return e&&D(We,q.default.isString(e)?`${e} theme`:`theme`,{fontSize:`1.2rem`,mr:`.3em`})}};p();function vt(){let[e,t]=(0,V.useState)(``),{list:n,error:r,initializing:a}=L(`get_online_plugins`,{text:we(e,1e3)}),o=Se();return(0,V.createElement)(V.Fragment,{},(0,V.createElement)(y,{value:e,onChange:t,start:(0,V.createElement)(Fe),typing:!0,label:`Search text`}),(0,V.createElement)(i,{error:r&&Me(F(r,N)),rows:n.length?n:[],noRows:`No compatible plugins have been found`,fillFlex:!0,initializing:a,columnVisibilityModel:o.onlinePluginsColumns,onColumnVisibilityModelChange:e=>Oe.onlinePluginsColumns=e,columns:[{field:`id`,headerName:`name`,flex:1,renderCell:O,mergeRender:{description:{sx:{fontSize:`x-small`}}}},{field:`version`,width:70},{field:`pushed_at`,headerName:`last update`,valueGetter:e=>new Date(e).toLocaleDateString()},{field:`license`,width:80},_t,m(m({},gt),{},{flex:3,hideUnder:`sm`}),{field:`stargazers_count`,width:50,headerName:`stars`,align:`center`,hideUnder:`sm`}],actions:({row:e,id:t})=>[(0,V.createElement)(f,{icon:Pe,title:`Install`,progress:e.downloading,disabled:e.installed&&`Already installed`,tooltipProps:{placement:`bottom-end`},onClick:()=>Ee(e)}),(0,V.createElement)(f,{icon:Re,disabled:!e.preview,onClick:()=>le({title:t,Content:()=>(0,V.createElement)(yt,{imgs:De(e.preview)})})})]}))}function yt({imgs:e}){let[t,n]=(0,V.useState)(0);return(0,V.createElement)(_,{vert:!0,flex:1},(0,V.createElement)(_,{vert:!0,center:!0,height:0,flex:`auto`,minHeight:`50vh`,minWidth:`50vw`},(0,V.createElement)(`img`,{src:e[t],style:{margin:`auto`,maxWidth:`100%`,maxHeight:`100%`}})),e.length>1&&(0,V.createElement)(_,{center:!0},(0,V.createElement)(f,{icon:Be,disabled:!t,onClick:()=>n(t-1)}),(0,V.createElement)(f,{icon:Ge,disabled:t>=e.length-1,onClick:()=>n(t+1)})))}var $=[{label:`Installed`,path:`installed`,Pane:Q},{label:`Get more`,path:`get`,Pane:vt},{label:`Check updates`,path:`updates`,Pane:()=>(0,V.createElement)(Q,{updates:!0})}],bt=$.map(e=>e.path);function xt(){let[e,t]=Ke(`plugins`,bt),{Pane:n}=$[e];return(0,V.createElement)(V.Fragment,{},(0,V.createElement)(s,{value:e,onChange(e,n){t(n)}},$.map(e=>(0,V.createElement)(o,{key:e.path,label:e.label}))),(0,V.createElement)(n))}export{xt as default};