@my-js/utils
v0.0.16
Published
Useful JavaScript Utilities.
Downloads
6
Maintainers
Readme
Utils
Useful JavaScript Utilities.
Installation
yarn add @my-js/utils
# or
npm i @my-js/utils
Usage
import { randInt } from '@my-js/utils'
const int = randInt(1, 10)
console.log(int) // 6
List
Number
randInt(min: number, max: number)
sortNum(arr: number[], asc = true)
range(stop: number, start = 0, step = 1): [start, step, ...stop)
String
escape(str: string)
: converts&<>'"
to&<>'"
unescape(str: string)
randStr(len = 10, symbols = UPPER + LOWER + NUM)
:UPPER
:'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
,LOWER
:'abcdefghijklmnopqrstuvwxyz'
,NUM
:'0123456789'
sortStr(arr: string[], acs = true)
:sortStr.locales: string | string[]
sortStr.options: Intl.CollatorOptions
trim(str: string)
: removes all extra spacestruncate(str: string, max: number, end = '...')
: examplewords(count = 3, minMax = [2, 10], cap = true)
:cap: true
enables capitalization of each word:capitilize(word: string)
wrap(str: string, max: number, end = '\n')
: example
Array
choice<T>(arr: T[]): random T
chunk<T>(arr: T[], size: number): T[] | T[][]
: exampleshuffle<T>(arr: T[])
Object
iterable<T extends object>(obj: T)
: makesobj
iterable; exampleequal<T>(objA: T, objB: T)
: deeply comparesobjA
andobjB
: example
Function
curry(fn: Function)
partial(fn: Function, ...args: any[])
debounce(fn: Function, ms: number)
throttle(fn: Function, ms: number)
measure(fn: Function, ...args: any[])
measureAsync(fn: Function, ...args: any[])
memo(fn: Function, cacheKey?: any)
: by defaultargs.length ? JSON.stringify(args) : fn.name
used as key for cache; examplememoAsync(fn: Function, cacheKey?: any)
: examplepipe(...fns: Function[])
: examplepipeAsync(...fns: Function[])
: examplesleep(ms: number)
Common
empty(val: any)
size(val: any)
type(val: any)
fake(len = 1, fields: Field[])
: returns fake data; examplemask(val: string | number, count: number, mask = '*')
randColor()
: returns random HEX color
Web API
clickInside(el: Element, cb: Function)
clickOutside(el: Element, cb: Function)
copyText(str: string): Promise<void>
: copies text to clipboardpasteText(el: Element): Promise<void>
: pastes text from clipboard toel.textContent
formToObj<T>(form: HTMLFormElement): T
formToQuery(form: HTMLFormElement): string
objToQuery<T extends {}>(obj: T): string
queryToObj<T>(q: string): T
cookieToObj<T>(str: string): T
: JSDoc example availableobjToCookie<T extends {}>(obj: T): string
: JSDoc example availableuuid(): string
: JSDoc example availablehash(str: string): Promise<string>
: JSDoc example availablecustomFetch<T>(options: Options): FetchResponse<T>
: advanced version of Fetch; exampleintl
: set of functions to work with locale sensitive data; exampleobserveIntersection(el: Element, cb: Function, options?: IntersectionObserverInit)
observeMutations(el: Element, cb: Function, options: MutationObserverInit = { childList: true, attributes: true, subtree: true })
visibilityChange(onHidden?: Function, onVisible?: Function)
worker(fn: Function)
: executesfn
in Web Worker
Examples
truncate
import { truncate } from '@my-js/utils'
const str = 'JavaScript'
const truncated = truncate(str, 4)
console.log(truncated) // Java...
const truncated2 = truncate(str, 4, '?')
console.log(truncated2) // Java?
wrap
import { wrap } from '@my-js/utils'
const str =
'Lorem, ipsum dolor sit amet consectetur adipisicing elit. Est, veniam?'
const wrapped = wrap(str, 30)
console.log(wrapped)
/*
Lorem, ipsum dolor sit amet
consectetur adipisicing elit.
Est, veniam?
*/
chunk
import { chunk } from '@my-js/utils'
const arr = [1, 2, 3, 4, 5]
const chunked = chunk(arr, 2)
console.log(chunked)
/*
[
[1, 2],
[3, 4],
[5]
]
*/
iterable
import { iterable } from '@my-js/utils'
const user = {
name: 'Harry',
age: 32
}
const iter = iterable<typeof user>(user)
for (const v of iter) {
console.log(v)
}
/*
Harry
32
*/
equal
import { equal } from '@my-js/utils'
const objA = {
name: 'Harry',
job: {
position: 'Chief Engineer'
}
}
const objB = {
name: 'Harry',
job: {
position: 'Chief Engineer'
}
}
console.log(equal(objA, objB)) // true
// or `new Set()`
const mapA = new Map()
mapA.set('name', 'Harry')
const job = { position: 'Chief Engineer' }
mapA.set('job', job)
const mapB = new Map()
mapB.set('name', 'Harry')
mapB.set('job', job)
console.log(equal(mapA, mapB)) // true
const mapC = new Map()
mapC.set('name', 'Harry')
mapC.set('job', { position: 'Chief Engineer' })
console.log(equal(mapB, mapC)) // false
const objC = {
0: 'Harry',
1: 32
}
// just for demonstration purposes
const arr = ['Harry', 32] as unknown as typeof objC
console.log(equal(objC, arr)) // false
// can be used in `React.useEffect` or `React.memo`
memo
import { memo, measure } from '@my-js/utils'
const fact = (n: number): number => (n < 2 ? n : n * fact(n - 1))
const memoFact = memo(fact)
// result calculates
console.log(measure(memoFact, 10000).toFixed(2)) // 0.30
// result delivers from cache
console.log(measure(memoFact, 10000).toFixed(2)) // 0
memoAsync
import { measureAsync, memoAsync } from '@my-js/utils'
const fetchUserById = memoAsync((id: number) =>
fetch(`https://jsonplaceholder.typicode.com/todos/${id}`)
)
console.log(Math.round(await measureAsync(fetchUserById, 1))) // 60
console.log(Math.round(await measureAsync(fetchUserById, 1))) // 0
pipe
import { pipe } from '@my-js/utils'
const toUpperCase = (str) => str.toUpperCase()
const removeSpaces = (str) => str.replace(/\s/g, '')
const addExclamation = (str) => str + '!'
const format = pipe(toUpperCase, removeSpaces, addExclamation)
console.log(format('hello world')) // HELLOWORLD!
pipeAsync
const sayHiAndSleep = async (name: string) => {
console.log(`Hi, ${name}!`)
await sleep(1000)
return name.toUpperCase()
}
const askQuestionAndSleep = async (name: string) => {
console.log(`How are you, ${name}?`)
await sleep(1000)
return new TextEncoder()
.encode(name) // Uint8Array
.toString()
.replaceAll(',', '-')
}
const sayBi = async (name: string) => {
console.log(`Bye, ${name}.`)
}
const speak = pipeAsync(sayHiAndSleep, askQuestionAndSleep, sayBi)
speak('Harry')
/*
Hi, Harry!
// waiting for 1s
How are you, HARRY?
// waiting for 1s
Bye, 72-65-82-82-89.
*/
fake
import { fake, randInt, range, TYPE, words } from '@my-js/utils'
const fields = [
{ name: 'id', type: TYPE.ID },
{ name: 'firstName', type: TYPE.STR, count: 1 },
{ name: 'lastName', type: TYPE.STR, count: 1 },
{ name: 'age', type: TYPE.NUM, minMax: [18, 65] },
{ name: 'isMarried', type: TYPE.BOOL },
{
name: 'company',
type: TYPE.OBJ,
fields: [
{
name: 'name',
type: TYPE.STR,
count: 3
},
{
name: 'position',
type: TYPE.STR,
count: 2
}
]
},
{ name: 'scores', value: range(5).map(() => randInt(1, 10)) },
{ name: 'movies', value: range(5).map(() => words(randInt(1, 3))) },
{
name: 'friends',
value: fake(2, [
{ name: 'id', type: TYPE.ID },
{ name: 'firstName', type: TYPE.STR, count: 1 },
{ name: 'lastName', type: TYPE.STR, count: 1 }
])
}
]
const data = fake(1, fields)
console.log(JSON.stringify(data, null, 2))
/*
[
{
"id": "ZvO3fE25Kq",
"firstName": "Kwvan",
"lastName": "Iaiazwlu",
"age": 52,
"isMarried": false,
"company": {
"name": "Kvh Iebz Tceysx",
"position": "Wejg Ugkswkztsf"
},
"scores": [
10,
10,
9,
9,
6
],
"movies": [
"Vlcpmtjqo",
"Yldzevozge Wocr Pxgwdhwtf",
"Avch Obtgwk",
"Mpqld Gpnsmxe",
"Xrpsqaqzb Sgloho"
],
"friends": [
{
"id": "4RHtu6RyBH",
"firstName": "Ticnf",
"lastName": "Chk"
},
{
"id": "8o9QwrgPXs",
"firstName": "Ocjo",
"lastName": "Jbjtl"
}
]
}
]
*/
customFetch
import { customFetch } from '@my-js/utils'
// receives `options` object
const response = await customFetch({
url: 'https://jsonplaceholder.typicode.com/todos/1',
/*
// optional
// results caching, `false` by default
customCache: true,
// logging, `false` by default
log: true,
// query params, converts to query string - `q=search`, `undefined` by default
params: { q: 'search' },
handlers: {
onSuccess: (data) => {},
onError: (error) => {},
onAbort: () => {}
}
*/
})
console.log(response)
/*
{
"data": {
"userId": 1,
"id": 1,
"title": "delectus aut autem",
"completed": false
},
"error": null,
"info": {
"headers": {
"cache-control": "max-age=43200",
"content-type": "application/json; charset=utf-8",
"expires": "-1",
"pragma": "no-cache"
},
"status": 200,
"statusText": "",
"url": "https://jsonplaceholder.typicode.com/todos/1"
}
}
*/
// wrong URL
const response2 = await customFetch.get(
'https://jsonplaceholder.typicod.com/todos/1'
/* options */
)
console.log(response2)
/*
{
"data": null,
"error": Error,
"info": null
}
*/
// let's suppose, that our server responds with
// `res.status(400).json({ message: 'Some required fields is missing' })`
const response3 = await customFetch.get('https://my-js.org')
console.log(response3)
/*
{
"data": null,
"error": {
"message": "Some required fields is missing"
},
"info": {
"status": 400
// ...
}
}
*/
// other method aliases
customFetch.post<T>(url: string | BodyInit, body?: BodyInit | Omit<Options, 'url'>, options?: Omit<Options, 'url'>)
customFetch.update<T>(url: string | BodyInit, body?: BodyInit | Omit<Options, 'url'>, options?: Omit<Options, 'url'>)
customFetch.remove<T>(url: string | BodyInit,options?: Omit<Options, 'url'>)
// we can also provide
customFetch.baseUrl = 'https://my-js.org/docs/'
customFetch.get('/guide/nextjs')
// final URL will be `https://my-js.org/docs/guide/nextjs`
// and
customFetch.accessToken = 'T0k3n'
// 'T0k3n' will be added to `headers` object - `Authorization: Bearer T0k3n`
// every request can be cancelled
customFetch.cancel(customFetch.currentRequestId)
intl
import { intl } from './index'
intl.locales = 'de'
console.log(intl.formatDate(new Date())) // 9.2.2023
intl.locales = 'en-US'
intl.dateOptions = {
dateStyle: 'long',
timeStyle: 'medium'
}
console.log(intl.formatDate(new Date()))
// February 9, 2023 at 10:35:20 PM
intl.numberOptions = {
style: 'currency',
currency: 'EUR'
}
const formatCurrency = intl.formatNumber
console.log(formatCurrency(100)) // €100.00
intl.locales = 'fr'
console.log(formatCurrency(100)) // 100,00 €
// other options
intl.listOptions: Intl.ListFormatOptions
intl.compareOptions: Intl.CollatorOptions
// other methods
intl.formatList(list?: Iterable<string>)
intl.compareValues(values?: string | string[])
PRs are very welcome.