Remove sql-template-strings dependency

Frivolous dependencies are bad for perf and bad for security.

The usual justification for frivolous dependencies is something like
"a community-maintained package is more likely to be bug-free and
maintained than something you wrote yourself", but:

1. frivolous dependencies are usually maintained by Just Some Random
   Guy, not by some community
2. you are probably more likely to introduce a bug using some guy's API
   incorrectly, than by writing a few lines of raw JavaScript that you
   understand inside and out
3. if that guy deprecates his package, or decides to ragequit, or
   whatever, you do not want to be depending on it
4. debugging becomes a lot more annoying
5. the dependency is full of unnecessary complexity to support use
   cases we're not even using

Anyway, yeah, there's no need for this dependency.
This commit is contained in:
Guangcong Luo 2023-03-06 21:31:35 -08:00
parent f2dae2a3fc
commit 317c0623db
No known key found for this signature in database
9 changed files with 31 additions and 27 deletions

14
package-lock.json generated
View File

@ -15,7 +15,6 @@
"google-auth-library": "^3.1.2",
"mysql2": "^2.3.3",
"pm2": "^5.1.2",
"sql-template-strings": "^2.2.2",
"testcontainers": "^9.1.1"
},
"devDependencies": {
@ -5295,14 +5294,6 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"node_modules/sql-template-strings": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
"integrity": "sha512-UXhXR2869FQaD+GMly8jAMCRZ94nU5KcrFetZfWEMd+LVVG6y0ExgHAhatEcKZ/wk8YcKPdi+hiD2wm75lq3/Q==",
"engines": {
"node": ">=4.0.0"
}
},
"node_modules/sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",
@ -10255,11 +10246,6 @@
"resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
"integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g=="
},
"sql-template-strings": {
"version": "2.2.2",
"resolved": "https://registry.npmjs.org/sql-template-strings/-/sql-template-strings-2.2.2.tgz",
"integrity": "sha512-UXhXR2869FQaD+GMly8jAMCRZ94nU5KcrFetZfWEMd+LVVG6y0ExgHAhatEcKZ/wk8YcKPdi+hiD2wm75lq3/Q=="
},
"sqlstring": {
"version": "2.3.3",
"resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz",

View File

@ -19,7 +19,6 @@
"google-auth-library": "^3.1.2",
"mysql2": "^2.3.3",
"pm2": "^5.1.2",
"sql-template-strings": "^2.2.2",
"testcontainers": "^9.1.1"
},
"devDependencies": {

View File

@ -8,7 +8,7 @@ import {Config} from './config-loader';
import {ActionError, Dispatcher, QueryHandler} from './dispatcher';
import * as fs from 'fs';
import * as child_process from 'child_process';
import SQL from 'sql-template-strings';
import {SQL} from './database';
import {NTBBLadder} from './ladder';
import {Replays, md5} from './replays';
import {toID} from './server';

View File

@ -4,10 +4,31 @@
* @author mia-pi-git
*/
import * as mysql from 'mysql2';
import SQL, {SQLStatement} from 'sql-template-strings';
import {Config} from './config-loader';
export type SQLInput = string | number | null;
export class SQLStatement {
sql: string;
values: SQLInput[];
constructor(strings: TemplateStringsArray, values: SQLInput[]) {
this.sql = strings.join(`?`);
this.values = values;
}
append(statement: SQLStatement | string) {
if (typeof statement === 'string') {
this.sql += statement;
} else {
this.sql += statement.sql;
this.values = this.values.concat(statement.values);
}
}
}
export function SQL(strings: TemplateStringsArray, ...values: SQLInput[]) {
return new SQLStatement(strings, values);
}
export interface ResultRow {[k: string]: SQLInput}
export type DBConfig = mysql.PoolOptions & {prefix?: string};
@ -131,7 +152,7 @@ export class DatabaseTable<T> {
return this.selectOne(entries, query, db);
}
updateAll(toParams: Partial<T>, where?: SQLStatement, limit?: number, db?: PSDatabase) {
const to = Object.entries(toParams);
const to = Object.entries(toParams) as [string, SQLInput][];
const query = SQL`UPDATE `;
query.append(this.getName(db) + ' SET ');
for (let i = 0; i < to.length; i++) {
@ -190,7 +211,7 @@ export class DatabaseTable<T> {
query.append(') VALUES (');
for (let i = 0; i < keys.length; i++) {
const key = keys[i];
query.append(SQL`${colMap[key as keyof T]}`);
query.append(SQL`${colMap[key as keyof T] as SQLInput}`);
if (typeof keys[i + 1] !== 'undefined') query.append(', ');
}
query.append(') ');

View File

@ -7,8 +7,7 @@
import {time} from './session';
import {toID} from './server';
import {ladder} from './tables';
import {ladderDB as db} from './database';
import SQL from 'sql-template-strings';
import {ladderDB as db, SQL} from './database';
import type {User} from './user';
export interface LadderEntry {

View File

@ -5,12 +5,11 @@
*/
import * as crypto from 'crypto';
import {ActionError, Dispatcher} from './dispatcher';
import SQL from 'sql-template-strings';
import {Session, time} from './session';
import {toID} from './server';
import {prepreplays, replays} from './tables';
import {Config} from './config-loader';
import {replaysDB as db} from './database';
import {replaysDB as db, SQL} from './database';
export interface ReplayData {
id: string;
@ -281,7 +280,7 @@ export const Replays = new class {
const privacy = preppedReplay.private ? 1 : 0;
const {p1, p2, format, uploadtime, rating, inputlog} = preppedReplay;
const onDupe = SQL`ON DUPLICATE KEY UPDATE log = ${params.log}, `;
const onDupe = SQL`ON DUPLICATE KEY UPDATE log = ${params.log as string}, `;
onDupe.append(SQL`inputlog = ${inputlog}, rating = ${rating}, `);
onDupe.append(SQL` private = ${privacy}, \`password\` = ${password}`);
await replays.insert({

View File

@ -10,7 +10,7 @@ import {Config} from './config-loader';
import * as crypto from 'crypto';
import {ActionError, Dispatcher} from './dispatcher';
import * as gal from 'google-auth-library';
import SQL from 'sql-template-strings';
import {SQL} from './database';
import {toID} from './server';
import {ladder, loginthrottle, sessions, users, usermodlog} from './tables';
import type {User} from './user';

View File

@ -6,7 +6,7 @@
import {strict as assert} from 'assert';
import {NTBBLadder} from '../ladder';
import * as utils from './test-utils';
import SQL from 'sql-template-strings';
import {SQL} from '../database';
import * as tables from '../tables';
const token = '42354y6dhgfdsretr';

View File

@ -5,7 +5,7 @@
import {Replays, md5, stripNonAscii, ReplayData} from '../replays';
import {prepreplays, replays} from '../tables';
import {strict as assert} from 'assert';
import SQL from 'sql-template-strings';
import {SQL} from '../database';
import * as utils from './test-utils';
(describe.skip)('Replay database manipulation', () => {