From 7f57a0c182e0c68399e0d279c06e0288301ff55c Mon Sep 17 00:00:00 2001 From: Lynn Date: Wed, 1 Jan 2025 19:57:33 +0100 Subject: [PATCH] Use `const` instead of `let` where possible (#61) --- core/api.ts | 46 ++++++++++++++++++++-------------------- core/commons.ts | 16 +++++++------- core/search.ts | 40 +++++++++++++++++----------------- core/server.ts | 34 ++++++++++++++--------------- frontend/App.vue | 16 +++++++------- frontend/shared/index.ts | 30 +++++++++++++------------- modules/announce.ts | 2 +- modules/cleanup.ts | 2 +- modules/disk.ts | 12 +++++------ modules/housekeep.ts | 14 ++++++------ modules/update.ts | 26 +++++++++++------------ 11 files changed, 120 insertions(+), 118 deletions(-) diff --git a/core/api.ts b/core/api.ts index 90a7bcc..78ad4d2 100644 --- a/core/api.ts +++ b/core/api.ts @@ -38,17 +38,17 @@ export function call( ret: (response: ApiResponse) => any, uname?: string, ) { - let time = +new Date(); - let action = actions.hasOwnProperty(i.action) && actions[i.action]; + const time = +new Date(); + const action = actions.hasOwnProperty(i.action) && actions[i.action]; if (!action) { console.log(`%% action '${i.action}' unknown`); return ret(flip('unknown action')); } if (!uname && 'token' in i && typeof i.token === 'string') { - let token = store.pass.tokens[i.token]; + const token = store.pass.tokens[i.token]; if (token) { uname = token.name; - let now = +new Date(); + const now = +new Date(); if (now > token.last + config().token_expiry) { delete store.pass.tokens[i.token]; ret = (old_ret => data => { @@ -59,7 +59,7 @@ export function call( } else store.pass.tokens[i.token].last = now; } } - let entries = Object.entries(i) + const entries = Object.entries(i) .filter( ([k, v]) => Object.keys({ ...(action.checks || {}), uname: uname }).includes(k) && @@ -83,7 +83,7 @@ export function call( if (!store.db) store.db = { entries: [] }; if (!store.pass) store.pass = { hashes: {}, tokens: {} }; -let actions: Record = {}; +const actions: Record = {}; const flip = (e: string): ApiError => ({ success: false, error: e }); const good = (d?: ApiBody): ApiResponse => ({ success: true, ...d }); @@ -95,11 +95,11 @@ function guard( conds: Record, f: ActionFunction, ): Action { - let res: any = (ret, i: object, uname: string | undefined) => { + const res: any = (ret, i: object, uname: string | undefined) => { if (logged_in && !uname) return ret(flip('must be logged in')); if (conds) - for (let [k, v] of Object.entries(conds)) { - let err = v(i[k]); + for (const [k, v] of Object.entries(conds)) { + const err = v(i[k]); if (err !== true) return ret(flip(`invalid field '${k}'${`: ${err}`}`)); } f(ret, i, uname); @@ -164,7 +164,7 @@ actions.search = guard( preferred_scope_bias: checks.optional(checks.number), }, (ret, i, uname) => { - let data = search.search(i, uname); + const data = search.search(i, uname); if (typeof data === 'string') ret(flip(data)); else ret(good({ results: data })); }, @@ -181,8 +181,8 @@ actions.vote = guard( vote: _ => [-1, 0, 1].includes(_) || 'invalid vote', }, (ret, i, uname) => { - let e = by_id(i.id); - let old_vote = e.votes[uname] || 0; + const e = by_id(i.id); + const old_vote = e.votes[uname] || 0; e.votes[uname] = i.vote; e.score += i.vote - old_vote; ret(good({ entry: present(e, uname) })); @@ -197,8 +197,8 @@ actions.note = guard( content: checks.nobomb, }, (ret, i, uname) => { - let word = by_id(i.id); - let this_note = { + const word = by_id(i.id); + const this_note = { date: new Date().toISOString(), user: uname, content: replacements(i.content), @@ -217,7 +217,7 @@ actions.edit = guard( scope: checks.scope, }, (ret, i, uname) => { - let word = by_id(i.id); + const word = by_id(i.id); if (word.user !== uname) { return ret(flip('you are not the owner of this entry')); } @@ -242,9 +242,9 @@ actions.removenote = guard( date: checks.present, }, (ret, i, uname) => { - let word = by_id(i.id); - let keep = []; - let removed_notes = []; + const word = by_id(i.id); + const keep = []; + const removed_notes = []; for (const note of word.notes) { if (note.user === uname && note.date === i.date) { removed_notes.push(note); @@ -274,8 +274,8 @@ actions.create = guard( scope: checks.scope, }, (ret, i, uname) => { - let id = shortid.generate(); - let this_entry: Entry = { + const id = shortid.generate(); + const this_entry: Entry = { id, date: new Date().toISOString(), head: shared.normalize(i.head), @@ -299,7 +299,7 @@ actions.login = guard( pass: checks.present, }, (ret, i) => { - let expected = store.pass.hashes[i.name]; + const expected = store.pass.hashes[i.name]; if (!expected) return ret(flip('user not registered')); if (bcrypt.compareSync(i.pass, expected)) { var token = uuid.v4(); @@ -339,8 +339,8 @@ actions.remove = guard( id: checks.goodid, }, (ret, i, uname) => { - let index = index_of(i.id); - let entry = store.db.entries[index]; + const index = index_of(i.id); + const entry = store.db.entries[index]; if (entry.user !== uname) return ret(flip('you are not the owner of this entry')); store.db.entries.splice(index, 1); diff --git a/core/commons.ts b/core/commons.ts index 4d542fd..1178a5f 100644 --- a/core/commons.ts +++ b/core/commons.ts @@ -10,12 +10,12 @@ import { EventEmitter } from 'events'; const old_log = console.log; export function log(...args: any[]): void { - let date = new Date() + const date = new Date() .toISOString() .replace(/[:-]/g, '') .replace('T', '.') .substring(4, 15); - let message = Array.from(args) + const message = Array.from(args) .join(' ') // padding the message so that it doesn't interfere // with the timestamp column: @@ -52,26 +52,26 @@ export function deburrMatch( (a: string, b: string) => a == b, ][mode]; let count = 0; - for (let w of what) if (where.some(y => predicate(w, y))) count++; + for (const w of what) if (where.some(y => predicate(w, y))) count++; return count; } const real_setInterval = global.setInterval; const real_clearInterval = global.clearInterval; -let interval_cache = []; +const interval_cache = []; export function setInterval( callback: (...args: any[]) => void, ms?: number, ): NodeJS.Timer { - let this_one = real_setInterval(callback, ms).unref(); + const this_one = real_setInterval(callback, ms).unref(); interval_cache.push(this_one); return this_one; } export function clearInterval(i: string | number | NodeJS.Timeout): void { real_clearInterval(i); - let index = interval_cache.indexOf(i); + const index = interval_cache.indexOf(i); if (index !== -1) interval_cache.splice(index, 1); } @@ -111,7 +111,7 @@ const FluidConfig = { }; Object.setPrototypeOf(FluidConfig, new EventEmitter()); export function fluid_config(fname: string) { - let f: any = () => { + const f: any = () => { return f.cache; }; f.fname = fname; @@ -127,7 +127,7 @@ const MAIN_CONFIG = 'config/config.yml', __dirname = dirname(fileURLToPath(import.meta.url)), DEFAULT_CONFIG = `${__dirname}/../../config/defaults.yml`; // initialise the global config file -let main_config = fluid_config(MAIN_CONFIG), +const main_config = fluid_config(MAIN_CONFIG), default_config = yaml(readFileSync(DEFAULT_CONFIG)); export const config: any = () => ({ ...default_config, ...main_config() }); diff --git a/core/search.ts b/core/search.ts index 7f9b887..3a6d702 100644 --- a/core/search.ts +++ b/core/search.ts @@ -52,9 +52,9 @@ export interface PresentedEntry extends Omit { // compute a few fields for faster processing export function cacheify(e: Entry): CachedEntry { - let deburredHead = deburr(e.head); - let deburredBody = deburr(e.body); - let deburredNotes = e.notes.flatMap(({ content }) => deburr(content)); + const deburredHead = deburr(e.head); + const deburredBody = deburr(e.body); + const deburredNotes = e.notes.flatMap(({ content }) => deburr(content)); return { $: e, id: e.id, @@ -88,7 +88,7 @@ export function score(entry: Entry): number { emitter.on('remove', (_, entry) => cache.splice(cached_index(entry.id), 1)); emitter.on('create', (_, entry) => cache.push(cacheify(entry))); -for (let k of ['vote', 'note', 'removenote', 'edit', 'move']) +for (const k of ['vote', 'note', 'removenote', 'edit', 'move']) emitter.on(k, (_, entry) => cache.splice(cached_index(entry.id), 1, cacheify(entry)), ); @@ -113,12 +113,12 @@ interface Operation { build: (args: any[]) => (entry: CachedEntry) => boolean; } -let operations: Record = (search.operations = { +const operations: Record = (search.operations = { and: { type: OperationType.Functor, check: all_funcs, build: args => entry => { - for (let a of args) if (!a(entry)) return false; + for (const a of args) if (!a(entry)) return false; return true; }, }, @@ -126,7 +126,7 @@ let operations: Record = (search.operations = { type: OperationType.Functor, check: all_funcs, build: args => entry => { - for (let a of args) if (a(entry)) return true; + for (const a of args) if (a(entry)) return true; return false; }, }, @@ -153,8 +153,8 @@ let operations: Record = (search.operations = { type: OperationType.Textual, check: one_string, build: ([s]) => { - let deburred = deburr(s); - let deburredW = deburred.some(x => /vy?|w|y/.test(x)) + const deburred = deburr(s); + const deburredW = deburred.some(x => /vy?|w|y/.test(x)) ? deburred.map(x => x.replace(/vy?|w|y/g, 'ꝡ')) : undefined; return entry => @@ -167,7 +167,7 @@ let operations: Record = (search.operations = { }, }); -for (let trait of RE_TRAITS) { +for (const trait of RE_TRAITS) { operations[trait] = { type: OperationType.Other, check: one_string, @@ -203,7 +203,7 @@ function make_re(trait: Trait, s: string): (entry: CachedEntry) => boolean { .replace(/V\\\+/g, 'V+') .replace(/V/g, '[aeıiouy]'); - let regexp = new RegExp(`^${s}\$`, 'iu'); + const regexp = new RegExp(`^${s}\$`, 'iu'); return entry => regexp.test(String(entry.$[trait])); } catch (_) { return entry => s === String(entry.$[trait]); @@ -224,22 +224,22 @@ function parse_query( if (!(query instanceof Array)) return 'found non-array branch'; if (!query.length) return 'found empty array node'; query = [...query]; - let op_name = query.shift(); - let op = + const op_name = query.shift(); + const op = Object.hasOwnProperty.call(operations, op_name) && operations[op_name]; if (!op) return `unknown operation ${op_name}`; let args; try { args = query.map(arg => { if (typeof arg !== 'object') return arg; - let might_be_it = parse_query(arg); + const might_be_it = parse_query(arg); if (typeof might_be_it === 'string') throw might_be_it; return might_be_it; }); } catch (e) { return e; } - let check = op.check(args); + const check = op.check(args); if (check !== true) return check; return op.build(args); } @@ -247,7 +247,7 @@ function parse_query( search.bare_terms = bare_terms; function bare_terms(o: any[]) { // `o` must be instanceof Array. - let op = operations[o[0]]; + const op = operations[o[0]]; switch (op.type) { case OperationType.Textual: return [o[1]]; @@ -319,9 +319,9 @@ export function search(i: any, uname?: string): string | PresentedEntry[] { query = parsed.query; requested_ordering ??= parsed.ordering; } - let filter = parse_query(query); + const filter = parse_query(query); if (typeof filter !== 'function') return `malformed query: ${filter}`; - let bares = bare_terms(query), + const bares = bare_terms(query), deburrs = bares.map(deburr).flat(); const ordering = interpret_ordering( @@ -352,6 +352,8 @@ export function search(i: any, uname?: string): string | PresentedEntry[] { } } - let presented = results.map(([e, relevance]) => present(e, uname, relevance)); + const presented = results.map(([e, relevance]) => + present(e, uname, relevance), + ); return presented; } diff --git a/core/server.ts b/core/server.ts index c22cf5b..b6abd75 100644 --- a/core/server.ts +++ b/core/server.ts @@ -21,16 +21,16 @@ argparser.add_argument('-p', '--port', { help: 'Bind port', type: 'int', }); -let args = argparser.parse_args(); +const args = argparser.parse_args(); const __dirname = dirname(fileURLToPath(import.meta.url)); const installation_dir = `${__dirname}/../..`; -let dir = args.data_directory +const dir = args.data_directory ? fs.realpathSync(args.data_directory) : installation_dir; process.chdir(dir); import * as commons from './commons.js'; -let config = commons.config; +const config = commons.config; const VERSION = ( await import(pathToFileURL(`${installation_dir}/package.json`).href, { @@ -43,7 +43,7 @@ console.log(`starting up v${VERSION}...`); import * as http from 'http'; import * as api from './api.js'; -let fourohfour = static_handler('frontend/404.html', 'text/html', 404), +const fourohfour = static_handler('frontend/404.html', 'text/html', 404), routes = { '/api': api_handler, '/': static_handler('frontend/index.html', 'text/html'), @@ -114,12 +114,12 @@ function api_handler(r, s) { } function static_handler(fn: string, mime: string, code?: number) { - let fname = `${installation_dir}/${fn}`; + const fname = `${installation_dir}/${fn}`; code = code || 200; let f = fs.readFileSync(fname); - let t = fs.statSync(fname).mtimeMs; + const t = fs.statSync(fname).mtimeMs; return function static_handler(r, s) { - let t_ = fs.statSync(fname).mtimeMs; + const t_ = fs.statSync(fname).mtimeMs; if (t_ > t) { console.log( `file '${fname}' has been reloaded (${f.length}b; mtime ${t_} > ${t})`, @@ -134,12 +134,12 @@ function static_handler(fn: string, mime: string, code?: number) { } function handler(r, s_) { - let time = +new Date(); - let url = new URL(r.url, config().entry_point); - let handler = routes.hasOwnProperty(url.pathname) + const time = +new Date(); + const url = new URL(r.url, config().entry_point); + const handler = routes.hasOwnProperty(url.pathname) ? routes[url.pathname] : fourohfour; - let s = { + const s = { writeHead(code, headers?) { if (code !== 200) console.log( @@ -149,7 +149,7 @@ function handler(r, s_) { return this; }, write(what) { - let w = what instanceof Buffer ? what : Buffer.from(what); + const w = what instanceof Buffer ? what : Buffer.from(what); console.log(`sent off ${w.length}b`); return s_.write(w); }, @@ -160,7 +160,7 @@ function handler(r, s_) { }, }; Object.setPrototypeOf(s, s_); - let { address, port } = r.socket.address(); + const { address, port } = r.socket.address(); console.log(`${r.url} ${address}:${port} -> ${handler.name}`); try { handler(r, s, url); @@ -176,7 +176,7 @@ function handler(r, s_) { } } -let modules: Record = {}; +const modules: Record = {}; await config_update(config()); config.on('update', config_update); @@ -193,8 +193,8 @@ async function config_update(data) { } } } - for (let path in modules) { - let new_options = data.modules[path]; + for (const path in modules) { + const new_options = data.modules[path]; // note that when an entry in the module table is removed, // `new_options === undefined`. this is all right if (JSON.stringify(new_options) !== JSON.stringify(modules[path].options)) { @@ -220,7 +220,7 @@ server.on('connection', conn => { }); const SIGNALS = ['SIGINT', 'SIGTERM', 'SIGHUP', 'uncaughtException']; -for (let s of SIGNALS) process.once(s, bye); +for (const s of SIGNALS) process.once(s, bye); function bye(error) { if (error.stack) console.log(`uncaught exception: ${error.stack}`); diff --git a/frontend/App.vue b/frontend/App.vue index 980e9ca..b752ac0 100644 --- a/frontend/App.vue +++ b/frontend/App.vue @@ -242,7 +242,7 @@ export default defineComponent({ focus_body(): void { setTimeout(() => { - let body = document.getElementById('create_body')!; + const body = document.getElementById('create_body')!; body.focus(); }, 0); }, @@ -259,11 +259,11 @@ export default defineComponent({ req.open('POST', 'api', true); if (this && this.token) what.token = this.token; req.send(JSON.stringify(what)); - let app = this; + const app = this; req.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { try { - let data = JSON.parse(this.responseText); + const data = JSON.parse(this.responseText); if (data.success) { setTimeout(() => and(data), 0); } else { @@ -325,7 +325,7 @@ export default defineComponent({ this.scroll_up = true; return; } - let parsed_query = this.parse_query(); + const parsed_query = this.parse_query(); if (this.limit_search) parsed_query.query = ['and', ['scope', this.scope], parsed_query.query]; parsed_query.action = 'search'; @@ -405,7 +405,7 @@ export default defineComponent({ }, update_entry(whom: Entry, what_with: Partial): void { - for (let p in what_with) + for (const p in what_with) if (Object.hasOwnProperty.call(what_with, p)) whom[p] = what_with[p]; }, @@ -456,11 +456,11 @@ export default defineComponent({ }, resize(): void { - let create = document.getElementById( + const create = document.getElementById( 'create_body', ) as HTMLTextAreaElement; if (!create) return; - let clone = create.cloneNode() as HTMLTextAreaElement; + const clone = create.cloneNode() as HTMLTextAreaElement; create.parentNode!.insertBefore(clone, create); clone.style.visibility = 'hidden'; // clone.style.position = 'absolute'; @@ -478,7 +478,7 @@ export default defineComponent({ }, scrape_cache(): void { - let screens = + const screens = (document.body.scrollHeight - window.scrollY + document.body.scrollTop) / diff --git a/frontend/shared/index.ts b/frontend/shared/index.ts index b76376d..ef5c35b 100644 --- a/frontend/shared/index.ts +++ b/frontend/shared/index.ts @@ -44,9 +44,9 @@ export function convert_hue(h: number, theme?: string): Color { */ export function normalize(s: string, trim?: boolean): string { if (trim === undefined) trim = true; - let suffix = trim ? '' : s.match(/\s*$/)[0]; + const suffix = trim ? '' : s.match(/\s*$/)[0]; s = s.normalize('NFD').replace(/ı/g, 'i').replace(/ȷ/g, 'j'); - let words = s.split(/\s+/gi).filter(_ => _); + const words = s.split(/\s+/gi).filter(_ => _); return ( words .map(w => @@ -69,7 +69,7 @@ export function normalize(s: string, trim?: boolean): string { if (tone === '\u0304' || tone === '\u0309') tone = ''; if (num !== '' && num >= 2 && num <= 4) tone = ['\u0301', '\u0308', '\u0302'][num - 2]; - let abnormal = offset && tone !== ''; + const abnormal = offset && tone !== ''; return [ abnormal && ' ', offset && !initial && !abnormal && "'", @@ -116,13 +116,13 @@ export function score_number(n: number): string { } function escape(s: string): string { - let el = document.createElement('p'); + const el = document.createElement('p'); el.innerText = s; return el.innerHTML; } function make_link(href: string, text: string): string { - let el = document.createElement('a'); + const el = document.createElement('a'); el.innerText = text; el.setAttribute('href', href); return el.outerHTML; @@ -137,7 +137,7 @@ export function replacements( content = plain_text ? content : escape(content); content = content.replace(/___/g, '▯'); let i = 0; - let accum: string[] = []; + const accum: string[] = []; const starters: RegExp[] = [ plain_text ? /(<)(.*?)(>)/g : /(<)(.*?)(>)/g, ...(still_editing ? [/([*]{2})(?!.*?[*]{2})(.*)()/g] : []), @@ -146,12 +146,12 @@ export function replacements( /()(#[0-9a-zA-Z_-]+)()/g, /(https?:\/\/)(\S*[\w\/])()/g, ]; - let matches = starters + const matches = starters .flatMap(starter => [...content.matchAll(starter)]) .sort((a, b) => (a.index ?? 0) - (b.index ?? 0)); while (i < content.length && matches.length) { - let nearestMatch = matches[0]; - let [all, start, cont, end] = nearestMatch; + const nearestMatch = matches[0]; + const [all, start, cont, end] = nearestMatch; accum.push(content.substring(i, nearestMatch.index)); i = (nearestMatch.index ?? 0) + all.length; let replacement; @@ -160,8 +160,8 @@ export function replacements( } else if (start.startsWith('http') && !still_editing) { replacement = make_link(all, cont.replace(/^www\.|\/$/g, '')); } else if (!plain_text && !still_editing) { - let href = '#' + encodeURIComponent(cont); - let style = cont.startsWith('@') + const href = '#' + encodeURIComponent(cont); + const style = cont.startsWith('@') ? `style="${color_for(cont.substring(1), theme).css}"` : ''; replacement = `${cont}`; @@ -195,8 +195,8 @@ export function parse_query(query_string: string): { ordering: string | undefined; } { let ordering: string | undefined; - let parts = query_string.split(/ /).map(a => { - let parts = a.split(/\|/).map(b => { + const parts = query_string.split(/ /).map(a => { + const parts = a.split(/\|/).map(b => { let negative, what; if ((negative = b[0] === '!')) b = b.substring(1); let parts = b.split(':'); @@ -211,11 +211,11 @@ export function parse_query(query_string: string): { ]; } else { parts = b.split(/(?=[\/@#=])/); - let operations: [string, string | number][] = []; + const operations: [string, string | number][] = []; if (!parts[0].match(/^[\/@#=]/)) operations.push(['term', parts.shift()]); for (let i = 0; i < parts.length; ++i) { - let rest = parts[i].substring(1); + const rest = parts[i].substring(1); operations.push([ character_operators[parts[i][0]], parts[i][0] === '/' ? parseInt(rest, 10) || 0 : rest, diff --git a/modules/announce.ts b/modules/announce.ts index d5c98eb..93ded74 100644 --- a/modules/announce.ts +++ b/modules/announce.ts @@ -88,7 +88,7 @@ export function message(what: WebhookEmbed) { function send_off() { if (!queue.length) return; if (queue.length > 10) { - let top = queue[0]; + const top = queue[0]; if (top?.body?.embeds?.[0]?.title) { top.body.embeds[0].title = trim(200, top.body.embeds[0].title) + diff --git a/modules/cleanup.ts b/modules/cleanup.ts index 54503e8..b1c6b8d 100644 --- a/modules/cleanup.ts +++ b/modules/cleanup.ts @@ -8,7 +8,7 @@ var options: any = {}; export function remove_obsoleted(_, { score, user, id, head }, voter) { if (!options) return; - let { users, vote_threshold } = options; + const { users, vote_threshold } = options; if ((users && !users.includes(user)) || score > vote_threshold) // || user == voter) return; diff --git a/modules/disk.ts b/modules/disk.ts index 9f3f0e9..f0891ff 100644 --- a/modules/disk.ts +++ b/modules/disk.ts @@ -2,7 +2,7 @@ // load from disk, save to disk, do backups import * as commons from '../core/commons.js'; -let store = commons.store; +const store = commons.store; import * as http from 'http'; import * as fs from 'fs'; @@ -20,21 +20,21 @@ export function read(fname, deft) { write(fname, deft); return deft; } - let buf = zlib.gunzipSync(gzip); - let o = JSON.parse(buf.toString()); + const buf = zlib.gunzipSync(gzip); + const o = JSON.parse(buf.toString()); console.log(`successfully read ${buf.length}b from '${fname}'`); return o; } function write_(fname, data, guard_override) { - let gzip = zlib.gzipSync(Buffer.from(JSON.stringify(data))); + const gzip = zlib.gzipSync(Buffer.from(JSON.stringify(data))); let backup = fname + '~', our_size = gzip.length, success = false, unbackup = true; if (!guard_override) try { - let { size: old_size } = fs.statSync(fname); + const { size: old_size } = fs.statSync(fname); if (gzip.length / (old_size || 1) < 0.5) { console.log( `warning: refusing to destructively write ${our_size}b over ${old_size}b file '${fname}'`, @@ -119,7 +119,7 @@ const acts = { save_interval: save, backup_interval: backup }; let first_go = true, intervals = {}; export function state_change() { - for (let k of Object.keys(acts)) { + for (const k of Object.keys(acts)) { if (intervals[k]) commons.clearInterval(intervals[k]); if (this && this.enabled && this[k]) intervals[k] = commons.setInterval(acts[k], this[k]); diff --git a/modules/housekeep.ts b/modules/housekeep.ts index 5006a3c..371512b 100644 --- a/modules/housekeep.ts +++ b/modules/housekeep.ts @@ -5,26 +5,26 @@ import * as commons from '../core/commons.js'; import { Token } from '../core/commons.js'; import * as search from '../core/search.js'; import * as shared from '../frontend/shared/index.js'; -let { store, config } = commons; +const { store, config } = commons; let first_go = true; export function state_change() { if (!first_go) return; first_go = false; - let now = +new Date(); + const now = +new Date(); const entries: [string, Token][] = Object.entries(store.pass.tokens); - for (let [k, { last }] of entries) + for (const [k, { last }] of entries) if (now > last + config().token_expiry) delete store.pass.tokens[k]; let reformed = 0; const reform = (e, p, f) => { - let normalized = f(e[p]); - let retval = normalized !== e[p]; + const normalized = f(e[p]); + const retval = normalized !== e[p]; e[p] = normalized; return retval; }; - for (let entry of store.db.entries) { + for (const entry of store.db.entries) { // update to modern Toaq let didReform = reform(entry, 'head', shared.normalize); if (entry.scope === 'toa') @@ -33,7 +33,7 @@ export function state_change() { const normalizePlaceholders = s => s.replace(/___|◌(?!\p{Diacritic})/gu, '▯'); didReform ||= reform(entry, 'body', normalizePlaceholders); - for (let note of entry.notes) + for (const note of entry.notes) didReform ||= reform(note, 'content', normalizePlaceholders); if (didReform) reformed++; diff --git a/modules/update.ts b/modules/update.ts index 8710a7d..27a194b 100644 --- a/modules/update.ts +++ b/modules/update.ts @@ -7,7 +7,7 @@ import * as api from '../core/api.js'; import * as announce from './announce.js'; import * as shared from '../frontend/shared/index.js'; -let { store } = commons; +const { store } = commons; import request from 'request-promise-native'; const config = commons.fluid_config('config/sources.yml'); @@ -45,7 +45,7 @@ const FORMATS = { }; // Word list cache. -let word_lists = {}; +const word_lists = {}; // poll for new entries at remote TSV spreadsheets and add them to the // dictionary every now and then @@ -60,7 +60,7 @@ export async function sync_resources() { try { data = await request.get(source); console.log(`updating resource '${name}'`); - let word_list = Object.fromEntries( + const word_list = Object.fromEntries( FORMATS[format](data, rest) .filter(_ => _.head && _.body) .map(_ => [shared.normalize(_.head), api.replacements(_.body)]), @@ -85,10 +85,10 @@ export async function sync_resources() { return; } console.log('adding...'); - for (let [name, words] of Object.entries(word_lists)) { - let user = cf[name].user; - for (let [head, body] of Object.entries(words)) { - let s = search.search({ + for (const [name, words] of Object.entries(word_lists)) { + const user = cf[name].user; + for (const [head, body] of Object.entries(words)) { + const s = search.search({ query: [ 'and', ['user_raw', user], @@ -112,12 +112,12 @@ export async function sync_resources() { } } - let messages: Record = {}; + const messages: Record = {}; if (Object.keys(word_lists).length === Object.keys(cf).length) { console.log('obsoleting...'); - let unames = new Set(Object.values(cf).map(_ => _.user)); + const unames = new Set(Object.values(cf).map(_ => _.user)); // ...I do have the right to write messy code, don't I? - let fetched = Object.fromEntries( + const fetched = Object.fromEntries( [...unames].map(uname => [ uname, Object.fromEntries( @@ -132,7 +132,7 @@ export async function sync_resources() { store.db.entries .filter(e => unames.has(e.user)) .forEach(e => { - let found = fetched[e.user][e.head]; + const found = fetched[e.user][e.head]; if (found && found === e.body) return; // we need to re-find the entry because `search` makes // copies on output @@ -152,7 +152,7 @@ export async function sync_resources() { search.recache(); - for (let [user, msgs] of Object.entries(messages)) { + for (const [user, msgs] of Object.entries(messages)) { if (msgs.length > 5) announce.message({ title: `${msgs.length} definitions obsoleted for user *${user}*`, @@ -164,7 +164,7 @@ export async function sync_resources() { (msgs.length > 50 ? `, and ${msgs.length - 50} more` : ''), }); else - for (let { title, description, url } of msgs) + for (const { title, description, url } of msgs) announce.message({ title, description, url }); }