mirror of
https://github.com/djhackersdev/minime.git
synced 2026-08-21 18:04:04 -05:00
sql/util.ts: Add a simple SQL record mapper
sql-bricks can write queries for us, and the mapper handles type conversions to and from SQL-friendly strings.
This commit is contained in:
86
src/sql/util.ts
Normal file
86
src/sql/util.ts
Normal file
@@ -0,0 +1,86 @@
|
||||
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 };
|
||||
}
|
||||
Reference in New Issue
Block a user