sql-bricks can write queries for us, and the mapper handles type conversions to and from SQL-friendly strings.
87 lines
1.8 KiB
TypeScript
87 lines
1.8 KiB
TypeScript
import snakeCase from "snake-case";
|
|
|
|
import { Row } from "./api";
|
|
|
|
interface ColMapper<F> {
|
|
_read(str: string): F;
|
|
|
|
_write(val: F): string;
|
|
}
|
|
|
|
type Spec<R> = {
|
|
[K in keyof R]: ColMapper<R[K]>;
|
|
};
|
|
|
|
/**
|
|
* Function objects describing the precise way in which our SQL driver
|
|
* transmits and receives values to the database as strings. Note that we could
|
|
* potentially have more than one SQL driver so this probably needs to be
|
|
* pushed down into `/sql/api.ts` somehow...
|
|
*/
|
|
export const T = {
|
|
bigint: {
|
|
_read: (str: string) => BigInt(str),
|
|
_write: (val: bigint) => val.toString(),
|
|
},
|
|
boolean: {
|
|
_read: (str: string) => str === "true",
|
|
_write: (val: boolean) => val.toString(),
|
|
},
|
|
number: {
|
|
_read: (str: string) => parseInt(str),
|
|
_write: (val: number) => val.toString(),
|
|
},
|
|
string: {
|
|
_read: (str: string) => str,
|
|
_write: (val: string) => val,
|
|
},
|
|
Date: {
|
|
_read: (str: string) => new Date(str),
|
|
_write: (val: Date) => val.toISOString(),
|
|
},
|
|
};
|
|
|
|
/**
|
|
* Boilerplate-reducing SQL <-> JavaScript record mapper. The TypeScript
|
|
* compiler will ensure that the mapping is correct.
|
|
*/
|
|
export function createSqlMapper<R>(spec: Spec<R>) {
|
|
const snaked = new Map<string, string>();
|
|
const colNames = new Array<string>();
|
|
|
|
for (const k in spec) {
|
|
const sk = snakeCase(k);
|
|
|
|
snaked.set(k, sk);
|
|
colNames.push(sk);
|
|
}
|
|
|
|
function readRow(row: Row): R {
|
|
const result = {} as R;
|
|
|
|
for (const k in spec) {
|
|
const sk = snaked.get(k);
|
|
const v = spec[k]._read(row[sk!]);
|
|
|
|
result[k] = v;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
function writeRow(obj: R): Row {
|
|
const result = {};
|
|
|
|
for (const k in spec) {
|
|
const sk = snaked.get(k);
|
|
const v = spec[k]._write(obj[k]);
|
|
|
|
result[sk!] = v;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
return { readRow, writeRow, colNames };
|
|
}
|