chore: split app to commons and web (squash commit)
This commit is contained in:
44
packages/hoppscotch-common/src/helpers/functional/array.ts
Normal file
44
packages/hoppscotch-common/src/helpers/functional/array.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
import { clone } from "lodash-es"
|
||||
/**
|
||||
* Sorts the array based on the sort func.
|
||||
* NOTE: Creates a new array, if you don't need ref
|
||||
* to original array, use `arrayUnsafeSort` for better perf
|
||||
* @param sortFunc Sort function to sort against
|
||||
*/
|
||||
export const arraySort =
|
||||
<T>(sortFunc: (a: T, b: T) => number) =>
|
||||
(arr: T[]) => {
|
||||
const newArr = clone(arr)
|
||||
|
||||
newArr.sort(sortFunc)
|
||||
|
||||
return newArr
|
||||
}
|
||||
|
||||
/**
|
||||
* Sorts an array based on the sort func.
|
||||
* Unsafe because this sort mutates the passed array
|
||||
* and returns it. So use it if you do not want the
|
||||
* original array for better performance
|
||||
* @param sortFunc sort function to sort against (same as Array.sort)
|
||||
*/
|
||||
export const arrayUnsafeSort =
|
||||
<T>(sortFunc: (a: T, b: T) => number) =>
|
||||
(arr: T[]) => {
|
||||
arr.sort(sortFunc)
|
||||
|
||||
return arr
|
||||
}
|
||||
|
||||
/**
|
||||
* Equivalent to `Array.prototype.flatMap`
|
||||
* @param mapFunc The map function
|
||||
* @returns
|
||||
*/
|
||||
export const arrayFlatMap =
|
||||
<T, U>(mapFunc: (value: T, index: number, arr: T[]) => U[]) =>
|
||||
(arr: T[]) =>
|
||||
arr.flatMap(mapFunc)
|
||||
|
||||
export const stringArrayJoin = (separator: string) => (arr: string[]) =>
|
||||
arr.join(separator)
|
||||
22
packages/hoppscotch-common/src/helpers/functional/debug.ts
Normal file
22
packages/hoppscotch-common/src/helpers/functional/debug.ts
Normal file
@@ -0,0 +1,22 @@
|
||||
/**
|
||||
* Logs the current value and returns the same value
|
||||
* @param x The value to log
|
||||
* @returns The parameter `x` passed to this
|
||||
*/
|
||||
export const trace = <T>(x: T) => {
|
||||
console.log(x)
|
||||
return x
|
||||
}
|
||||
|
||||
/**
|
||||
* Logs the annotated current value and returns the same value
|
||||
* @param name The name of the log
|
||||
* @curried_param `x` The value to log
|
||||
* @returns The parameter `x` passed to this
|
||||
*/
|
||||
export const namedTrace =
|
||||
(name: string) =>
|
||||
<T>(x: T) => {
|
||||
console.log(`${name}:`, x)
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
export const throwError = (message: string): never => {
|
||||
throw new Error(message)
|
||||
}
|
||||
19
packages/hoppscotch-common/src/helpers/functional/files.ts
Normal file
19
packages/hoppscotch-common/src/helpers/functional/files.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as TO from "fp-ts/TaskOption"
|
||||
|
||||
export const readFileAsText = (file: File) =>
|
||||
TO.tryCatch(
|
||||
() =>
|
||||
new Promise<string>((resolve, reject) => {
|
||||
const reader = new FileReader()
|
||||
|
||||
reader.onload = () => {
|
||||
resolve(reader.result as string)
|
||||
}
|
||||
|
||||
reader.onerror = () => {
|
||||
reject(new Error("File err"))
|
||||
}
|
||||
|
||||
reader.readAsText(file)
|
||||
})
|
||||
)
|
||||
@@ -0,0 +1,12 @@
|
||||
type FormDataEntry = {
|
||||
key: string
|
||||
value: string | Blob
|
||||
}
|
||||
|
||||
export const toFormData = (values: FormDataEntry[]) => {
|
||||
const formData = new FormData()
|
||||
|
||||
values.forEach(({ key, value }) => formData.append(key, value))
|
||||
|
||||
return formData
|
||||
}
|
||||
17
packages/hoppscotch-common/src/helpers/functional/json.ts
Normal file
17
packages/hoppscotch-common/src/helpers/functional/json.ts
Normal file
@@ -0,0 +1,17 @@
|
||||
import * as O from "fp-ts/Option"
|
||||
import { flow } from "fp-ts/function"
|
||||
|
||||
/**
|
||||
* Checks and Parses JSON string
|
||||
* @param str Raw JSON data to be parsed
|
||||
* @returns Option type with some(JSON data) or none
|
||||
*/
|
||||
export const safeParseJSON = (str: string): O.Option<object> =>
|
||||
O.tryCatch(() => JSON.parse(str))
|
||||
|
||||
/**
|
||||
* Checks if given string is a JSON string
|
||||
* @param str Raw string to be checked
|
||||
* @returns If string is a JSON string
|
||||
*/
|
||||
export const isJSON = flow(safeParseJSON, O.isSome)
|
||||
65
packages/hoppscotch-common/src/helpers/functional/object.ts
Normal file
65
packages/hoppscotch-common/src/helpers/functional/object.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import { pipe } from "fp-ts/function"
|
||||
import { isEqual, cloneDeep } from "lodash-es"
|
||||
import { JSPrimitive, TypeFromPrimitive } from "./primtive"
|
||||
|
||||
export const objRemoveKey =
|
||||
<T, K extends keyof T>(key: K) =>
|
||||
(obj: T): Omit<T, K> =>
|
||||
pipe(cloneDeep(obj), (e) => {
|
||||
delete e[key]
|
||||
return e
|
||||
})
|
||||
|
||||
export const objFieldMatches =
|
||||
<T, K extends keyof T, V extends T[K]>(
|
||||
fieldName: K,
|
||||
matches: ReadonlyArray<V>
|
||||
) =>
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
(obj: T): obj is T & { [_ in K]: V } =>
|
||||
matches.findIndex((x) => isEqual(obj[fieldName], x)) !== -1
|
||||
|
||||
export const objHasProperty =
|
||||
<O extends object, K extends string, P extends JSPrimitive | undefined>(
|
||||
prop: K,
|
||||
type?: P
|
||||
) =>
|
||||
// eslint-disable-next-line
|
||||
(obj: O): obj is O & { [_ in K]: TypeFromPrimitive<P> } =>
|
||||
// eslint-disable-next-line
|
||||
prop in obj && (type === undefined || typeof (obj as any)[prop] === type)
|
||||
|
||||
type TypeFromPrimitiveArray<P extends JSPrimitive | undefined> =
|
||||
P extends "undefined"
|
||||
? undefined
|
||||
: P extends "object"
|
||||
? object[] | null
|
||||
: P extends "boolean"
|
||||
? boolean[]
|
||||
: P extends "number"
|
||||
? number[]
|
||||
: P extends "bigint"
|
||||
? bigint[]
|
||||
: P extends "string"
|
||||
? string[]
|
||||
: P extends "symbol"
|
||||
? symbol[]
|
||||
: P extends "function"
|
||||
? Function[] // eslint-disable-line @typescript-eslint/ban-types
|
||||
: unknown[]
|
||||
|
||||
// The ban-types silence is because in this case,
|
||||
// we can't get the Function type info to make a better guess
|
||||
|
||||
export const objHasArrayProperty =
|
||||
<O extends object, K extends string, P extends JSPrimitive>(
|
||||
prop: K,
|
||||
type: P
|
||||
) =>
|
||||
// eslint-disable-next-line
|
||||
(obj: O): obj is O & { [_ in K]: TypeFromPrimitiveArray<P> } =>
|
||||
prop in obj &&
|
||||
Array.isArray((obj as any)[prop]) &&
|
||||
(obj as any)[prop].every(
|
||||
(val: unknown) => typeof val === type // eslint-disable-line
|
||||
)
|
||||
19
packages/hoppscotch-common/src/helpers/functional/option.ts
Normal file
19
packages/hoppscotch-common/src/helpers/functional/option.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
import * as O from "fp-ts/Option"
|
||||
import * as A from "fp-ts/Array"
|
||||
import { pipe } from "fp-ts/function"
|
||||
|
||||
/**
|
||||
* Tries to match one of the given predicates.
|
||||
* If a predicate is matched, the associated value is returned in a Some.
|
||||
* Else if none of the predicates is matched, None is returned.
|
||||
* @param choice An array of tuples having a predicate function and the selected value
|
||||
* @returns A function which takes the input and returns an Option
|
||||
*/
|
||||
export const optionChoose =
|
||||
<T, V>(choice: Array<[(x: T) => boolean, V]>) =>
|
||||
(input: T): O.Option<V> =>
|
||||
pipe(
|
||||
choice,
|
||||
A.findFirst(([pred]) => pred(input)),
|
||||
O.map(([, value]) => value)
|
||||
)
|
||||
@@ -0,0 +1,37 @@
|
||||
export type JSPrimitive =
|
||||
| "undefined"
|
||||
| "object"
|
||||
| "boolean"
|
||||
| "number"
|
||||
| "bigint"
|
||||
| "string"
|
||||
| "symbol"
|
||||
| "function"
|
||||
|
||||
export type TypeFromPrimitive<P extends JSPrimitive | undefined> =
|
||||
P extends "undefined"
|
||||
? undefined
|
||||
: P extends "object"
|
||||
? object | null // typeof null === "object"
|
||||
: P extends "boolean"
|
||||
? boolean
|
||||
: P extends "number"
|
||||
? number
|
||||
: P extends "bigint"
|
||||
? bigint
|
||||
: P extends "string"
|
||||
? string
|
||||
: P extends "symbol"
|
||||
? symbol
|
||||
: P extends "function"
|
||||
? Function // eslint-disable-line @typescript-eslint/ban-types
|
||||
: unknown
|
||||
|
||||
// The ban-types silence is because in this case,
|
||||
// we can't get the Function type info to make a better guess
|
||||
|
||||
export const isOfType =
|
||||
<T extends JSPrimitive>(type: T) =>
|
||||
(value: unknown): value is T =>
|
||||
// eslint-disable-next-line valid-typeof
|
||||
typeof value === type
|
||||
44
packages/hoppscotch-common/src/helpers/functional/record.ts
Normal file
44
packages/hoppscotch-common/src/helpers/functional/record.ts
Normal file
@@ -0,0 +1,44 @@
|
||||
/**
|
||||
* Converts an array of key-value tuples (for e.g ["key", "value"]), into a record.
|
||||
* (for eg. output -> { "key": "value" })
|
||||
* NOTE: This function will discard duplicate key occurances and only keep the last occurance. If you do not want that behaviour,
|
||||
* use `tupleWithSamesKeysToRecord`.
|
||||
* @param tuples Array of tuples ([key, value])
|
||||
* @returns A record with value corresponding to the last occurance of that key
|
||||
*/
|
||||
export const tupleToRecord = <
|
||||
KeyType extends string | number | symbol,
|
||||
ValueType
|
||||
>(
|
||||
tuples: [KeyType, ValueType][]
|
||||
): Record<KeyType, ValueType> =>
|
||||
tuples.length > 0
|
||||
? (Object.assign as any)(...tuples.map(([key, val]) => ({ [key]: val }))) // This is technically valid, but we have no way of telling TypeScript it is valid. Hence the assertion
|
||||
: {}
|
||||
|
||||
/**
|
||||
* Converts an array of key-value tuples (for e.g ["key", "value"]), into a record.
|
||||
* (for eg. output -> { "key": ["value"] })
|
||||
* NOTE: If you do not want the array as values (because of duplicate keys) and want to instead get the last occurance, use `tupleToRecord`
|
||||
* @param tuples Array of tuples ([key, value])
|
||||
* @returns A Record with values being arrays corresponding to each key occurance
|
||||
*/
|
||||
export const tupleWithSameKeysToRecord = <
|
||||
KeyType extends string | number | symbol,
|
||||
ValueType
|
||||
>(
|
||||
tuples: [KeyType, ValueType][]
|
||||
): Record<KeyType, ValueType[]> => {
|
||||
// By the end of the function we do ensure this typing, this can't be infered now though, hence the assertion
|
||||
const out = {} as Record<KeyType, ValueType[]>
|
||||
|
||||
for (const [key, value] of tuples) {
|
||||
if (!out[key]) {
|
||||
out[key] = [value]
|
||||
} else {
|
||||
out[key].push(value)
|
||||
}
|
||||
}
|
||||
|
||||
return out
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import * as TE from "fp-ts/TaskEither"
|
||||
|
||||
/**
|
||||
* A utility type which gives you the type of the left value of a TaskEither
|
||||
*/
|
||||
export type TELeftType<T extends TE.TaskEither<any, any>> =
|
||||
T extends TE.TaskEither<
|
||||
infer U,
|
||||
// eslint-disable-next-line
|
||||
infer _
|
||||
>
|
||||
? U
|
||||
: never
|
||||
Reference in New Issue
Block a user