/
filter-functions.ts
339 lines (311 loc) · 11.2 KB
/
filter-functions.ts
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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
import type { DbObject } from "pg-structure";
import { EOL } from "os";
import { inspect } from "util";
import inflection from "inflection";
import { Column } from "pg-structure";
//
// ──────────────────────────────────────────────────────────────────── I ──────────
// :::::: S T R I N G F I L T E R S : : : : : : : :
// ──────────────────────────────────────────────────────────────────────────────
//
/**
* Clears the default value of a database object.
* - Converts two quotes `''` to single quote `'`
* - Removes quotes at the start and end of string.
* - Escapes result according to JSON standards.
*
* @param input is the default for a database object.
* @returns default value to be used in a template.
*
* @example
* clearDefaultValue("'No ''value'' given'"); // "No value 'given'"
*/
export function clearDefault(input?: string): string | undefined {
// Does not support SQL functions. IMHO it is better to handle sql function default values in RDMS.
let result;
if (input === null || input === undefined) return undefined;
if (input === "") result = "";
else if (input.charAt(0) === "'" || input.charAt(0) === '"') result = input.substring(1, input.length - 1).replace(/''/g, "'");
else if (!Number.isNaN(+input)) return input;
else if (input.toLowerCase() === "true") result = true;
else if (input.toLowerCase() === "false") result = false;
return JSON.stringify(result);
}
/**
* Converts the given input to the camel case.
*
* @param input is the input string to convert.
* @returns string as camel case.
*
* @example
* camelCase("user-name"); // userName
*/
export function camelCase(input: string): string {
return inflection.camelize(input.replace("-", "_"), true);
}
/**
* Converts the given input to the pascal case.
*
* @param input is the input string to convert.
* @returns string as pascal case.
*
* @example
* pascalCase("user-name"); // UserName
*/
export function pascalCase(input: string): string {
return inflection.camelize(input.replace("-", "_"), false);
}
/**
* Converts the given input to the class name.
*
* @param input is the input string to convert.
* @returns string as class case.
*
* @example
* classCase("user-name"); // UserName
*/
export function classCase(input: string): string {
return inflection.classify(input.replace("-", "_"));
}
/**
* Converts the given input to the snake case.
*
* @param input is the input string to convert.
* @returns string as snake case.
*
* @example
* snakeCase("userName"); // user_name
*/
export function snakeCase(input: string): string {
return inflection.underscore(input.replace("-", "_"));
}
/**
* Converts the given input to the dash case.
*
* @param input is the input string to convert.
* @returns string as dash case.
*
* @example
* dashCase("User Name"); // user-name
*/
export function dashCase(input: string): string {
return inflection.transform(input, ["underscore", "dasherize"]);
}
/**
* Converts the given input to the singular form.
*
* @param input is the input string to convert.
* @returns string in singular form.
*
* @example
* singular("user_names"); // user_name
*/
export function singular(input: string): string {
return inflection.singularize(input);
}
/**
* Converts the given input to the plural form.
*
* @param input is the input string to convert.
* @returns string in plural form.
*
* @example
* plural("user_name"); // user_names
*/
export function plural(input: string): string {
return inflection.pluralize(input);
}
/**
* Converts the given input's first letter to the lower case.
*
* @param input is the input string to convert.
* @returns string with lower first case.
*
* @example
* plural("User_name"); // User_name
*/
export function lcFirst(input: string): string {
return input[0].toLowerCase() + input.slice(1);
}
/**
* Wraps the given string with quotes.
*
* @param input is the input string to wrap with quotes.
* @returns string with quotes.
*
* @example
* plural("user_name"); // "user_name"
*/
export function quote(input: string): string {
return JSON.stringify(input);
}
/**
* Wraps the given string with single quotes.
*
* @param input is the input string to wrap with quotes.
* @returns string with quotes.
*
* @example
* plural("Some 'example' text"); // 'some \'example\' text'
*/
export function singleQuote(input: string): string {
return `'${input.replace(/'/g, "\\'")}'`;
}
/**
* Vairadic function which strips all of the given strings or database object's names from the start of the source string.
*
* @param input is the input string to convert.
* @param removeList is the list of strings or objects to remove from input.
* @returns converted string.
*/
export function stripPrefix(input: string, ...removeList: Array<string | { name: string }>): string {
return removeList
.map((item) => (typeof item === "object" ? item.name : item))
.reduce((result, item) => result.replace(new RegExp(`^${item}[_\\s-]*`), ""), input);
}
/**
* Vairadic function which strips all of the given strings or database object's names from the end of the source string.
*
* @param input is the input string to convert.
* @param removeList is the list of strings or objects to remove from input.
* @returns converted string.
*/
export function stripSuffix(input: string, ...removeList: Array<string | { name: string }>): string {
return removeList
.map((item) => (typeof item === "object" ? item.name : item))
.reduce((result, item) => result.replace(new RegExp(`[_\\s-]*${item}$`), ""), input);
}
/**
* Vairadic function which strips all of the given strings or database object's names from the source string.
*
* @param input is the input string to convert.
* @param removeList is the list of strings or objects to remove from input.
* @returns converted string.
*/
export function strip(input: string, ...removeList: Array<string | { name: string }>): string {
return removeList
.map((item) => (typeof item === "object" ? item.name : item))
.reduce((result, item) => result.replace(new RegExp(`${item}[_\\s-]*`), ""), input);
}
/**
* Pads given string's end with given padding string to complete its length to count.
*
* @param input is the input string to convert.
* @param totalLength is the total length of the result string.
* @param paddingString is the string to pad with.
* @returns the string padded with padding string.
*/
export function padRight(input: string, totalLength: number, paddingString = " "): string {
if (input === undefined || paddingString === undefined || input.length >= totalLength) return input;
const count = Math.floor((totalLength - input.length) / paddingString.length);
return input + paddingString.repeat(count);
}
/**
* Converts given string to JSOC lines by adding "*" at the start of each line.
*
* @param input is the input string to convert.
* @returs the result string.
*
* @example
* makeJsDoc(`
* Text line 1
* Text line 2
* `);
*
* // * Text line 1
* // * Text line 1
*/
export function makeJsDoc(input = ""): string {
const result = input.replace(new RegExp(`(\n|${EOL})`, "g"), "$1 * ");
return ` * ${result}`;
}
/**
* Converts `null` values to `undefined` recursively.
*
* @private
* @param input is the input to convert.
* @returns null values converted to `undefined`.
*/
function _convertNullToUndef<T extends string | Record<string, any> | any[]>(input: T): T | undefined {
if (Array.isArray(input)) return (input as any).map((val: any) => _convertNullToUndef(val));
if (input === null) return undefined;
if (typeof input === "object") {
const result = {} as typeof input;
(Object.keys(input) as Array<keyof typeof input>).forEach((key) => (result[key] = _convertNullToUndef(input[key]) as any)); // eslint-disable-line no-return-assign
return result;
}
return input;
}
/**
* If given data is object or array, converts it to string.
* 1. If it has `toString` method uses it. If it returns [object Object] tries other steps.
* 2. Uses `util.inspect()`;
*
* @param input is the input to convert.
* @param raw if true, does not add quotes around values.
* @param nullToUndef if true, converts all null values to undefined.
* @returns converted value.
*/
export function stringify(input: any, options: { nullToUndef?: boolean; raw?: boolean } = {}): string {
const result = options.nullToUndef ? _convertNullToUndef(input) : input;
if (typeof result !== "object") return JSON.stringify(result) ?? "undefined";
if (options.raw) {
return Array.isArray(result)
? result.join(", ")
: Object.entries(result)
.reduce((reducedResult, [key, value]) => `${reducedResult}${key}: ${value},\n`, "")
.replace(/,\n$/, "");
}
if (result === undefined || typeof result === "object") return inspect(result, { depth: null });
return result.toString();
}
/**
* If given data is a multi line string replcaes new lines with escape characters. May be used to prevent JS multi line errors.
*
* @param input is the input to convert.
* @returns the string with escape characters.
*/
export function singleLine(input: string): string {
return input.replace(/\r\n/g, "\\r\\n").replace(/\n/g, "\\n");
}
/**
* Returns given array with unique elements by eliminating duplicate values.
*
* @param input is the input array to eliminate duplicates from.
* @returns the array with unique values.
*/
export function uniqueArray<T extends any>(input: T[]): T[] {
return [...new Set(input)];
}
//
// ──────────────────────────────────────────────────────────────────────── I ──────────
// :::::: D A T A B A S E F I L T E R S : : : : : : : :
// ──────────────────────────────────────────────────────────────────────────────────
//
/**
* Returns given the given database object name as a class name.
*
* @param object is the object to get the name as a class name.
* @param schema is whether to include schema name.
*/
export function dboClassName(object: DbObject, schema = false): string {
return classCase(schema ? object.fullName.replace(".", "_") : object.name);
}
/**
* Returns column length, precision and scale ready to be used in templates.
*
* @param column is the column to get details.
* @returns modifier string.
*
* @example
* columnTypeModifier(price); // (10,4)
* columnTypeModifier(name); // (20)
*/
export function dboColumnTypeModifier(column: Column): string {
if (column.length !== undefined) return `(${column.length})`;
const result = [];
if (column.precision !== undefined) result.push(column.precision);
if (column.scale !== undefined) result.push(column.precision);
return result.length > 0 ? `(${result.join(", ")})` : "";
}