better code
Massimo Melina committed
May 4, 2024 at 23:59 UTC
1e2a21b46741adb6d501a88595d053c3d60706af
7 files changed
+26
-33
admin/src/index.ts
-4
@@ -5,10 +5,6 @@ import { createRoot } from 'react-dom/client'
5
import './index.scss'
6
import '@hfs/shared/min-crypto-polyfill'
7
import App from './App'
8
-import { disableConsoleDebug } from '@hfs/shared'
9
-
10
-//@ts-ignore
11
-if (import.meta.env.PROD) disableConsoleDebug()
8
9
createRoot(document.getElementById('root')!)
10
.render( h(StrictMode, {}, h(App)) )
frontend/src/index.ts
-4
@@ -6,10 +6,6 @@ import './index.scss'
6
import '@hfs/shared/min-crypto-polyfill'
7
import '@hfs/shared/polyfills'
8
import App from './App'
9
-import { disableConsoleDebug } from '@hfs/shared'
10
-
11
-//@ts-ignore
12
-if (import.meta.env.PROD) disableConsoleDebug()
9
10
createRoot(document.getElementById('root')!)
11
.render( h(StrictMode, {}, h(App)) )
shared/index.ts
+6
-5
@@ -29,6 +29,12 @@ Object.assign(HFS, {
29
cpuSpeedIndex,
30
})
31
32
+//@ts-ignore
33
+if (import.meta.env.PROD) {
34
+ const was = console.debug
35
+ console.debug = (...args) => (window as any).DEV && was(...args)
36
+}
37
+
38
function getScriptAttr(k: string) {
39
return document.currentScript?.getAttribute(k)
40
|| console.error("this function must be called at the very top of your file")
@@ -114,11 +120,6 @@ export function focusSelector(selector: string, root: HTMLElement | Document=doc
120
}
121
}
122
117
-export function disableConsoleDebug() {
118
- const was = console.debug
119
- console.debug = (...args) => (window as any).DEV && was(...args)
120
-}
121
-
123
export function loadScript(url: string, more={}) {
124
const el = document.createElement('script')
125
el.type = 'text/javascript'
src/api.auth.ts
+2
-2
@@ -28,7 +28,7 @@ export const loginSrp1: ApiHandler = async ({ username }, ctx) => {
28
const sid = Math.random()
29
ongoingLogins[sid] = step1
30
setTimeout(()=> delete ongoingLogins[sid], 60_000)
31
- ctx.session.loggingIn = { username, sid }
31
+ ctx.session.loggingIn = { username, sid } // temporarily store until process is complete
32
return rest
33
}
34
catch (code: any) {
@@ -42,13 +42,13 @@ export const loginSrp2: ApiHandler = async ({ pubKey, proof }, ctx) => {
42
if (!ctx.session.loggingIn)
43
return new ApiError(HTTP_CONFLICT)
44
const { username, sid } = ctx.session.loggingIn
45
+ delete ctx.session.loggingIn
46
const step1 = ongoingLogins[sid]
47
if (!step1)
48
return new ApiError(HTTP_NOT_FOUND)
49
try {
50
const M2 = await step1.step2(BigInt(pubKey), BigInt(proof))
51
await setLoggedIn(ctx, username)
51
- delete ctx.session.loggingIn
52
return {
53
proof: String(M2),
54
redirect: ctx.state.account?.redirect,
src/plugins.ts
+3
-3
@@ -217,12 +217,12 @@ export class Plugin implements CommonPluginInterface {
217
}
218
}
219
220
-const SERVER_CODE_ID = '.'
220
+export const SERVER_CODE_ID = '.' // a name that will surely be not found among plugin folders
221
const serverCode = defineConfig('server_code', '', async (script, { k }) => {
222
const res: any = {}
223
try {
224
new Function('exports', script)(res) // parse
225
- return new Plugin(SERVER_CODE_ID, '', await initPlugin(res), _.noop) // '.' is a name that will surely be not found among plugin folders
225
+ return new Plugin(SERVER_CODE_ID, '', await initPlugin(res), _.noop)
226
}
227
catch (e: any) {
228
return console.error(k + ':', e.message || String(e))
@@ -246,7 +246,7 @@ type PluginMiddleware = (ctx:Koa.Context) => Promisable<void | Stop | CallMeAfte
246
type Stop = true
247
type CallMeAfter = ()=>any
248
249
-export type Repo = string | { web?: string, main: string, zip?: string, zipRoot?: string }
249
+export type Repo = string | { web?: string, main: string, zip?: string, zipRoot?: string } // string is github, object is custom
250
type Depend = { repo: string, version?: number }[]
251
export interface CommonPluginInterface {
252
id: string
src/serveGuiFiles.ts
+5
-5
@@ -73,7 +73,7 @@ async function treatIndex(ctx: Koa.Context, filesUri: string, body: string) {
73
ctx.set('Cache-Control', 'no-store, no-cache, must-revalidate')
74
ctx.type = 'html'
75
76
- const isFrontend = filesUri === FRONTEND_URI
76
+ const isFrontend = filesUri === FRONTEND_URI ? ' ' : '' // as a string will allow neater code later
77
78
const pub = ctx.state.revProxyPath + PLUGINS_PUB_URI
79
@@ -96,7 +96,7 @@ async function treatIndex(ctx: Koa.Context, filesUri: string, body: string) {
96
const isOpen = !isClose
97
if (isHead && isOpen)
98
return all + `
99
- ${!isFrontend ? '' : `
99
+ ${isFrontend && `
100
<title>${title.get()}</title>
101
<link rel="shortcut icon" href="/favicon.ico?${timestamp}" />
102
` + getSection('htmlHead')}
@@ -120,14 +120,14 @@ async function treatIndex(ctx: Koa.Context, filesUri: string, body: string) {
120
`
121
if (isBody && isOpen)
122
return all + `
123
- ${!isFrontend ? '' : getSection('top')}
123
+ ${isFrontend && getSection('top')}
124
<style>
125
:root {
126
- ${_.map(plugins, (configs, pluginName) =>
126
+ ${_.map(plugins, (configs, pluginName) => // make plugin configs accessible via css
127
_.map(configs, (v,k) => `--${pluginName}-${k}: ${serializeCss(v)};`).join('\n')).join('')}
128
}
129
</style>
130
- ${!isFrontend ? '' : mapPlugins((plug,id) =>
130
+ ${isFrontend && mapPlugins((plug,id) =>
131
plug.frontend_css?.map(f =>
132
`<link rel='stylesheet' type='text/css' href='${f.includes('//') ? f : pub + id + '/' + f}' plugin=${JSON.stringify(id)}/>`))
133
.flat().filter(Boolean).join('\n')}
src/throttler.ts
+10
-10
@@ -17,13 +17,17 @@ defineConfig('max_kbps', Infinity).sub(v =>
17
const ip2group: Record<string, {
18
count: number
19
group: ThrottleGroup
20
- destroy: () => void
20
}> = {}
21
22
const SymThrStr = Symbol('stream')
23
const SymTimeout = Symbol('timeout')
24
25
const maxKbpsPerIp = defineConfig('max_kbps_per_ip', Infinity)
26
+maxKbpsPerIp.sub(v => {
27
+ for (const [ip, {group}] of Object.entries(ip2group))
28
+ if (ip) // empty-string = unlimited group
29
+ group.updateLimit(v)
30
+})
31
32
export const throttler: Koa.Middleware = async (ctx, next) => {
33
await next()
@@ -34,14 +38,11 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
38
if (!body || !(body instanceof Readable))
39
return
40
// we wrap the stream also for unlimited connections to get speed and other features
37
- const ipGroup = getOrSet(ip2group, ctx.ip, ()=> {
38
- const doLimit = ctx.state.account?.ignore_limits || isLocalHost(ctx) ? undefined : true
39
- const group = new ThrottleGroup(Infinity, doLimit && mainThrottleGroup)
40
-
41
- const unsub = doLimit && maxKbpsPerIp.sub(v =>
42
- group.updateLimit(v))
43
- return { group, count:0, destroy: unsub }
44
- })
41
+ const noLimit = ctx.state.account?.ignore_limits || isLocalHost(ctx)
42
+ const ipGroup = getOrSet(ip2group, noLimit ? '' : ctx.ip, () => ({
43
+ count:0,
44
+ group: new ThrottleGroup(noLimit ? Infinity : maxKbpsPerIp.get(), noLimit ? undefined : mainThrottleGroup),
45
+ }))
46
const conn = getConnection(ctx)
47
if (!conn) throw 'assert throttler connection'
48
@@ -72,7 +73,6 @@ export const throttler: Koa.Middleware = async (ctx, next) => {
73
update.flush()
74
closed = true
75
if (--ipGroup.count) return // any left?
75
- ipGroup.destroy?.()
76
delete ip2group[ctx.ip]
77
})
78