mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
205 lines
5.1 KiB
TypeScript
205 lines
5.1 KiB
TypeScript
import type { UnwrapRef } from 'vue'
|
|
|
|
import type { Obj } from '@/types/commons'
|
|
|
|
/**
|
|
* Allow to set a timeout on a `Promise` expected response.
|
|
* The returned Promise will be rejected if the original Promise is not resolved or
|
|
* rejected before the delay.
|
|
*
|
|
* @param promise - A promise (like a fetch call).
|
|
* @param delay - delay after which the promise is rejected
|
|
*/
|
|
export function timeout<T extends unknown>(
|
|
promise: Promise<T>,
|
|
delay: number,
|
|
): Promise<T> {
|
|
return new Promise((resolve, reject) => {
|
|
// FIXME reject(new Error('api_not_responding')) for post-install
|
|
setTimeout(() => reject, delay)
|
|
promise.then(resolve, reject)
|
|
})
|
|
}
|
|
|
|
/**
|
|
* Check if passed value is an object literal.
|
|
*
|
|
* @param value - Anything.
|
|
*/
|
|
export function isObjectLiteral(value: any): value is object {
|
|
return (
|
|
value !== null &&
|
|
value !== undefined &&
|
|
Object.is(value.constructor, Object)
|
|
)
|
|
}
|
|
|
|
export function objectGet<
|
|
T extends Obj,
|
|
K extends keyof T | string,
|
|
F extends any = undefined,
|
|
>(obj: T, key: K, fallback?: F) {
|
|
return (key in obj ? obj[key] : fallback) as K extends keyof T ? T[K] : F
|
|
}
|
|
|
|
/**
|
|
* Check if value is "empty" (`null`, `undefined`, `''`, `[]`, '{}').
|
|
* Note: `0` is not considered "empty" in that helper.
|
|
*
|
|
* @param value - Anything.
|
|
*/
|
|
export function isEmptyValue(
|
|
value: any,
|
|
): value is null | undefined | '' | [] | {} {
|
|
if (typeof value === 'number' || typeof value === 'boolean') return false
|
|
return (
|
|
!value ||
|
|
(Array.isArray(value) && value.length === 0) ||
|
|
Object.keys(value).length === 0
|
|
)
|
|
}
|
|
|
|
type Flatten<T extends object> = object extends T
|
|
? object
|
|
: {
|
|
[K in keyof T]-?: (
|
|
x: NonNullable<T[K]> extends infer V
|
|
? V extends object
|
|
? V extends readonly any[]
|
|
? Pick<T, K>
|
|
: Flatten<V> extends infer FV
|
|
? {
|
|
[P in keyof FV as `${Extract<P, string | number>}`]: FV[P]
|
|
}
|
|
: never
|
|
: Pick<T, K>
|
|
: never,
|
|
) => void
|
|
} extends Record<keyof T, (y: infer O) => void>
|
|
? O extends infer U
|
|
? { [K in keyof O]: O[K] }
|
|
: never
|
|
: never
|
|
|
|
/**
|
|
* Returns an flattened object literal, with all keys at first level and removing nested ones.
|
|
*
|
|
* @param obj - An object literal to flatten.
|
|
* @param flattened - An object literal to add passed obj keys/values.
|
|
*/
|
|
export function flattenObjectLiteral<T extends object>(
|
|
obj: T,
|
|
flattened: Partial<Flatten<T>> = {},
|
|
) {
|
|
function flatten(objLit: Partial<Flatten<T>>) {
|
|
for (const key in objLit) {
|
|
const value = objLit[key]
|
|
if (isObjectLiteral(value)) {
|
|
flatten(value)
|
|
} else {
|
|
flattened[key] = value
|
|
}
|
|
}
|
|
}
|
|
flatten(obj)
|
|
return flattened as Flatten<T>
|
|
}
|
|
|
|
/**
|
|
* Returns an new Object filtered with passed filter function.
|
|
* Each entry `[key, value]` will be forwarded to the `filter` function.
|
|
*
|
|
* @param obj - object to filter.
|
|
* @param filter - the filter function to call for each entry.
|
|
*/
|
|
export function filterObject<T extends Obj>(
|
|
obj: T,
|
|
filter: (
|
|
entries: [string, any],
|
|
index: number,
|
|
array: [string, any][],
|
|
) => boolean,
|
|
) {
|
|
return Object.fromEntries(
|
|
Object.entries(obj).filter((...args) => filter(...args)),
|
|
)
|
|
}
|
|
|
|
/**
|
|
* Returns an new array containing items that are in first array but not in the other.
|
|
*/
|
|
export function arrayDiff<T extends string>(
|
|
arr1: T[] = [],
|
|
arr2: T[] = [],
|
|
): T[] {
|
|
return arr1.filter((item) => !arr2.includes(item))
|
|
}
|
|
|
|
/**
|
|
* Returns a new string with escaped HTML (`&<>"'` replaced by entities).
|
|
*
|
|
* @param unsafe - string to escape
|
|
*/
|
|
export function escapeHtml(unsafe: string) {
|
|
return unsafe
|
|
.replace(/&/g, '&')
|
|
.replace(/</g, '<')
|
|
.replace(/>/g, '>')
|
|
.replace(/"/g, '"')
|
|
.replace(/'/g, ''')
|
|
}
|
|
|
|
/**
|
|
* Returns a random integer between `min` and `max`.
|
|
*
|
|
* @param min - min possible value
|
|
* @param max - max possible value
|
|
*/
|
|
export function randint(min: number, max: number) {
|
|
return Math.floor(Math.random() * (max - min + 1)) + min
|
|
}
|
|
|
|
/**
|
|
* Returns a File content.
|
|
*
|
|
* @param file -
|
|
* @param base64 - returns a base64 representation of the file.
|
|
*/
|
|
export function getFileContent(
|
|
file: File,
|
|
{ base64 = false } = {},
|
|
): Promise<string> {
|
|
return new Promise((resolve, reject) => {
|
|
const reader = new FileReader()
|
|
reader.onerror = reject
|
|
reader.onload = () => resolve(reader.result as string)
|
|
|
|
if (base64) {
|
|
reader.readAsDataURL(file)
|
|
} else {
|
|
reader.readAsText(file)
|
|
}
|
|
})
|
|
}
|
|
|
|
export function toEntries<T extends Record<PropertyKey, unknown>>(
|
|
obj: T,
|
|
): { [K in keyof T]: [K, T[K]] }[keyof T][] {
|
|
return Object.entries(obj) as { [K in keyof T]: [K, T[K]] }[keyof T][]
|
|
}
|
|
}
|
|
|
|
export function omit<T extends Obj, K extends (keyof T)[]>(
|
|
obj: T,
|
|
keys: K,
|
|
): Omit<T, K[number]> {
|
|
return Object.fromEntries(
|
|
Object.keys(obj)
|
|
.filter((key) => !keys.includes(key))
|
|
.map((key) => [key, obj[key]]),
|
|
) as Omit<T, K[number]>
|
|
}
|
|
|
|
export function asUnreffed<T>(value: T): UnwrapRef<T> {
|
|
return value as UnwrapRef<T>
|
|
}
|