Spaces:
Paused
Paused
File size: 1,360 Bytes
f55c62a | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 | /**
* Tagged template helper for composing parameterized SQL.
*
* Usage:
* sql`SELECT * FROM users WHERE uuid = ${uuid}`
*
* Values are pushed as positional `?` placeholders, in order. Nested
* `SqlFragment` values are inlined verbatim and their params merged.
* Use `raw` for trusted strings (identifiers, keywords) that must not
* be parameterized.
*/
export class SqlFragment {
constructor(
readonly text: string,
readonly params: readonly unknown[]
) {}
}
export function sql(
strings: TemplateStringsArray,
...values: unknown[]
): SqlFragment {
let text = '';
const params: unknown[] = [];
for (let i = 0; i < strings.length; i++) {
text += strings[i];
if (i < values.length) {
const v = values[i];
if (v instanceof SqlFragment) {
text += v.text;
params.push(...v.params);
} else {
text += '?';
params.push(v);
}
}
}
return new SqlFragment(text, params);
}
export function raw(s: string): SqlFragment {
return new SqlFragment(s, []);
}
export function join(
fragments: readonly SqlFragment[],
separator = ', '
): SqlFragment {
let text = '';
const params: unknown[] = [];
fragments.forEach((f, i) => {
if (i > 0) text += separator;
text += f.text;
params.push(...f.params);
});
return new SqlFragment(text, params);
}
|