topkat-utils 1.2.32 → 1.2.34
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +6 -0
- package/dist/src/config.d.ts +10 -10
- package/dist/src/config.js +5 -5
- package/dist/src/config.js.map +1 -1
- package/dist/src/date-utils.js +1 -1
- package/dist/src/date-utils.js.map +1 -1
- package/dist/src/error-utils.d.ts +1 -1
- package/dist/src/error-utils.js +1 -0
- package/dist/src/error-utils.js.map +1 -1
- package/dist/src/is-empty.d.ts +1 -1
- package/dist/src/logger-utils.d.ts +4 -4
- package/dist/src/logger-utils.js +50 -22
- package/dist/src/logger-utils.js.map +1 -1
- package/dist/src/loop-utils.js.map +1 -1
- package/dist/src/mongo-utils.d.ts +1 -1
- package/dist/src/mongo-utils.js +2 -0
- package/dist/src/mongo-utils.js.map +1 -1
- package/dist/src/object-utils.d.ts +3 -3
- package/dist/src/object-utils.js +2 -0
- package/dist/src/object-utils.js.map +1 -1
- package/dist/src/regexp-utils.js.map +1 -1
- package/dist/src/string-utils.d.ts +4 -4
- package/dist/src/string-utils.js +2 -2
- package/dist/src/string-utils.js.map +1 -1
- package/dist/src/tests-utils.js.map +1 -1
- package/dist/src/timer-utils.js.map +1 -1
- package/dist/src/validation-utils.js +21 -20
- package/dist/src/validation-utils.js.map +1 -1
- package/dist/src/wtf-utils.js +2 -2
- package/dist/src/wtf-utils.js.map +1 -1
- package/package.json +1 -1
- package/src/config.ts +16 -16
- package/src/date-utils.ts +1 -1
- package/src/error-utils.ts +4 -4
- package/src/logger-utils.ts +31 -31
- package/src/loop-utils.ts +4 -4
- package/src/mongo-utils.ts +2 -1
- package/src/object-utils.ts +7 -6
- package/src/regexp-utils.ts +1 -1
- package/src/string-utils.ts +9 -9
- package/src/tests-utils.ts +1 -1
- package/src/timer-utils.ts +2 -2
- package/src/validation-utils.ts +21 -21
- package/src/wtf-utils.ts +8 -6
- package/tsconfig.json +1 -0
package/src/logger-utils.ts
CHANGED
|
@@ -19,7 +19,7 @@ export const logger = {
|
|
|
19
19
|
else console.log(str)
|
|
20
20
|
|
|
21
21
|
logger.raw.push(str + `\n`)
|
|
22
|
-
logger.raw = logger.raw.slice(logger.raw.length - configFn()
|
|
22
|
+
logger.raw = logger.raw.slice(logger.raw.length - configFn()?.nbOfLogsToKeep, logger?.raw?.length)
|
|
23
23
|
},
|
|
24
24
|
/**
|
|
25
25
|
* @param {String[]|String} inputLogs
|
|
@@ -55,8 +55,8 @@ export const logger = {
|
|
|
55
55
|
const str = Array.isArray(inputLogs) ? inputLogs.join('\n') : inputLogs
|
|
56
56
|
return str.replace(/\x1b\[.*?m/g, '')
|
|
57
57
|
},
|
|
58
|
-
raw: [],
|
|
59
|
-
json: [],
|
|
58
|
+
raw: [] as string[],
|
|
59
|
+
json: [] as string[],
|
|
60
60
|
}
|
|
61
61
|
|
|
62
62
|
/**
|
|
@@ -76,27 +76,27 @@ export const C = {
|
|
|
76
76
|
cyan: str => C.output(36, str),
|
|
77
77
|
blue: str => C.output(34, str),
|
|
78
78
|
primary: str => {
|
|
79
|
-
const primary: Color = configFn()
|
|
79
|
+
const primary: Color = configFn()?.terminal?.theme?.primary
|
|
80
80
|
return C.rgb(...primary) + str + C.reset
|
|
81
81
|
},
|
|
82
82
|
reset: '\x1b[0m',
|
|
83
|
-
output: (code, str = '') => configFn()
|
|
83
|
+
output: (code, str = '') => configFn()?.terminal?.noColor ? str : `\x1b[${code}m${str}\x1b[0m`,
|
|
84
84
|
// true RGB colors B-*
|
|
85
|
-
rgb: (r, g = 0, b = 0) => configFn()
|
|
86
|
-
bg: (r?, g?, b?) => configFn()
|
|
85
|
+
rgb: (r, g = 0, b = 0) => configFn()?.terminal?.noColor || !isset(r, g, b) ? '' : `\x1b[38;2;${r};${g};${b}m`,
|
|
86
|
+
bg: (r?, g?, b?) => configFn()?.terminal?.noColor || !isset(r, g, b) ? '' : `${'\x1b['}48;2;${r};${g};${b}m`,
|
|
87
87
|
/** Output a line of title */
|
|
88
|
-
line(title = '', length = configFn()
|
|
89
|
-
const padX = ' '.repeat(paddingX)
|
|
90
|
-
this.log('\u00A0\n' + padX + this.rgb(...clr) + (title + ' ').padEnd(length, char) + this.reset + padX + '\u00A0\n')
|
|
88
|
+
line(title = '', length = configFn()?.terminal?.theme?.pageWidth, clr = configFn()?.terminal?.theme?.primary, char = '=', paddingX = configFn()?.terminal?.theme?.paddingX) {
|
|
89
|
+
const padX = ' '.repeat(paddingX || 0)
|
|
90
|
+
this.log('\u00A0\n' + padX + this.rgb(...clr) + (title + ' ').padEnd(length || 0, char) + this.reset + padX + '\u00A0\n')
|
|
91
91
|
},
|
|
92
92
|
/** Eg: ['cell1', 'cell2', 'cell3'], [25, 15] will start cell2 at 25 and cell 3 at 25 + 15
|
|
93
93
|
* @param {Array} limits default divide the viewport
|
|
94
94
|
*/
|
|
95
|
-
cols(strings, limits = [], clr = configFn()
|
|
95
|
+
cols(strings, limits: number[] = [], clr = configFn()?.terminal?.theme?.fontColor, paddingX = configFn()?.terminal?.theme?.paddingX) {
|
|
96
96
|
|
|
97
97
|
if (!limits.length) {
|
|
98
|
-
const colWidth = Math.round(configFn()
|
|
99
|
-
limits = Array(strings.length - 1).fill(2).map((itm, i) => colWidth * i + 1)
|
|
98
|
+
const colWidth = Math.round(configFn()?.terminal?.theme.pageWidth / strings.length)
|
|
99
|
+
limits = Array(strings.length - 1).fill(2).map((itm, i) => colWidth * i + 1) as number[]
|
|
100
100
|
}
|
|
101
101
|
const str = strings.reduce((glob, str = '', i) => {
|
|
102
102
|
const realCharLength = str.toString().replace(/\x1b\[.*?m/, '').length
|
|
@@ -110,15 +110,15 @@ export const C = {
|
|
|
110
110
|
log(...stringsCtxMayBeFirstParam) {
|
|
111
111
|
stringsCtxMayBeFirstParam.forEach(str => this.logClr(str, undefined, undefined))
|
|
112
112
|
},
|
|
113
|
-
logClr(str, clr = configFn()
|
|
113
|
+
logClr(str, clr = configFn()?.terminal?.theme?.fontColor, paddingX = configFn()?.terminal?.theme?.paddingX) {
|
|
114
114
|
if (!isset(str)) return
|
|
115
|
-
const padX = ' '.repeat(paddingX)
|
|
116
|
-
str = padX + (
|
|
115
|
+
const padX = ' '.repeat(paddingX || 0)
|
|
116
|
+
str = padX + (typeof clr !== 'undefined' ? this.rgb(...clr) : '') + str.toString().replace(/\n/g, '\n' + padX + (typeof clr !== 'undefined' ? this.rgb(...clr) : ''))
|
|
117
117
|
logger.log(str + this.reset, 'info')
|
|
118
118
|
},
|
|
119
119
|
info(...str) {
|
|
120
120
|
str.forEach((s, i) => {
|
|
121
|
-
if (i === 0) this.logClr('ⓘ ' + s, configFn()
|
|
121
|
+
if (i === 0) this.logClr('ⓘ ' + s, configFn()?.terminal?.theme?.primary)
|
|
122
122
|
else this.log(this.dimStrSplit(s))
|
|
123
123
|
})
|
|
124
124
|
this.log(' ')
|
|
@@ -138,7 +138,7 @@ export const C = {
|
|
|
138
138
|
applicationError: (color, ...str) => logErrPrivate('warn', color, ...str),
|
|
139
139
|
warningLight: (color, ...str) => logErrPrivate('warn', [196, 120, 52], ...str),
|
|
140
140
|
dimStrSplit(...logs) {
|
|
141
|
-
let logsStr = []
|
|
141
|
+
let logsStr: string[] = []
|
|
142
142
|
logs.filter(isset).forEach(log => log.toString().split('\n').forEach(line => line && logsStr.push(this.dim(` ${line}`))))
|
|
143
143
|
return logsStr.join('\n')
|
|
144
144
|
},
|
|
@@ -159,26 +159,26 @@ export const C = {
|
|
|
159
159
|
}
|
|
160
160
|
})
|
|
161
161
|
},
|
|
162
|
-
notifications: [],
|
|
162
|
+
notifications: [] as any[], // fn array
|
|
163
163
|
/** Gratientize lines of text (separated by \n) */
|
|
164
|
-
gradientize(str = '', rgb1 = configFn()
|
|
164
|
+
gradientize(str = '', rgb1 = configFn()?.terminal?.theme?.shade1, rgb2 = configFn()?.terminal?.theme?.shade2, bgRgb = configFn()?.terminal?.theme?.bgColor, paddingY = configFn()?.terminal?.theme?.paddingY, paddingX = configFn()?.terminal?.theme?.paddingX) {
|
|
165
165
|
|
|
166
166
|
const lines = str.split('\n')
|
|
167
167
|
const largestLine = lines.reduce((sum, line) => sum < line.length ? line.length : sum, 0)
|
|
168
168
|
const rgbParts = rgb1.map((val, i) => (val - rgb2[i]) / (lines.length))
|
|
169
169
|
|
|
170
170
|
const bg = bgRgb ? this.bg(bgRgb[0], bgRgb[1], bgRgb[2]) : ''
|
|
171
|
-
const padX = ' '.repeat(paddingX)
|
|
171
|
+
const padX = ' '.repeat(paddingX || 0)
|
|
172
172
|
const padLine = bg + padX + ' '.padEnd(largestLine, ' ') + padX + '\x1b[0m\n'
|
|
173
173
|
|
|
174
|
-
console.log(padLine.repeat(paddingY) +
|
|
174
|
+
console.log(padLine.repeat(paddingY || 0) +
|
|
175
175
|
lines.reduce((s, line, i) => {
|
|
176
|
-
return s + bg + padX + this.rgb(...rgb1.map((val, i2) => Math.round(val - i * rgbParts[i2]))) + line.padEnd(largestLine, ' ') + padX + '\x1b[0m\n'
|
|
176
|
+
return s + bg + padX + this.rgb(...((rgb1 as Color).map((val, i2) => Math.round(val - i * rgbParts[i2]))) as Color) + line.padEnd(largestLine, ' ') + padX + '\x1b[0m\n'
|
|
177
177
|
}, '') +
|
|
178
|
-
padLine.repeat(paddingY))
|
|
178
|
+
padLine.repeat(paddingY || 0))
|
|
179
179
|
},
|
|
180
180
|
debugModeLog(title, ...string) {
|
|
181
|
-
this.logClr('🐞 ' + title, configFn()
|
|
181
|
+
this.logClr('🐞 ' + title, configFn()?.terminal?.theme?.debugModeColor, 0)
|
|
182
182
|
this.log(this.dimStrSplit(...string))
|
|
183
183
|
},
|
|
184
184
|
// DEPRECATED
|
|
@@ -216,7 +216,7 @@ function logErrPrivate(level: NotInfoLogLevel, color: Color, ...errors) {
|
|
|
216
216
|
|
|
217
217
|
if (errors.length && errors[0]) {
|
|
218
218
|
const messages = errors.map((e, i) => {
|
|
219
|
-
if (typeof e
|
|
219
|
+
if (typeof e?.log === 'function') {
|
|
220
220
|
e.log()
|
|
221
221
|
return ''
|
|
222
222
|
} else return getStringFromErr(e, i)
|
|
@@ -286,7 +286,7 @@ function stringifyExtraInfos(extraInfoOriginal, type, color, level = 0) {
|
|
|
286
286
|
* @param {String} char Default: '.'
|
|
287
287
|
* @param {String} msg String before char. Final output will be `${str}${char.repeat(step)}`
|
|
288
288
|
*/
|
|
289
|
-
export function cliProgressBar(step, char = '.', msg = `\x1b[2mⓘ Waiting response`) {
|
|
289
|
+
export function cliProgressBar(step: number, char = '.', msg = `\x1b[2mⓘ Waiting response`) {
|
|
290
290
|
if (isset(process) && isset(process.stdout) && isset(process.stdout.clearLine)) {
|
|
291
291
|
process.stdout.clearLine(0)
|
|
292
292
|
process.stdout.cursorTo(0)
|
|
@@ -304,9 +304,9 @@ export class cliLoadingSpinner {
|
|
|
304
304
|
frameRate: number
|
|
305
305
|
animFrames: string[]
|
|
306
306
|
activeProcess: any
|
|
307
|
-
frameNb: number
|
|
308
|
-
progressMessage: string
|
|
309
|
-
interval: any
|
|
307
|
+
frameNb: number = 0
|
|
308
|
+
progressMessage: string = ''
|
|
309
|
+
interval: any = -1
|
|
310
310
|
|
|
311
311
|
constructor(type = 'dots' as loadingSpinnerTypes, activeProcess = process) {
|
|
312
312
|
const anims = {
|
|
@@ -349,6 +349,6 @@ export class cliLoadingSpinner {
|
|
|
349
349
|
|
|
350
350
|
|
|
351
351
|
export function dim(str = '') {
|
|
352
|
-
return configFn()
|
|
352
|
+
return configFn()?.terminal?.noColor ? str : `\x1b[2m${str.toString().split('\n').join('\x1b[0m\n\x1b[2m')}\x1b[0m`
|
|
353
353
|
}
|
|
354
354
|
|
package/src/loop-utils.ts
CHANGED
|
@@ -6,7 +6,7 @@ import { err500IfNotSet } from "./error-utils"
|
|
|
6
6
|
import { isObject } from "./is-object"
|
|
7
7
|
|
|
8
8
|
export function forI<T extends any[] | any>(nbIterations: number, callback: (number: number, previousValue, arrayOfPreviousValues: any[]) => T): T[] {
|
|
9
|
-
const results = []
|
|
9
|
+
const results: any[] = []
|
|
10
10
|
for (let i = 0; i < nbIterations; i++) {
|
|
11
11
|
const prevValue = results[results.length - 1]
|
|
12
12
|
results.push(callback(i, prevValue, results))
|
|
@@ -15,7 +15,7 @@ export function forI<T extends any[] | any>(nbIterations: number, callback: (num
|
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
export async function forIasync<T extends any[] | any>(nbIterations: number, callback: (number) => T): Promise<T[]> {
|
|
18
|
-
const results = []
|
|
18
|
+
const results: any[] = []
|
|
19
19
|
for (let i = 0; i < nbIterations; i++) {
|
|
20
20
|
results.push(await callback(i))
|
|
21
21
|
}
|
|
@@ -41,7 +41,7 @@ export type RecursiveConfig = { disableCircularDependencyRemoval?: boolean }
|
|
|
41
41
|
* NOTE: will remove circular references
|
|
42
42
|
* /!\ check return values
|
|
43
43
|
*/
|
|
44
|
-
export async function recursiveGenericFunction(item: ObjectGeneric | any[], callback: RecursiveCallback, config: RecursiveConfig = {}, addr$ = '', lastElementKey: string | number = '', parent?, techFieldToAvoidCircularDependency = []) {
|
|
44
|
+
export async function recursiveGenericFunction(item: ObjectGeneric | any[], callback: RecursiveCallback, config: RecursiveConfig = {}, addr$ = '', lastElementKey: string | number = '', parent?, techFieldToAvoidCircularDependency: any[] = []) {
|
|
45
45
|
err500IfNotSet({ callback })
|
|
46
46
|
|
|
47
47
|
if (!techFieldToAvoidCircularDependency.includes(item)) {
|
|
@@ -81,7 +81,7 @@ export async function recursiveGenericFunction(item: ObjectGeneric | any[], call
|
|
|
81
81
|
* NOTE: will remove circular references
|
|
82
82
|
* /!\ check return values
|
|
83
83
|
*/
|
|
84
|
-
export function recursiveGenericFunctionSync(item: ObjectGeneric | any[], callback: RecursiveCallback, config: RecursiveConfig = {}, addr$ = '', lastElementKey: string | number = '', parent?, techFieldToAvoidCircularDependency = []) {
|
|
84
|
+
export function recursiveGenericFunctionSync(item: ObjectGeneric | any[], callback: RecursiveCallback, config: RecursiveConfig = {}, addr$ = '', lastElementKey: string | number = '', parent?, techFieldToAvoidCircularDependency: any[] = []) {
|
|
85
85
|
err500IfNotSet({ callback })
|
|
86
86
|
|
|
87
87
|
if (!techFieldToAvoidCircularDependency.includes(item)) {
|
package/src/mongo-utils.ts
CHANGED
|
@@ -5,10 +5,11 @@ import { isType } from "./validation-utils"
|
|
|
5
5
|
import { isset } from "./isset"
|
|
6
6
|
|
|
7
7
|
/** @return undefined if cannot find _id */
|
|
8
|
-
export function getId(obj: any = {}): string {
|
|
8
|
+
export function getId(obj: any = {}): string | undefined {
|
|
9
9
|
if (!obj) return // null case
|
|
10
10
|
if (obj._id) return obj._id.toString()
|
|
11
11
|
else if (isType(obj, 'objectId')) return obj.toString()
|
|
12
|
+
else return
|
|
12
13
|
}
|
|
13
14
|
|
|
14
15
|
/** Merge filter with correct handling of OR and AND
|
package/src/object-utils.ts
CHANGED
|
@@ -76,7 +76,7 @@ export function findByAddressAll(obj, addr, returnAddresses = false) {
|
|
|
76
76
|
.replace(/\.\*/g, '.[^.]+') // replace * by [^. (all but a point)]
|
|
77
77
|
+ '$')
|
|
78
78
|
|
|
79
|
-
const matchingItems = []
|
|
79
|
+
const matchingItems: any[] = []
|
|
80
80
|
|
|
81
81
|
recursiveGenericFunctionSync(obj, (item, address) => {
|
|
82
82
|
if (addrRegexp.test(address)) matchingItems.push(returnAddresses ? [address, item] : item)
|
|
@@ -122,6 +122,7 @@ export const objForceWritePath = forcePathInObject
|
|
|
122
122
|
*/
|
|
123
123
|
export function objForceWriteIfNotSet<MainObj extends Record<string, any>>(obj: MainObj, addr: string, item): MainObj {
|
|
124
124
|
if (!isset(findByAddress(obj, addr))) return objForceWrite(obj, addr, item)
|
|
125
|
+
else return obj
|
|
125
126
|
}
|
|
126
127
|
|
|
127
128
|
/** Merge mixins into class. Use it in the constructor like: mergeMixins(this, {myMixin: true}) */
|
|
@@ -140,10 +141,10 @@ export function cloneObject<MainObj extends Record<string, any>>(o: MainObj): Ma
|
|
|
140
141
|
/** Deep clone. WILL REMOVE circular references */
|
|
141
142
|
export function deepClone<MainObj extends Record<string, any>>(obj: MainObj, cache = []): MainObj {
|
|
142
143
|
|
|
143
|
-
let copy
|
|
144
|
+
let copy: any | any[]
|
|
144
145
|
// usefull to not modify 1st level objet by lower levels
|
|
145
146
|
// this is required for the same object to be referenced not in a redundant way
|
|
146
|
-
const newCache = [...cache]
|
|
147
|
+
const newCache: any[] = [...cache]
|
|
147
148
|
if (obj instanceof Date) return new Date(obj) as any
|
|
148
149
|
|
|
149
150
|
// Handle Array
|
|
@@ -152,7 +153,7 @@ export function deepClone<MainObj extends Record<string, any>>(obj: MainObj, cac
|
|
|
152
153
|
newCache.push(obj)
|
|
153
154
|
copy = []
|
|
154
155
|
for (var i = 0, len = obj.length; i < len; i++) {
|
|
155
|
-
copy[i] = deepClone(obj[i], newCache)
|
|
156
|
+
copy[i] = deepClone(obj[i], newCache as any)
|
|
156
157
|
}
|
|
157
158
|
return copy
|
|
158
159
|
}
|
|
@@ -163,7 +164,7 @@ export function deepClone<MainObj extends Record<string, any>>(obj: MainObj, cac
|
|
|
163
164
|
copy = {}
|
|
164
165
|
for (var key in obj) {
|
|
165
166
|
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
166
|
-
copy[key] = deepClone(obj[key], newCache)
|
|
167
|
+
copy[key] = deepClone(obj[key], newCache as any)
|
|
167
168
|
}
|
|
168
169
|
}
|
|
169
170
|
return copy
|
|
@@ -336,7 +337,7 @@ export function mergeDeepConfigurable(replacerForArrays = (prev, curr) => curr,
|
|
|
336
337
|
export function flattenObject(data, config: { withoutArraySyntax?: boolean, withArraySyntaxMinified?: boolean } = {}) {
|
|
337
338
|
const { withoutArraySyntax = false, withArraySyntaxMinified = false } = config
|
|
338
339
|
const result = {}
|
|
339
|
-
const seenObjects = [] // avoidCircular reference to infinite loop
|
|
340
|
+
const seenObjects: any[] = [] // avoidCircular reference to infinite loop
|
|
340
341
|
const recurse = (cur, prop) => {
|
|
341
342
|
if (Array.isArray(cur)) {
|
|
342
343
|
let l = cur.length
|
package/src/regexp-utils.ts
CHANGED
|
@@ -24,7 +24,7 @@ export function firstMatch(str: string, regExp: RegExp): string | undefined { re
|
|
|
24
24
|
export function allMatches(str: string, reg: RegExp): string[] {
|
|
25
25
|
let i = 0
|
|
26
26
|
let matches
|
|
27
|
-
const arr = []
|
|
27
|
+
const arr: string[] = []
|
|
28
28
|
if (typeof str !== 'string') C.error('Not a string provided as first argument for allMatches()')
|
|
29
29
|
else {
|
|
30
30
|
reg = new RegExp(reg, 'g')
|
package/src/string-utils.ts
CHANGED
|
@@ -96,8 +96,8 @@ export function getValuesBetweenStrings(str: string, openingOrSeparator, closing
|
|
|
96
96
|
|
|
97
97
|
str = str.replace(/<</g, '§§"').replace(/>>/g, '"§§')
|
|
98
98
|
|
|
99
|
-
const arrayValues = []
|
|
100
|
-
const betweenArray = []
|
|
99
|
+
const arrayValues: string[] = []
|
|
100
|
+
const betweenArray: string[] = []
|
|
101
101
|
let level = 0
|
|
102
102
|
let ignoreUntil: boolean | string = false
|
|
103
103
|
let actualValue = ''
|
|
@@ -170,7 +170,7 @@ export function convertAccentedCharacters(str, config: { removeNumbers?: boolean
|
|
|
170
170
|
}
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
let generatedTokens = [] // cache to avoid collision
|
|
173
|
+
let generatedTokens: string[] = [] // cache to avoid collision
|
|
174
174
|
let lastTs = new Date().getTime()
|
|
175
175
|
/** minLength 8 if unique
|
|
176
176
|
* @param {Number} length default: 20
|
|
@@ -213,9 +213,9 @@ export function pathJoinSafe(...pathBits: string[]) {
|
|
|
213
213
|
|
|
214
214
|
|
|
215
215
|
export type MiniTemplaterOptions = {
|
|
216
|
-
valueWhenNotSet
|
|
217
|
-
regexp
|
|
218
|
-
valueWhenContentUndefined
|
|
216
|
+
valueWhenNotSet: string
|
|
217
|
+
regexp: RegExp
|
|
218
|
+
valueWhenContentUndefined: string
|
|
219
219
|
}
|
|
220
220
|
/** Replace variables in a string like: `Hello {{userName}}!`
|
|
221
221
|
* @param {String} content
|
|
@@ -224,14 +224,14 @@ export type MiniTemplaterOptions = {
|
|
|
224
224
|
* * valueWhenNotSet => replacer for undefined values. Default: ''
|
|
225
225
|
* * regexp => must be 'g' and first capturing group matching the value to replace. Default: /{{\s*([^}]*)\s*}}/g
|
|
226
226
|
*/
|
|
227
|
-
export function miniTemplater(content: string, varz: ObjectGeneric, options: MiniTemplaterOptions = {}): string {
|
|
228
|
-
|
|
227
|
+
export function miniTemplater(content: string, varz: ObjectGeneric, options: Partial<MiniTemplaterOptions> = {}): string {
|
|
228
|
+
const options2:MiniTemplaterOptions = {
|
|
229
229
|
valueWhenNotSet: '',
|
|
230
230
|
regexp: /{{\s*([^}]*)\s*}}/g,
|
|
231
231
|
valueWhenContentUndefined: '',
|
|
232
232
|
...options,
|
|
233
233
|
}
|
|
234
|
-
return isset(content) ? content.replace(
|
|
234
|
+
return isset(content) ? content.replace(options2.regexp, (m, $1) => isset(varz[$1]) ? varz[$1] : options2.valueWhenNotSet) : options2.valueWhenContentUndefined
|
|
235
235
|
}
|
|
236
236
|
|
|
237
237
|
|
package/src/tests-utils.ts
CHANGED
package/src/timer-utils.ts
CHANGED
|
@@ -33,7 +33,7 @@ export async function waitUntilTrue(callback, timeoutSec = 10, errorAfterNSecond
|
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
|
|
36
|
-
const delayedLoopParams = []
|
|
36
|
+
const delayedLoopParams: [any, number, any][] = []
|
|
37
37
|
let isExecuting = false
|
|
38
38
|
|
|
39
39
|
/** Allow to perform an action in a delayed loop, useful for example to avoid reaching limits on servers. This function can be securely called multiple times.
|
|
@@ -46,7 +46,7 @@ export async function executeInDelayedLoop(callback, time = 500, errorCallback =
|
|
|
46
46
|
if (isExecuting) return
|
|
47
47
|
isExecuting = true
|
|
48
48
|
while (delayedLoopParams.length) {
|
|
49
|
-
const [callback, time, errorCallback] = delayedLoopParams.shift()
|
|
49
|
+
const [callback, time, errorCallback] = delayedLoopParams.shift() as any
|
|
50
50
|
try {
|
|
51
51
|
await callback()
|
|
52
52
|
await timeout(time)
|
package/src/validation-utils.ts
CHANGED
|
@@ -90,7 +90,7 @@ export type ValidatorObject = {
|
|
|
90
90
|
}
|
|
91
91
|
export function validator(...paramsToValidate: ValidatorObject[]) {
|
|
92
92
|
const errArray = validatorReturnErrArray(...paramsToValidate)
|
|
93
|
-
if (errArray.length) throw new DescriptiveError(...errArray)
|
|
93
|
+
if (errArray.length) throw new DescriptiveError(...(errArray as [string, object]))
|
|
94
94
|
}
|
|
95
95
|
|
|
96
96
|
|
|
@@ -117,7 +117,7 @@ export function validatorReturnErrArray(...paramsToValidate: ValidatorObject[]):
|
|
|
117
117
|
|
|
118
118
|
// parse => name: {myVar1: 'blah, myvar2: myvar2}
|
|
119
119
|
if (typeof param.name === 'object' && !Array.isArray(param.name))
|
|
120
|
-
Object.keys(param.name).forEach(name => paramsFormatted.push(Object.assign({}, param, { name: name, value: param
|
|
120
|
+
Object.keys(param.name).forEach(name => paramsFormatted.push(Object.assign({}, param, { name: name, value: param?.name?.[name] })))
|
|
121
121
|
else paramsFormatted.push(param)
|
|
122
122
|
})
|
|
123
123
|
|
|
@@ -131,28 +131,28 @@ export function validatorReturnErrArray(...paramsToValidate: ValidatorObject[]):
|
|
|
131
131
|
const errMess = (msg, extraInfos = {}, errCode = 422): [string, object] => [msg, { code: errCode, origin: 'Generic validator', varName: name, gotValue: isset(value) && isset(value.data) && isset(value.data.data) ? { ...value, data: 'Buffer' } : value, ...extraInfos }]
|
|
132
132
|
|
|
133
133
|
// accept syntax { 'myVar.var2': myVar.var2, ... }
|
|
134
|
-
if (
|
|
134
|
+
if (typeof name !== 'undefined' && !hasValue) {
|
|
135
135
|
name = Object.keys(paramObj).find(param => !['name', 'value', 'type', 'eq', 'neq', 'in', 'lt', 'gt', 'lte', 'gte', 'length', 'minLength', 'maxLength', 'emptyAllowed', 'regexp', 'mustNotBeSet', 'isset', 'optional', 'isArray'].includes(param))
|
|
136
|
-
if (
|
|
136
|
+
if (typeof name !== 'undefined') value = paramObj[name]
|
|
137
137
|
}
|
|
138
138
|
// if nameString ends by $ sign it is optional
|
|
139
|
-
if (
|
|
139
|
+
if (typeof name !== 'undefined' && /.*\$$/.test(name)) {
|
|
140
140
|
name = name.substr(0, name.length - 1)
|
|
141
141
|
optional = true
|
|
142
142
|
}
|
|
143
143
|
|
|
144
144
|
// DEFINED AND NOT EMPTY
|
|
145
|
-
if (
|
|
146
|
-
if (
|
|
145
|
+
if (typeof value === 'undefined' && optional) continue
|
|
146
|
+
if (typeof value !== 'undefined' && paramObj.mustNotBeSet) return errMess('variableMustNotBeSet')
|
|
147
147
|
if (paramObj.mustNotBeSet) continue // exit
|
|
148
|
-
if (
|
|
148
|
+
if (typeof value === 'undefined') return errMess('requiredVariableEmptyOrNotSet')
|
|
149
149
|
if (!emptyAllowed && value === '') return errMess('requiredVariableEmpty')
|
|
150
150
|
|
|
151
151
|
const isArray = paramObj.isArray
|
|
152
152
|
if (isArray && !Array.isArray(value)) return errMess('wrongTypeForVar', { expectedType: 'array', gotType: typeof value })
|
|
153
153
|
|
|
154
154
|
// TYPE
|
|
155
|
-
if (
|
|
155
|
+
if (typeof paramObj.type !== 'undefined') {
|
|
156
156
|
const types = asArray(paramObj.type) // support for multiple type
|
|
157
157
|
const areSomeTypeValid = types.some(type => {
|
|
158
158
|
if (type.endsWith('[]')) {
|
|
@@ -204,21 +204,21 @@ export function validatorReturnErrArray(...paramsToValidate: ValidatorObject[]):
|
|
|
204
204
|
any: () => true,
|
|
205
205
|
}
|
|
206
206
|
|
|
207
|
-
return
|
|
207
|
+
return typeof basicTypeCheck?.[type] !== 'undefined' && basicTypeCheck?.[type](value) ||
|
|
208
208
|
typeof value === type && type !== 'object' || // for string, number, boolean...
|
|
209
|
-
|
|
209
|
+
typeof configFn()?.customTypes?.[type] !== 'undefined' && configFn()?.customTypes?.[type]?.test(value)
|
|
210
210
|
})
|
|
211
211
|
if (!areSomeTypeValid) return errMess(`wrongTypeForVar`, { expectedTypes: types.join(', '), gotType: Object.prototype.toString.call(value), gotValue: removeCircularJSONstringify(value).substring(0, 999) })
|
|
212
212
|
}
|
|
213
213
|
|
|
214
214
|
// GREATER / LESS
|
|
215
|
-
if (
|
|
216
|
-
if (
|
|
217
|
-
if (
|
|
218
|
-
if (
|
|
215
|
+
if (typeof paramObj.gte !== 'undefined' && value < paramObj.gte) return errMess(`valueShouldBeSuperiorOrEqualForVar`, { shouldBeSupOrEqTo: paramObj.gte })
|
|
216
|
+
if (typeof paramObj.lte !== 'undefined' && value > paramObj.lte) return errMess(`valueShouldBeInferiorOrEqualForVar`, { shouldBeInfOrEqTo: paramObj.lte })
|
|
217
|
+
if (typeof paramObj.gt !== 'undefined' && value <= paramObj.gt) return errMess(`valueShouldBeSuperiorForVar`, { shouldBeSupOrEqTo: paramObj.gt })
|
|
218
|
+
if (typeof paramObj.lt !== 'undefined' && value >= paramObj.lt) return errMess(`valueShouldBeInferiorForVar`, { shouldBeInfOrEqTo: paramObj.lt })
|
|
219
219
|
|
|
220
220
|
// IN VALUES
|
|
221
|
-
if (
|
|
221
|
+
if (typeof paramObj.in !== 'undefined') {
|
|
222
222
|
const equals = Array.isArray(paramObj.in) ? paramObj.in : [paramObj.in]
|
|
223
223
|
if (!equals.some(equalVal => equalVal === value)) return errMess(`wrongValueForVar`, { supportedValues: JSON.stringify(equals) })
|
|
224
224
|
}
|
|
@@ -236,19 +236,19 @@ export function validatorReturnErrArray(...paramsToValidate: ValidatorObject[]):
|
|
|
236
236
|
}
|
|
237
237
|
|
|
238
238
|
// INCLUDES
|
|
239
|
-
if (
|
|
239
|
+
if (typeof paramObj.includes !== 'undefined' && !value.includes(paramObj.includes))
|
|
240
240
|
return errMess(`wrongValueForVar`, { shouldIncludes: paramObj.includes })
|
|
241
241
|
|
|
242
242
|
// REGEXP
|
|
243
|
-
if (
|
|
243
|
+
if (typeof paramObj.regexp !== 'undefined' && !paramObj.regexp.test(value))
|
|
244
244
|
return errMess(`wrongValueForVar`, { shouldMatchRegexp: paramObj.regexp.toString() })
|
|
245
245
|
|
|
246
246
|
// MIN / MAX LENGTH works for number length. Eg: 20180101.length == 8
|
|
247
|
-
if (
|
|
247
|
+
if (typeof paramObj.minLength !== 'undefined' && paramObj.minLength > (typeof value == 'number' ? value + '' : value).length)
|
|
248
248
|
return errMess(`wrongLengthForVar`, { minLength: paramObj.minLength })
|
|
249
|
-
if (
|
|
249
|
+
if (typeof paramObj.maxLength !== 'undefined' && paramObj.maxLength < (typeof value == 'number' ? value + '' : value).length)
|
|
250
250
|
return errMess(`wrongLengthForVar`, { maxLength: paramObj.maxLength })
|
|
251
|
-
if (
|
|
251
|
+
if (typeof paramObj.length !== 'undefined' && paramObj.length !== (typeof value == 'number' ? value + '' : value).length)
|
|
252
252
|
return errMess(`wrongLengthForVar`, { length: paramObj.length })
|
|
253
253
|
}
|
|
254
254
|
|
package/src/wtf-utils.ts
CHANGED
|
@@ -17,6 +17,8 @@ export function randomEmoji(msg, length = 20) {
|
|
|
17
17
|
return o.padEnd(length, ' ') + (msg ? '< ' + msg : '')
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
+
type CompObject = { char: string, replacement: string }
|
|
21
|
+
|
|
20
22
|
/** STRING COMPRESSOR
|
|
21
23
|
* peut facilement être utilisé par uncomp directement (stock les metadonnées sur la comp)
|
|
22
24
|
*/
|
|
@@ -27,7 +29,7 @@ export function compAuto(str) {
|
|
|
27
29
|
|
|
28
30
|
|
|
29
31
|
const unusedChars = utf8Chars.filter(c => !str.includes(c))
|
|
30
|
-
const charMap = []
|
|
32
|
+
const charMap: CompObject[] = []
|
|
31
33
|
|
|
32
34
|
const mostFreqStr = str2 => {
|
|
33
35
|
const o = {}
|
|
@@ -51,7 +53,7 @@ export function compAuto(str) {
|
|
|
51
53
|
strLengthBefore = str.length
|
|
52
54
|
const toReplace = mostFreqStr(str)
|
|
53
55
|
if (isset(toReplace)) {
|
|
54
|
-
const char = unusedChars.shift()
|
|
56
|
+
const char: string = unusedChars.shift() as any
|
|
55
57
|
charMap.push({ char, replacement: toReplace }) // { ù: 'aa' }
|
|
56
58
|
str = str.replace(new RegExp(escapeRegexp(toReplace), 'g'), char)
|
|
57
59
|
}
|
|
@@ -67,15 +69,15 @@ export function compAuto(str) {
|
|
|
67
69
|
}
|
|
68
70
|
|
|
69
71
|
export function unComp(str) {
|
|
70
|
-
const charMap = []
|
|
72
|
+
const charMap: CompObject[] = []
|
|
71
73
|
const map = str.split('§')
|
|
72
74
|
str = map.pop()
|
|
73
75
|
map.forEach(e => {
|
|
74
|
-
|
|
76
|
+
const char: string = e[0]
|
|
75
77
|
let replacement = e.substring(1, 999)
|
|
76
78
|
if (replacement.includes('Ơ')) {
|
|
77
|
-
const [char, nb] = replacement.split('Ơ')
|
|
78
|
-
replacement = char.repeat(nb)
|
|
79
|
+
const [char, nb] = replacement.split('Ơ') as [string, string]
|
|
80
|
+
replacement = char.repeat(parseInt(nb))
|
|
79
81
|
}
|
|
80
82
|
charMap.push({ char, replacement })
|
|
81
83
|
})
|