kysely
Version:
Type safe SQL query builder
106 lines (105 loc) • 3.66 kB
JavaScript
/// <reference types="./camel-case.d.ts" />
/**
* Creates a function that transforms camel case strings to snake case.
*/
export function createSnakeCaseMapper({ upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
return memoize((str) => {
if (str.length === 0) {
return str;
}
const upper = str.toUpperCase();
const lower = str.toLowerCase();
let out = lower[0];
for (let i = 1, l = str.length; i < l; ++i) {
const char = str[i];
const prevChar = str[i - 1];
const upperChar = upper[i];
const prevUpperChar = upper[i - 1];
const lowerChar = lower[i];
const prevLowerChar = lower[i - 1];
// If underScoreBeforeDigits is true then, well, insert an underscore
// before digits :). Only the first digit gets an underscore if
// there are multiple.
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
out += '_' + char;
continue;
}
// Test if `char` is an upper-case character and that the character
// actually has different upper and lower case versions.
if (char === upperChar && upperChar !== lowerChar) {
const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
out += '_' + lowerChar;
}
else {
out += lowerChar;
}
}
else {
out += char;
}
}
if (upperCase) {
return out.toUpperCase();
}
else {
return out;
}
});
}
/**
* Creates a function that transforms snake case strings to camel case.
*/
export function createCamelCaseMapper({ upperCase = false, } = {}) {
return memoize((str) => {
if (str.length === 0) {
return str;
}
if (upperCase && isAllUpperCaseSnakeCase(str)) {
// Only convert to lower case if the string is all upper
// case snake_case. This allows camelCase strings to go
// through without changing.
str = str.toLowerCase();
}
let out = str[0];
for (let i = 1, l = str.length; i < l; ++i) {
const char = str[i];
const prevChar = str[i - 1];
if (char !== '_') {
if (prevChar === '_') {
out += char.toUpperCase();
}
else {
out += char;
}
}
}
return out;
});
}
function isAllUpperCaseSnakeCase(str) {
for (let i = 1, l = str.length; i < l; ++i) {
const char = str[i];
if (char !== '_' && char !== char.toUpperCase()) {
return false;
}
}
return true;
}
function isDigit(char) {
return char >= '0' && char <= '9';
}
function memoize(func) {
const cache = new Map();
return (str) => {
let mapped = cache.get(str);
if (!mapped) {
mapped = func(str);
cache.set(str, mapped);
}
return mapped;
};
}