start console messages with uppercase

Massimo Melina committed Apr 7, 2026 at 11:11 UTC 8bfbdba64655ce12ce41417bd5e14056207641e2
33 files changed +124 -124
src/QuickZipStream.ts
+1 -1
@@ -160,7 +160,7 @@ export class QuickZipStream extends Readable {
160 const data = this.workingFile = getData()
161 data.on('error', (err) => {
162 if ((err as any)?.code !== 'EACCES')
163 - console.error('zipping:', String(err))
163 + console.error('Zipping:', String(err))
164 data.destroy(err)
165 resolve()
166 })
src/acme.ts
+8 -8
@@ -19,7 +19,7 @@ const acmeListener = (req: IncomingMessage, res: ServerResponse) => { // node li
19 const BASE = '/.well-known/acme-challenge/'
20 if (!req.url?.startsWith(BASE)) return
21 const token = req.url.slice(BASE.length)
22 - console.debug("got http challenge", token)
22 + console.debug("Got http challenge", token)
23 res.statusCode = HTTP_OK
24 res.end(acmeTokens[token])
25 return true // true = responded
@@ -50,17 +50,17 @@ async function generateSSLCert(domain: string, email?: string, altNames?: string
50 if (tempSrv)
51 await new Promise<void>(resolve =>
52 tempSrv.listen(80, resolve).on('error', (e: any) => {
53 - console.debug("cannot listen on 80", e.code || e)
53 + console.debug("Cannot listen on 80", e.code || e)
54 resolve() // go on anyway
55 }) )
56 acmeOngoing = true
57 - console.debug("acme challenge server ready")
57 + console.debug("ACME challenge server ready")
58 let tempMap: any
59 try {
60 const checkUrl = `http://${domain.split(',')[0]}`
61 let check = await selfCheck(checkUrl) // some check services may not consider the domain, but we already verified that
62 if (check?.success === false && nat.upnp && !nat.mapped80) {
63 - console.debug("setting temporary port forward")
63 + console.debug("Setting temporary port forward")
64 tempMap = await haveTimeout(10_000, upnpClient.createMapping(TEMP_MAP).catch(() => {})).catch(() => {})
65 check = await selfCheck(checkUrl) // repeat test
66 }
@@ -82,17 +82,17 @@ async function generateSSLCert(domain: string, email?: string, altNames?: string
82 async challengeCreateFn(_, c, ka) { acmeTokens[c.token] = ka },
83 async challengeRemoveFn(_, c) { delete acmeTokens[c.token] },
84 })
85 - console.log("acme certificate generated")
85 + console.log("ACME certificate generated")
86 return { key, cert }
87 }
88 finally {
89 if (tempMap) {
90 - console.debug("removing temporary port forward")
90 + console.debug("Removing temporary port forward")
91 upnpClient.removeMapping(TEMP_MAP).catch(() => {}) // clean after ourselves
92 }
93 acmeOngoing = false
94 if (tempSrv) await new Promise(res => tempSrv.close(res))
95 - console.debug('acme terminated')
95 + console.debug('ACME terminated')
96 }
97 }
98
@@ -127,7 +127,7 @@ const renewCert = debounceAsync(async () => {
127 const validTo = new Date(cert.validTo)
128 // not expiring in a month
129 if (now > new Date(cert.validFrom) && now < validTo && validTo.getTime() - now.getTime() >= 30 * DAY)
130 - return console.log("certificate still good")
130 + return console.log("Certificate still good")
131 await makeCert(domain, undefined, altNames)
132 .catch(e => console.log(acmeRenewError = `Error renewing certificate, expiring ${formatDate(validTo)}: ${String(e.message || e)}`))
133 }, { retain: DAY, retainFailure: HOUR })
src/api.get_file_list.ts
+1 -1
@@ -94,7 +94,7 @@ export const get_file_list: ApiHandler = async ({ uri='/', offset, limit, c, onl
94 continue
95 }
96 catch(e) {
97 - console.log("a plugin with onDirEntry is causing problems:", e)
97 + console.log("A plugin with onDirEntry is causing problems:", e)
98 }
99 if (offset) {
100 --offset
src/block.ts
+1 -1
@@ -35,7 +35,7 @@ setInterval(() => { // twice a minute, check if any block has expired
35 const next = block.get().filter(x => !x.expire || x.expire > now)
36 const n = block.get().length - next.length
37 if (!n) return
38 - console.log("blocking rules:", n, "expired")
38 + console.log("Blocking rules:", n, "expired")
39 block.set(next)
40 }, MINUTE/2)
41
src/commands.ts
+8 -8
@@ -56,7 +56,7 @@ if (!argv.updating && !showHelp) {
56
57 }
58 catch {
59 - console.log("console commands not available")
59 + console.log("Console commands not available")
60 const original = console.debug
61 console.debug = (...args: any[]) => debugEnabled && original(...args)
62 }
@@ -72,17 +72,17 @@ async function parseCommandLine(line: string) {
72 if (cmd?.alias)
73 cmd = (commands as any)[cmd.alias]
74 if (!cmd)
75 - return console.error("invalid command, try 'help'")
75 + return console.error("Invalid command, try 'help'")
76 if (cmd.cb.length > params.length)
77 - return console.error("insufficient parameters, expected: " + cmd.params)
77 + return console.error("Insufficient parameters, expected: " + cmd.params)
78 try {
79 await cmd.cb(...params)
80 - console.log("+++ command executed")
80 + console.log("+++ Command executed")
81 }
82 catch(err: any) {
83 if (typeof err !== 'string' && !err?.message)
84 throw err
85 - console.error("command failed:", err.message || err)
85 + console.error("Command failed:", err.message || err)
86 }
87 }
88
@@ -92,7 +92,7 @@ const commands = {
92 help: {
93 params: '',
94 cb() {
95 - console.log("available commands:",
95 + console.log("Available commands:",
96 ..._.map(commands, ({ params }, name) =>
97 '\n - ' + name + ' ' + params))
98 }
@@ -151,7 +151,7 @@ const commands = {
151 const update = await getBestUpdate()
152 if (!update)
153 throw "you already have the latest version: " + VERSION
154 - console.log("new version available", update.name)
154 + console.log("New version available", update.name)
155 }
156 },
157 version: {
@@ -164,7 +164,7 @@ const commands = {
164 params: '',
165 cb() {
166 debugEnabled = !debugEnabled
167 - console.log(`debug messages ${debugEnabled ? "on" : "off"}`)
167 + console.log(`Debug messages ${debugEnabled ? "on" : "off"}`)
168 }
169 },
170 'start-plugin': {
src/config.ts
+1 -1
@@ -199,7 +199,7 @@ function stringify(obj: any) {
199 }
200
201 let startedWithoutConfig = false
202 -console.log("config", filePath)
202 +console.log("Config", filePath)
203 export const configFile = watchLoad(filePath, text => {
204 startedWithoutConfig = !text
205 try { return setConfig(yaml.parse(text, { uniqueKeys: false }) || {}, false) }
src/connections.ts
+1 -1
@@ -93,7 +93,7 @@ export function disconnect(what: Context | Socket | Connection, logMessage='') {
93 what = what.socket
94 const ip = normalizeIp(what.remoteAddress || '')
95 if (logMessage)
96 - console.debug("disconnection:", logMessage, ip)
96 + console.debug("Disconnection:", logMessage, ip)
97 ip2country(ip).then(res => {
98 const rec = { ip, country: res || undefined, ts: new Date, msg: logMessage || undefined }
99 disconnectionsLog.unshift(rec)
src/const.ts
+10 -10
@@ -17,7 +17,7 @@ export const COMPATIBLE_API_VERSION = 1 // the day we break with the past, we'll
17 export const ARGS_FILE = join(homedir(), 'hfs-args')
18 try {
19 const s = fs.readFileSync(ARGS_FILE, 'utf-8')
20 - console.log('additional arguments', s)
20 + console.log('Additional arguments', s)
21 _.defaults(argv, minimist(JSON.parse(s)))
22 fs.unlinkSync(ARGS_FILE)
23 }
@@ -48,9 +48,9 @@ if (DEV) {
48 }
49 console.log(`HFS ~ HTTP File Server`)
50 console.log(`© Massimo Melina <a@rejetto.com> - License https://www.gnu.org/licenses/gpl-3.0.txt`)
51 -console.log('started', formatTimestamp(HFS_STARTED), DEV)
52 -console.log('version', VERSION||'-')
53 -console.log('build', BUILD_TIMESTAMP||'-')
51 +console.log('Started', formatTimestamp(HFS_STARTED), DEV)
52 +console.log('Version', VERSION||'-')
53 +console.log('Build', BUILD_TIMESTAMP||'-')
54 // still considering whether to use ".hfs" with Windows users, who may be less accustomed to it
55 const dir = argv.cwd || useHomeDir() && join(homedir(), '.hfs')
56 if (dir) {
@@ -63,14 +63,14 @@ if (dir) {
63 }
64 else if (process.cwd().startsWith(process.env.windir + '\\')) // this happens if you run hfs from task scheduler
65 process.chdir(APP_PATH)
66 -console.log('working directory (cwd)', process.cwd())
66 +console.log('Working directory (cwd)', process.cwd())
67 if (APP_PATH !== process.cwd())
68 - console.log('app', APP_PATH)
69 -console.log('node', process.version)
68 + console.log('App', APP_PATH)
69 +console.log('Node', process.version)
70 const bun = (globalThis as any).Bun
71 -if (bun) console.log('bun', bun.version)
72 -console.log('platform', process.platform, process.arch, IS_BINARY ? 'binary' : basename(process.execPath))
73 -console.log('pid', process.pid)
71 +if (bun) console.log('Bun', bun.version)
72 +console.log('Platform', process.platform, process.arch, IS_BINARY ? 'binary' : basename(process.execPath))
73 +console.log('Pid', process.pid)
74
75 function useHomeDir() {
76 if (!IS_WINDOWS || !IS_BINARY) return true
src/ddns.ts
+1 -1
@@ -54,7 +54,7 @@ dynamicDnsUrl.sub(v => {
54 }))
55 last = _.find(all, 'error') || all[0] // the system is designed for just one result, and we give precedence to errors
56 events.emit('dynamicDnsError', last)
57 - console.log('dynamic dns update', last?.error || 'ok')
57 + console.log('Dynamic dns update', last?.error || 'ok')
58 }, { callNow: true })
59 })
60
src/fileAttr.ts
+2 -2
@@ -35,7 +35,7 @@ export async function storeFileAttr(path: string, k: string, v: any) {
35 else await fileAttrDb.open(FN)
36 // pipe should be a safe separator
37 return await fileAttrDb.put(`${path}|${k}`, v)?.catch((e: any) => {
38 - console.error("couldn't store metadata on", path, String(e.message || e))
38 + console.error("Couldn't store metadata on", path, String(e.message || e))
39 return false
40 }) ?? true // if put is undefined, the value was already there
41 }
@@ -56,5 +56,5 @@ export async function purgeFileAttr() {
56 }))
57 if (n)
58 await fileAttrDb.rewrite()
59 - console.log(`removed ${n} entrie(s)`)
59 + console.log(`Removed ${n} entrie(s)`)
60 }
\ No newline at end of file
src/first.ts
+2 -2
@@ -12,9 +12,9 @@ export let quitting = false
12 // 'exit' event is handled as the last resort, but it's not compatible with async callbacks
13 onFirstEvent(process, ['exit', 'SIGQUIT', 'SIGTERM', 'SIGINT', 'SIGHUP'], signal => {
14 quitting = true
15 - console.log('quitting', signal || '')
15 + console.log('Quitting', signal || '')
16 return Promise.allSettled(Array.from(cbsOnExit).map(cb => cb(signal))).then(() => {
17 - console.debug('process exit')
17 + console.debug('Process exit')
18 process.exit(0)
19 })
20 })
src/geo.ts
+2 -2
@@ -46,7 +46,7 @@ async function checkFiles() {
46 if (+mtime < now - 31 * DAY) // month-old or non-existing
47 try {
48 const req = await httpStream(URL)
49 - console.log(`downloading ${name}`)
49 + console.log(`Downloading ${name}`)
50 await unzip(req, path => path.toUpperCase().endsWith(ZIP_FILE) && TEMP)
51 await statWithTimeout(TEMP) // check existence
52 if (isOpen())
@@ -60,6 +60,6 @@ async function checkFiles() {
60 console.error(`Failed to download ${name}${mtime ? ", falling back on old data" : ''}:`, e?.message || String(e))
61 }
62 else if (isOpen()) return
63 - console.debug(`loading ${name}`)
63 + console.debug(`Loading ${name}`)
64 ip2location.open(LOCAL_FILE) // using openAsync causes a DEP0137 error within 10 seconds
65 }
src/github.ts
+5 -5
@@ -57,7 +57,7 @@ export async function downloadPlugin(repo: Repo, { branch='', overwrite=false }=
57 const msg = await isPluginBlacklisted(repo) // check before downloading, in case other filters were passed somehow
58 if (msg)
59 throw new ApiError(HTTP_FORBIDDEN, "blacklisted: " + msg)
60 - console.log('downloading plugin', repo)
60 + console.log('Downloading plugin', repo)
61 downloadProgress(repo, true)
62 try {
63 const pl = findPluginByRepo(repo)
@@ -117,7 +117,7 @@ export async function downloadPlugin(repo: Repo, { branch='', overwrite=false }=
117 }
118 }
119 catch (e) { // don't abort the whole procedure just because of the check above. It should never fail, but a user reported a mysterious ENOENT on the readFile()
120 - console.warn("plugin's repo check failed", e)
120 + console.warn("Plugin's repo check failed", e)
121 }
122 // ready to replace
123 const wasRunning = isPluginRunning(folder)
@@ -130,10 +130,10 @@ export async function downloadPlugin(repo: Repo, { branch='', overwrite=false }=
130 const deleteMe = installPath + DELETE_ME_SUFFIX
131 await retry(() => rename(installPath, deleteMe).then(() => 1, (e: any) => {
132 if (e.code === 'ENOENT') return 1 // nothing to do
133 - console.warn("error renaming old plugin folder:", String(e))
133 + console.warn("Error renaming old plugin folder:", String(e))
134 }))
135 await retry(() => rm(deleteMe, { recursive: true, force: true /*ignore ENOENT*/ }).then(() => 1, e => {
136 - console.warn("error deleting old plugin folder:", String(e))
136 + console.warn("Error deleting old plugin folder:", String(e))
137 }))
138 // final replace
139 await rename(tempInstallPath, installPath)
@@ -318,7 +318,7 @@ export const getProjectInfo = debounceAsync(async () => {
318 const black = onlyTruthy(Object.keys(obj.repo_blacklist || {}).map(findPluginByRepo))
319 blacklistedInstalledPlugins = onlyTruthy(black.map(x => _.isString(x.repo) && x.repo))
320 if (black.length) {
321 - console.log("blacklisted plugins found:", black.join(', '))
321 + console.log("Blacklisted plugins found:", black.join(', '))
322 for (const p of black)
323 enablePlugin(p.id, false)
324 }
src/i18n.ts
+2 -2
@@ -45,7 +45,7 @@ export function i18nFromTranslations(translations: Record<string, any>, embedded
45 if (found) break
46 if (!warns.has(key) && langs.length && langs[0] !== embedded) {
47 warns.add(key)
48 - console.debug("miss i18n:", key)
48 + console.debug("i18n miss:", key)
49 }
50 }
51 if (!found) {
@@ -106,7 +106,7 @@ export function i18nFromTranslations(translations: Record<string, any>, embedded
106 ofs++
107 }
108 if (stack)
109 - return console.debug('tokenizer: unclosed') // invalid, abort
109 + return console.debug('Tokenizer: unclosed') // invalid, abort
110 yield [s.slice(open + 1, ofs-1), true]
111 }
112 yield [s.slice(ofs), false]
src/index.ts
+2 -2
@@ -68,12 +68,12 @@ function errorHandler(err: Error & { code?: string, path?: string }) {
68 || code === 'ERR_STREAM_WRITE_AFTER_END' // happens disconnecting uploads, don't care
69 || code === 'ERR_STREAM_PREMATURE_CLOSE' // happens when many files are sent (not locally), but I checked that the files are written completely. Introduced after node18.5.0 and is thrown by pipeline() used by PUT method handler.
70 || code?.startsWith('HPE')) return // malformed client/probe HTTP parser errors, not internal failures
71 - console.error('server error', err)
71 + console.error('Server error', err)
72 }
73
74 process.on('uncaughtException', (err: any) => {
75 if (err.syscall !== 'watch' && err.code !== 'ECONNRESET' && err.code !== 'EIO') // EIO seems to happen when the terminal is closed
76 - try { console.error("uncaught:", err) }
76 + try { console.error("Uncaught:", err) }
77 catch {} // in case we are writing to a closed terminal, we may throw with "write eio at afterwritedispatched", causing an infinite loop
78 })
79 // this warning is scaring users, and has been removed in node 20.12.0 https://github.com/nodejs/node/pull/51204
src/listen.ts
+9 -9
@@ -89,14 +89,14 @@ export function openAdmin() {
89 const baseUrl = `${srv!.name}://${hostname}:${a.port}`
90 open(baseUrl + ADMIN_URI, { wait: true}).catch(async e => {
91 console.debug(String(e))
92 - console.warn("cannot launch browser on this machine >PLEASE< open your browser and reach one of these (you may need a different address)",
92 + console.warn("Cannot launch browser on this machine >PLEASE< open your browser and reach one of these (you may need a different address)",
93 ...Object.values(await getUrls()).flat().map(x => '\n - ' + x + ADMIN_URI))
94 if (! anyAccountCanLoginAdmin())
95 consoleHint(`you can enter this command: create-admin YOUR_PASSWORD`)
96 })
97 return true
98 }
99 - console.log("openAdmin failed")
99 + console.log("OpenAdmin failed")
100 }
101
102 export function getCertObject() {
@@ -131,7 +131,7 @@ const considerHttps = debounceAsync(async () => {
131 if (certObj) {
132 const cn = certObj.subject?.CN
133 if (cn)
134 - console.log("certificate loaded for", certObj.altNames?.join(' + ') || cn)
134 + console.log("Certificate loaded for", certObj.altNames?.join(' + ') || cn)
135 const now = new Date()
136 const from = new Date(certObj.validFrom)
137 const to = new Date(certObj.validTo)
@@ -158,7 +158,7 @@ const considerHttps = debounceAsync(async () => {
158 catch(e: any) {
159 httpsSrv ||= Object.assign(https.createServer({}), { name: 'https' }) // a dummy container, in case creation failed because of certificate errors
160 httpsSrv.error = "bad private key or certificate"
161 - console.error("failed to create https server: check your private key and certificate", e.message)
161 + console.error("Failed to create https server: check your private key and certificate", e.message)
162 return
163 }
164 httpsSrv.on('connection', newConnection) // this event is emitted as soon as the tcp layer is connected
@@ -215,12 +215,12 @@ export function startServer(srv: typeof httpSrv, { port, host }: StartServer) {
215 srv.on('checkContinue', (req, res) => srv.emit('request', req, res))
216 port = await listen(host)
217 if (port)
218 - console.log(srv.name, "serving on", renderHost(host || ''), ':', port)
218 + console.log(srv.name, "Serving on", renderHost(host || ''), ':', port)
219 resolve(port)
220 }
221 catch(e) {
222 srv.error = String(e)
223 - console.error(srv.name, `couldn't listen on port ${port}:`, srv.error)
223 + console.error(srv.name, `Couldn't listen on port ${port}:`, srv.error)
224 resolve(0)
225 }
226 })
@@ -273,10 +273,10 @@ export function stopServer(srv?: http.Server) {
273 return resolve(null)
274 const ad = srv.address()
275 if (ad && typeof ad !== 'string')
276 - console.log("stopped port", ad.port)
276 + console.log("Stopped port", ad.port)
277 srv.close(err => {
278 if (err && (err as any).code !== 'ERR_SERVER_NOT_RUNNING')
279 - console.debug("failed to stop server", String(err))
279 + console.debug("Failed to stop server", String(err))
280 resolve(err)
281 })
282 srv.closeAllConnections()
@@ -343,5 +343,5 @@ export async function getUrls() {
343 function printUrls(srvName: string) {
344 getUrls().then(urls =>
345 _.each(urls[srvName], url =>
346 - console.log('serving on', url)))
346 + console.log('Serving on', url)))
347 }
src/log.ts
+4 -4
@@ -37,7 +37,7 @@ class Logger {
37 }
38 catch {
39 if (await ensureParentFolder(path) === false)
40 - console.log("cannot create folder for", path)
40 + console.log("Cannot create folder for", path)
41 }
42 this.reopen()
43 }
@@ -54,13 +54,13 @@ const accessErrorLog = new Logger(CFG.error_log)
54 export const loggers = [accessLogger, accessErrorLog]
55
56 defineConfig(accessLogger.name, 'logs/access.log').sub(path => {
57 - console.debug('access log file: ' + (path || 'disabled'))
57 + console.debug('Access log file: ' + (path || 'disabled'))
58 accessLogger.setPath(path)
59 })
60
61 const errorLogFile = defineConfig(accessErrorLog.name, 'logs/access-error.log')
62 errorLogFile.sub(path => {
63 - console.debug('access error log: ' + (path || 'disabled'))
63 + console.debug('Access error log: ' + (path || 'disabled'))
64 accessErrorLog.setPath(path)
65 })
66
@@ -204,4 +204,4 @@ debugLogFile.once('open', () => {
204 renameSync(path, 'old-' + path)
205 debugLogFile = createWriteStream(path) // new file
206 })
207 -}).on('error', () => console.log("cannot create debug.log"))
207 +}).on('error', () => console.log("Cannot create debug.log"))
src/middlewares.ts
+1 -1
@@ -143,7 +143,7 @@ export function failAllowNet(ctx: Koa.Context, a: Account | undefined) {
143 ctx.session.allowNet = mask // must be deleted on logout by setLoggedIn
144 const ret = mask && !netMatches(ctx.ip, mask, true)
145 if (ret)
146 - console.debug("login failed: allow_net")
146 + console.debug("Login failed: allow_net")
147 return ret
148 }
149
src/misc.ts
+1 -1
@@ -68,7 +68,7 @@ export function makeNetMatcher(mask: string, emptyMaskReturns=false) {
68 return (ip: string) => {
69 try { return neg !== bl.check(parseAddress(ip)) }
70 catch {
71 - console.error("invalid address ", ip)
71 + console.error("Invalid address ", ip)
72 return false
73 }
74 }
src/nat.ts
+4 -4
@@ -31,8 +31,8 @@ const originalMethod = upnpClient.getGateway
31 // other client methods call getGateway too, so this will ensure they reuse this same result
32 upnpClient.getGateway = debounceAsync(() => originalMethod.apply(upnpClient), { retain: HOUR, retainFailure: 30_000 })
33 upnpClient.getGateway().then(res => {
34 - console.log("upnp found", res.gateway.description)
35 -}, e => console.debug('upnp failed:', e.message || String(e)))
34 + console.log("UPnP found", res.gateway.description)
35 +}, e => console.debug('UPnP failed:', e.message || String(e)))
36
37 // poll external ip – asking the modem is cheap, so it can be done often
38 repeat(MINUTE, () => upnpClient.getPublicIp().then(v => {
@@ -48,7 +48,7 @@ export const getPublicIps = debounceAsync(async () => {
48 Promise.any(singleVersion.map(async (svc: any) => {
49 if (typeof svc === 'string')
50 svc = { type: 'http', url: svc }
51 - console.debug("trying ip service", svc.url || svc.name)
51 + console.debug("Trying ip service", svc.url || svc.name)
52 if (svc.type === 'http') {
53 const timeout = 5_000
54 return httpString(svc.url, { timeout, proxy: '' }).catch(e => { // first try without a proxy
@@ -74,7 +74,7 @@ export const getNatInfo = debounceAsync(async () => {
74 const res = await haveTimeout(10_000, upnpClient.getGateway()).catch(() => null)
75 const status = await getServerStatus()
76 const mappings = res && await haveTimeout(5_000, upnpClient.getMappings()).catch(() => null)
77 - console.debug("mappings found:", mappings?.map(x => x.description).join(', ') || "none")
77 + console.debug("Mappings found:", mappings?.map(x => x.description).join(', ') || "none")
78 const localIps = await getIps(false)
79 const gatewayIp = await gatewayIpPromise
80 const localIp = res?.address || (gatewayIp ? _.maxBy(localIps, x => inCommon(x, gatewayIp)) : localIps[0])
src/outboundProxy.ts
+4 -4
@@ -11,12 +11,12 @@ const outboundProxy = defineConfig(CFG.outbound_proxy, '', v => {
11 httpStream.defaultProxy = v
12 if (!v || process.env.HFS_SKIP_PROXY_TEST) return
13 const test = 'https://google.com'
14 - console.debug("testing proxy using", test)
14 + console.debug("Testing proxy using", test)
15 httpString(test, { noRedirect: true }).catch(e =>
16 - console.error(`proxy test failed on ${test} : ${e?.errors?.[0] || e}`)) // `.errors` in case of AggregateError
16 + console.error(`Proxy test failed on ${test} : ${e?.errors?.[0] || e}`)) // `.errors` in case of AggregateError
17 }
18 catch {
19 - console.warn("invalid URL", v)
19 + console.warn("Invalid URL", v)
20 return ''
21 }
22 })
@@ -34,5 +34,5 @@ configReady.then(async ([startedWithoutConfig]) => {
34 || !read.includes('=') && 'http://' + read // simpler form
35 if (!url) return
36 outboundProxy.set(url)
37 - console.log("detected proxy", read)
37 + console.log("Detected proxy", read)
38 })
\ No newline at end of file
src/perm.ts
+4 -4
@@ -73,7 +73,7 @@ createAdminConfig.sub(v => {
73
74 export async function createAdmin(password: string, username='admin') {
75 const acc = await addAccount(username, { admin: true, password }, true)
76 - console.log(acc ? "account admin set" : "something went wrong")
76 + console.log(acc ? "Account admin set" : "Something went wrong")
77 }
78
79 const srp6aNimbusRoutines = new SRPRoutines(new SRPParameters())
@@ -94,7 +94,7 @@ export async function updateAccount(account: Account, change: Partial<Account> |
94 if (!v) delete account[k] // we consider all account fields, when falsy, as equivalent to be missing (so, default value applies)
95 const { username, password } = account
96 if (password) {
97 - console.debug('hashing password for', username)
97 + console.debug('Hashing password for', username)
98 delete account.password
99 const res = await createVerifierAndSalt(srp6aNimbusRoutines, username, password)
100 saveSrpInfo(account, res.s, res.v)
@@ -103,7 +103,7 @@ export async function updateAccount(account: Account, change: Partial<Account> |
103 account.belongs = wantArray(account.belongs)
104 _.remove(account.belongs, b => {
105 if (accounts.get().hasOwnProperty(b)) return
106 - console.error(`account ${username} belongs to non-existing ${b}`)
106 + console.error(`Account ${username} belongs to non-existing ${b}`)
107 return true
108 })
109 if (!account.belongs.length)
@@ -245,4 +245,4 @@ declare module "koa" {
245 interface DefaultState {
246 usernames?: Set<string>
247 }
248 -}
\ No newline at end of file
248 +}
src/plugins.ts
+17 -17
@@ -64,7 +64,7 @@ export function enablePlugin(id: string, state=true) {
64 enablePlugins.set(arr => {
65 if (arr.includes(id) === state)
66 return arr
67 - console.log("switching plugin", id, state ? "on" : "off")
67 + console.log("Switching plugin", id, state ? "on" : "off")
68 return arr.includes(id) === state ? arr
69 : state ? [...arr, id]
70 : arr.filter((x: string) => x !== id)
@@ -192,7 +192,7 @@ export const pluginsMiddleware: Koa.Middleware = async (ctx, next) => {
192 ctx.stop()
193 // don't just check ctx.isStopped, as the async plugin that called ctx.stop will reach here after sync ones
194 if (ctx.isStopped && !ctx.pluginBlockedRequest)
195 - console.debug("plugin blocked request", ctx.pluginBlockedRequest = id)
195 + console.debug("Plugin blocked request", ctx.pluginBlockedRequest = id)
196 if (typeof res === 'function')
197 after[id] = res
198 }
@@ -228,13 +228,13 @@ export const pluginsMiddleware: Koa.Middleware = async (ctx, next) => {
228
229 function printChange(id: string) {
230 if (id === SERVER_CODE_ID || (lastStatus === ctx.status && lastBody === ctx.body)) return
231 - console.debug("plugin changed response:", id)
231 + console.debug("Plugin changed response:", id)
232 lastStatus = ctx.status
233 lastBody = ctx.body
234 }
235
236 function printError(id: string, e: any) {
237 - console.log(`error middleware plugin ${id}: ${e?.message || e}`)
237 + console.log(`Error middleware plugin ${id}: ${e?.message || e}`)
238 console.debug(e)
239 }
240 }
@@ -270,7 +270,7 @@ export class Plugin implements CommonPluginInterface {
270 data[k] = [v]
271 else if (v && !Array.isArray(v)) {
272 delete data[k]
273 - console.warn('invalid', k)
273 + console.warn('Invalid', k)
274 }
275 }
276 plugins.set(id, this)
@@ -323,11 +323,11 @@ export class Plugin implements CommonPluginInterface {
323 const { id } = this
324 try { await this.data?.unload?.() }
325 catch(e) {
326 - console.log('error unloading plugin', id, String(e))
326 + console.log('Error unloading plugin', id, String(e))
327 }
328 await this.onUnload()
329 if (!reloading && id !== SERVER_CODE_ID) // we already printed 'reloading'
330 - console.log('unloaded plugin', id)
330 + console.log('Unloaded plugin', id)
331 if (this.data)
332 this.data.unload = undefined
333 }
@@ -355,7 +355,7 @@ export function mapPlugins<T>(cb:(plugin:Readonly<Plugin>, pluginName:string, id
355 if (!includeServerCode && plName === SERVER_CODE_ID) return
356 try { return cb(pl,plName,i++) }
357 catch(e) {
358 - console.log('plugin error', plName, String(e))
358 + console.log('Plugin error', plName, String(e))
359 }
360 }).filter(x => x !== undefined) as Exclude<T,undefined>[]
361 }
@@ -369,7 +369,7 @@ export function firstPlugin<T>(cb:(plugin:Readonly<Plugin>, pluginName:string)=>
369 return ret
370 }
371 catch(e) {
372 - console.log('plugin error', plName, String(e))
372 + console.log('Plugin error', plName, String(e))
373 }
374 }
375 }
@@ -420,7 +420,7 @@ export const PLUGIN_MAIN_FILE = 'plugin.js'
420 const pluginWatchers = new Map<string, ReturnType<typeof watchPlugin>>()
421
422 export async function rescan() {
423 - console.debug('scanning plugins')
423 + console.debug('Scanning plugins')
424 const patterns = [PATH + '/*']
425 if (APP_PATH !== process.cwd())
426 patterns.unshift(escapeGlobPath(APP_PATH) + '/' + patterns[0]) // first search bundled plugins, because otherwise they won't be loaded because of the folders with same name in .hfs/plugins (used for storage)
@@ -442,7 +442,7 @@ export async function rescan() {
442 }
443
444 function watchPlugin(id: string, path: string) {
445 - console.debug('plugin watch', id)
445 + console.debug('Plugin watch', id)
446 const module = resolve(path)
447 let starting: PendingPromise | undefined
448 const unsub = subMultipleConfigs(() => {
@@ -465,7 +465,7 @@ function watchPlugin(id: string, path: string) {
465 events.emit(notRunning ? 'pluginUpdated' : 'pluginInstalled', p)
466 })
467 return () => {
468 - console.debug('plugin unwatch', id)
468 + console.debug('Plugin unwatch', id)
469 unsub()
470 unwatch()
471 return onUninstalled()
@@ -509,7 +509,7 @@ function watchPlugin(id: string, path: string) {
509 if (getPluginInfo(id))
510 setError(id, '')
511 const alreadyRunning = plugins.get(id)
512 - console.log(alreadyRunning ? "reloading plugin" : "loading plugin", id)
512 + console.log(alreadyRunning ? "Reloading plugin" : "Loading plugin", id)
513 const pluginData = require(module)
514 deleteModule(require.resolve(module)) // avoid caching at next import
515 calculateBadApi(pluginData)
@@ -517,7 +517,7 @@ function watchPlugin(id: string, path: string) {
517 throw Error(pluginData.badApi)
518
519 await alreadyRunning?.unload(true)
520 - console.debug("starting plugin", id)
520 + console.debug("Starting plugin", id)
521 const storageDir = resolve(PATH, id, STORAGE_FOLDER) + (IS_WINDOWS ? '\\' : '/')
522 await mkdir(storageDir, { recursive: true })
523 const openDbs: KvStorage[] = []
@@ -536,7 +536,7 @@ function watchPlugin(id: string, path: string) {
536 return db
537 },
538 log(...args: any[]) {
539 - console.log('plugin', id+':', ...args)
539 + console.log('Plugin', id+':', ...args)
540 pluginReady.then(() => { // log() maybe invoked during init(), while plugin is undefined
541 if (!plugin) return
542 const msg = { ts: new Date, msg: args.map(x => x && typeof x === 'object' ? JSON.stringify(x) : String(x)).join(' ') }
@@ -626,7 +626,7 @@ function setError(id: string, error: string) {
626 info.error = error
627 events.emit('pluginUpdated', info)
628 if (!error) return
629 - console.warn(`plugin error: ${id}:`, error)
629 + console.warn(`Plugin error: ${id}:`, error)
630 return true
631 }
632
@@ -663,7 +663,7 @@ export function parsePluginSource(id: string, source: string) {
663 pl.preview = tryJson(/exports.preview\s*=\s*("(?:[^"\\]|\\.)*"|\[[\s\S]*?\])/.exec(source)?.[1]) ?? undefined
664 pl.depend = tryJson(/exports.depend\s*=\s*(\[[\s\S]*?])/m.exec(source)?.[1])?.filter((x: any) =>
665 typeof x.repo === 'string' && x.version === undefined || typeof x.version === 'number'
666 - || console.warn("plugin dependency discarded", x) )
666 + || console.warn("Plugin dependency discarded", x) )
667 pl.changelog = tryJson(/exports.changelog\s*=\s*(\[[\s\S]*?])/m.exec(source)?.[1])
668 if (Array.isArray(pl.apiRequired) && (pl.apiRequired.length !== 2 || !pl.apiRequired.every(_.isFinite))) // validate [from,to] form
669 pl.apiRequired = undefined
src/selfCheck.ts
+2 -2
@@ -33,7 +33,7 @@ export async function selfCheck(url: string) {
33 regexpSuccess: string
34 }
35 const prjInfo = await getProjectInfo()
36 - console.log(`checking server ${url}`)
36 + console.log(`Checking server ${url}`)
37 const parsed = new URL(url)
38 const family = !isIP(parsed.hostname) ? undefined : isIPv6(parsed.hostname) ? 6 : 4
39 try {
@@ -44,7 +44,7 @@ export async function selfCheck(url: string) {
44 if (!svc.url || svc.type) throw 'unsupported ' + svc.type // only default type supported for now
45 let { url: serviceUrl, body, regexpSuccess, regexpFailure, ...rest } = svc
46 const service = new URL(serviceUrl).hostname
47 - console.log('trying external service', service)
47 + console.log('Trying external service', service)
48 console.debug(svc)
49 body = applySymbols(body)
50 serviceUrl = applySymbols(serviceUrl)!
src/serveGuiAndSharedFiles.ts
+2 -2
@@ -180,9 +180,9 @@ async function calcHash(fn: string, limit=Infinity) {
180 }
181 })
182 fs.createReadStream(fn, { end: limit - 1 }).pipe(stream)
183 - console.debug('hashing', fn)
183 + console.debug('Hashing', fn)
184 await once(stream, 'finish')
185 - console.debug('hashed', fn)
185 + console.debug('Hashed', fn)
186 return hash.digest().toString(16)
187 }
188
src/serveGuiFiles.ts
+1 -1
@@ -182,7 +182,7 @@ function serializeCss(v: any) {
182 function serveProxied(port: string | undefined, uri: string) { // used for development only
183 if (!port)
184 return
185 - console.debug('proxied on port', port)
185 + console.debug('Proxied on port', port)
186 let proxy: Koa.Middleware
187 import('koa-better-http-proxy').then(lib => // dynamic import to avoid having this in final distribution
188 proxy = lib.default('127.0.0.1:'+port, {
src/update.ts
+10 -10
@@ -35,10 +35,10 @@ configReady.then(lastCheckUpdate.ready).then(() => repeat(HOUR, () => {
35 }))
36
37 export const checkForUpdates = debounceAsync(async () => {
38 - console.log("checking for updates")
38 + console.log("Checking for updates")
39 try {
40 const u = await getBestUpdate()
41 - if (u) console.log("new version available", u.name)
41 + if (u) console.log("New version available", u.name)
42 autoCheckUpdateResult.set(u)
43 lastCheckUpdate.set(Date.now())
44 }
@@ -86,7 +86,7 @@ export async function getVersions(interrupt?: (r: Release) => boolean) {
86 }
87
88 export async function getUpdates(strict=false) {
89 - console.log("checking for updates")
89 + console.log("Checking for updates")
90 void getProjectInfo() // also check for alerts and print them asap in the console
91 const stable: Release = prepareRelease(await getRepoInfo(HFS_REPO + '/releases/latest'))
92 const res = await getVersions(r => r.versionScalar < stable.versionScalar) // we don't consider betas before stable
@@ -125,7 +125,7 @@ export async function update(tagOrUrl: string='') {
125 tagOrUrl = 'v' + tagOrUrl
126 const update = !tagOrUrl ? await getBestUpdate()
127 : await getRepoInfo(HFS_REPO + '/releases/tags/' + tagOrUrl).catch(e => {
128 - if (e.message === '404') console.error("version not found")
128 + if (e.message === '404') console.error("Version not found")
129 else throw e
130 }) as Release | undefined
131 if (!update)
@@ -140,7 +140,7 @@ export async function update(tagOrUrl: string='') {
140 url = asset.browser_download_url
141 }
142 if (url) {
143 - console.log("downloading", url)
143 + console.log("Downloading", url)
144 const temp = LOCAL_UPDATE + '-temp'
145 await rm(temp, { force: true })
146 try {
@@ -151,7 +151,7 @@ export async function update(tagOrUrl: string='') {
151 throw "Download failed for " + url + prefix(' – ', e?.message)
152 }
153 await rename(temp, LOCAL_UPDATE)
154 - console.debug("download finished")
154 + console.debug("Download finished")
155 }
156 const bin = process.execPath
157 const binPath = dirname(bin)
@@ -181,10 +181,10 @@ export async function update(tagOrUrl: string='') {
181 try { unlinkSync(oldBin) }
182 catch {}
183 renameSync(bin, oldBin)
184 - console.log("launching new version in background", newBinFile)
184 + console.log("Launching new version in background", newBinFile)
185 spawnSync(cmdEscape(newBin), ['--updating', binFile, '--cwd .'], { shell: true, stdio: [0,1,2] }) // sync necessary to work on Mac by double-click
186 })
187 - console.log("quitting")
187 + console.log("Quitting")
188 setTimeout(() => process.exit()) // give time to return (and caller to complete, eg: rest api to reply)
189 }
190 catch (e: any) {
@@ -198,7 +198,7 @@ if (argv.updating) { // we were launched with a temporary name, restore original
198 const dest = join(dirname(bin), argv.updating)
199 renameSync(bin, dest)
200 // have to relaunch with the new name, or otherwise the next update will fail with EBUSY on hfs.exe
201 - console.log(`renamed binary file to "${argv.updating}" and now restarting`)
201 + console.log(`Renamed binary file to "${argv.updating}" and now restarting`)
202 // if you change anything, be sure to test launching both double-clicking and in a terminal
203 if (IS_WINDOWS) // windows-only; this method on mac+linux works only once, and without the console
204 onProcessExit(() =>
@@ -209,7 +209,7 @@ if (argv.updating) { // we were launched with a temporary name, restore original
209 // For the record, on mac you can: write "./hfs arg1 arg2" to /tmp/tmp.sh with 0o700, and then spawn "open -a Terminal /tmp/tmp.sh"
210 try { writeFileSync(ARGS_FILE, JSON.stringify(['--updated', '--cwd', process.cwd()])) }
211 catch {}
212 - console.log('open-ing')
212 + console.log('Open-ing')
213 void open(dest)
214 }
215 else { // linux and other *nix
src/upload.ts
+7 -7
@@ -33,7 +33,7 @@ const waitingToBeDeleted: Record<string, {
33 }> = {}
34 onProcessExit(() => {
35 if (!Object.keys(waitingToBeDeleted).length) return
36 - console.log("removing unfinished uploads")
36 + console.log("Removing unfinished uploads")
37 for (const path in waitingToBeDeleted)
38 try { fs.rmSync(path, { force: true }) }
39 catch {}
@@ -97,7 +97,7 @@ export function uploadWriter(base: VfsNode, baseUri: string, filename: string, c
97 return fail(HTTP_INSUFFICIENT_STORAGE)
98 }
99 catch(e: any) { // warn, but let it through
100 - console.warn("can't check disk size:", e.message || String(e))
100 + console.warn("Can't check disk size:", e.message || String(e))
101 }
102 // optionally 'skip'
103 if (ctx.query.existing === 'skip' && fs.existsSync(fullPath))
@@ -154,14 +154,14 @@ export function uploadWriter(base: VfsNode, baseUri: string, filename: string, c
154 cancelDeletion(tempName)
155 const tracked = { ctx, got: 0, size: stillToWrite }
156 uploadingFiles.set(fullPath, tracked)
157 - console.debug('upload started')
157 + console.debug('Upload started')
158 // the file stream doesn't have an event for data being written, so we use 'data' of its feeder, which happens before, so we postpone a bit, trying to have a fresher number
159 writeStream.on('data', () => setTimeout(() => tracked.got = bytesGot()))
160
161 const lockMiddleware = pendingPromise<string>() // expose outside, to let know when all operations stopped
162 let errored: any
163 fileStream.on('error', (e: any) => {
164 - console.warn('file error while uploading', filename, ':', e.message)
164 + console.warn('File error while uploading', filename, ':', e.message)
165 errored = e
166 fail(HTTP_SERVER_ERROR, e.code) // don't send e.message as it may contain a disk paths we don't want to leak
167 })
@@ -207,14 +207,14 @@ export function uploadWriter(base: VfsNode, baseUri: string, filename: string, c
207 void setCommentFor(dest, String(ctx.query.comment))
208 obj.uri = enforceFinal('/', baseUri) + pathEncode(basename(dest))
209 events.emit('uploadFinished', obj)
210 - console.debug("upload finished", dest)
210 + console.debug("Upload finished", dest)
211 if (resEvent) for (const cb of resEvent)
212 if (_.isFunction(cb))
213 cb(obj)
214 }
215 catch (err: any) {
216 void setUploadMeta(tempName, ctx)
217 - console.error("couldn't rename temp to", dest, String(err))
217 + console.error("Couldn't rename temp to", dest, String(err))
218 }
219 }
220 finally {
@@ -284,7 +284,7 @@ export function uploadWriter(base: VfsNode, baseUri: string, filename: string, c
284 }
285
286 function fail(status=ctx.status, msg?: string) {
287 - console.debug('upload failed', status, msg||'')
287 + console.debug('Upload failed', status, msg||'')
288 ctx.status = status
289 if (msg)
290 ctx.body = msg
src/util-files.ts
+2 -2
@@ -38,7 +38,7 @@ export async function readFileWithBusyRetry(path: string): Promise<string> {
38 return readFile(path, 'utf8').catch(e => {
39 if ((e as any)?.code !== 'EBUSY')
40 throw e
41 - console.debug('busy')
41 + console.debug('Busy')
42 return wait(100).then(()=> readFileWithBusyRetry(path))
43 })
44 }
@@ -103,7 +103,7 @@ export async function unzip(stream: Readable, cb: (path: string) => Promisable<f
103 const dest = await try_(() => cb(path), e => console.warn(String(e)))
104 if (!dest || type !== 'File')
105 return entry.autodrain()
106 - console.debug('unzip', dest)
106 + console.debug('Unzip', dest)
107 const thisFile = entry.pipe(await createSafeWriteStream(dest))
108 await once(thisFile, 'finish')
109 }) )
src/util-http.ts
+3 -3
@@ -74,7 +74,7 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
74
75 const proto = options.protocol === 'https:' ? https : http
76 const req = proto.request(options, res => {
77 - console.debug("http responded", res.statusCode, "to", url)
77 + console.debug("HTTP responded", res.statusCode, "to", url)
78 if (hostJar) for (const entry of res.headers['set-cookie'] || []) {
79 const [, k, v] = /(.+?)=([^;]+)/.exec(entry) || []
80 if (!k) continue
@@ -101,7 +101,7 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
101 resolve(res)
102 }).on('error', (e: any) => {
103 if (proxy && e?.code === 'ECONNREFUSED')
104 - console.debug("cannot connect to proxy ", proxy)
104 + console.debug("Cannot connect to proxy ", proxy)
105 e.cause ??= req // enrich the error
106 reject(e)
107 })
@@ -126,7 +126,7 @@ export function httpStream(url: string, { body, proxy, jar, noRedirect, httpThro
126 options.createConnection = () => tls.connect({ socket, servername: parsed.hostname || undefined })
127 resolve(true)
128 }).on('response', res => {
129 - console.debug("proxy CONNECT response", res.statusCode, res.statusMessage)
129 + console.debug("Proxy CONNECT response", res.statusCode, res.statusMessage)
130 resolve(false)
131 }).on('error', reject)
132 .end()
src/util-os.ts
+2 -2
@@ -81,10 +81,10 @@ async function getWindowsServicePids() {
81
82 export const RUNNING_AS_SERVICE = detectRunningAsService().then(ret => {
83 if (ret)
84 - console.log("running as service", ret)
84 + console.log("Running as service", ret)
85 return ret
86 }, e => {
87 - console.log("couldn't determine if we are running as a service")
87 + console.log("Couldn't determine if we are running as a service")
88 console.debug(e)
89 return false
90 })
src/vfs.ts
+1 -1
@@ -287,7 +287,7 @@ export function statusCodeForMissingPerm(node: VfsNode, perm: keyof VfsPerms, ct
287 if (typeof who !== 'string' || who === WHO_ANY_ACCOUNT)
288 break
289 if (!max--) {
290 - console.error(`endless loop in permission ${perm}=${node[perm] ?? defaultPerms[perm]} for ${node.url || getNodeName(node)}`)
290 + console.error(`Endless loop in permission ${perm}=${node[perm] ?? defaultPerms[perm]} for ${node.url || getNodeName(node)}`)
291 return HTTP_SERVER_ERROR
292 }
293 cur = who
src/watchLoad.ts
+3 -3
@@ -59,7 +59,7 @@ export function watchLoad(path:string, parser:(data:any)=>void|Promise<void>, {
59 await save.flush() // apply pending saves first
60 const text = await readFileWithBusyRetry(path).catch(e => { // ignore read errors
61 if (e.code === 'EPERM')
62 - console.error("missing permissions on file", path) // warn user, who could be clueless about this problem
62 + console.error("Missing permissions on file", path) // warn user, who could be clueless about this problem
63 // keep the last good content on transient read failures so we don't apply accidental "empty file" state
64 if (e.code === 'ENOENT')
65 return ''
@@ -69,12 +69,12 @@ export function watchLoad(path:string, parser:(data:any)=>void|Promise<void>, {
69 return
70 last = text
71 emitter.emit('change', last)
72 - console.debug('loaded', path)
72 + console.debug('Loaded', path)
73 unwatch(); install() // reinstall, as the original file could have been renamed. We watch by the name.
74 await parser(text)
75 }
76 catch(e) {
77 - console.error("error loading", path, String(e))
77 + console.error("Error loading", path, String(e))
78 }
79 finally {
80 doing = false