├── .lintstagedrc.json ├── pnpm-workspace.yaml ├── commitlint.config.js ├── packages └── std │ ├── .lintstagedrc.json │ ├── .prettierignore │ ├── jest.config.js │ ├── jsr.json │ ├── .prettierrc.json │ ├── .eslintrc.json │ ├── src │ ├── function │ │ ├── noop.ts │ │ ├── sleep.ts │ │ ├── pipe.ts │ │ ├── compose.ts │ │ ├── pipeFn.ts │ │ └── composeFn.ts │ ├── string │ │ ├── insertAt.ts │ │ ├── replaceAt.ts │ │ ├── pascalCase.ts │ │ ├── capitalize.ts │ │ ├── isEmail.ts │ │ ├── strReplace.ts │ │ └── camelCase.ts │ ├── maths │ │ ├── isOdd.ts │ │ ├── isEven.ts │ │ ├── percentage.ts │ │ ├── divMod.ts │ │ ├── percentageOf.ts │ │ ├── mean.ts │ │ ├── avg.ts │ │ ├── clamp.ts │ │ ├── sum.ts │ │ ├── prod.ts │ │ ├── median.ts │ │ ├── mode.ts │ │ ├── isSubsetOf.ts │ │ ├── isDisjointFrom.ts │ │ └── isSupersetOf.ts │ ├── number │ │ ├── isZero.ts │ │ ├── isNegZero.ts │ │ └── toNum.ts │ ├── types │ │ ├── isNull.ts │ │ ├── isBigInt.ts │ │ ├── isBlob.ts │ │ ├── isBool.ts │ │ ├── isDef.ts │ │ ├── isStr.ts │ │ ├── isErr.ts │ │ ├── isArr.ts │ │ ├── isSym.ts │ │ ├── isUndef.ts │ │ ├── isFn.ts │ │ ├── isArrBuf.ts │ │ ├── isPureObj.ts │ │ ├── isWkSet.ts │ │ ├── isPromise.ts │ │ ├── isSet.ts │ │ ├── isRegEx.ts │ │ ├── isWkMap.ts │ │ ├── isMap.ts │ │ ├── isWkRef.ts │ │ ├── isDataView.ts │ │ ├── isGenFn.ts │ │ ├── isDate.ts │ │ ├── isInfinity.ts │ │ ├── isJSON.ts │ │ ├── isAsyFn.ts │ │ ├── isObj.ts │ │ ├── isNum.ts │ │ └── isTypedArr.ts │ ├── array │ │ ├── swap.ts │ │ ├── reverse.ts │ │ ├── arrRm.ts │ │ ├── arrIns.ts │ │ ├── shuffle.ts │ │ ├── sort.ts │ │ ├── move.ts │ │ ├── arrReplace.ts │ │ ├── compact.ts │ │ ├── groupBy.ts │ │ ├── chunk.ts │ │ ├── bounds.ts │ │ ├── countBy.ts │ │ ├── max.ts │ │ ├── min.ts │ │ ├── uniq.ts │ │ ├── intersperse.ts │ │ ├── take.ts │ │ ├── intersection.ts │ │ ├── sortBy.ts │ │ ├── diff.ts │ │ ├── union.ts │ │ └── drop.ts │ ├── colors │ │ ├── hexToRGB.ts │ │ └── rgbToHex.ts │ ├── async │ │ ├── aForEach.ts │ │ ├── aPipe.ts │ │ ├── aMap.ts │ │ ├── aFilter.ts │ │ ├── aCompose.ts │ │ ├── aPipeFn.ts │ │ ├── aResolvers.ts │ │ └── aComposeFn.ts │ ├── assert │ │ ├── isNil.ts │ │ ├── isEmpty.ts │ │ └── isEqlArr.ts │ └── object │ │ ├── fromPath.ts │ │ ├── shallowMerge.ts │ │ ├── shallowMergeAll.ts │ │ ├── get.ts │ │ ├── merge.ts │ │ ├── has.ts │ │ ├── toPath.ts │ │ ├── size.ts │ │ ├── unset.ts │ │ ├── mergeAll.ts │ │ ├── set.ts │ │ └── toSet.ts │ ├── __tests__ │ ├── function │ │ ├── noop.spec.js │ │ ├── sleep.spec.js │ │ ├── pipe.spec.js │ │ ├── compose.spec.js │ │ ├── pipeFn.spec.js │ │ └── composeFn.spec.js │ ├── maths │ │ ├── mean.spec.ts │ │ ├── isEven.spec.ts │ │ ├── divMod.spec.ts │ │ ├── median.spec.ts │ │ ├── isOdd.spec.ts │ │ ├── clamp.spec.ts │ │ ├── prod.spec.ts │ │ ├── mode.spec.ts │ │ ├── avg.spec.ts │ │ ├── percentageOf.spec.js │ │ ├── isDisjointFrom.spec.ts │ │ ├── sum.spec.ts │ │ └── percentage.spec.js │ ├── types │ │ ├── isBlob.spec.ts │ │ ├── isBigInt.spec.ts │ │ ├── isRegEx.spec.ts │ │ ├── isUndef.spec.ts │ │ ├── isWkRef.spec.ts │ │ ├── isWkMap.spec.ts │ │ ├── isWkSet.spec.ts │ │ ├── isNull.spec.ts │ │ ├── isErr.spec.ts │ │ ├── isArrBuf.spec.ts │ │ ├── isFn.spec.ts │ │ ├── isMap.spec.ts │ │ ├── isSet.spec.ts │ │ ├── isStr.spec.ts │ │ ├── isSym.spec.ts │ │ ├── isAsyFn.spec.ts │ │ ├── isGenFn.spec.ts │ │ ├── isDataView.spec.ts │ │ ├── isBool.spec.ts │ │ ├── isDef.spec.ts │ │ ├── isArr.spec.ts │ │ ├── isTypedArr.spec.ts │ │ ├── isDate.spec.ts │ │ ├── isInfinity.spec.ts │ │ ├── isPromise.spec.ts │ │ └── isJSON.spec.ts │ ├── object │ │ └── fromPath.spec.ts │ ├── async │ │ ├── aMap.spec.ts │ │ ├── aFilter.spec.ts │ │ ├── aResolvers.spec.ts │ │ ├── aCompose.spec.js │ │ ├── aForEach.spec.ts │ │ └── aPipe.spec.js │ ├── assert │ │ ├── isNil.spec.ts │ │ └── isEmpty.spec.ts │ ├── number │ │ ├── isZero.spec.ts │ │ └── isNegZero.spec.ts │ ├── array │ │ ├── shuffle.spec.ts │ │ ├── symDiff.spec.js │ │ ├── chunk.spec.ts │ │ ├── reverse.spec.ts │ │ ├── arrRm.spec.ts │ │ ├── compact.spec.ts │ │ ├── swap.spec.ts │ │ ├── arrIns.spec.ts │ │ ├── move.spec.ts │ │ ├── arrReplace.spec.ts │ │ ├── countBy.spec.ts │ │ ├── union.spec.ts │ │ └── max.spec.ts │ ├── string │ │ ├── capitalize.spec.js │ │ ├── pascalCase.spec.js │ │ ├── insertAt.spec.js │ │ └── replaceAt.spec.js │ └── colors │ │ ├── hexToRGB.spec.js │ │ └── rgbToHex.spec.js │ └── tsup.config.js ├── apps └── docs │ ├── pages │ ├── Colors │ │ ├── _meta.json │ │ ├── hexToRGB.mdx │ │ └── rgbToHex.mdx │ ├── Number │ │ ├── _meta.json │ │ ├── toNum.mdx │ │ ├── isNegZero.mdx │ │ └── isZero.mdx │ ├── Assert │ │ ├── _meta.json │ │ ├── isNil.mdx │ │ └── isEqlArr.mdx │ ├── Function │ │ ├── _meta.json │ │ ├── noop.mdx │ │ └── sleep.mdx │ ├── _meta.json │ ├── String │ │ ├── _meta.json │ │ ├── isEmail.mdx │ │ ├── capitalize.mdx │ │ ├── pascalCase.mdx │ │ ├── insertAt.mdx │ │ └── replaceAt.mdx │ ├── Async │ │ ├── _meta.json │ │ ├── aMap.mdx │ │ ├── aFilter.mdx │ │ └── aResolvers.mdx │ ├── Maths │ │ ├── _meta.json │ │ ├── isOdd.mdx │ │ ├── isEven.mdx │ │ ├── clamp.mdx │ │ ├── divMod.mdx │ │ ├── prod.mdx │ │ ├── percentage.mdx │ │ ├── percentageOf.mdx │ │ ├── avg.mdx │ │ ├── sum.mdx │ │ ├── mean.mdx │ │ ├── mode.mdx │ │ └── median.mdx │ ├── Object │ │ ├── _meta.json │ │ ├── toPath.mdx │ │ ├── fromPath.mdx │ │ ├── mergeAll.mdx │ │ ├── shallowMergeAll.mdx │ │ ├── shallowMerge.mdx │ │ ├── pick.mdx │ │ ├── merge.mdx │ │ ├── has.mdx │ │ ├── omit.mdx │ │ └── get.mdx │ ├── Types │ │ ├── isBlob.mdx │ │ ├── isNull.mdx │ │ ├── isErr.mdx │ │ ├── isMap.mdx │ │ ├── isBigInt.mdx │ │ ├── isStr.mdx │ │ ├── isWkMap.mdx │ │ ├── isWkSet.mdx │ │ ├── isArr.mdx │ │ ├── isSet.mdx │ │ ├── isArrBuf.mdx │ │ ├── isSym.mdx │ │ ├── isRegEx.mdx │ │ ├── isUndef.mdx │ │ ├── isDate.mdx │ │ ├── isBool.mdx │ │ ├── isWkRef.mdx │ │ ├── isTypedArr.mdx │ │ ├── isFn.mdx │ │ ├── isDef.mdx │ │ ├── isDataView.mdx │ │ ├── _meta.json │ │ ├── isInfinity.mdx │ │ ├── isAsyFn.mdx │ │ ├── isGenFn.mdx │ │ └── isJSON.mdx │ ├── playground.mdx │ └── Array │ │ ├── _meta.json │ │ ├── chunk.mdx │ │ ├── move.mdx │ │ ├── shuffle.mdx │ │ ├── uniq.mdx │ │ ├── reverse.mdx │ │ ├── swap.mdx │ │ ├── compact.mdx │ │ ├── max.mdx │ │ ├── arrRm.mdx │ │ ├── bounds.mdx │ │ └── min.mdx │ ├── public │ ├── _headers │ └── assets │ │ ├── isDisjointFrom-venn-diagram.svg │ │ ├── isSubsetOf-venn-diagram.svg │ │ ├── isSupersetOf-venn-diagram.svg │ │ ├── intersection-venn-diagram.svg │ │ ├── diff-venn-diagram.svg │ │ ├── union-venn-diagram.svg │ │ └── sym-diff-venn-diagram.svg │ ├── next-sitemap.config.js │ └── package.json ├── .github ├── FUNDING.yml └── workflows │ ├── publish.yml │ └── build.yml ├── .husky ├── commit-msg └── pre-commit ├── .gitignore ├── .changeset ├── config.json └── README.md ├── turbo.json └── LICENSE /.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { "*.md": "prettier --write" } 2 | -------------------------------------------------------------------------------- /pnpm-workspace.yaml: -------------------------------------------------------------------------------- 1 | packages: 2 | - "packages/*" 3 | - "apps/*" -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /packages/std/.lintstagedrc.json: -------------------------------------------------------------------------------- 1 | { "*.{ts,tsx}": ["prettier --write", "pnpm run lint --"] } 2 | -------------------------------------------------------------------------------- /packages/std/.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | coverage 3 | build 4 | built 5 | dist 6 | lib -------------------------------------------------------------------------------- /apps/docs/pages/Colors/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "hexToRGB": "hexToRGB", 3 | "rgbToHex": "rgbToHex" 4 | } 5 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: [Open-Tech-Foundation] 4 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | npx --no -- commitlint --edit ${1} 5 | -------------------------------------------------------------------------------- /packages/std/jest.config.js: -------------------------------------------------------------------------------- 1 | export default { 2 | transform: { 3 | '^.+\\.(t|j)sx?$': '@swc/jest', 4 | }, 5 | }; 6 | -------------------------------------------------------------------------------- /packages/std/jsr.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@opentf/std", 3 | "version": "0.12.0", 4 | "exports": "./src/index.ts" 5 | } 6 | -------------------------------------------------------------------------------- /apps/docs/pages/Number/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "isNegZero": "isNegZero", 3 | "isZero": "isZero", 4 | "toNum": "toNum" 5 | } 6 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env sh 2 | . "$(dirname -- "$0")/_/husky.sh" 3 | 4 | pnpm lint-staged --concurrent false 5 | 6 | # exit 1 -------------------------------------------------------------------------------- /packages/std/.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "es5", 3 | "tabWidth": 2, 4 | "semi": true, 5 | "singleQuote": true 6 | } 7 | -------------------------------------------------------------------------------- /apps/docs/public/_headers: -------------------------------------------------------------------------------- 1 | https://js-std.pages.dev/* 2 | Cross-Origin-Embedder-Policy: require-corp 3 | Cross-Origin-Opener-Policy: same-origin -------------------------------------------------------------------------------- /packages/std/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "extends": ["@opentf/eslint-config-base"], 4 | "ignorePatterns": ["*.spec.[tj]s"] 5 | } 6 | -------------------------------------------------------------------------------- /packages/std/src/function/noop.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * The No Operation function. 3 | * 4 | * @example 5 | * 6 | * noop() //=> undefined 7 | */ 8 | export default function noop() {} 9 | -------------------------------------------------------------------------------- /apps/docs/pages/Assert/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "isEmpty": "isEmpty", 3 | "isEql": "isEql", 4 | "isEqlArr": "isEqlArr", 5 | "isNil": "isNil", 6 | "isShallowEql": "isShallowEql" 7 | } 8 | -------------------------------------------------------------------------------- /apps/docs/pages/Function/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "compose": "compose", 3 | "composeFn": "composeFn", 4 | "noop": "noop", 5 | "pipe": "pipe", 6 | "pipeFn": "pipeFn", 7 | "sleep": "sleep" 8 | } 9 | -------------------------------------------------------------------------------- /packages/std/src/string/insertAt.ts: -------------------------------------------------------------------------------- 1 | function insertAt(str: string, index = 0, insertStr = ''): string { 2 | return str.slice(0, index) + insertStr + str.slice(index); 3 | } 4 | 5 | export default insertAt; 6 | -------------------------------------------------------------------------------- /apps/docs/pages/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "index": "Introduction", 3 | "playground": { 4 | "title": "Playground", 5 | "type": "page", 6 | "theme": { 7 | "layout": "full" 8 | } 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /apps/docs/next-sitemap.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next-sitemap').IConfig} */ 2 | module.exports = { 3 | siteUrl: 'https://js-std.pages.dev', 4 | generateIndexSitemap: false, 5 | priority: false, 6 | changefreq: false, 7 | outDir: "build" 8 | } -------------------------------------------------------------------------------- /apps/docs/pages/String/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "camelCase": "camelCase", 3 | "capitalize": "capitalize", 4 | "insertAt": "insertAt", 5 | "isEmail": "isEmail", 6 | "pascalCase": "pascalCase", 7 | "replaceAt": "replaceAt", 8 | "strReplace": "strReplace" 9 | } 10 | -------------------------------------------------------------------------------- /apps/docs/pages/Async/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "aCompose": "aCompose", 3 | "aComposeFn": "aComposeFn", 4 | "aFilter": "aFilter", 5 | "aForEach": "aForEach", 6 | "aMap": "aMap", 7 | "aPipe": "aPipe", 8 | "aPipeFn": "aPipeFn", 9 | "aResolvers": "aResolvers" 10 | } 11 | -------------------------------------------------------------------------------- /packages/std/src/maths/isOdd.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given number is an Odd number. 3 | * 4 | * @example 5 | * 6 | * isOdd(1) //=> true 7 | * isOdd(2) //=> false 8 | */ 9 | 10 | export default function isOdd(n: number): boolean { 11 | return n % 2 !== 0; 12 | } 13 | -------------------------------------------------------------------------------- /packages/std/src/maths/isEven.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given number is an Even number. 3 | * 4 | * @example 5 | * 6 | * isEven(1) //=> false 7 | * isEven(2) //=> true 8 | */ 9 | 10 | export default function isEven(n: number): boolean { 11 | return n % 2 === 0; 12 | } 13 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/noop.spec.js: -------------------------------------------------------------------------------- 1 | import { noop } from '../../src'; 2 | 3 | describe('Function', () => { 4 | test('noop', () => { 5 | expect(noop()).toBe(undefined); 6 | expect(noop(null)).toBe(undefined); 7 | expect(noop(1)).toBe(undefined); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/std/src/number/isZero.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given number is positive zero (0). 3 | * 4 | * @example 5 | * 6 | * isZero(-0) //=> false 7 | * isZero(0) //=> true 8 | */ 9 | 10 | export default function isZero(n: number): boolean { 11 | return Object.is(n, 0); 12 | } 13 | -------------------------------------------------------------------------------- /packages/std/src/string/replaceAt.ts: -------------------------------------------------------------------------------- 1 | function replaceAt(str: string, index = 0, replaceStr = ''): string { 2 | const rStrLen = index + (replaceStr.length === 0 ? 1 : replaceStr.length); 3 | 4 | return str.slice(0, index) + replaceStr + str.slice(rStrLen); 5 | } 6 | 7 | export default replaceAt; 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | 8 | # Dependency directories 9 | node_modules/ 10 | jspm_packages/ 11 | 12 | # Artifacts 13 | dist 14 | build 15 | built 16 | lib 17 | 18 | .parcel-cache 19 | 20 | play.js 21 | .turbo 22 | 23 | .next -------------------------------------------------------------------------------- /packages/std/tsup.config.js: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | entry: ['src/index.ts'], 5 | splitting: false, 6 | sourcemap: true, 7 | clean: true, 8 | format: ['cjs', 'esm'], 9 | dts: true, 10 | minify: true, 11 | name: 'utils', 12 | }); 13 | -------------------------------------------------------------------------------- /packages/std/src/number/isNegZero.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given number is negative zero (-0). 3 | * 4 | * @example 5 | * 6 | * isNegZero(0) //=> false 7 | * isNegZero(-0) //=> true 8 | */ 9 | 10 | export default function isNegZero(n: number): boolean { 11 | return Object.is(n, -0); 12 | } 13 | -------------------------------------------------------------------------------- /packages/std/src/types/isNull.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is null. 3 | * 4 | * @example 5 | * 6 | * isNull(null) //=> true 7 | * 8 | * isNull(undefined) //=> false 9 | * 10 | */ 11 | 12 | export default function isNull(val: unknown): val is null { 13 | return val === null; 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/src/string/pascalCase.ts: -------------------------------------------------------------------------------- 1 | import camelCase from './camelCase'; 2 | import replaceAt from './replaceAt'; 3 | 4 | function pascalCase(str: string): string { 5 | const result = camelCase(str); 6 | 7 | return replaceAt(result, 0, result[0].toUpperCase()); 8 | } 9 | 10 | export default pascalCase; 11 | -------------------------------------------------------------------------------- /packages/std/src/types/isBigInt.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a BigInt. 3 | * 4 | * @example 5 | * 6 | * isBigInt(1) //=> false 7 | * 8 | * isBigInt(1n) //=> true 9 | * 10 | */ 11 | 12 | export default function isBigInt(val: unknown): val is bigint { 13 | return typeof val === 'bigint'; 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/src/function/sleep.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * It suspends the execution for the given milliseconds. 3 | * 4 | * @example 5 | * 6 | * await sleep(1000) // It sleeps for 1 second 7 | */ 8 | export default async function sleep(ms: number): Promise { 9 | return new Promise((resolve) => setTimeout(resolve, ms)); 10 | } 11 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/sleep.spec.js: -------------------------------------------------------------------------------- 1 | import { sleep } from '../../src'; 2 | 3 | describe('Function', () => { 4 | test('sleep', async () => { 5 | await expect(sleep()).resolves.not.toThrow(); 6 | await expect(sleep(0)).resolves.not.toThrow(); 7 | await expect(sleep(10)).resolves.not.toThrow(); 8 | }); 9 | }); 10 | -------------------------------------------------------------------------------- /packages/std/src/maths/percentage.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * It returns percentage of value & total. 3 | * @param {number} value - The current value 4 | * @param {number} total - The total value 5 | * @returns {number} 6 | */ 7 | export default function percentage(value: number, total: number): number { 8 | return (value / total) * 100; 9 | } 10 | -------------------------------------------------------------------------------- /packages/std/src/types/isBlob.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a blob. 3 | * 4 | * @example 5 | * 6 | * isBlob(new Blob()) //=> true 7 | * 8 | * isBlob({}) //=> false 9 | */ 10 | 11 | export default function isBlob(val: unknown): val is Blob { 12 | return Object.prototype.toString.call(val) === '[object Blob]'; 13 | } 14 | -------------------------------------------------------------------------------- /packages/std/src/types/isBool.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is boolean. 3 | * 4 | * @example 5 | * 6 | * isBool(true) //=> true 7 | * 8 | * isBool(false) //=> true 9 | * 10 | * isBool(null) //=> false 11 | */ 12 | 13 | export default function isBool(val: unknown): boolean { 14 | return typeof val === 'boolean'; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/mean.spec.ts: -------------------------------------------------------------------------------- 1 | import { mean } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('mean', () => { 5 | expect(mean()).toBe(NaN); 6 | expect(mean([])).toBe(NaN); 7 | expect(mean([1])).toBe(1); 8 | expect(mean([4, 1, 7])).toBe(4); 9 | expect(mean([4, 2, 8])).toBeCloseTo(4.67); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/std/src/types/isDef.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is defined. 3 | * 4 | * @example 5 | * 6 | * isDef() //=> false 7 | * isDef(undefined) //=> false 8 | * isDef(null) //=> true 9 | * isDef('') //=> true 10 | * 11 | */ 12 | 13 | export default function isDef(val: unknown): boolean { 14 | return val !== undefined; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/types/isStr.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a string. 3 | * 4 | * @example 5 | * 6 | * isStr('abc') //=> true 7 | * 8 | * isStr(String(1)) //=> true 9 | * 10 | * isStr(1) //=> false 11 | * 12 | */ 13 | 14 | export default function isStr(val: unknown): val is string { 15 | return typeof val === 'string'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/isEven.spec.ts: -------------------------------------------------------------------------------- 1 | import { isEven } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('isEven', () => { 5 | expect(isEven(0)).toBe(true); 6 | expect(isEven(1)).toBe(false); 7 | expect(isEven(2)).toBe(true); 8 | expect(isEven(-1)).toBe(false); 9 | expect(isEven(-2)).toBe(true); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/std/src/array/swap.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Swaps two elements in an array. 3 | * 4 | * @example 5 | * swap([1, 2, 3, 4, 5], 0, 1) //=> [2, 1, 3, 4, 5] 6 | */ 7 | export default function swap(arr: T[], x: number, y: number): T[] { 8 | const a = [...arr]; 9 | const b = a[y]; 10 | 11 | a[y] = a[x]; 12 | a[x] = b; 13 | 14 | return a; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/maths/divMod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a tuple with Quotient and Remainder. 3 | * 4 | * @example 5 | * 6 | * divMod(4, 2) //=> [2, 0] 7 | * divMod(11, 4) //=> [2.75, 3] 8 | * divMod(1, 0) //=> [Infinity, NaN] 9 | */ 10 | 11 | export default function divMod(a: number, b: number): [number, number] { 12 | return [a / b, a % b]; 13 | } 14 | -------------------------------------------------------------------------------- /packages/std/src/types/isErr.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is an error. 3 | * 4 | * @example 5 | * 6 | * isErr(new Error()) //=> true 7 | * 8 | * isErr({msg: '', name: ''}) //=> false 9 | */ 10 | 11 | export default function isErr(val: unknown): val is Error { 12 | return Object.prototype.toString.call(val) === '[object Error]'; 13 | } 14 | -------------------------------------------------------------------------------- /packages/std/src/array/reverse.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Reverses the given list of elements order. 3 | * 4 | * @example 5 | * reverse([1, 2, 3]) //=> [3, 2, 1] 6 | */ 7 | export default function reverse(arr: T[] = []): T[] { 8 | const a = []; 9 | 10 | for (let i = arr.length - 1; i >= 0; i--) { 11 | a.push(arr[i]); 12 | } 13 | 14 | return a; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/string/capitalize.ts: -------------------------------------------------------------------------------- 1 | import replaceAt from './replaceAt'; 2 | 3 | function capitalize(str: string): string { 4 | if (str.length === 0) { 5 | return ''; 6 | } 7 | 8 | let result = str.toLowerCase(); 9 | result = replaceAt(result, 0, result[0].toUpperCase()); 10 | 11 | return result; 12 | } 13 | 14 | export default capitalize; 15 | -------------------------------------------------------------------------------- /packages/std/src/string/isEmail.ts: -------------------------------------------------------------------------------- 1 | export default function isEmail(str: string): boolean { 2 | const regex = new RegExp( 3 | /[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?/ 4 | ); 5 | const result = regex.exec(str); 6 | 7 | return result ? result[0] === str : false; 8 | } 9 | -------------------------------------------------------------------------------- /packages/std/src/types/isArr.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is an array. 3 | * 4 | * @example 5 | * 6 | * isArr([]) //=> true 7 | * 8 | * isArr(new Array('a', 'b', 'c')) //=> true 9 | * 10 | * isArr('abc') //=> false 11 | */ 12 | 13 | export default function isArr(val: unknown): val is Array { 14 | return Array.isArray(val); 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/types/isSym.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a Symbol. 3 | * 4 | * @example 5 | * 6 | * isSym(Symbol()) //=> true 7 | * 8 | * isSym(Symbol('abc')) //=> true 9 | * 10 | * isSym('abc') //=> false 11 | * 12 | */ 13 | 14 | export default function isSym(val: unknown): val is symbol { 15 | return typeof val === 'symbol'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/src/maths/percentageOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * It returns percentage of a number. 3 | * @param {number} percentage - The percentage to calculate 4 | * @param {number} num - The number to find percentage 5 | * @returns {number} 6 | */ 7 | export default function percentageOf(percentage: number, num: number): number { 8 | return (percentage / 100) * num; 9 | } 10 | -------------------------------------------------------------------------------- /packages/std/src/types/isUndef.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is undefined. 3 | * 4 | * @example 5 | * 6 | * isUndef() //=> true 7 | * 8 | * isUndef(undefined) //=> true 9 | * 10 | * isUndef(null) //=> false 11 | * 12 | */ 13 | 14 | export default function isUndef(val: unknown): val is undefined { 15 | return typeof val === 'undefined'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/src/types/isFn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a function. 3 | * 4 | * @example 5 | * 6 | * isFn(function() {}) //=> true 7 | * 8 | * isFn({}) //=> false 9 | */ 10 | 11 | // eslint-disable-next-line @typescript-eslint/ban-types 12 | export default function isFn(val: unknown): val is Function { 13 | return typeof val === 'function'; 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/src/types/isArrBuf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is an ArrayBuffer. 3 | * 4 | * @example 5 | * 6 | * isArrBuf([]) //=> false 7 | * 8 | * isArrBuf(new ArrayBuffer(8)) //=> true 9 | */ 10 | 11 | export default function isArrBuf(val: unknown): val is ArrayBuffer { 12 | return Object.prototype.toString.call(val) === '[object ArrayBuffer]'; 13 | } 14 | -------------------------------------------------------------------------------- /.github/workflows/publish.yml: -------------------------------------------------------------------------------- 1 | name: Publish 2 | on: 3 | push: 4 | branches: 5 | - main 6 | 7 | jobs: 8 | publish: 9 | runs-on: ubuntu-latest 10 | 11 | permissions: 12 | contents: read 13 | id-token: write 14 | 15 | steps: 16 | - uses: actions/checkout@v4 17 | 18 | - name: Publish package 19 | run: cd packages/std && npx jsr publish -------------------------------------------------------------------------------- /apps/docs/public/assets/isDisjointFrom-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB -------------------------------------------------------------------------------- /packages/std/src/types/isPureObj.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is an object and not null. 3 | * 4 | * @example 5 | * 6 | * isPureObj({}) //=> true 7 | * 8 | * isPureObj([]) //=> true 9 | * 10 | * isPureObj(null) //=> false 11 | * 12 | */ 13 | 14 | export default function isPureObj(val: unknown): boolean { 15 | return typeof val === 'object' && val !== null; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/src/types/isWkSet.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a WeakSet object. 3 | * 4 | * @example 5 | * 6 | * isWkSet(new Set()) //=> false 7 | * 8 | * isWkSet(new WeakSet()) //=> true 9 | * 10 | */ 11 | 12 | export default function isWkSet(val: unknown): val is WeakSet { 13 | return Object.prototype.toString.call(val) === '[object WeakSet]'; 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isBlob.spec.ts: -------------------------------------------------------------------------------- 1 | import { Blob } from 'node:buffer'; 2 | import { isBlob } from '../../src'; 3 | 4 | describe('Types > isBlob', () => { 5 | test('invalid cases', () => { 6 | expect(isBlob()).toBe(false); 7 | expect(isBlob({})).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isBlob(new Blob())).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isBigInt.spec.ts: -------------------------------------------------------------------------------- 1 | import { isBigInt } from '../../src'; 2 | 3 | describe('Types > isBigInt', () => { 4 | test('invalid cases', () => { 5 | expect(isBigInt()).toBe(false); 6 | expect(isBigInt(null)).toBe(false); 7 | expect(isBigInt(1)).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isBigInt(1n)).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/src/maths/mean.ts: -------------------------------------------------------------------------------- 1 | import sum from './sum'; 2 | 3 | /** 4 | * Calculates the mean value of the given array. 5 | * 6 | * @example 7 | * 8 | * mean([4, 1, 7]) //=> 4 9 | */ 10 | 11 | export default function mean( 12 | arr: number[] = [], 13 | cb?: (v: number, index: number) => number 14 | ): number { 15 | const a = cb ? arr.map(cb) : arr; 16 | return sum(a) / a.length; 17 | } 18 | -------------------------------------------------------------------------------- /packages/std/src/types/isPromise.ts: -------------------------------------------------------------------------------- 1 | import isFn from './isFn'; 2 | 3 | /** 4 | * Checks if the given value is a Promise object. 5 | * 6 | * @example 7 | * 8 | * isPromise({}) //=> false 9 | * 10 | * isPromise(Promise.resolve()) //=> true 11 | */ 12 | export default function isPromise(val: unknown): val is Promise { 13 | return isFn((val as Record)?.then); 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/src/types/isSet.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a Set object. 3 | * 4 | * @example 5 | * 6 | * isSet(new Set()) //=> true 7 | * 8 | * isSet(new WeakSet()) //=> false 9 | * 10 | * isSet({}) //=> false 11 | * 12 | */ 13 | 14 | export default function isSet(val: unknown): val is Set { 15 | return Object.prototype.toString.call(val) === '[object Set]'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isRegEx.spec.ts: -------------------------------------------------------------------------------- 1 | import { isRegEx } from '../../src'; 2 | 3 | describe('Types > isRegEx', () => { 4 | test('invalid cases', () => { 5 | expect(isRegEx({})).toBe(false); 6 | expect(isRegEx('/a/')).toBe(false); 7 | }); 8 | 9 | test('valid cases', () => { 10 | expect(isRegEx(new RegExp())).toBe(true); 11 | expect(isRegEx(/a/)).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isUndef.spec.ts: -------------------------------------------------------------------------------- 1 | import { isUndef } from '../../src'; 2 | 3 | describe('Types > isUndef', () => { 4 | test('invalid cases', () => { 5 | expect(isUndef(null)).toBe(false); 6 | }); 7 | 8 | test('valid cases', () => { 9 | expect(isUndef()).toBe(true); 10 | expect(isUndef(undefined)).toBe(true); 11 | expect(isUndef(void 0)).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isWkRef.spec.ts: -------------------------------------------------------------------------------- 1 | import { isWkRef } from '../../src'; 2 | 3 | describe('Types > isWkRef', () => { 4 | test('invalid cases', () => { 5 | expect(isWkRef()).toBe(false); 6 | expect(isWkRef(null)).toBe(false); 7 | expect(isWkRef({})).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isWkRef(new WeakRef({}))).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/src/types/isRegEx.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a RegExp object. 3 | * 4 | * @example 5 | * 6 | * isRegEx(new RegExp()) //=> true 7 | * 8 | * isRegEx(/a/) //=> true 9 | * 10 | * isRegEx({}) //=> false 11 | * 12 | */ 13 | 14 | export default function isRegEx(val: unknown): val is RegExp { 15 | return Object.prototype.toString.call(val) === '[object RegExp]'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/src/types/isWkMap.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a WeakMap object. 3 | * 4 | * @example 5 | * 6 | * isWkMap(new Map()) //=> false 7 | * 8 | * isWkMap(new WeakMap()) //=> true 9 | * 10 | */ 11 | 12 | export default function isWkMap( 13 | val: unknown 14 | ): val is WeakMap { 15 | return Object.prototype.toString.call(val) === '[object WeakMap]'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/divMod.spec.ts: -------------------------------------------------------------------------------- 1 | import { divMod } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('divMod', () => { 5 | expect(divMod(4, 2)).toEqual([2, 0]); 6 | expect(divMod(11, 4)).toEqual([2.75, 3]); 7 | expect(divMod(1, 0)).toEqual([Infinity, NaN]); 8 | expect(divMod(0, 1)).toEqual([0, 0]); 9 | expect(divMod(-9, -2)).toEqual([4.5, -1]); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isWkMap.spec.ts: -------------------------------------------------------------------------------- 1 | import { isWkMap } from '../../src'; 2 | 3 | describe('Types > isWkMap', () => { 4 | test('invalid cases', () => { 5 | expect(isWkMap()).toBe(false); 6 | expect(isWkMap(null)).toBe(false); 7 | expect(isWkMap(new Map())).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isWkMap(new WeakMap())).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isWkSet.spec.ts: -------------------------------------------------------------------------------- 1 | import { isWkSet } from '../../src'; 2 | 3 | describe('Types > isWkSet', () => { 4 | test('invalid cases', () => { 5 | expect(isWkSet()).toBe(false); 6 | expect(isWkSet(null)).toBe(false); 7 | expect(isWkSet(new Set())).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isWkSet(new WeakSet())).toBe(true); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/src/types/isMap.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a Map object. 3 | * 4 | * @example 5 | * 6 | * isMap(new Map()) //=> true 7 | * 8 | * isMap(new WeakMap()) //=> false 9 | * 10 | * isMap({}) //=> false 11 | * 12 | */ 13 | 14 | export default function isMap(val: unknown): val is Map { 15 | return Object.prototype.toString.call(val) === '[object Map]'; 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/src/colors/hexToRGB.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert hexadecimal color values into RGB color values. 3 | * 4 | * @example 5 | * 6 | * hexToRGB('#FF851B') => [ 255, 133, 27 ] 7 | */ 8 | 9 | export default function hexToRGB(hex: string): number[] { 10 | return [ 11 | parseInt(hex.substring(1, 3), 16), 12 | parseInt(hex.substring(3, 5), 16), 13 | parseInt(hex.substring(5, 7), 16), 14 | ]; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/function/pipe.ts: -------------------------------------------------------------------------------- 1 | /** Performs functions composition from left to right. 2 | * 3 | * @example 4 | * 5 | * pipe(1, (x) => x + 1, (x) => x * 5) //=> 10 6 | */ 7 | export default function pipe( 8 | val: unknown, 9 | ...fns: ((...args: unknown[]) => unknown)[] 10 | ): unknown { 11 | let out = val; 12 | 13 | for (const fn of fns) { 14 | out = fn(out); 15 | } 16 | 17 | return out; 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/types/isWkRef.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a WeakRef object. 3 | * 4 | * @example 5 | * 6 | * isWkRef({}) //=> false 7 | * 8 | * let user = { name: "John" }; 9 | * isWkRef(new WeakRef(user)) //=> true 10 | * 11 | */ 12 | 13 | export default function isWkRef(val: unknown): val is WeakRef { 14 | return Object.prototype.toString.call(val) === '[object WeakRef]'; 15 | } 16 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@2.3.0/schema.json", 3 | "changelog": "@changesets/cli/changelog", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "public", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": ["docs"], 11 | "privatePackages": false, 12 | "bumpVersionsWithWorkspaceProtocolOnly": true 13 | } 14 | -------------------------------------------------------------------------------- /apps/docs/public/assets/isSubsetOf-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB -------------------------------------------------------------------------------- /apps/docs/public/assets/isSupersetOf-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB -------------------------------------------------------------------------------- /packages/std/src/array/arrRm.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Removes items at the given index from the given array. 3 | * 4 | * @example 5 | * 6 | * arrRm([1, 2, 3], 1, 2); // [1] 7 | */ 8 | export default function arrRm( 9 | arr: T[] = [], 10 | index?: number, 11 | count: number = 1 12 | ): T[] { 13 | const idx = index ?? arr.length - 1; 14 | const a = [...arr]; 15 | 16 | a.splice(idx, count); 17 | 18 | return a; 19 | } 20 | -------------------------------------------------------------------------------- /packages/std/src/types/isDataView.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a DataView object. 3 | * 4 | * @example 5 | * 6 | * const buffer = new ArrayBuffer(8) 7 | * 8 | * isDataView(buffer) //=> false 9 | * 10 | * isDataView(new DataView(buffer)) //=> true 11 | */ 12 | 13 | export default function isDataView(val: unknown): val is DataView { 14 | return Object.prototype.toString.call(val) === '[object DataView]'; 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isNull.spec.ts: -------------------------------------------------------------------------------- 1 | import { isNull } from '../../src'; 2 | 3 | describe('Types > isNull', () => { 4 | test('invalid cases', () => { 5 | expect(isNull(undefined)).toBe(false); 6 | expect(isNull('')).toBe(false); 7 | expect(isNull(0)).toBe(false); 8 | expect(isNull(false)).toBe(false); 9 | }); 10 | 11 | test('valid cases', () => { 12 | expect(isNull(null)).toBe(true); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/src/maths/avg.ts: -------------------------------------------------------------------------------- 1 | import sum from './sum'; 2 | 3 | /** 4 | * Calculates the average of values in the given array. 5 | * 6 | * @example 7 | * 8 | * avg([1, 2, 3, 4, 5]) //=> 3 9 | * avg([-1, -2]) //=> -1.5 10 | */ 11 | export default function avg( 12 | arr: number[] = [], 13 | cb?: (val: number, index: number) => number 14 | ): number { 15 | const s = sum(arr, cb); 16 | 17 | return s / arr.length || 0; 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/array/arrIns.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Inserts items at the given index into the given array. 3 | * 4 | * @example 5 | * 6 | * arrIns([1, 2, 3], 1, 5); // [1, 5, 2, 3] 7 | */ 8 | export default function arrIns( 9 | arr: T[] = [], 10 | index: number | null | undefined, 11 | ...items: T[] 12 | ): T[] { 13 | const idx = index ?? arr.length; 14 | const a = [...arr]; 15 | a.splice(idx, 0, ...items); 16 | return a; 17 | } 18 | -------------------------------------------------------------------------------- /packages/std/__tests__/object/fromPath.spec.ts: -------------------------------------------------------------------------------- 1 | import { fromPath } from '../../src'; 2 | 3 | describe('Object > fromPath', () => { 4 | test('invalid', () => { 5 | expect(fromPath()).toBe(''); 6 | }); 7 | 8 | test('valid', () => { 9 | expect(fromPath(['a', '0', 'b', 'c'])).toBe('a[0].b.c'); 10 | expect(fromPath(['a', 1, 'b', 'c'])).toBe('a[1].b.c'); 11 | expect(fromPath(['a', 'b.c', 'd'])).toBe('a.b.c.d'); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/src/async/aForEach.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Array forEach with `Async` callback function. 3 | * 4 | * @example 5 | * 6 | * await aForEach([1, 3, 5], async () => await someDelayedFn()) 7 | */ 8 | export default async function aForEach( 9 | arr: T[], 10 | cb: (value: T, index: number) => Promise 11 | ): Promise { 12 | let i = 0; 13 | 14 | for (const e of arr) { 15 | await cb(e, i); 16 | i++; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/maths/clamp.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a value clamped to the inclusive range of min and max. 3 | * 4 | * @example 5 | * 6 | * clamp(0, 1000, 1366) //=> 1000 7 | * clamp(1000, 1000, 1366) //=> 1000 8 | * clamp(1001, 1000, 1366) //=> 1001 9 | * clamp(1500, 1000, 1366) //=> 1366 10 | */ 11 | 12 | export default function clamp(val: number, min: number, max: number): number { 13 | return Math.min(Math.max(val, min), max); 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/src/maths/sum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Calculates the sum of values in the given array. 3 | * 4 | * @example 5 | * 6 | * sum([1, 2, 3, 4, 5]) //=> 15 7 | * sum([-1, -2]) //=> -3 8 | */ 9 | 10 | export default function sum( 11 | arr: number[] = [], 12 | cb?: (val: number, index: number) => number 13 | ): number { 14 | const a = cb ? arr.map(cb) : arr; 15 | return a.reduce((prev, cur) => { 16 | return prev + cur; 17 | }, 0); 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/types/isGenFn.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a generator function. 3 | * 4 | * @example 5 | * 6 | * isFn(function() {}) //=> false 7 | * 8 | * isFn(function*() {}) //=> true 9 | */ 10 | 11 | export default function isGenFn(val: unknown): val is GeneratorFunction { 12 | const a = ['[object GeneratorFunction]', '[object AsyncGeneratorFunction]']; 13 | return a.includes(Object.prototype.toString.call(val)); 14 | } 15 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/median.spec.ts: -------------------------------------------------------------------------------- 1 | import { median } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('median', () => { 5 | expect(median()).toBe(NaN); 6 | expect(median([])).toBe(NaN); 7 | expect(median([1])).toBe(1); 8 | expect(median([4, 1, 7])).toBe(1); 9 | expect(median([4, 2, 8])).toBe(2); 10 | expect(median([1, 4, 2, 5, 0])).toBe(2); 11 | expect(median([10, 20, 40, 50])).toBe(30); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isErr.spec.ts: -------------------------------------------------------------------------------- 1 | import { isErr } from '../../src'; 2 | 3 | describe('Types > isErr', () => { 4 | test('invalid cases', () => { 5 | expect(isErr()).toBe(false); 6 | expect(isErr({})).toBe(false); 7 | }); 8 | 9 | test('valid cases', () => { 10 | expect(isErr(new Error())).toBe(true); 11 | expect(isErr(new Error('error msg'))).toBe(true); 12 | expect(isErr(Error('error msg'))).toBe(true); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/src/array/shuffle.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Shuffles the given array values. 3 | * 4 | * shuffle([1, 2, 3]) //=> [3, 1, 2] 5 | */ 6 | 7 | export default function shuffle(arr: T[]): T[] { 8 | const a = [...arr]; 9 | let i = a.length, 10 | randIdx, 11 | t; 12 | 13 | while (i) { 14 | randIdx = Math.floor(Math.random() * i--); 15 | t = a[i]; 16 | a[i] = a[randIdx]; 17 | a[randIdx] = t; 18 | } 19 | 20 | return a; 21 | } 22 | -------------------------------------------------------------------------------- /packages/std/src/maths/prod.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Calculates the product of values in the given array. 3 | * 4 | * @example 5 | * 6 | * prod([1, 2, 3, 4, 5]) //=> 120 7 | * prod([-1, -2]) //=> 2 8 | */ 9 | 10 | export default function prod( 11 | arr: number[] = [], 12 | cb?: (val: number, index: number) => number 13 | ): number { 14 | const a = cb ? arr.map(cb) : arr; 15 | return a.reduce((prev, cur) => { 16 | return prev * cur; 17 | }, 1); 18 | } 19 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "avg": "avg", 3 | "clamp": "clamp", 4 | "divMod": "divMod", 5 | "isDisjointFrom": "isDisjointFrom", 6 | "isEven": "isEven", 7 | "isOdd": "isOdd", 8 | "isSubsetOf": "isSubsetOf", 9 | "isSupersetOf": "isSupersetOf", 10 | "mean": "mean", 11 | "median": "median", 12 | "mode": "mode", 13 | "percentage": "percentage", 14 | "percentageOf": "percentageOf", 15 | "prod": "prod", 16 | "sum": "sum" 17 | } 18 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "clone": "clone", 3 | "fromPath": "fromPath", 4 | "get": "get", 5 | "has": "has", 6 | "merge": "merge", 7 | "mergeAll": "mergeAll", 8 | "omit": "omit", 9 | "pick": "pick", 10 | "set": "set", 11 | "shallowMerge": "shallowMerge", 12 | "shallowMergeAll": "shallowMergeAll", 13 | "size": "size", 14 | "toPath": "toPath", 15 | "toSet": "toSet", 16 | "toUnset": "toUnset", 17 | "unset": "unset" 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/isOdd.spec.ts: -------------------------------------------------------------------------------- 1 | import { isOdd } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('isOdd', () => { 5 | expect(isOdd(0)).toBe(false); 6 | expect(isOdd(1)).toBe(true); 7 | expect(isOdd(2)).toBe(false); 8 | expect(isOdd(-1)).toBe(true); 9 | expect(isOdd(-2)).toBe(false); 10 | expect(isOdd(-3)).toBe(true); 11 | expect(isOdd(-4)).toBe(false); 12 | expect(isOdd(-5)).toBe(true); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isArrBuf.spec.ts: -------------------------------------------------------------------------------- 1 | import { isArrBuf } from '../../src'; 2 | 3 | describe('Types > isArrBuf', () => { 4 | test('invalid cases', () => { 5 | expect(isArrBuf()).toBe(false); 6 | expect(isArrBuf(null)).toBe(false); 7 | expect(isArrBuf([])).toBe(false); 8 | expect(isArrBuf(new Uint8Array())).toBe(false); 9 | }); 10 | 11 | test('valid cases', () => { 12 | expect(isArrBuf(new ArrayBuffer(8))).toBe(true); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/src/colors/rgbToHex.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Convert RGB colors into hexadecimal color values. 3 | * 4 | * @example 5 | * 6 | * rgbToHex([ 255, 133, 27 ]) //=> '#FF851B' 7 | */ 8 | 9 | export default function RGBToHex(rgb: [number, number, number]): string { 10 | const r = rgb[0].toString(16); 11 | const g = rgb[1].toString(16); 12 | const b = rgb[2].toString(16); 13 | 14 | return '#' + r.padStart(2, '0') + g.padStart(2, '0') + b.padStart(2, '0'); 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/src/assert/isNil.ts: -------------------------------------------------------------------------------- 1 | import isNull from '../types/isNull'; 2 | import isUndef from '../types/isUndef'; 3 | 4 | /** 5 | * Checks if the given value is nil or noting. 6 | * 7 | * @example 8 | * 9 | * isNil() //=> true 10 | * 11 | * isNil(null) //=> true 12 | * 13 | * isNil(true) //=> false 14 | */ 15 | export default function isNil(val: unknown): boolean { 16 | if (isNull(val) || isUndef(val)) { 17 | return true; 18 | } 19 | 20 | return false; 21 | } 22 | -------------------------------------------------------------------------------- /packages/std/src/types/isDate.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a valid date object. 3 | * 4 | * @example 5 | * 6 | * isDate(new Date()) //=> true 7 | * 8 | * isDate(new Date('')) //=> false 9 | * 10 | * isDate('2000-01-01') //=> false 11 | */ 12 | 13 | export default function isDate(val: unknown): val is Date { 14 | return ( 15 | Object.prototype.toString.call(val) === '[object Date]' && 16 | (val as Date).toString() !== 'Invalid Date' 17 | ); 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/types/isInfinity.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is Infinity. 3 | * 4 | * @example 5 | * 6 | * isInfinity(0) //=> false 7 | * 8 | * isInfinity(NaN) //=> false 9 | * 10 | * isInfinity(Infinity) //=> true 11 | */ 12 | export default function isInfinity(x: unknown): x is typeof Infinity { 13 | if (typeof x !== 'number') return false; 14 | if (Number.isNaN(x)) return false; 15 | if (Number.isFinite(x)) return false; 16 | 17 | return true; 18 | } 19 | -------------------------------------------------------------------------------- /packages/std/src/async/aPipe.ts: -------------------------------------------------------------------------------- 1 | /** Performs functions composition from left to right asynchronously. 2 | * 3 | * @example 4 | * await aPipe(5, (x) => Promise.resolve(x ** 2), (x) => Promise.resolve(x - 5)) //=> 20 5 | */ 6 | export default async function aPipe( 7 | val: unknown, 8 | ...fns: ((...args: unknown[]) => unknown)[] 9 | ): Promise { 10 | let out = val; 11 | 12 | for (const fn of fns) { 13 | out = await fn(out); 14 | } 15 | 16 | return out; 17 | } 18 | -------------------------------------------------------------------------------- /packages/std/src/function/compose.ts: -------------------------------------------------------------------------------- 1 | import reverse from '../array/reverse'; 2 | 3 | /** Performs functions composition from right to left. 4 | * 5 | * @example 6 | * 7 | * compose(1, (x) => x + 1, (x) => x * 5) //=> 6 8 | */ 9 | export default function compose( 10 | val: unknown, 11 | ...fns: ((...args: unknown[]) => unknown)[] 12 | ): unknown { 13 | let out = val; 14 | 15 | for (const fn of reverse(fns)) { 16 | out = fn(out); 17 | } 18 | 19 | return out; 20 | } 21 | -------------------------------------------------------------------------------- /packages/std/src/types/isJSON.ts: -------------------------------------------------------------------------------- 1 | import isObj from './isObj'; 2 | /** 3 | * Checks whether the given string is a valid JSON plain object 4 | * 5 | * @example 6 | * 7 | * isJSON("null") //=> false 8 | * 9 | * isJSON("[]") //=> false 10 | * 11 | * isJSON("{}") //=> true 12 | */ 13 | 14 | export default function isJSON(str: string): boolean { 15 | try { 16 | const o = JSON.parse(str); 17 | return isObj(o); 18 | } catch (error) { 19 | return false; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aMap.spec.ts: -------------------------------------------------------------------------------- 1 | import { aMap, sleep } from '../../src'; 2 | 3 | describe('Array > aMap', () => { 4 | test('async map', async () => { 5 | const arr = [1, 2, 3, 4, 5]; 6 | 7 | function multiply(n, i) { 8 | return new Promise((resolve) => { 9 | resolve(n * i); 10 | }); 11 | } 12 | 13 | const result = await aMap(arr, async (n, i) => await multiply(n, i)); 14 | 15 | expect(result).toEqual([0, 2, 6, 12, 20]); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isFn.spec.ts: -------------------------------------------------------------------------------- 1 | import { isFn } from '../../src'; 2 | 3 | describe('Types > isFn', () => { 4 | test('invalid cases', () => { 5 | expect(isFn()).toBe(false); 6 | expect(isFn({})).toBe(false); 7 | }); 8 | 9 | test('valid cases', () => { 10 | expect(isFn(() => {})).toBe(true); 11 | expect(isFn(function () {})).toBe(true); 12 | expect(isFn(async function () {})).toBe(true); 13 | expect(isFn(function* () {})).toBe(true); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/std/src/assert/isEmpty.ts: -------------------------------------------------------------------------------- 1 | import size from '../object/size'; 2 | import isArr from '../types/isArr'; 3 | 4 | /** 5 | * Checks if the given collection is empty. 6 | * 7 | * @example 8 | * 9 | * isEmpty([]) //=> true 10 | * 11 | * isEmpty({a: null}) //=> false 12 | */ 13 | export default function isEmpty(val: unknown, sparse = false): boolean { 14 | if (sparse && isArr(val)) { 15 | return Object.keys(val).length === 0; 16 | } 17 | 18 | return size(val) === 0; 19 | } 20 | -------------------------------------------------------------------------------- /packages/std/src/async/aMap.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Array map with `Async` callback function. 3 | * 4 | * @example 5 | * await aMap([1, 2, 3], (n) => await someDelayedFn(n)) 6 | */ 7 | export default async function aMap( 8 | arr: T[], 9 | cb: (value: T, index: number) => Promise 10 | ): Promise { 11 | let i = 0; 12 | const out: unknown[] = []; 13 | 14 | for (const e of arr) { 15 | out.push(await cb(e, i)); 16 | i++; 17 | } 18 | 19 | return out; 20 | } 21 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/clamp.spec.ts: -------------------------------------------------------------------------------- 1 | import { clamp } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('clamp', () => { 5 | expect(clamp(10, -5, 5)).toBe(5); 6 | expect(clamp(-10, -5, 5)).toBe(-5); 7 | expect(clamp(-10, -1, -50)).toBe(-50); 8 | expect(clamp(0, 1000, 1366)).toBe(1000); 9 | expect(clamp(1000, 1000, 1366)).toBe(1000); 10 | expect(clamp(1001, 1000, 1366)).toBe(1001); 11 | expect(clamp(1500, 1000, 1366)).toBe(1366); 12 | }); 13 | }); 14 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/prod.spec.ts: -------------------------------------------------------------------------------- 1 | import { prod } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('prod', () => { 5 | expect(prod()).toBe(1); 6 | expect(prod([])).toBe(1); 7 | expect(prod([1])).toBe(1); 8 | expect(prod([1, -1])).toBe(-1); 9 | expect(prod([-1, -2])).toBe(2); 10 | expect(prod([1, 2, 3, 4, 5])).toBe(120); 11 | const objects = [{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }]; 12 | expect(prod(objects, (v) => v.n)).toBe(384); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/src/object/fromPath.ts: -------------------------------------------------------------------------------- 1 | import isNum from '../types/isNum'; 2 | 3 | /** 4 | * Converts the given array values into an object property path string. 5 | * 6 | * @example 7 | * fromPath(['a', '0', 'b', 'c']) //=> 'a[0].b.c' 8 | */ 9 | export default function fromPath(arr: (string | number)[] = []): string { 10 | const out = arr.reduce((acc, cur) => { 11 | return isNum(cur, true) ? `${acc}[${cur}]` : acc + '.' + cur; 12 | }, ''); 13 | 14 | return (out as string).slice(1); 15 | } 16 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aFilter.spec.ts: -------------------------------------------------------------------------------- 1 | import { aFilter } from '../../src'; 2 | 3 | describe('Array > aFilter', () => { 4 | test('filters only even numbers', async () => { 5 | const arr = [1, 2, 3, 4, 5]; 6 | 7 | function isEven(n) { 8 | return new Promise((resolve) => { 9 | resolve(n % 2 === 0); 10 | }); 11 | } 12 | 13 | const filteredArr = await aFilter(arr, async (n) => await isEven(n)); 14 | 15 | expect(filteredArr).toEqual([2, 4]); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/src/array/sort.ts: -------------------------------------------------------------------------------- 1 | export type OrderType = 'asc' | 'desc'; 2 | /** 3 | * Sorts a list of items and returns a new array. 4 | * 5 | * @example 6 | * 7 | * sort([1, 3, 2]) // [1, 2, 3] 8 | * sort(['x', 'z', 'y'], 'desc') // ['z', 'y', 'x'] 9 | */ 10 | export default function sort(arr: T[] = [], order: OrderType = 'asc'): T[] { 11 | return [...arr].sort((a: T, b: T) => { 12 | const val = a < b ? -1 : a > b ? 1 : 0; 13 | 14 | return order === 'asc' ? val : -val; 15 | }); 16 | } 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isMap.spec.ts: -------------------------------------------------------------------------------- 1 | import { isMap } from '../../src'; 2 | 3 | describe('Types > isMap', () => { 4 | test('invalid cases', () => { 5 | expect(isMap()).toBe(false); 6 | expect(isMap(null)).toBe(false); 7 | expect(isMap({})).toBe(false); 8 | expect(isMap([])).toBe(false); 9 | expect(isMap(Map)).toBe(false); 10 | expect(isMap(new WeakMap())).toBe(false); 11 | }); 12 | 13 | test('valid cases', () => { 14 | expect(isMap(new Map())).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isSet.spec.ts: -------------------------------------------------------------------------------- 1 | import { isSet } from '../../src'; 2 | 3 | describe('Types > isSet', () => { 4 | test('invalid cases', () => { 5 | expect(isSet()).toBe(false); 6 | expect(isSet(null)).toBe(false); 7 | expect(isSet({})).toBe(false); 8 | expect(isSet([])).toBe(false); 9 | expect(isSet(Set)).toBe(false); 10 | expect(isSet(new WeakSet())).toBe(false); 11 | }); 12 | 13 | test('valid cases', () => { 14 | expect(isSet(new Set())).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/src/array/move.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * It moves an array element from one index position to another. 3 | * 4 | * Note: It mutates the array. 5 | * 6 | * @example 7 | * 8 | * move([1, 2, 3], 0, 2) //=> [2, 3, 1] 9 | */ 10 | 11 | export default function move(arr: T[], from: number, to: number): T[] { 12 | if (arr.length === 0 || from === to || from >= arr.length) { 13 | return arr; 14 | } 15 | 16 | const a = [...arr]; 17 | a.splice(to, 0, a.splice(from, 1)[0]); 18 | 19 | return a; 20 | } 21 | -------------------------------------------------------------------------------- /apps/docs/public/assets/intersection-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB -------------------------------------------------------------------------------- /packages/std/src/object/shallowMerge.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | 3 | /** 4 | * Shallow merges objects or arrays. 5 | * 6 | * @example 7 | * const a = { a: 1 }; 8 | * const b = { b: 2 }; 9 | * shallowMerge(a, b); //=> { a: 1, b: 2 } 10 | */ 11 | export default function shallowMerge(...objs: object[]): object { 12 | return objs.reduce((acc, cur) => { 13 | if (isArr(cur) && isArr(acc)) { 14 | return Object.assign([], acc, cur); 15 | } 16 | 17 | return { ...acc, ...cur }; 18 | }); 19 | } 20 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isBlob.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [Blob](https://developer.mozilla.org/en-US/docs/Web/API/Blob). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isBlob } from '@opentf/std'; 9 | 10 | isBlob(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isBlob(new Blob()) //=> true 17 | 18 | isBlob({}) //=> false 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /packages/std/src/array/arrReplace.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Replaces items at the given index from the given array. 3 | * 4 | * @example 5 | * 6 | * arrReplace([1, 2, 3], 1, 5); // [1, 5, 3] 7 | */ 8 | export default function arrReplace( 9 | arr: T[] = [], 10 | index: number | null, 11 | deleteCount: number | null, 12 | ...replacements: T[] 13 | ): T[] { 14 | const idx = index ?? arr.length - 1; 15 | const a = [...arr]; 16 | 17 | a.splice(idx, deleteCount ?? replacements.length, ...replacements); 18 | 19 | return a; 20 | } 21 | -------------------------------------------------------------------------------- /packages/std/src/types/isAsyFn.ts: -------------------------------------------------------------------------------- 1 | /* eslint-disable @typescript-eslint/ban-types */ 2 | /** 3 | * Checks if the given value is an Async function. 4 | * 5 | * @example 6 | * 7 | * isAsyFn(function() {}) //=> false 8 | * 9 | * isAsyFn(async function() {}) //=> true 10 | */ 11 | 12 | export default function isAsyFn( 13 | val: unknown 14 | ): val is Function | AsyncGeneratorFunction { 15 | const a = ['[object AsyncFunction]', '[object AsyncGeneratorFunction]']; 16 | return a.includes(Object.prototype.toString.call(val)); 17 | } 18 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/toPath.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Converts the given string into an object property path array. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { toPath } from '@opentf/std'; 10 | 11 | toPath(str: string): (string | number)[] 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | toPath('a[0].b.c') //=> ['a', 0, 'b', 'c'] 18 | ``` 19 | 20 | ## Try 21 | 22 | -------------------------------------------------------------------------------- /packages/std/src/types/isObj.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a plain object. 3 | * 4 | * @example 5 | * 6 | * isObj({}) //=> true 7 | * 8 | * isObj([]) //=> false 9 | * 10 | * isObj(Object.create(null)) //=> true 11 | * 12 | */ 13 | 14 | export default function isObj(val: unknown): val is object { 15 | if (Object.prototype.toString.call(val) !== '[object Object]') { 16 | return false; 17 | } 18 | 19 | const p = Object.getPrototypeOf(val); 20 | 21 | return p === null || Object.getPrototypeOf(p) === null; 22 | } 23 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/isOdd.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given number is a `Odd` number. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isOdd } from '@opentf/std'; 9 | 10 | isOdd(n: number): boolean 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isOdd(0) //=> false 17 | 18 | isOdd(1) //=> true 19 | 20 | isOdd(2) //=> false 21 | 22 | isOdd(-1) //=> true 23 | 24 | isOdd(-2) //=> false 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aResolvers.spec.ts: -------------------------------------------------------------------------------- 1 | import { aResolvers } from '../../src'; 2 | 3 | describe('Async > aResolvers', () => { 4 | test('resolve', async () => { 5 | const { promise, resolve, reject } = aResolvers(); 6 | resolve('fulfilled'); 7 | await expect(promise).resolves.toBe('fulfilled'); 8 | }); 9 | 10 | test('reject', async () => { 11 | const { promise, resolve, reject } = aResolvers(); 12 | 13 | reject(new Error('Rejected')); 14 | await expect(promise).rejects.toThrow('Rejected'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/src/async/aFilter.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Array filter with `Async` callback function. 3 | * 4 | * @example 5 | * 6 | * const arr = [1, 2, 3] 7 | * aFilter(arr, (n) => isOdd(n)) //=> [1, 3] 8 | */ 9 | export default async function aFilter( 10 | arr: T[], 11 | cb: (value: T, index: number) => Promise 12 | ): Promise> { 13 | let i = 0; 14 | const out = []; 15 | 16 | for (const e of arr) { 17 | if (await cb(e, i)) { 18 | out.push(e); 19 | } 20 | i++; 21 | } 22 | 23 | return out; 24 | } 25 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isNull.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [null](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/null). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isNull } from '@opentf/std'; 9 | 10 | isNull(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isNull(null) //=> true 17 | 18 | isNull(undefined) //=> false 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /packages/std/src/object/shallowMergeAll.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | 3 | /** 4 | * Shallow merges objects and concatenates the array. 5 | * 6 | * @example 7 | * const a = [1]; 8 | * const b = [2]; 9 | * const c = [3]; 10 | * shallowMergeAll(a, b, c); //=> [1, 2, 3] 11 | */ 12 | export default function shallowMergeAll(...objs: object[]): object { 13 | return objs.reduce((acc, cur) => { 14 | if (isArr(cur) && isArr(acc)) { 15 | return [...acc, ...cur]; 16 | } 17 | 18 | return { ...acc, ...cur }; 19 | }); 20 | } 21 | -------------------------------------------------------------------------------- /turbo.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://turbo.build/schema.json", 3 | "pipeline": { 4 | "dev": { 5 | "cache": false, 6 | "persistent": true 7 | }, 8 | "build": { 9 | "dependsOn": ["^build"], 10 | "outputs": ["dist/**"] 11 | }, 12 | "test": { 13 | "dependsOn": ["build"], 14 | "inputs": ["src/**/*.tsx", "src/**/*.ts", "test/**/*.ts", "test/**/*.tsx"] 15 | }, 16 | "lint": {}, 17 | "ci": {}, 18 | "check-types": {}, 19 | "start": { 20 | "cache": false 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /packages/std/__tests__/assert/isNil.spec.ts: -------------------------------------------------------------------------------- 1 | import { isNil } from '../../src'; 2 | 3 | describe('Assert => isNil', () => { 4 | test('falsy', () => { 5 | expect(isNil('')).toBe(false); 6 | expect(isNil([])).toBe(false); 7 | expect(isNil({})).toBe(false); 8 | }); 9 | 10 | test('truthy', () => { 11 | expect(isNil()).toBe(true); 12 | expect(isNil(undefined)).toBe(true); 13 | expect(isNil(null)).toBe(true); 14 | expect([1, null, 2, undefined, 3].filter((i) => !isNil(i))).toEqual([ 15 | 1, 2, 3, 16 | ]); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/mode.spec.ts: -------------------------------------------------------------------------------- 1 | import { mode } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('mode', () => { 5 | expect(mode()).toEqual([]); 6 | expect(mode([1])).toEqual([]); 7 | expect(mode([1, 2, 3, 4, 5])).toEqual([]); 8 | expect(mode([4, 2])).toEqual([]); 9 | expect(mode([4, 2, 3, 2, 2])).toEqual([2]); 10 | expect(mode([0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4])).toEqual([1, 2]); 11 | expect( 12 | mode([{ n: 1 }, { n: 2 }, { n: 3 }, { n: 2 }], ({ n }) => n) 13 | ).toEqual([2]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/std/src/async/aCompose.ts: -------------------------------------------------------------------------------- 1 | import reverse from '../array/reverse'; 2 | 3 | /** Performs functions composition from right to left asynchronously. 4 | * 5 | * @example 6 | * 7 | * await aCompose(1, (x) => Promise.resolve(x + 1), (x) => Promise.resolve(x * 5)) //=> 6 8 | */ 9 | export default async function aCompose( 10 | val: unknown, 11 | ...fns: ((...args: unknown[]) => unknown)[] 12 | ): Promise { 13 | let out = val; 14 | 15 | for (const fn of reverse(fns)) { 16 | out = await fn(out); 17 | } 18 | 19 | return out; 20 | } 21 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/isEven.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given number is an `Even` number. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isEven } from '@opentf/std'; 9 | 10 | isEven(n: number): boolean 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isEven(0) //=> true 17 | 18 | isEven(1) //=> false 19 | 20 | isEven(2) //=> true 21 | 22 | isEven(-1) //=> false 23 | 24 | isEven(-2) //=> true 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isErr.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is an [Error](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Error). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isErr } from '@opentf/std'; 9 | 10 | isErr(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isErr(new Error()) //=> true 17 | 18 | isErr({}) //=> false 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isMap.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [Map](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Map) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isMap } from '@opentf/std'; 9 | 10 | isMap(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isMap(new Map()) //=> true 17 | 18 | isMap({}) //=> false 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /apps/docs/public/assets/diff-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB 2 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isStr.spec.ts: -------------------------------------------------------------------------------- 1 | import { isStr } from '../../src'; 2 | 3 | describe('Types > isStr', () => { 4 | test('invalid cases', () => { 5 | expect(isStr()).toBe(false); 6 | expect(isStr(null)).toBe(false); 7 | expect(isStr(1)).toBe(false); 8 | expect(isStr(['a', 'b', 'c'])).toBe(false); 9 | }); 10 | 11 | test('valid cases', () => { 12 | expect(isStr('')).toBe(true); 13 | expect(isStr('abc')).toBe(true); 14 | expect(isStr(String('abc'))).toBe(true); 15 | expect(isStr(String(123))).toBe(true); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/src/array/compact.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | 3 | type Falsy = null | undefined | boolean | number | string; 4 | 5 | /** 6 | * Removes all the falsy values in the given array. 7 | * 8 | * @example 9 | * 10 | * compact([1, null, 2, 0, 3]) //=> [1, 2, 3] 11 | */ 12 | export default function compact(arr: T[] = []): Partial { 13 | if (!isArr(arr)) { 14 | return []; 15 | } 16 | 17 | const falsy: (T | Falsy)[] = [undefined, null, false, NaN, 0, '']; 18 | 19 | return arr.filter((val) => !falsy.includes(val)); 20 | } 21 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isBigInt.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is an [BigInt](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isBigInt } from '@opentf/std'; 9 | 10 | isBigInt(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isBigInt(1) //=> false 17 | 18 | isBigInt(1n) //=> true 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /packages/std/__tests__/number/isZero.spec.ts: -------------------------------------------------------------------------------- 1 | import { isZero } from '../../src'; 2 | 3 | describe('Number', () => { 4 | test('isZero', () => { 5 | expect(isZero()).toBe(false); 6 | expect(isZero(undefined)).toBe(false); 7 | expect(isZero(null)).toBe(false); 8 | expect(isZero('')).toBe(false); 9 | expect(isZero('0')).toBe(false); 10 | expect(isZero([])).toBe(false); 11 | expect(isZero({})).toBe(false); 12 | expect(isZero(-0)).toBe(false); 13 | expect(isZero(0)).toBe(true); 14 | expect(isZero(+0)).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isSym.spec.ts: -------------------------------------------------------------------------------- 1 | import { isSym } from '../../src'; 2 | 3 | describe('Types > isSym', () => { 4 | test('invalid cases', () => { 5 | expect(isSym()).toBe(false); 6 | expect(isSym(null)).toBe(false); 7 | expect(isSym(1)).toBe(false); 8 | expect(isSym('abc')).toBe(false); 9 | expect(isSym(Symbol)).toBe(false); 10 | }); 11 | 12 | test('valid cases', () => { 13 | expect(isSym(Symbol())).toBe(true); 14 | expect(isSym(Symbol('abc'))).toBe(true); 15 | expect(isSym(Symbol.iterator)).toBe(true); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/src/array/groupBy.ts: -------------------------------------------------------------------------------- 1 | export type GroupKey = ((a: T) => string) | string; 2 | 3 | /** 4 | * It groups the elements of a given array according to the given key. 5 | * 6 | */ 7 | export default function groupBy( 8 | arr: T[], 9 | key: GroupKey 10 | ): Record { 11 | return arr.reduce((acc: Record, obj: T) => { 12 | const k = 13 | typeof key === 'function' ? key(obj) : (obj[key as keyof T] as string); 14 | const curGroup = acc[k] ?? []; 15 | return { ...acc, [k]: [...curGroup, obj] }; 16 | }, {}); 17 | } 18 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isAsyFn.spec.ts: -------------------------------------------------------------------------------- 1 | import { isAsyFn } from '../../src'; 2 | 3 | describe('Types > isAsyFn', () => { 4 | test('invalid cases', () => { 5 | expect(isAsyFn()).toBe(false); 6 | expect(isAsyFn({})).toBe(false); 7 | expect(isAsyFn(() => {})).toBe(false); 8 | expect(isAsyFn(function () {})).toBe(false); 9 | expect(isAsyFn(function* () {})).toBe(false); 10 | }); 11 | 12 | test('valid cases', () => { 13 | expect(isAsyFn(async function () {})).toBe(true); 14 | expect(isAsyFn(async function* () {})).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isGenFn.spec.ts: -------------------------------------------------------------------------------- 1 | import { isGenFn } from '../../src'; 2 | 3 | describe('Types > isGenFn', () => { 4 | test('invalid cases', () => { 5 | expect(isGenFn()).toBe(false); 6 | expect(isGenFn({})).toBe(false); 7 | expect(isGenFn(() => {})).toBe(false); 8 | expect(isGenFn(function () {})).toBe(false); 9 | expect(isGenFn(async function () {})).toBe(false); 10 | }); 11 | 12 | test('valid cases', () => { 13 | expect(isGenFn(function* () {})).toBe(true); 14 | expect(isGenFn(async function* () {})).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/avg.spec.ts: -------------------------------------------------------------------------------- 1 | import { avg } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('avg', () => { 5 | expect(avg()).toBe(0); 6 | expect(avg([])).toBe(0); 7 | expect(avg([1])).toBe(1); 8 | expect(avg([4, 1, 7])).toBe(4); 9 | expect(avg([4, 2, 8])).toBeCloseTo(4.666); 10 | expect(avg([1, 4, 2, 5, 0])).toBe(2.4); 11 | expect(avg([10, 20, 40, 50])).toBe(30); 12 | expect(avg([1, 2, 3, 4, 5])).toBe(3); 13 | expect(avg([-1, -2])).toBe(-1.5); 14 | expect(avg([1, 2, 3, 4, 5], (n) => n ** 2)).toBe(11); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isStr.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isStr } from '@opentf/std'; 9 | 10 | isStr(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isStr('abc') //=> true 17 | 18 | isStr(String(1)) //=> true 19 | 20 | isStr(1) //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isWkMap.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [WeakMap](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakMap). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isWkMap } from '@opentf/std'; 9 | 10 | isWkMap(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isWkMap(new Map()) //=> false 17 | 18 | isWkMap(new WeakMap()) //=> true 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isWkSet.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [WeakSet](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakSet). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isWkSet } from '@opentf/std'; 9 | 10 | isWkSet(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isWkSet(new Set()) //=> false 17 | 18 | isWkSet(new WeakSet()) //=> true 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/shuffle.spec.ts: -------------------------------------------------------------------------------- 1 | import { shuffle } from '../../src'; 2 | 3 | describe('Array > shuffle', () => { 4 | test('empty array', () => { 5 | expect(shuffle([])).toEqual([]); 6 | }); 7 | 8 | test('single element array', () => { 9 | expect(shuffle([1])).toEqual([1]); 10 | }); 11 | 12 | test('array of numbers', () => { 13 | const arr = [1, 2, 3, 4, 5]; 14 | expect(shuffle(arr)).toEqual(expect.arrayContaining([1, 2, 3, 4, 5])); 15 | expect(shuffle(arr)).not.toEqual([1, 2, 3, 4, 5]); 16 | expect(arr).toEqual([1, 2, 3, 4, 5]); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /apps/docs/public/assets/union-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB 2 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isArr.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isArr } from '@opentf/std'; 9 | 10 | isArr(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isArr([]) //=> true 17 | 18 | isArr(new Array('a', 'b', 'c')) //=> true 19 | 20 | isArr('abc') //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isSet.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [Set](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isSet } from '@opentf/std'; 9 | 10 | isSet(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isSet(new Set()) //=> true 17 | 18 | isSet(new WeakSet()) //=> false 19 | 20 | isSet({}) //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /packages/std/__tests__/string/capitalize.spec.js: -------------------------------------------------------------------------------- 1 | import { capitalize } from '../../src'; 2 | 3 | describe('String', () => { 4 | test('capitalize', () => { 5 | expect(() => capitalize()).toThrow(); 6 | expect(capitalize('')).toBe(''); 7 | expect(capitalize('a')).toBe('A'); 8 | expect(capitalize('ab')).toBe('Ab'); 9 | expect(capitalize('FOO')).toBe('Foo'); 10 | expect(capitalize('the quick brown fox')).toBe('The quick brown fox'); 11 | expect(capitalize('the Quick Brown FOX')).toBe('The quick brown fox'); 12 | expect(capitalize('1apple')).toBe('1apple'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /packages/std/src/array/chunk.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | 3 | /** 4 | * Splits the given array values into groups of a given size. 5 | * 6 | * @example 7 | * 8 | * chunk([1, 2, 3, 4, 5], 2) //=> [[1, 2], [3, 4], [5]] 9 | */ 10 | export default function chunk(arr: T[] = [], size = 1): unknown[] { 11 | if (size < 1 || !isArr(arr)) { 12 | return []; 13 | } 14 | 15 | return arr.reduce((acc: Iterable[], cur: T, i: number) => { 16 | return i % size === 0 17 | ? [...acc, [cur]] 18 | : [...acc.slice(0, -1), [...acc.slice(-1)[0], cur]]; 19 | }, []); 20 | } 21 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isArrBuf.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is an [ArrayBuffer](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isArrBuf } from '@opentf/std'; 9 | 10 | isArrBuf(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isArrBuf([]) //=> false 17 | 18 | isArrBuf(new ArrayBuffer(8)) //=> true 19 | ``` 20 | 21 | ## Try 22 | 23 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isSym.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [Symbol](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Symbol). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isSym } from '@opentf/std'; 9 | 10 | isSym(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isSym(Symbol()) //=> true 17 | 18 | isSym(Symbol('abc')) //=> true 19 | 20 | isSym('abc') //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /packages/std/__tests__/number/isNegZero.spec.ts: -------------------------------------------------------------------------------- 1 | import { isNegZero } from '../../src'; 2 | 3 | describe('Number', () => { 4 | test('isNegZero', () => { 5 | expect(isNegZero()).toBe(false); 6 | expect(isNegZero(undefined)).toBe(false); 7 | expect(isNegZero(null)).toBe(false); 8 | expect(isNegZero('')).toBe(false); 9 | expect(isNegZero('0')).toBe(false); 10 | expect(isNegZero([])).toBe(false); 11 | expect(isNegZero({})).toBe(false); 12 | expect(isNegZero(0)).toBe(false); 13 | expect(isNegZero(+0)).toBe(false); 14 | expect(isNegZero(-0)).toBe(true); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/clamp.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Returns a value clamped to the inclusive range of min and max. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { clamp } from '@opentf/std'; 9 | 10 | clamp(val: number, min: number, max: number): number; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | clamp(10, -5, 5) //=> 5 17 | 18 | clamp(0, 1000, 1366) //=> 1000 19 | 20 | clamp(1001, 1000, 1366) //=> 1001 21 | 22 | clamp(1500, 1000, 1366) //=> 1366 23 | ``` 24 | 25 | ## Try 26 | 27 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isRegEx.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [RegExp](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/RegExp) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isRegEx } from '@opentf/std'; 9 | 10 | isRegEx(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isRegEx(new RegExp()) //=> true 17 | 18 | isRegEx(/\d+/) //=> true 19 | 20 | isRegEx({}) //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isUndef.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [undefined](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/undefined). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isUndef } from '@opentf/std'; 9 | 10 | isUndef(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isUndef() //=> true 17 | 18 | isUndef(undefined) //=> true 19 | 20 | isUndef(null) //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /packages/std/src/array/bounds.ts: -------------------------------------------------------------------------------- 1 | import max from './max'; 2 | import min from './min'; 3 | import isEmpty from '../assert/isEmpty'; 4 | import compact from './compact'; 5 | 6 | /** 7 | * Returns a tuple of the min & max values of the given array. 8 | * 9 | * @example 10 | * bounds([10, 20, 50, 30]) //=> [10, 50] 11 | */ 12 | export default function bounds( 13 | arr: T[] = [], 14 | by: (val: T) => number = (x: T) => x as number 15 | ): [T, T] | null { 16 | const a = compact(arr); 17 | 18 | if (isEmpty(a)) { 19 | return null; 20 | } 21 | 22 | return [min(arr, by), max(arr, by)] as [T, T]; 23 | } 24 | -------------------------------------------------------------------------------- /packages/std/__tests__/string/pascalCase.spec.js: -------------------------------------------------------------------------------- 1 | import { pascalCase } from '../../src'; 2 | 3 | describe('String', () => { 4 | test('pascalCase', () => { 5 | expect(() => pascalCase()).toThrow(); 6 | expect(pascalCase('na cl')).toBe('NaCl'); 7 | expect(pascalCase('Foo-Bar')).toBe('FooBar'); 8 | expect(pascalCase('fooBAR')).toBe('FooBar'); 9 | expect(pascalCase('react_component')).toBe('ReactComponent'); 10 | expect(pascalCase('--foo.bar')).toBe('FooBar'); 11 | expect(pascalCase('__foo__--bar')).toBe('FooBar'); 12 | expect(pascalCase('cinema Scope')).toBe('CinemaScope'); 13 | }); 14 | }); 15 | -------------------------------------------------------------------------------- /apps/docs/pages/Function/noop.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > The No Operation function. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { noop } from '@opentf/std'; 9 | 10 | noop(): undefined; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | noop(); //=> undefined 17 | 18 | function test(cb) { 19 | const fn = cb || noop; 20 | fn(); 21 | } 22 | 23 | test(); // It can safely calls the callback fn 24 | ``` 25 | 26 | ## Try 27 | 28 | 37 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/divMod.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Returns a tuple with `Quotient` and `Remainder`. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { divMod } from '@opentf/std'; 9 | 10 | divMod(a: number, b: number): [number, number] 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | divMod(4, 2) //=> [2, 0]); 17 | 18 | divMod(11, 4) //=> [2.75, 3]); 19 | 20 | divMod(1, 0) //=> [Infinity, NaN]); 21 | 22 | divMod(0, 1) //=> [0, 0]); 23 | 24 | divMod(-9, -2) //=> [4.5, -1]); 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/fromPath.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Converts the given array values into an object property path string. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { fromPath } from '@opentf/std'; 10 | 11 | fromPath(arr: (string | number)[] = []): string 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | fromPath(['a', '0', 'b', 'c']) //=> 'a[0].b.c' 18 | 19 | fromPath(['a', 1, 'b', 'c']) //=> 'a[1].b.c' 20 | ``` 21 | 22 | ## Try 23 | 24 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isDate.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a valid [Date](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isDate } from '@opentf/std'; 9 | 10 | isDate(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isDate(new Date()) //=> true 17 | 18 | isDate(new Date('')) //=> false 19 | 20 | isDate('2000-01-01') //=> false 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /apps/docs/pages/playground.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import PlaygroundREPL from "../components/PlaygroundREPL"; 3 | 4 |
5 | ### Playground 6 |
7 | 8 | 9 | 10 | 11 | Press `CTRL + Enter` in the editor to run the code. 12 | 13 | 14 | 15 | - The [Lodash](https://lodash.com/docs/) methods were preloaded. You can use it like, `_.isEmpty(value)` 16 | 17 | - The [Ramda](https://ramdajs.com/) methods were preloaded. You can use it like, `R.pipe(Math.pow, R.negate, R.inc)` 18 | 19 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isDataView.spec.ts: -------------------------------------------------------------------------------- 1 | import { isDataView } from '../../src'; 2 | 3 | describe('Types > isDataView', () => { 4 | test('invalid cases', () => { 5 | expect(isDataView()).toBe(false); 6 | expect(isDataView(null)).toBe(false); 7 | expect(isDataView([])).toBe(false); 8 | expect(isDataView({})).toBe(false); 9 | expect(isDataView(new Uint8Array())).toBe(false); 10 | expect(isDataView(new ArrayBuffer(8))).toBe(false); 11 | }); 12 | 13 | test('valid cases', () => { 14 | const buffer = new ArrayBuffer(8); 15 | expect(isDataView(new DataView(buffer))).toBe(true); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isBool.spec.ts: -------------------------------------------------------------------------------- 1 | import { isBool } from '../../src'; 2 | 3 | describe('Types > isBool', () => { 4 | test('invalid cases', () => { 5 | expect(isBool()).toBe(false); 6 | expect(isBool(null)).toBe(false); 7 | expect(isBool('')).toBe(false); 8 | expect(isBool(1)).toBe(false); 9 | expect(isBool(0)).toBe(false); 10 | expect(isBool('true')).toBe(false); 11 | expect(isBool('false')).toBe(false); 12 | expect(isBool('null')).toBe(false); 13 | }); 14 | 15 | test('valid cases', () => { 16 | expect(isBool(true)).toBe(true); 17 | expect(isBool(false)).toBe(true); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isDef.spec.ts: -------------------------------------------------------------------------------- 1 | import { isDef } from '../../src'; 2 | 3 | describe('Types > isDef', () => { 4 | test('invalid cases', () => { 5 | expect(isDef()).toBe(false); 6 | expect(isDef(undefined)).toBe(false); 7 | expect(isDef(void 0)).toBe(false); 8 | }); 9 | 10 | test('valid cases', () => { 11 | expect(isDef(null)).toBe(true); 12 | expect(isDef(0)).toBe(true); 13 | expect(isDef(1)).toBe(true); 14 | expect(isDef('')).toBe(true); 15 | expect(isDef([])).toBe(true); 16 | expect(isDef({})).toBe(true); 17 | expect([1, undefined, 2].filter(isDef)).toEqual([1, 2]); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/std/src/function/pipeFn.ts: -------------------------------------------------------------------------------- 1 | /** Returns a function that performs functions composition from left to right. 2 | * 3 | * @example 4 | * const transform = pipeFn(Math.pow, Math.abs) 5 | * transform(-2, 3) //=> 8 6 | */ 7 | export default function pipeFn( 8 | ...fns: ((...args: unknown[]) => unknown)[] 9 | ): (...args: unknown[]) => unknown { 10 | return function (...args) { 11 | const firstFn = fns.shift(); 12 | 13 | if (!firstFn) { 14 | return; 15 | } 16 | 17 | let out = firstFn(...args); 18 | 19 | for (const fn of fns) { 20 | out = fn(out); 21 | } 22 | 23 | return out; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isArr.spec.ts: -------------------------------------------------------------------------------- 1 | import { isArr } from '../../src'; 2 | 3 | describe('Types > isArr', () => { 4 | test('invalid cases', () => { 5 | expect(isArr()).toBe(false); 6 | expect(isArr('[]')).toBe(false); 7 | expect(isArr('Array')).toBe(false); 8 | expect(isArr({})).toBe(false); 9 | expect(isArr(new Uint8Array(32))).toBe(false); 10 | }); 11 | 12 | test('valid cases', () => { 13 | expect(isArr([])).toBe(true); 14 | expect(isArr([1])).toBe(true); 15 | expect(isArr([])).toBe(true); 16 | expect(isArr(['a', 'b', 'c'])).toBe(true); 17 | expect(isArr(new Array(3))).toBe(true); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /apps/docs/pages/Number/toNum.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Try to convert the given value into a finite number. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { toNum } from '@opentf/std'; 10 | 11 | toNum(val: unknown): number; 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | toNum(1) //=> 1 18 | 19 | toNum('1.3') //=> 1.3 20 | 21 | toNum('1_000') //=> 1000 22 | 23 | toNum(Infinity) //=> NaN 24 | 25 | toNum('a') //=> NaN 26 | 27 | toNum('0xF') //=> 15 28 | ``` 29 | 30 | ## Try 31 | 32 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isBool.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [Boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Boolean). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isBool } from '@opentf/std'; 9 | 10 | isBool(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isBool(true) //=> true 17 | 18 | isBool(false) //=> true 19 | 20 | isBool(null) //=> false 21 | 22 | isBool(1) //=> false 23 | 24 | isBool() //=> false 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isWkRef.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [WeakRef](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WeakRef). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isWkRef } from '@opentf/std'; 9 | 10 | isWkRef(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isWkRef({}) //=> false 17 | 18 | let user = { name: "John" }; 19 | isWkRef(new WeakRef(user)) //=> true 20 | ``` 21 | 22 | ## Try 23 | 24 | -------------------------------------------------------------------------------- /packages/std/src/maths/median.ts: -------------------------------------------------------------------------------- 1 | import sort from '../array/sort'; 2 | import isEven from './isEven'; 3 | 4 | /** 5 | * Calculates the median value of the given array. 6 | * 7 | * @example 8 | * 9 | * median([1, 4, 2, 5, 0]) //=> 2 10 | * 11 | * median([10, 20, 40, 50]) //=> 30; 12 | */ 13 | export default function median( 14 | arr: number[] = [], 15 | cb?: (val: number, index: number) => number 16 | ): number { 17 | let a = cb ? arr.map(cb) : arr; 18 | a = sort(arr); 19 | 20 | if (isEven(a.length)) { 21 | const i = a.length / 2; 22 | return (arr[i] + arr[i - 1]) / 2; 23 | } 24 | 25 | return arr[Math.floor(a.length / 2)]; 26 | } 27 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isTypedArr.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is [TypedArray](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/TypedArray). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isTypedArr } from '@opentf/std'; 9 | 10 | isTypedArr(value: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isTypedArr([]) //=> false 17 | 18 | isTypedArr(new Int8Array()) //=> true 19 | 20 | isTypedArr(new Float64Array()) //=> true 21 | ``` 22 | 23 | ## Try 24 | 25 | -------------------------------------------------------------------------------- /packages/std/src/array/countBy.ts: -------------------------------------------------------------------------------- 1 | import isFn from '../types/isFn'; 2 | 3 | /** 4 | * Counts the items in the given array and groups them by the name provided. 5 | * 6 | * @example 7 | * 8 | * countBy([1, 2, 3, 4, 5], n => n % 2 === 0 ? 'Even' : 'Odd') //=> { Odd: 3, Even: 2 } 9 | */ 10 | export default function countBy( 11 | arr: T[] = [], 12 | by: ((val: T) => string) | string 13 | ): { [k: string]: number } { 14 | return arr.reduce((acc: Record, cur: T) => { 15 | const k = isFn(by) ? by(cur) : (cur[by as keyof T] as string); 16 | const count = acc[k] ? acc[k] + 1 : 1; 17 | return { ...acc, [k]: count }; 18 | }, {}); 19 | } 20 | -------------------------------------------------------------------------------- /packages/std/src/number/toNum.ts: -------------------------------------------------------------------------------- 1 | import isNum from '../types/isNum'; 2 | import isStr from '../types/isStr'; 3 | 4 | /** 5 | * Try to convert the given value into a finite number. 6 | * 7 | * @example 8 | * 9 | * toNum(1) //=> 1 10 | * toNum('1.3') //=> 1.3 11 | * toNum('1_000') //=> 1000 12 | * toNum(Infinity) //=> NaN 13 | */ 14 | 15 | export default function toNum(val: unknown): number { 16 | if (isNum(val)) { 17 | return val as number; 18 | } 19 | 20 | if (isStr(val) && isNum(val, true)) { 21 | return (val as string).includes('_') 22 | ? +(val as string).replaceAll('_', '') 23 | : +(val as string); 24 | } 25 | 26 | return NaN; 27 | } 28 | -------------------------------------------------------------------------------- /packages/std/__tests__/string/insertAt.spec.js: -------------------------------------------------------------------------------- 1 | import { insertAt } from '../../src'; 2 | 3 | describe('String', () => { 4 | test('insertAt', () => { 5 | expect(() => insertAt()).toThrow(); 6 | expect(insertAt('')).toBe(''); 7 | expect(insertAt('', 0)).toBe(''); 8 | expect(insertAt('', 1, 'abc')).toBe('abc'); 9 | expect(insertAt('a', 0, 'b')).toBe('ba'); 10 | expect(insertAt('a', 1, 'b')).toBe('ab'); 11 | expect(insertAt('a', 1, 'bc')).toBe('abc'); 12 | expect(insertAt('foo baz', 3, ' bar')).toBe('foo bar baz'); 13 | expect(insertAt('I 🍊', 2, 'ate an')).toBe('I ate an 🍊'); 14 | expect(insertAt('IU', 1, '❤️')).toBe('I❤️U'); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /packages/std/src/array/max.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import compact from './compact'; 3 | 4 | /** 5 | * Returns the maximum value of the given array. 6 | * 7 | * @example 8 | * max([10, 20, 50, 30]) //=> 50 9 | */ 10 | export default function max( 11 | arr: T[] = [], 12 | by: (val: T) => number = (x: T) => x as number 13 | ): T | null { 14 | const a = compact(arr); 15 | 16 | if (isEmpty(a)) { 17 | return null; 18 | } 19 | 20 | return (a as T[]).reduce((acc, cur) => { 21 | const a = by(acc); 22 | const b = by(cur); 23 | if (a === b) { 24 | return acc; 25 | } 26 | return a > b ? acc : cur; 27 | }) as T | null; 28 | } 29 | -------------------------------------------------------------------------------- /packages/std/src/array/min.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import compact from './compact'; 3 | 4 | /** 5 | * Returns the minimum value of the given array. 6 | * 7 | * @example 8 | * min([10, 20, 50, 30]) //=> 50 9 | */ 10 | export default function min( 11 | arr: T[] = [], 12 | by: (val: T) => number = (x: T) => x as number 13 | ): T | null { 14 | const a = compact(arr); 15 | 16 | if (isEmpty(a)) { 17 | return null; 18 | } 19 | 20 | return (a as T[]).reduce((acc, cur) => { 21 | const a = by(acc); 22 | const b = by(cur); 23 | if (a === b) { 24 | return acc; 25 | } 26 | return a > b ? cur : acc; 27 | }) as T | null; 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "arrIns": "arrIns", 3 | "arrReplace": "arrReplace", 4 | "arrRm": "arrRm", 5 | "bounds": "bounds", 6 | "chunk": "chunk", 7 | "compact": "compact", 8 | "countBy": "countBy", 9 | "diff": "diff", 10 | "drop": "drop", 11 | "groupBy": "groupBy", 12 | "intersection": "intersection", 13 | "intersperse": "intersperse", 14 | "max": "max", 15 | "min": "min", 16 | "move": "move", 17 | "range": "range", 18 | "reverse": "reverse", 19 | "shuffle": "shuffle", 20 | "sort": "sort", 21 | "sortBy": "sortBy", 22 | "swap": "swap", 23 | "symDiff": "symDiff", 24 | "take": "take", 25 | "union": "union", 26 | "uniq": "uniq" 27 | } 28 | -------------------------------------------------------------------------------- /apps/docs/pages/String/isEmail.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Check whether the given string is an email address. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isEmail } from '@opentf/std'; 9 | 10 | isEmail(str: string): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isEmail('user@example.com'); // true 17 | 18 | isEmail('test.email.with+symbol@example.org'); // true 19 | 20 | isEmail('example.net'); // false 21 | 22 | isEmail('email@example'); // false 23 | 24 | isEmail('email@example@example.com'); // false 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isTypedArr.spec.ts: -------------------------------------------------------------------------------- 1 | import { isTypedArr } from '../../src'; 2 | 3 | describe('Types > isTypedArr', () => { 4 | test('invalid cases', () => { 5 | expect(isTypedArr()).toBe(false); 6 | expect(isTypedArr(null)).toBe(false); 7 | expect(isTypedArr([])).toBe(false); 8 | expect(isTypedArr([])).toBe(false); 9 | expect(isTypedArr({})).toBe(false); 10 | }); 11 | 12 | test('valid cases', () => { 13 | expect(isTypedArr(new Uint8Array())).toBe(true); 14 | expect(isTypedArr(new Float32Array())).toBe(true); 15 | expect(isTypedArr(new Int8Array())).toBe(true); 16 | expect(isTypedArr(new Uint8ClampedArray())).toBe(true); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /packages/std/src/object/get.ts: -------------------------------------------------------------------------------- 1 | import has from './has'; 2 | import { IterableObj } from './merge'; 3 | import toPath from './toPath'; 4 | 5 | /** 6 | * Gets the value of an object at the given path. 7 | * 8 | * @example 9 | * 10 | * get({a: {b: {c: 1}}}, 'a.b.c') //=> 1 11 | */ 12 | export default function get( 13 | obj: object, 14 | path: string | unknown[], 15 | defVal?: unknown 16 | ): unknown { 17 | if (!has(obj, path)) { 18 | return defVal; 19 | } 20 | 21 | let curObj = obj; 22 | const pathArr = toPath(path); 23 | for (const prop of pathArr) { 24 | curObj = (curObj as IterableObj)[prop as PropertyKey] as object; 25 | } 26 | 27 | return curObj; 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isFn.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isFn } from '@opentf/std'; 9 | 10 | isFn(val: unknown): boolean 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | isFn(function() {}) //=> true 17 | 18 | isFn({}) //=> false 19 | 20 | function* generator(i) { 21 | yield i; 22 | yield i + 10; 23 | } 24 | 25 | isFn(generator); //=> true 26 | ``` 27 | 28 | ## Try 29 | 30 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/percentageOf.spec.js: -------------------------------------------------------------------------------- 1 | import { percentageOf } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('percentage', async () => { 5 | expect(() => percentageOf()).not.toThrow(); 6 | expect(percentageOf()).toBe(NaN); 7 | expect(percentageOf(0)).toBe(NaN); 8 | expect(percentageOf(undefined, 0)).toBe(NaN); 9 | expect(percentageOf(0, 0)).toBe(0); 10 | expect(percentageOf(1, 0)).toBe(0); 11 | expect(percentageOf(1, 1)).toBe(0.01); 12 | expect(percentageOf(0.5, 10)).toBe(0.05); 13 | expect(percentageOf(17.5, 10)).toBe(1.75); 14 | expect(percentageOf(10, 80)).toBe(8); 15 | expect(percentageOf(50, 900)).toBe(450); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /apps/docs/public/assets/sym-diff-venn-diagram.svg: -------------------------------------------------------------------------------- 1 | AB -------------------------------------------------------------------------------- /packages/std/__tests__/colors/hexToRGB.spec.js: -------------------------------------------------------------------------------- 1 | import { hexToRGB } from '../../src'; 2 | 3 | describe('Colors > hexToRGB', () => { 4 | test('colors', async () => { 5 | expect(hexToRGB('#000000')).toEqual([0, 0, 0]); 6 | expect(hexToRGB('#FFFFFF')).toEqual([255, 255, 255]); 7 | expect(hexToRGB('#ffffff')).toEqual([255, 255, 255]); 8 | expect(hexToRGB('#FF0000')).toEqual([255, 0, 0]); 9 | expect(hexToRGB('#00FF00')).toEqual([0, 255, 0]); 10 | expect(hexToRGB('#0000FF')).toEqual([0, 0, 255]); 11 | expect(hexToRGB('#AAAAAA')).toEqual([170, 170, 170]); 12 | expect(hexToRGB('#DDDDDD')).toEqual([221, 221, 221]); 13 | expect(hexToRGB('#ff851b')).toEqual([255, 133, 27]); 14 | }); 15 | }); 16 | -------------------------------------------------------------------------------- /packages/std/src/async/aPipeFn.ts: -------------------------------------------------------------------------------- 1 | /** Returns a function that performs functions composition from left to right asynchronously. 2 | * 3 | * @example 4 | * const transform = aPipe((x) => Promise.resolve(x ** 2), (x) => Promise.resolve(x - 5)) 5 | * await transform(5) //=> 20 6 | */ 7 | export default function aPipeFn( 8 | ...fns: ((...args: unknown[]) => unknown)[] 9 | ): (...args: unknown[]) => unknown { 10 | return async function (...args) { 11 | const firstFn = fns.shift(); 12 | 13 | if (!firstFn) { 14 | return; 15 | } 16 | 17 | let out = await firstFn(...args); 18 | 19 | for (const fn of fns) { 20 | out = await fn(out); 21 | } 22 | 23 | return out; 24 | }; 25 | } 26 | -------------------------------------------------------------------------------- /apps/docs/pages/Number/isNegZero.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks if the given number is negative zero (-0). 5 | 6 | 7 | In JavaScript 0 === -0 is true. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { isNegZero } from '@opentf/std'; 14 | 15 | isNegZero(n: number): boolean; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | isNegZero(0) //=> false 22 | 23 | isNegZero(-0) //=> true 24 | 25 | isNegZero(-0.0) //=> true 26 | 27 | isNegZero(-0x0) //=> true 28 | ``` 29 | 30 | ## Try 31 | 32 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/pipe.spec.js: -------------------------------------------------------------------------------- 1 | import { pipe } from '../../src'; 2 | 3 | describe('Function > Pipe', () => { 4 | test('empty pipe', () => { 5 | expect(pipe()).toBe(undefined); 6 | }); 7 | 8 | test('returns passed value if no functions', () => { 9 | expect(pipe(1)).toBe(1); 10 | }); 11 | 12 | test('single functions', () => { 13 | expect(pipe(-1, Math.abs)).toBe(1); 14 | }); 15 | 16 | test('two functions', () => { 17 | expect(pipe(-4, Math.abs, Math.sqrt)).toBe(2); 18 | }); 19 | 20 | test('multiple functions', () => { 21 | expect( 22 | pipe( 23 | 1, 24 | (x) => x + 1, 25 | (x) => x * 5 26 | ) 27 | ).toBe(10); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/isDisjointFrom.spec.ts: -------------------------------------------------------------------------------- 1 | import { isDisjointFrom } from '../../src'; 2 | 3 | describe('Maths > isDisjointFrom', () => { 4 | test('truthy', () => { 5 | expect(isDisjointFrom([1, 3, 5], [2, 4])).toBe(true); 6 | const primes = new Set([2, 3, 5, 7, 11, 13, 17, 19]); 7 | const squares = new Set([1, 4, 9, 16]); 8 | expect(isDisjointFrom(primes, squares)).toBe(true); 9 | }); 10 | 11 | test('falsy', () => { 12 | expect(isDisjointFrom([1, 2, 3, 5], [2, 4])).toBe(false); 13 | const composites = new Set([4, 6, 8, 9, 10, 12, 14, 15, 16, 18]); 14 | const squares = new Set([1, 4, 9, 16]); 15 | expect(isDisjointFrom(composites, squares)).toBe(false); 16 | }); 17 | }); 18 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/sum.spec.ts: -------------------------------------------------------------------------------- 1 | import { sum } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('sum', () => { 5 | expect(sum()).toBe(0); 6 | expect(sum([])).toBe(0); 7 | expect(sum([1])).toBe(1); 8 | expect(sum([1, -1])).toBe(0); 9 | expect(sum([-1, -2])).toBe(-3); 10 | expect(sum([1, 2, 3, 4, 5])).toBe(15); 11 | expect(sum([1.2, Math.PI])).toBeCloseTo(4.34); 12 | expect(sum([1, 2, 3, 4, 5.4], Math.round)).toBe(15); 13 | const objects = [{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }]; 14 | expect(sum(objects, (v) => v.n)).toBe(20); 15 | expect(sum(objects, (v, i) => v.n * i)).toBe(36); 16 | expect(sum([Infinity, Infinity])).toBe(Infinity); 17 | }); 18 | }); 19 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isDef.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is defined. 4 | 5 | ## Related 6 | 7 | - [isUndef](/Types/isUndef) 8 | 9 | ## Syntax 10 | 11 | ```ts 12 | import { isDef } from '@opentf/std'; 13 | 14 | isDef(value: unknown): boolean; 15 | ``` 16 | 17 | ## Examples 18 | 19 | ```ts 20 | isDef() //=> false 21 | 22 | isDef(undefined) //=> false 23 | 24 | isDef(null) //=> true 25 | 26 | isDef('') //=> true 27 | 28 | isDef(0) //=> true 29 | 30 | isDef([]) //=> true 31 | 32 | isDef({}) //=> true 33 | ``` 34 | 35 | ## Try 36 | 37 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isDate.spec.ts: -------------------------------------------------------------------------------- 1 | import { isDate } from '../../src'; 2 | 3 | describe('Types > isDate', () => { 4 | test('invalid cases', () => { 5 | expect(isDate()).toBe(false); 6 | expect(isDate(null)).toBe(false); 7 | expect(isDate('abc')).toBe(false); 8 | expect(isDate(123)).toBe(false); 9 | expect(isDate({})).toBe(false); 10 | expect(isDate([])).toBe(false); 11 | expect(isDate(new Date(''))).toBe(false); 12 | expect(isDate(new Date('2000-13-01'))).toBe(false); 13 | }); 14 | 15 | test('valid cases', () => { 16 | expect(isDate(new Date())).toBe(true); 17 | expect(isDate(new Date())).toBe(true); 18 | expect(isDate(new Date('2000-01-01'))).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/std/src/async/aResolvers.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Creates a promise with custom resolvers for `resolve` and `reject`. 3 | * 4 | * @example 5 | * const { promise, resolve, reject } = Promise.withResolvers(); 6 | * Math.random() > 0.5 ? resolve("ok") : reject("not ok"); 7 | */ 8 | 9 | export default function aResolvers(): { 10 | promise: Promise; 11 | resolve: (value: T) => void; 12 | reject: (reason?: unknown) => void; 13 | } { 14 | let resolve: (value: T) => void; 15 | let reject: (reason?: unknown) => void; 16 | const promise = new Promise((res, rej) => { 17 | resolve = res; 18 | reject = rej; 19 | }); 20 | 21 | //@ts-expect-error Ignore errors 22 | return { promise, resolve, reject }; 23 | } 24 | -------------------------------------------------------------------------------- /packages/std/src/types/isNum.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is number. 3 | * 4 | * @example 5 | * 6 | * isNum(1) //=> true 7 | * 8 | * isNum('1') //=> false 9 | * 10 | * isNum('1', true) //=> true 11 | * 12 | * isNum(NaN) //=> false 13 | * 14 | * isNum(Infinity) //=> false 15 | * 16 | */ 17 | export default function isNum(val: unknown, coerce = false): val is number { 18 | let n = val; 19 | if (coerce && typeof val === 'string' && val.trim().length) { 20 | const regex = /_{2,}|^0_1|^_|_$/; 21 | if (val.includes('_') && !regex.test(val.trim())) { 22 | n = val.replaceAll('_', ''); 23 | } 24 | n = Number(n); 25 | } 26 | 27 | return typeof n === 'number' && Number.isFinite(n); 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/chunk.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Splits the given array values into groups of a given size. 5 | 6 | ## Syntax 7 | 8 | ```ts copy 9 | import { chunk } from '@opentf/std'; 10 | 11 | chunk(arr: unknown[], size = 1): unknown[]; 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | chunk([1, 2, 3]) //=> [[1], [2], [3]] 18 | 19 | chunk([1, 2, 3], 1) //=> [[1], [2], [3]] 20 | 21 | chunk([1, 2, 3], 2) //=> [[1, 2], [3]] 22 | 23 | chunk([1, 2, 3], 3) //=> [[1, 2, 3]] 24 | 25 | chunk([1, 2, 3], 4) //=> [[1, 2, 3]] 26 | ``` 27 | 28 | ## Try 29 | 30 | 33 | -------------------------------------------------------------------------------- /packages/std/src/maths/mode.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Calculates the mode value of the given array. 3 | * 4 | * @example 5 | * 6 | * mode([0, 0, 1, 1, 1, 2, 3]) //=> [1] 7 | */ 8 | 9 | export default function mode( 10 | arr: T[] = [], 11 | cb?: (v: T, index: number) => number 12 | ): number[] { 13 | const a = cb ? arr.map(cb) : arr; 14 | const map = new Map(); 15 | a.forEach((i) => { 16 | map.set(i, (map.get(i) ?? 0) + 1); 17 | }); 18 | 19 | const values = [...map.values()]; 20 | 21 | const max = Math.max(...values); 22 | 23 | const out = []; 24 | 25 | for (const [key, val] of map) { 26 | if (val === max) { 27 | out.push(key); 28 | } 29 | } 30 | 31 | return out.length === arr.length ? [] : out; 32 | } 33 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/compose.spec.js: -------------------------------------------------------------------------------- 1 | import { compose } from '../../src'; 2 | 3 | describe('Function > compose', () => { 4 | test('empty compose', () => { 5 | expect(compose()).toBe(undefined); 6 | }); 7 | 8 | test('returns passed value if no functions', () => { 9 | expect(compose(1)).toBe(1); 10 | }); 11 | 12 | test('single functions', () => { 13 | expect(compose(-1, Math.abs)).toBe(1); 14 | }); 15 | 16 | test('two functions', () => { 17 | expect(compose(-4, Math.sqrt, Math.abs)).toBe(2); 18 | }); 19 | 20 | test('multiple functions', () => { 21 | expect( 22 | compose( 23 | 1, 24 | (x) => x + 1, 25 | (x) => x * 5 26 | ) 27 | ).toBe(6); 28 | }); 29 | }); 30 | -------------------------------------------------------------------------------- /apps/docs/pages/Function/sleep.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Suspend the execution for the specified milliseconds. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { sleep } from '@opentf/std'; 9 | 10 | sleep(ms: number): Promise; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | (async () => { 17 | await sleep(); // It does not suspend the exection. 18 | 19 | await sleep(0); // It also does not suspend the exection. 20 | 21 | await sleep(1000); // It suspends the exection for 1 second. 22 | })(); 23 | ``` 24 | 25 | ## Try 26 | 27 | { 31 | await sleep(1000); 32 | console.log('Second'); 33 | })() 34 | `} /> 35 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isInfinity.spec.ts: -------------------------------------------------------------------------------- 1 | import { isInfinity } from '../../src'; 2 | 3 | describe('Types > isInfinity', () => { 4 | test('invalid cases', () => { 5 | expect(isInfinity()).toBe(false); 6 | expect(isInfinity('')).toBe(false); 7 | expect(isInfinity(0)).toBe(false); 8 | expect(isInfinity(false)).toBe(false); 9 | expect(isInfinity(null)).toBe(false); 10 | expect(isInfinity(NaN)).toBe(false); 11 | expect(isInfinity('Infinity')).toBe(false); 12 | expect(isInfinity('1/0')).toBe(false); 13 | }); 14 | 15 | test('valid cases', () => { 16 | expect(isInfinity(1 / 0)).toBe(true); 17 | expect(isInfinity(Infinity)).toBe(true); 18 | expect(isInfinity(-Infinity)).toBe(true); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/std/src/function/composeFn.ts: -------------------------------------------------------------------------------- 1 | import reverse from '../array/reverse'; 2 | 3 | /** Returns a function that performs functions composition from right to left. 4 | * 5 | * @example 6 | * const transform = composeFn(Math.abs, Math.pow); 7 | * transform(-2, 3) //=> 8 8 | */ 9 | export default function composeFn( 10 | ...fns: ((...args: unknown[]) => unknown)[] 11 | ): (...args: unknown[]) => unknown { 12 | return function (...args) { 13 | const revFns = reverse(fns); 14 | 15 | const firstFn = revFns.shift(); 16 | 17 | if (!firstFn) { 18 | return; 19 | } 20 | 21 | let out = firstFn(...args); 22 | 23 | for (const fn of revFns) { 24 | out = fn(out); 25 | } 26 | 27 | return out; 28 | }; 29 | } 30 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aCompose.spec.js: -------------------------------------------------------------------------------- 1 | import { aCompose } from '../../src'; 2 | 3 | describe('Function > aCompose', () => { 4 | test('empty aCompose', async () => { 5 | await expect(aCompose()).resolves.toBe(undefined); 6 | }); 7 | 8 | test('single functions', async () => { 9 | await expect(aCompose(-5, Math.abs)).resolves.toBe(5); 10 | }); 11 | 12 | test('two functions', async () => { 13 | await expect(aCompose(-4, Math.sqrt, Math.abs)).resolves.toBe(2); 14 | }); 15 | 16 | test('multiple functions', async () => { 17 | await expect( 18 | aCompose( 19 | 1, 20 | (x) => Promise.resolve(x + 1), 21 | (x) => Promise.resolve(x * 5) 22 | ) 23 | ).resolves.toBe(6); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /apps/docs/pages/Number/isZero.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks if the given number is positive zero (0). 5 | 6 | 7 | In JavaScript 0 === -0 is true. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { isZero } from '@opentf/std'; 14 | 15 | isZero(n: number): boolean; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | isZero(0) //=> true 22 | 23 | isZero(0.0) //=> true 24 | 25 | isZero(0x0) //=> true 26 | 27 | isZero(-0) //=> false 28 | 29 | isZero(-0.0) //=> false 30 | 31 | isZero(-0x0) //=> false 32 | ``` 33 | 34 | ## Try 35 | 36 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isDataView.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [DataView](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/DataView) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isDataView } from '@opentf/std'; 9 | 10 | isDataView(val: unknown): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | const buffer = new ArrayBuffer(8); 17 | 18 | isDataView(buffer) //=> false 19 | 20 | isDataView(new Uint8Array(buffer)) //=> false 21 | 22 | isDataView(new DataView(buffer)) //=> true 23 | ``` 24 | 25 | ## Try 26 | 27 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/symDiff.spec.js: -------------------------------------------------------------------------------- 1 | import { symDiff } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('symDiff', () => { 5 | expect(symDiff()).toEqual([]); 6 | 7 | expect(symDiff([])).toEqual([]); 8 | 9 | expect(symDiff([[1, 2, 2, 3, 3, 4], [3, 4, 5]])).toEqual([1, 2, 5]); 10 | 11 | const evens = [2, 4, 6, 8]; 12 | const squares = [1, 4, 9]; 13 | expect(symDiff([evens, squares])).toEqual([2, 6, 8, 1, 9]); 14 | 15 | const bucket1 = ['Fruits', 'Vegs', 'Eggs', 'Cookies', 'Nuts']; 16 | const bucket2 = ['fruits', 'Snacks', 'cookies']; 17 | expect(symDiff([bucket1, bucket2], (v) => v.toLowerCase())).toEqual([ 18 | 'Vegs', 19 | 'Eggs', 20 | 'Nuts', 21 | 'Snacks', 22 | ]); 23 | }); 24 | }); 25 | -------------------------------------------------------------------------------- /apps/docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "private": true, 7 | "scripts": { 8 | "dev": "next", 9 | "build": "next build && pnpm run build:sitemap", 10 | "build:sitemap": "next-sitemap", 11 | "start": "next start", 12 | "test": "echo \"Error: no test specified\" && exit 1" 13 | }, 14 | "keywords": [], 15 | "author": "", 16 | "license": "ISC", 17 | "dependencies": { 18 | "@opentf/react-node-repl": "^0.14.0", 19 | "next": "^14.1.1", 20 | "next-sitemap": "^4.2.3", 21 | "nextra": "^2.13.4", 22 | "nextra-theme-docs": "^2.13.4", 23 | "react": "^18.2.0", 24 | "react-dom": "^18.2.0", 25 | "react-intersection-observer": "^9.8.1" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/prod.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Calculates the `product` of values in the given array. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { prod } from '@opentf/std'; 9 | 10 | prod( 11 | arr: number[] = [], 12 | cb?: (val: number, index: number) => number 13 | ): number 14 | ``` 15 | 16 | ## Examples 17 | 18 | ```ts 19 | prod() //=> 1 20 | 21 | prod([]) //=> 1 22 | 23 | prod([1]) //=> 1 24 | 25 | prod([1, -1]) //=> -1 26 | 27 | prod([-1, -2]) //=> 2 28 | 29 | prod([1, 2, 3, 4, 5]) //=> 120 30 | 31 | const objects = [{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }]; 32 | prod(objects, (v) => v.n) //=> 384 33 | ``` 34 | 35 | ## Try 36 | 37 | -------------------------------------------------------------------------------- /packages/std/__tests__/maths/percentage.spec.js: -------------------------------------------------------------------------------- 1 | import { percentage } from '../../src'; 2 | 3 | describe('Maths', () => { 4 | test('percentage', async () => { 5 | expect(() => percentage()).not.toThrow(); 6 | expect(percentage()).toBe(NaN); 7 | expect(percentage(0)).toBe(NaN); 8 | expect(percentage(undefined, 0)).toBe(NaN); 9 | expect(percentage(0, 0)).toBe(NaN); 10 | expect(percentage(1, 0)).toBe(Infinity); 11 | expect(percentage(1, 1)).toBe(100); 12 | expect(percentage(0.5, 1)).toBe(50); 13 | expect(percentage(25, 100)).toBe(25); 14 | expect(percentage(75, 150)).toBe(50); 15 | expect(percentage(8, 800)).toBe(1); 16 | expect(percentage(5, 150)).toBeCloseTo(3.33); 17 | expect(percentage(200, 100)).toBe(200); 18 | }); 19 | }); 20 | -------------------------------------------------------------------------------- /packages/std/src/maths/isSubsetOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a boolean indicating if all elements of this set are in the given set. 3 | * 4 | * @example 5 | * 6 | * const a = [1, 2, 3, 4] 7 | * const b = [2, 4] 8 | * isSubsetOf(b, a) //=> true 9 | */ 10 | export default function isSubsetOf( 11 | a: unknown[] | Set, 12 | b: unknown[] | Set, 13 | proper = false 14 | ): boolean { 15 | const setA = new Set(a); 16 | const setB = new Set(b); 17 | 18 | if (setA.size > setB.size) { 19 | return false; 20 | } 21 | 22 | for (const e of setA) { 23 | if (!setB.has(e)) { 24 | return false; 25 | } 26 | } 27 | 28 | if (proper) { 29 | if (setA.size === setB.size) { 30 | return false; 31 | } 32 | } 33 | 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/mergeAll.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > It deeply merges objects and concatenates the arrays if any present. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { mergeAll } from '@opentf/std'; 10 | 11 | mergeAll(obj1, ...objN); 12 | ``` 13 | 14 | 15 | Immutable: This does not mutate the given arrays or objects. 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | const a = { a: { b: [1] } }; 22 | const b = { a: { b: [2] } }; 23 | mergeAll(a, b); //=> { a: { b: [1, 2] } 24 | ``` 25 | 26 | ## Try 27 | 28 | -------------------------------------------------------------------------------- /packages/std/src/maths/isDisjointFrom.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a boolean indicating if this set has no elements in common with the given set. 3 | * 4 | * @example 5 | * 6 | * const a = [1, 3, 5] 7 | * const b = [2, 4] 8 | * isDisjointFrom(a, b) //=> true 9 | */ 10 | export default function isDisjointFrom( 11 | a: unknown[] | Set, 12 | b: unknown[] | Set 13 | ): boolean { 14 | const setA = new Set(a); 15 | const setB = new Set(b); 16 | 17 | if (setA.size > setB.size) { 18 | for (const e of setB) { 19 | if (setA.has(e)) { 20 | return false; 21 | } 22 | } 23 | 24 | return true; 25 | } 26 | 27 | for (const e of setA) { 28 | if (setB.has(e)) { 29 | return false; 30 | } 31 | } 32 | 33 | return true; 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/percentage.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Calculates percentage of a value with total. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { percentage } from '@opentf/std'; 9 | 10 | percentage(value: number, total: number): number; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | percentage(0, 0); // NaN 17 | 18 | percentage(1, 0); // Infinity 19 | 20 | percentage(1, 1); // 100 21 | 22 | percentage(0.5, 1); // 50 23 | 24 | percentage(25, 100); // 25 25 | 26 | percentage(75, 150); // 50 27 | 28 | percentage(8, 800); // 1 29 | 30 | percentage(5, 150); // 3.3333333333333335 31 | 32 | percentage(200, 100); // 200 33 | ``` 34 | 35 | ## Try 36 | 37 | 40 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/shallowMergeAll.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Shallow merges objects and concatenates the array. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { shallowMergeAll } from '@opentf/std'; 10 | 11 | shallowMergeAll(obj1, ...objN); 12 | ``` 13 | 14 | 15 | Immutable: This does not mutate the given arrays or objects. 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | const a = [1]; 22 | const b = [2]; 23 | const c = [3]; 24 | shallowMergeAll(a, b, c); //=> [1, 2, 3] 25 | ``` 26 | 27 | ## Try 28 | 29 | -------------------------------------------------------------------------------- /packages/std/src/maths/isSupersetOf.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Returns a boolean indicating if all elements of the given set are in this set. 3 | * 4 | * @example 5 | * 6 | * const a = [1, 2, 3, 4] 7 | * const b = [2, 4] 8 | * isSupersetOf(a, b) //=> true 9 | */ 10 | export default function isSupersetOf( 11 | a: unknown[] | Set, 12 | b: unknown[] | Set, 13 | proper = false 14 | ): boolean { 15 | const setA = new Set(a); 16 | const setB = new Set(b); 17 | 18 | if (setA.size < setB.size) { 19 | return false; 20 | } 21 | 22 | for (const e of setB) { 23 | if (!setA.has(e)) { 24 | return false; 25 | } 26 | } 27 | 28 | if (proper) { 29 | if (setA.size === setB.size) { 30 | return false; 31 | } 32 | } 33 | 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/_meta.json: -------------------------------------------------------------------------------- 1 | { 2 | "isArr": "isArr", 3 | "isArrBuf": "isArrBuf", 4 | "isAsyFn": "isAsyFn", 5 | "isBigInt": "isBigInt", 6 | "isBlob": "isBlob", 7 | "isBool": "isBool", 8 | "isDataView": "isDataView", 9 | "isDate": "isDate", 10 | "isDef": "isDef", 11 | "isErr": "isErr", 12 | "isFn": "isFn", 13 | "isGenFn": "isGenFn", 14 | "isInfinity": "isInfinity", 15 | "isJSON": "isJSON", 16 | "isMap": "isMap", 17 | "isNull": "isNull", 18 | "isNum": "isNum", 19 | "isObj": "isObj", 20 | "isPureObj": "isPureObj", 21 | "isRegEx": "isRegEx", 22 | "isSet": "isSet", 23 | "isStr": "isStr", 24 | "isSym": "isSym", 25 | "isTypedArr": "isTypedArr", 26 | "isUndef": "isUndef", 27 | "isWkMap": "isWkMap", 28 | "isWkRef": "isWkRef", 29 | "isWkSet": "isWkSet" 30 | } 31 | -------------------------------------------------------------------------------- /packages/std/src/assert/isEqlArr.ts: -------------------------------------------------------------------------------- 1 | import size from '../object/size'; 2 | import isEql from './isEql'; 3 | 4 | /** 5 | * Checks deeply if the given two arrays with different orders are equivalent. 6 | * 7 | * @example 8 | * 9 | * isEqlArr([1, 3, 2], [2, 1, 3]) //=> true 10 | * 11 | * isEqlArr([1, 3, 2], [2, 1, 5]) //=> false 12 | */ 13 | export default function isEqlArr(arr1: unknown[], arr2: unknown[]): boolean { 14 | const a1: unknown[] = arr1.flat(); 15 | const a2: unknown[] = arr2.flat(); 16 | 17 | if (size(a1) !== size(a2)) { 18 | return false; 19 | } 20 | 21 | for (const val of a1) { 22 | const index = a2.findIndex((item) => isEql(val, item)); 23 | 24 | if (index < 0) { 25 | return false; 26 | } 27 | 28 | delete a2[index]; 29 | } 30 | 31 | return true; 32 | } 33 | -------------------------------------------------------------------------------- /packages/std/src/async/aComposeFn.ts: -------------------------------------------------------------------------------- 1 | import reverse from '../array/reverse'; 2 | 3 | /** Returns a function that performs functions composition from right to left asynchronously. 4 | * 5 | * @example 6 | * const transform = aComposeFn((x) => Promise.resolve(x + 1), (x) => Promise.resolve(x * 5)) 7 | * await transform(1) //=> 6 8 | */ 9 | export default function aComposeFn( 10 | ...fns: ((...args: unknown[]) => unknown)[] 11 | ): (...args: unknown[]) => unknown { 12 | return async function (...args) { 13 | const revFns = reverse(fns); 14 | const firstFn = revFns.shift(); 15 | 16 | if (!firstFn) { 17 | return; 18 | } 19 | 20 | let out = await firstFn(...args); 21 | 22 | for (const fn of revFns) { 23 | out = await fn(out); 24 | } 25 | 26 | return out; 27 | }; 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/pages/String/capitalize.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > [Capitalize](https://en.wikipedia.org/wiki/Capitalization) a string. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { capitalize } from '@opentf/std'; 9 | 10 | capitalize(str: string): string; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | capitalize() // It throws an error; 17 | 18 | capitalize('') // '' 19 | 20 | capitalize('a') // 'A' 21 | 22 | capitalize('ab') // 'Ab' 23 | 24 | capitalize('FOO') // 'Foo' 25 | 26 | capitalize('the quick brown fox') // 'The quick brown fox' 27 | 28 | capitalize('the Quick Brown FOX') // 'The quick brown fox' 29 | 30 | capitalize('1apple') // '1apple' 31 | ``` 32 | 33 | ## Try 34 | 35 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/percentageOf.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Calculates percentage of a number. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { percentageOf } from '@opentf/std'; 9 | 10 | percentageOf(percentage: number, num: number): number; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | percentageOf(); // NaN 17 | 18 | percentageOf(0); // NaN 19 | 20 | percentageOf(undefined, 0); // NaN 21 | 22 | percentageOf(0, 0); // 0 23 | 24 | percentageOf(1, 0); // 0 25 | 26 | percentageOf(1, 1); // 0.01 27 | 28 | percentageOf(0.5, 10); // 0.05 29 | 30 | percentageOf(10, 80); // 8 31 | 32 | percentageOf(50, 900); // 450 33 | 34 | percentageOf(17.5, 10); // 1.75 35 | ``` 36 | 37 | ## Try 38 | 39 | 42 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isInfinity.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks if the given value is [Infinity](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Infinity). 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { isInfinity } from '@opentf/std'; 10 | 11 | isInfinity(value: unknown): boolean; 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | isInfinity(0) //=> false 18 | 19 | isInfinity(false) //=> false 20 | 21 | isInfinity(null) //=> false 22 | 23 | isInfinity(NaN) //=> false 24 | 25 | isInfinity(1/0) //=> true 26 | 27 | isInfinity(Infinity) //=> true 28 | 29 | isInfinity(-Infinity) //=> true 30 | ``` 31 | 32 | ## Try 33 | 34 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/shallowMerge.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Shallow Merges objects or arrays. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { shallowMerge } from '@opentf/std'; 10 | 11 | shallowMerge(obj1, ...objN); 12 | ``` 13 | 14 | 15 | Immutable: This does not mutate the given arrays or objects. 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | const a = { a: 1 }; 22 | const b = { b: 2 }; 23 | shallowMerge(a, b); //=> { a: 1, b: 2 } 24 | 25 | const a = [1]; 26 | const b = [2]; 27 | const c = [3]; 28 | shallowMerge(a, b, c); //=> [3] 29 | ``` 30 | 31 | ## Try 32 | 33 | -------------------------------------------------------------------------------- /packages/std/src/array/uniq.ts: -------------------------------------------------------------------------------- 1 | import isEql from '../assert/isEql'; 2 | import isFn from '../types/isFn'; 3 | 4 | /** 5 | * Creates a unique array by removing all duplicate values from the given array. 6 | * 7 | * @example 8 | * 9 | * uniq([1, 2, 2, 3]) //=> [1, 2, 3] 10 | */ 11 | 12 | export default function uniq( 13 | arr: T[] = [], 14 | by?: (val: T) => unknown 15 | ): Partial { 16 | return arr.reduce((acc: unknown[], cur) => { 17 | let flag = false; 18 | 19 | for (const item of acc) { 20 | const v1 = isFn(by) ? by(item as T) : item; 21 | const v2 = isFn(by) ? by(cur) : cur; 22 | if (isEql(v1, v2)) { 23 | flag = true; 24 | break; 25 | } 26 | } 27 | 28 | if (!flag) { 29 | acc.push(cur); 30 | } 31 | 32 | return acc; 33 | }, []) as Partial; 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/move.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > It moves an array element from one index position to another. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { move } from '@opentf/std'; 14 | 15 | move(arr: T[], from: number, to: number): T[]; 16 | ``` 17 | 18 | ## Usage 19 | 20 | ```ts 21 | import { move } from "@opentf/std"; 22 | 23 | move([], 0, 1); 24 | ``` 25 | 26 | ## Examples 27 | 28 | ```ts 29 | move([1, 2, 3], 0, 2); //=> [2, 3, 1] 30 | 31 | move([1, 2, 3], 0, 5); //=> [2, 3, 1] 32 | 33 | move([1, 2, 3], 5, 0); //=> [1, 2, 3] 34 | ``` 35 | 36 | ## Try 37 | 38 | 41 | -------------------------------------------------------------------------------- /apps/docs/pages/String/pascalCase.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Convert a string to [Pascal case](https://en.wikipedia.org/wiki/Camel_case). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { pascalCase } from '@opentf/std'; 9 | 10 | pascalCase(str: string): string; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | pascalCase() // It throws an error; 17 | 18 | pascalCase('na cl'); // 'NaCl' 19 | 20 | pascalCase('Foo-Bar'); // 'FooBar' 21 | 22 | pascalCase('fooBAR'); // 'FooBar' 23 | 24 | pascalCase('react_component'); // 'ReactComponent' 25 | 26 | pascalCase('--foo.bar'); // 'FooBar' 27 | 28 | pascalCase('__foo__--bar'); // 'FooBar' 29 | 30 | pascalCase('cinema Scope'); // 'CinemaScope' 31 | ``` 32 | 33 | ## Try 34 | 35 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/chunk.spec.ts: -------------------------------------------------------------------------------- 1 | import { chunk } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('chunk', () => { 5 | expect(chunk()).toEqual([]); 6 | expect(chunk({})).toEqual([]); 7 | expect(chunk([])).toEqual([]); 8 | expect(chunk([1, 2, 3])).toEqual([[1], [2], [3]]); 9 | expect(chunk([1, 2, 3], 1)).toEqual([[1], [2], [3]]); 10 | expect(chunk([1, 2, 3], 2)).toEqual([[1, 2], [3]]); 11 | expect(chunk([1, 2, 3], 3)).toEqual([[1, 2, 3]]); 12 | expect(chunk([1, 2, 3], 4)).toEqual([[1, 2, 3]]); 13 | expect(chunk([1, 2, 3], 100)).toEqual([[1, 2, 3]]); 14 | expect(chunk([1, 2, 3], 0)).toEqual([]); 15 | expect(chunk([1, 2, 3], -1)).toEqual([]); 16 | expect(chunk([{ a: 1 }, { a: 2 }, { a: 3 }], 2)).toEqual([ 17 | [{ a: 1 }, { a: 2 }], 18 | [{ a: 3 }], 19 | ]); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/shuffle.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Shuffles the given array values. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { shuffle } from '@opentf/std'; 14 | 15 | shuffle(arr: T[]): T[] 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | shuffle([]) //=> [] 22 | 23 | shuffle([1]) //=> [1] 24 | 25 | shuffle([1, 2, 3, 4, 5]) //=> [ 2, 4, 5, 1, 3 ] 26 | 27 | shuffle('Apple') //=> [ 'p', 'e', 'A', 'l', 'p' ] 28 | ``` 29 | 30 | ## Try 31 | 32 | 36 | 37 | ## Learn 38 | 39 | - [Fisher–Yates shuffle](https://en.wikipedia.org/wiki/Fisher%E2%80%93Yates_shuffle) -------------------------------------------------------------------------------- /apps/docs/pages/Object/pick.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Includes all the property paths from the given object for the given list of paths. 5 | 6 | 7 | The source object can `Plain Object` or `Array`. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { pick } from '@opentf/std'; 14 | 15 | pick(obj: object, ...paths: (string | unknown[])[]) 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | pick({ a: 1, b: 2 }, 'a') //=> { a: 1 } 22 | 23 | pick([1, 2, 3], '0') //=> [1] 24 | 25 | pick({ a: { b: { c: 1 }, d: null, e: [10, 20, 30] } }, 'a.b', ['a', 'e', '2']) 26 | //=> { 27 | // a: { b: { c: 1 } }, 28 | // e: [30] 29 | // } 30 | ``` 31 | ## Try 32 | 33 | -------------------------------------------------------------------------------- /packages/std/src/array/intersperse.ts: -------------------------------------------------------------------------------- 1 | import isFn from '../types/isFn'; 2 | import isStr from '../types/isStr'; 3 | import drop from './drop'; 4 | 5 | /** 6 | * Inserts a separator between the elements of its list argument. 7 | * 8 | * @example 9 | * 10 | * const arr = [1, 2, 3]; 11 | * intersperse(arr, '*') //=> [1, '*', 2, '*', 3] 12 | * 13 | * intersperse('Hello', '-') //=> H-e-l-l-o 14 | */ 15 | export default function intersperse( 16 | list: string | unknown[] = [], 17 | sep: ((index: number) => unknown) | unknown 18 | ): string | unknown[] { 19 | const a = isStr(list) ? Array.from(list) : list; 20 | const res = drop( 21 | a.reduce((acc: unknown[], cur, index) => { 22 | acc.push(isFn(sep) ? sep(index - 1) : sep, cur); 23 | return acc; 24 | }, []) 25 | ); 26 | 27 | return isStr(list) ? (res.join('') as string) : res; 28 | } 29 | -------------------------------------------------------------------------------- /apps/docs/pages/Assert/isNil.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks if the given value is Nil / Noting. 5 | 6 | 7 | The `undefined` & `null` values are considered [Nullish](https://developer.mozilla.org/en-US/docs/Glossary/Nullish). 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { isNil } from '@opentf/std'; 14 | 15 | isNil(val: unknown): Boolean; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | isNil('') //=> false 22 | 23 | isNil([]) //=> false 24 | 25 | isNil({}) //=> false 26 | 27 | isNil() //=> true 28 | 29 | isNil(undefined) //=> true 30 | 31 | isNil(null) //=> true 32 | ``` 33 | 34 | ## Try 35 | 36 | !isNil(i)); 40 | `} /> -------------------------------------------------------------------------------- /packages/std/__tests__/array/reverse.spec.ts: -------------------------------------------------------------------------------- 1 | import { reverse } from '../../src'; 2 | 3 | describe('Array > reverse', () => { 4 | test('empty array', () => { 5 | expect(reverse()).toEqual([]); 6 | expect(reverse([])).toEqual([]); 7 | }); 8 | 9 | test('array of numbers', () => { 10 | expect(reverse([1, 2, 3])).toEqual([3, 2, 1]); 11 | }); 12 | 13 | test('array of objects', () => { 14 | expect(reverse([{ a: 1 }, { b: 2 }, { c: 3 }])).toEqual([ 15 | { 16 | c: 3, 17 | }, 18 | { 19 | b: 2, 20 | }, 21 | { 22 | a: 1, 23 | }, 24 | ]); 25 | }); 26 | 27 | test('strings', () => { 28 | expect(reverse('Apple')).toEqual(['e', 'l', 'p', 'p', 'A']); 29 | }); 30 | 31 | test('sparse array', () => { 32 | expect(reverse([1, , 3])).toStrictEqual([3, undefined, 1]); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/std/__tests__/string/replaceAt.spec.js: -------------------------------------------------------------------------------- 1 | import { replaceAt } from '../../src'; 2 | 3 | describe('String', () => { 4 | test('replaceAt', () => { 5 | expect(() => replaceAt()).toThrow(); 6 | expect(replaceAt('')).toBe(''); 7 | expect(replaceAt('', 0)).toBe(''); 8 | expect(replaceAt('', 0, 'a')).toBe('a'); 9 | expect(replaceAt('', 1, 'abc')).toBe('abc'); 10 | expect(replaceAt('a')).toBe(''); 11 | expect(replaceAt('abc')).toBe('bc'); 12 | expect(replaceAt('abc', 1)).toBe('ac'); 13 | expect(replaceAt('abc', 5)).toBe('abc'); 14 | expect(replaceAt('abc', 1, '')).toBe('ac'); 15 | expect(replaceAt('abc', 0, 'z')).toBe('zbc'); 16 | expect(replaceAt('iphone', 1, 'P')).toBe('iPhone'); 17 | expect(replaceAt('I__JS', 1, '❤️')).toBe('I❤️JS'); 18 | expect(replaceAt('I HATE U', 2, 'LOVE')).toBe('I LOVE U'); 19 | }); 20 | }); 21 | -------------------------------------------------------------------------------- /packages/std/__tests__/colors/rgbToHex.spec.js: -------------------------------------------------------------------------------- 1 | import { rgbToHex } from '../../src'; 2 | 3 | describe('Colors > rgbToHex', () => { 4 | test('colors', async () => { 5 | expect(rgbToHex([0, 0, 0])).toEqual('#000000'); 6 | expect(rgbToHex([1, 1, 1])).toEqual('#010101'); 7 | expect(rgbToHex([255, 255, 255])).toEqual('#FFFFFF'.toLowerCase()); 8 | expect(rgbToHex([255, 255, 255])).toEqual('#ffffff'.toLowerCase()); 9 | expect(rgbToHex([255, 0, 0])).toEqual('#FF0000'.toLowerCase()); 10 | expect(rgbToHex([0, 255, 0])).toEqual('#00FF00'.toLowerCase()); 11 | expect(rgbToHex([0, 0, 255])).toEqual('#0000FF'.toLowerCase()); 12 | expect(rgbToHex([170, 170, 170])).toEqual('#AAAAAA'.toLowerCase()); 13 | expect(rgbToHex([221, 221, 221])).toEqual('#DDDDDD'.toLowerCase()); 14 | expect(rgbToHex([255, 133, 27])).toEqual('#ff851b'.toLowerCase()); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/avg.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Calculates the `average` value of the given array. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { avg } from '@opentf/std'; 10 | 11 | avg( 12 | arr: number[] = [], 13 | cb?: (val: number, index: number) => number 14 | ): number 15 | ``` 16 | 17 | ## Examples 18 | 19 | ```ts 20 | avg() //=> 0 21 | 22 | avg([]) //=> 0 23 | 24 | avg([1]) //=> 1 25 | 26 | avg([4, 1, 7]) //=> 4 27 | 28 | avg([4, 2, 8]) //=> 4.666666666666667 29 | 30 | avg([1, 4, 2, 5, 0]) //=> 2.4 31 | 32 | avg([10, 20, 40, 50]) //=> 30 33 | 34 | avg([1, 2, 3, 4, 5]) //=> 3 35 | 36 | avg([-1, -2]) //=> -1.5 37 | 38 | avg([1, 2, 3, 4, 5], (n) => n ** 2) //=> 11 39 | ``` 40 | 41 | ## Try 42 | 43 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aForEach.spec.ts: -------------------------------------------------------------------------------- 1 | import { aForEach } from '../../src'; 2 | 3 | describe('Array > aForEach', () => { 4 | test('async fn in cb fn', async () => { 5 | const flatten = async (val) => { 6 | return new Promise((resolve) => { 7 | Array.isArray(val) ? resolve(val.flat()) : resolve(val); 8 | }); 9 | }; 10 | 11 | const nested = [1, 2, 3, [4, 5, [6, 7], 8, 9]]; 12 | const tmpArr = []; 13 | await aForEach(nested, async (n) => { 14 | const val = await flatten(n); 15 | Array.isArray(val) ? tmpArr.push(...val) : tmpArr.push(val); 16 | }); 17 | expect(tmpArr).toEqual([1, 2, 3, 4, 5, 6, 7, 8, 9]); 18 | }); 19 | 20 | test('cb fn index', async () => { 21 | const arr = [1, 2, 3]; 22 | const out = []; 23 | await aForEach(arr, (_e, i) => out.push(i)); 24 | expect(out).toEqual([0, 1, 2]); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/uniq.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Creates a unique array by removing all duplicate values from the given array. 5 | 6 | 7 | It uses [isEql](/Assert/isEql) for deep comparison of values. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts copy 13 | import { uniq } from '@opentf/std'; 14 | 15 | uniq( 16 | arr: T[] = [], 17 | by?: (val: T) => unknown 18 | ): Partial 19 | ``` 20 | 21 | ## Examples 22 | 23 | ```ts 24 | const arr = [1, 2, 2, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5, 5, 5]; 25 | uniq(arr) //=> [1, 2, 3, 4, 5] 26 | 27 | const arr = [2.1, 1.2, 2.3]; 28 | uniq(a, Math.floor) //=> [2.1, 1.2] 29 | ``` 30 | 31 | ## Try 32 | 33 | 38 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/merge.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > It deeply merges objects or arrays. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { merge } from '@opentf/std'; 10 | 11 | merge(obj1, ...objN); 12 | ``` 13 | 14 | 15 | Immutable: This does not mutate the given arrays or objects. 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | const a = { a: { b: 1 }, d: 3 }; 22 | const b = { a: { c: 2 }, e: 5 }; 23 | merge(a, b); //=> { a: { b: 1, c: 2 }, d: 3, e: 5 } 24 | 25 | const a = { a: [1, 2] }; 26 | const b = { a: [3, 4, 5] }; 27 | const c = { a: [7, 8] }; 28 | merge(a, b, c); //=> { a: [7, 8, 5] } 29 | ``` 30 | 31 | ## Try 32 | 33 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/has.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks if the given path exists in the given object. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { has } from '@opentf/std'; 10 | 11 | has(obj: object, path: string | unknown[]): boolean 12 | ``` 13 | 14 | ## Examples 15 | 16 | ```ts 17 | has() //=> false 18 | 19 | has({}, '') //=> false 20 | 21 | has({ a: undefined }, 'a') //=> true 22 | 23 | has({ a: undefined }, ['a']) //=> true 24 | 25 | has({ a: null }, 'a') //=> true 26 | 27 | has({ a: 1 }, 'a') //=> true 28 | 29 | has({ a: { b: [1, 2, 3, { c: 5 }] } }, 'a.b[3].c') //=> true 30 | 31 | has({ a: { b: [1, 2, 3, { c: 5 }] } }, 'a.b[5].c') //=> false 32 | 33 | has({ a: { 'b.c': 1 } }, ['a', 'b.c']) //=> true 34 | ``` 35 | ## Try 36 | 37 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/reverse.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Reverses the given list of elements order. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { reverse } from '@opentf/std'; 14 | 15 | reverse(arr: T[] = []): T[] 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | reverse([1, 2, 3]) //=> [3, 2, 1] 22 | 23 | reverse([{ a: 1 }, { b: 2 }, { c: 3 }]) 24 | //=> [ 25 | // { 26 | // c: 3, 27 | // }, 28 | // { 29 | // b: 2, 30 | // }, 31 | // { 32 | // a: 1, 33 | // }, 34 | // ] 35 | 36 | reverse('Apple')//=> ['e', 'l', 'p', 'p', 'A'] 37 | 38 | reverse([1, , 3])//=> [3, undefined, 1] 39 | ``` 40 | 41 | ## Try 42 | 43 | 47 | -------------------------------------------------------------------------------- /packages/std/src/object/merge.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | import isObj from '../types/isObj'; 3 | 4 | export type IterableObj = { 5 | [key: number | string | symbol]: unknown; 6 | }; 7 | 8 | /** 9 | * It deeply merges objects or arrays. 10 | * 11 | * @example 12 | * const a = { a: { b: 1 } }; 13 | * const b = { a: { c: 2 } }; 14 | * merge(a, b); //=> {a: { b: 1, c: 2 } } 15 | */ 16 | export default function merge(...objs: object[]): object { 17 | const filteredObjs = objs.filter((v) => isArr(v) || isObj(v)); 18 | const initialVal = isArr(filteredObjs[0]) ? [] : {}; 19 | 20 | return filteredObjs.reduce((acc: IterableObj, cur) => { 21 | for (const [key, val] of Object.entries(cur)) { 22 | if (isArr(val) || isObj(val)) { 23 | acc[key] = merge(acc[key] as object, val); 24 | } else { 25 | acc[key] = val; 26 | } 27 | } 28 | return acc; 29 | }, initialVal); 30 | } 31 | -------------------------------------------------------------------------------- /apps/docs/pages/String/insertAt.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Insert a character or string at the index position. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { insertAt } from '@opentf/std'; 10 | 11 | insertAt(str: string, index?: number, insertStr?: string): string; 12 | ``` 13 | 14 | 15 | Default index = 0 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | insertAt() // It throws an error; 22 | 23 | insertAt('') //=> '' 24 | 25 | insertAt('', 0) //=> '' 26 | 27 | insertAt('', 1, 'abc') //=> 'abc' 28 | 29 | insertAt('a', 0, 'b') //=> 'ba' 30 | 31 | insertAt('a', 1, 'b') //=> 'ab' 32 | 33 | insertAt('a', 1, 'bc') //=> 'abc' 34 | 35 | insertAt('foo baz', 3, ' bar') //=> 'foo bar baz' 36 | ``` 37 | 38 | ## Try 39 | 40 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/arrRm.spec.ts: -------------------------------------------------------------------------------- 1 | import { arrRm } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('arrRm', () => { 5 | expect(arrRm()).toEqual([]); 6 | expect(arrRm([])).toEqual([]); 7 | expect(arrRm([1])).toEqual([]); 8 | expect(arrRm([1, 2])).toEqual([1]); 9 | expect(arrRm([1, 2], 1)).toEqual([1]); 10 | expect(arrRm([1, 2], 1, 1)).toEqual([1]); 11 | expect(arrRm([1, 2, 3, 4, 5], -1)).toEqual([1, 2, 3, 4]); 12 | expect(arrRm([1, 2, 3, 4, 5], -1, 1)).toEqual([1, 2, 3, 4]); 13 | expect(arrRm([1, 2, 3, 4, 5], -1, 3)).toEqual([1, 2, 3, 4]); 14 | expect(arrRm([1, 2, 3, 4, 5], -2, 2)).toEqual([1, 2, 3]); 15 | 16 | const a = ['a', 'b', 'c']; 17 | expect(arrRm(a)).toEqual(['a', 'b']); 18 | expect(a).toEqual(['a', 'b', 'c']); 19 | 20 | const myFish = ['angel', 'clown', 'mandarin', 'sturgeon']; 21 | expect(arrRm(myFish, 2, Infinity)).toEqual(['angel', 'clown']); 22 | }); 23 | }); 24 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/sum.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Calculates the `sum` of values in the given array. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { sum } from '@opentf/std'; 9 | 10 | sum( 11 | arr: number[] = [], 12 | cb?: (val: number, index: number) => number 13 | ): number 14 | ``` 15 | 16 | ## Examples 17 | 18 | ```ts 19 | sum() //=> 0 20 | 21 | sum([]) //=> 0 22 | 23 | sum([1]) //=> 1 24 | 25 | sum([1, -1]) //=> 0 26 | 27 | sum([-1, -2]) //=> -3 28 | 29 | sum([1, 2, 3, 4, 5]) //=> 15 30 | 31 | sum([1.2, Math.PI]) //=> 4.34 32 | 33 | sum([1, 2, 3, 4, 5.4], Math.round) //=> 15 34 | 35 | const objects = [{ n: 4 }, { n: 2 }, { n: 8 }, { n: 6 }]; 36 | sum(objects, (v) => v.n) //=> 20 37 | 38 | sum(objects, (v, i) => v.n * i) //=> 36 39 | 40 | sum([Infinity, Infinity]) //=> Infinity 41 | 42 | ``` 43 | 44 | ## Try 45 | 46 | -------------------------------------------------------------------------------- /packages/std/src/array/take.ts: -------------------------------------------------------------------------------- 1 | import isFn from '../types/isFn'; 2 | import isNull from '../types/isNull'; 3 | 4 | /** 5 | * Slices the given array from the start to the given limit. 6 | * 7 | * @example 8 | * take([1, 2, 3, 4, 5], 3) //=> [1, 2, 3] 9 | */ 10 | export default function take( 11 | arr: T[], 12 | limit: number | null = 1, 13 | cb?: (val: T) => boolean 14 | ): Partial { 15 | if (!isNull(limit) && (!Number.isInteger(limit) || limit < 0)) { 16 | throw RangeError('The limit must be positive'); 17 | } 18 | 19 | const curLimit = isNull(limit) ? arr.length : limit; 20 | 21 | const a = []; 22 | 23 | for (let i = 0; i < arr.length; i++) { 24 | const val = arr[i]; 25 | 26 | if (a.length === curLimit) { 27 | break; 28 | } 29 | 30 | if (isFn(cb)) { 31 | if (cb(val)) { 32 | a.push(val); 33 | } 34 | continue; 35 | } 36 | 37 | a.push(val); 38 | } 39 | 40 | return a; 41 | } 42 | -------------------------------------------------------------------------------- /packages/std/src/object/has.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import isPureObj from '../types/isPureObj'; 3 | import { IterableObj } from './merge'; 4 | import toPath from './toPath'; 5 | 6 | /** 7 | * Checks if the given path exists in the given object. 8 | * 9 | * @example 10 | * has({a: 1}, 'a') //=> true 11 | * has({a: {b: 2}}, ['a', 'b']) //=> true 12 | * has({a: {b: 2}}, ['a', 'b', 'c']) //=> false 13 | */ 14 | export default function has(obj: object, path: string | unknown[]): boolean { 15 | const pathArr = toPath(path); 16 | 17 | if (isEmpty(pathArr)) { 18 | return false; 19 | } 20 | 21 | let curObj = obj; 22 | for (const prop of pathArr) { 23 | if (!isPureObj(curObj)) { 24 | return false; 25 | } 26 | 27 | if (!Object.hasOwn(curObj, prop as PropertyKey)) { 28 | return false; 29 | } 30 | 31 | curObj = (curObj as IterableObj)[prop as PropertyKey] as object; 32 | } 33 | 34 | return true; 35 | } 36 | -------------------------------------------------------------------------------- /packages/std/src/object/toPath.ts: -------------------------------------------------------------------------------- 1 | import compact from '../array/compact'; 2 | import isArr from '../types/isArr'; 3 | import isNum from '../types/isNum'; 4 | import isStr from '../types/isStr'; 5 | import isSym from '../types/isSym'; 6 | 7 | /** 8 | * Converts the given value into an object property path array. 9 | * 10 | * @example 11 | * toPath('a.b.c') //=> ['a', 'b', 'c'] 12 | */ 13 | export default function toPath(val: string | unknown | unknown[]): unknown[] { 14 | if (isStr(val)) { 15 | const res = []; 16 | const regex = /\[(\d+)\]|\[(-?\d+\.?\d+)\]|([^.[\]]+)/g; 17 | const matches = val.matchAll(regex); 18 | for (const m of matches) { 19 | res.push(compact(m)[1]); 20 | } 21 | 22 | return res; 23 | } 24 | 25 | if (isArr(val)) { 26 | return [...val]; 27 | } 28 | 29 | if (isSym(val)) { 30 | return [val]; 31 | } 32 | 33 | if (isNum(val)) { 34 | return [String(val)]; 35 | } 36 | 37 | return []; 38 | } 39 | -------------------------------------------------------------------------------- /packages/std/src/string/strReplace.ts: -------------------------------------------------------------------------------- 1 | import shallowMerge from '../object/shallowMerge'; 2 | 3 | export type StrReplaceOptions = { all?: boolean; case?: boolean }; 4 | 5 | /** 6 | * Returns a new string with one, some, or all matches of a pattern replaced by a replacement. 7 | * 8 | * @example 9 | * const a = { a: { b: 1 } }; 10 | * const b = { a: { c: 2 } }; 11 | * merge(a, b); //=> {a: { b: 1, c: 2 } } 12 | */ 13 | export default function strReplace( 14 | str: string, 15 | pattern: string | RegExp, 16 | replacement: string, 17 | options?: StrReplaceOptions 18 | ): string { 19 | const defaultOptions: StrReplaceOptions = { all: false, case: false }; 20 | const opts = shallowMerge( 21 | defaultOptions, 22 | options as object 23 | ) as StrReplaceOptions; 24 | let flags = ''; 25 | flags = opts.all ? flags + 'g' : flags; 26 | flags = opts.case ? flags + 'i' : flags; 27 | 28 | return str.replace(new RegExp(pattern, flags), replacement); 29 | } 30 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/compact.spec.ts: -------------------------------------------------------------------------------- 1 | import { compact } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('compact', () => { 5 | expect(compact()).toEqual([]); 6 | expect(compact([])).toEqual([]); 7 | expect(compact([undefined])).toEqual([]); 8 | expect(compact([undefined, null])).toEqual([]); 9 | expect(compact([undefined, null, 0])).toEqual([]); 10 | expect(compact([undefined, null, 0, 1])).toEqual([1]); 11 | expect(compact([undefined, null, 0, 1, -0, 2])).toEqual([1, 2]); 12 | expect(compact([undefined, null, 0, 1, -0, 2, false, 3])).toEqual([ 13 | 1, 2, 3, 14 | ]); 15 | expect( 16 | compact([undefined, null, 0, 1, -0, 2, false, 3, true, NaN]) 17 | ).toEqual([1, 2, 3, true]); 18 | expect(compact(['apple', '', 'Mango'])).toEqual(['apple', 'Mango']); 19 | expect(compact(['apple', '', 'Mango', ' '])).toEqual([ 20 | 'apple', 21 | 'Mango', 22 | ' ', 23 | ]); 24 | }); 25 | }); 26 | -------------------------------------------------------------------------------- /packages/std/src/object/size.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | import isArrBuf from '../types/isArrBuf'; 3 | import isDataView from '../types/isDataView'; 4 | import isMap from '../types/isMap'; 5 | import isObj from '../types/isObj'; 6 | import isSet from '../types/isSet'; 7 | import isStr from '../types/isStr'; 8 | import isTypedArr from '../types/isTypedArr'; 9 | 10 | /** 11 | * Returns the size of the given value. 12 | * 13 | * @example 14 | * 15 | * size([]) //=> 0 16 | * 17 | * size('a') //=> 1 18 | * 19 | * size({a: 1, b: 3}) //=> 2 20 | */ 21 | export default function size(val: unknown): number { 22 | if (isArr(val) || isStr(val) || isTypedArr(val)) { 23 | return val.length; 24 | } 25 | 26 | if (isObj(val)) { 27 | return Object.keys(val).length; 28 | } 29 | 30 | if (isMap(val) || isSet(val)) { 31 | return val.size; 32 | } 33 | 34 | if (isArrBuf(val) || isDataView(val)) { 35 | return val.byteLength; 36 | } 37 | 38 | return -1; 39 | } 40 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isAsyFn.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is an [AsyncFunction](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/AsyncFunction). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isAsyFn } from '@opentf/std'; 9 | 10 | isAsyFn( 11 | val: unknown 12 | ): boolean 13 | ``` 14 | 15 | ## Examples 16 | 17 | ```ts 18 | isAsyFn(function() {}) //=> false 19 | 20 | isAsyFn({}) //=> false 21 | 22 | function* generator(i) { 23 | yield i; 24 | yield i + 10; 25 | } 26 | 27 | isAsyFn(generator); //=> false 28 | 29 | const afn = async () => {} 30 | isAsyFn(afn) //=> true 31 | 32 | async function getUsers() {} 33 | isAsyFn(getUsers) //=> true 34 | 35 | async function* aGen(i) { 36 | yield i; 37 | yield i + 10; 38 | } 39 | 40 | isAsyFn(aGen); //=> true 41 | ``` 42 | 43 | ## Try 44 | 45 | -------------------------------------------------------------------------------- /packages/std/src/array/intersection.ts: -------------------------------------------------------------------------------- 1 | import isEql from '../assert/isEql'; 2 | import isFn from '../types/isFn'; 3 | import uniq from './uniq'; 4 | 5 | /** 6 | * Returns a unique array of values only containing elements from each of the collections. 7 | * 8 | * @example 9 | * 10 | * const setA = [1, 2, 3, 4]; 11 | * const setB = [3, 5]; 12 | * intersection(setA, setB) //=> [3] 13 | */ 14 | export default function intersection( 15 | collections: unknown[][] = [], 16 | by?: (val: unknown) => unknown 17 | ): unknown[] { 18 | const byFlag = isFn(by); 19 | const out = collections.reduce((acc, cur) => { 20 | const _intersection = []; 21 | for (const val of acc) { 22 | for (const val2 of cur) { 23 | const v1 = byFlag ? by(val) : val; 24 | const v2 = byFlag ? by(val2) : val2; 25 | if (isEql(v1, v2)) { 26 | _intersection.push(val); 27 | } 28 | } 29 | } 30 | return _intersection; 31 | }); 32 | 33 | return uniq(out); 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs/pages/Object/omit.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Removes all the property paths from the given object for the given list of paths. 5 | 6 | 7 | The source object can `Plain Object` or `Array`. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { omit } from '@opentf/std'; 14 | 15 | omit(obj: object, ...paths: (string | unknown[])[]) 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | omit({ a: 1, b: 2 }, 'a') //=> { b: 2 } 22 | 23 | omit({ a: 1, b: 2 }, ['a']) //=> { b: 2 } 24 | 25 | omit([1, 2, 3], '1') //=> [1, 3] 26 | 27 | omit([1, 2, 3], 2) //=> [1, 2] 28 | 29 | omit({ a: 1, b: 2, c: 3, d: 4 }, 'b', 'd') 30 | //=> { 31 | // a: 1, 32 | // c: 3, 33 | // } 34 | 35 | obj = { a: { b: [1, 3, 5] } }; 36 | omit(obj, 'a.b[2]') //=> { a: { b: [1, 3] } }); 37 | ``` 38 | ## Try 39 | 40 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/mean.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Calculates the `mean` value of the given array. 5 | 6 | 7 | Mean: The "average" number; found by adding all data points and dividing by the number of data points. 8 |
9 | \- [Khan Academy](https://www.khanacademy.org/math/statistics-probability/summarizing-quantitative-data/mean-median-basics/a/mean-median-and-mode-review) 10 |
11 |
12 | 13 | ## Syntax 14 | 15 | ```ts 16 | import { mean } from '@opentf/std'; 17 | 18 | mean( 19 | arr: number[] = [], 20 | cb?: (v: number, index: number) => number 21 | ): number 22 | ``` 23 | 24 | ## Examples 25 | 26 | ```ts 27 | mean([]) //=> NaN 28 | 29 | mean([1]) //=> 1 30 | 31 | mean([4, 1, 7]) //=> 4 32 | 33 | mean([4, 2, 8]) //=> 4.67 34 | ``` 35 | 36 | ## Try 37 | 38 | -------------------------------------------------------------------------------- /packages/std/src/array/sortBy.ts: -------------------------------------------------------------------------------- 1 | import isStr from '../types/isStr'; 2 | import { OrderType } from './sort'; 3 | 4 | export type SortCB = (val: T) => number | string | boolean | Date; 5 | export type OrderTuples = [keyof T | SortCB, OrderType][]; 6 | 7 | /** 8 | * Sorts a list of objects and returns a new array. 9 | * 10 | * @example 11 | * 12 | * const arr = [{a: 1}, {a: 3}, {a: 2}] 13 | * sortBy(arr, ['a', 'asc']); //=> [{a: 1}, {a: 2}, {a: 3}] 14 | */ 15 | export default function sortBy(arr: T[], ...tuples: OrderTuples): T[] { 16 | return [...arr].sort((a: T, b: T) => { 17 | for (let i = 0; i < tuples.length; i++) { 18 | const [key, order] = tuples[i]; 19 | const x = isStr(key) ? a[key] : (key as SortCB)(a); 20 | const y = isStr(key) ? b[key] : (key as SortCB)(b); 21 | 22 | if (x !== y) { 23 | const val = x < y ? -1 : 1; 24 | 25 | return order === 'asc' ? val : -val; 26 | } 27 | } 28 | 29 | return 0; 30 | }); 31 | } 32 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/swap.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Swaps two elements in an array. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { swap } from '@opentf/std'; 14 | 15 | swap(arr: T[], x: number, y: number): T[] 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | swap([], 0, 0) //=> [] 22 | 23 | swap([], 0, 1) //=> [] 24 | 25 | swap([0], 0, 1) //=> [undefined, 0] 26 | 27 | swap([1, 2, 3], 1, 2) //=> [1, 3, 2] 28 | 29 | swap([1, 2, 3], 1, 5) //=> [1, undefined, 3, , , 2] 30 | 31 | const arr = [{ a: 1 }, { b: 'a' }, { c: [5] }]; 32 | swap(arr, 0, 2) 33 | //=> [ 34 | // { 35 | // c: [5], 36 | // }, 37 | // { 38 | // b: 'a', 39 | // }, 40 | // { 41 | // a: 1, 42 | // }, 43 | // ] 44 | ``` 45 | 46 | ## Try 47 | 48 | 52 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/swap.spec.ts: -------------------------------------------------------------------------------- 1 | import { swap } from '../../src'; 2 | 3 | describe('Array > swap', () => { 4 | test('empty array', () => { 5 | expect(swap([], 0, 0)).toEqual([]); 6 | }); 7 | 8 | test('immutable', () => { 9 | const arr = [1, 2, 3]; 10 | expect(swap(arr, 1, 2)).toEqual([1, 3, 2]); 11 | expect(arr).toEqual([1, 2, 3]); 12 | }); 13 | 14 | test('swap 0 index to 1', () => { 15 | expect(swap([], 0, 1)).toEqual([]); 16 | expect(swap([0], 0, 1)).toEqual([undefined, 0]); 17 | expect(swap([0, 1], 0, 1)).toEqual([1, 0]); 18 | }); 19 | 20 | test('swap index > length', () => { 21 | expect(swap([1, 2, 3], 1, 5)).toEqual([1, undefined, 3, , , 2]); 22 | }); 23 | 24 | test('array of objects', () => { 25 | const arr = [{ a: 1 }, { b: 'a' }, { c: [5] }]; 26 | expect(swap(arr, 0, 2)).toEqual([ 27 | { 28 | c: [5], 29 | }, 30 | { 31 | b: 'a', 32 | }, 33 | { 34 | a: 1, 35 | }, 36 | ]); 37 | }); 38 | }); 39 | -------------------------------------------------------------------------------- /apps/docs/pages/Colors/hexToRGB.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > It converts hexadecimal color values into RGB color values. 5 | 6 | 7 | It does not work with shorthand form & alpha param. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { hexToRGB } from '@opentf/std'; 14 | 15 | hexToRGB(hex: string): number[]; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | hexToRGB("#000000"); //=> [0, 0, 0] 22 | 23 | hexToRGB("#FFFFFF"); //=> [255, 255, 255] 24 | 25 | hexToRGB("#ffffff"); //=> [255, 255, 255] 26 | 27 | hexToRGB("#FF0000"); //=> [255, 0, 0] 28 | 29 | hexToRGB("#00FF00"); //=> [0, 255, 0] 30 | 31 | hexToRGB("#0000FF"); //=> [0, 0, 255] 32 | 33 | hexToRGB("#AAAAAA"); //=> [170, 170, 170] 34 | 35 | hexToRGB("#DDDDDD"); //=> [221, 221, 221] 36 | 37 | hexToRGB("#ff851b"); //=> [255, 133, 27] 38 | ``` 39 | 40 | ## Try 41 | 42 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/arrIns.spec.ts: -------------------------------------------------------------------------------- 1 | import { arrIns } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('arrIns', () => { 5 | expect(arrIns()).toEqual([]); 6 | expect(arrIns([])).toEqual([]); 7 | expect(arrIns([1])).toEqual([1]); 8 | expect(arrIns([1], 0)).toEqual([1]); 9 | expect(arrIns([1], 0, 0)).toEqual([0, 1]); 10 | expect(arrIns([1], 1, 0)).toEqual([1, 0]); 11 | expect(arrIns([1, 2, 3], 1, 5)).toEqual([1, 5, 2, 3]); 12 | expect(arrIns([1, 2, 3], -1, 5)).toEqual([1, 2, 5, 3]); 13 | expect(arrIns([1, 2, 3], -3, 5)).toEqual([5, 1, 2, 3]); 14 | expect(arrIns([1, 2, 3], 3, 5)).toEqual([1, 2, 3, 5]); 15 | expect(arrIns([1, 2, 3], 3, 5, 6)).toEqual([1, 2, 3, 5, 6]); 16 | expect(arrIns([1, 2, 3], null, 5, 6)).toEqual([1, 2, 3, 5, 6]); 17 | expect(arrIns([1, 2, 3], undefined, 5, 6)).toEqual([1, 2, 3, 5, 6]); 18 | expect(arrIns([1, 2, 3], 0, [5, 6])).toEqual([[5, 6], 1, 2, 3]); 19 | expect(arrIns([1, 2, 3], 0, ...[5, 6])).toEqual([5, 6, 1, 2, 3]); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /apps/docs/pages/Assert/isEqlArr.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Checks deeply if the given two arrays with different orders are equivalent. 5 | 6 | 7 | It performs comparisons using [isEql](/Assert/isEql) function. 8 | 9 | 10 | 11 | It also supports comparing [Sparse](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Indexed_collections#sparse_arrays) arrays. 12 | 13 | 14 | **Related** 15 | - [isEql](/Assert/isEql) 16 | 17 | - [isShallowEql](/Assert/isShallowEql) 18 | 19 | ## Syntax 20 | 21 | ```ts 22 | import { isEqlArr } from '@opentf/std'; 23 | 24 | isEqlArr(arr1: unknown[], arr2: unknown[]): Boolean; 25 | ``` 26 | 27 | ## Examples 28 | 29 | ```ts 30 | isEqlArr([1, 3, 2], [2, 1, 3]) //=> true 31 | 32 | isEqlArr([1, 3, 2], [2, 1, 5]) //=> false 33 | ``` 34 | 35 | ## Try 36 | 37 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/move.spec.ts: -------------------------------------------------------------------------------- 1 | import { move } from '../../src'; 2 | 3 | describe('Array > move', () => { 4 | test('empty array', () => { 5 | expect(move([], 0, 1)).toEqual([]); 6 | }); 7 | 8 | it('returns same ref', () => { 9 | const arr = [1, 5, 8]; 10 | expect(move(arr, 0, 0)).toBe(arr); 11 | }); 12 | 13 | it('returns new ref', () => { 14 | const arr = [1, 5, 8]; 15 | expect(move(arr, 0, 1)).not.toBe(arr); 16 | }); 17 | 18 | it('moves within range', () => { 19 | expect(move([1, 2, 3], 0, 2)).toEqual([2, 3, 1]); 20 | }); 21 | 22 | it('moves the element to the last index if to > length', () => { 23 | expect(move([1, 2, 3], 0, 5)).toEqual([2, 3, 1]); 24 | }); 25 | 26 | it('does not move the element', () => { 27 | expect(move([1, 2, 3], 5, 0)).toEqual([1, 2, 3]); 28 | }); 29 | 30 | test('negative index', () => { 31 | expect(move([1, 2, 3, 4, 5], 0, -1)).toEqual([2, 3, 4, 1, 5]); 32 | expect(move([1, 2, 3, 4, 5], -1, 2)).toEqual([1, 2, 5, 3, 4]); 33 | }); 34 | }); 35 | -------------------------------------------------------------------------------- /packages/std/src/object/unset.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import isArr from '../types/isArr'; 3 | import isObj from '../types/isObj'; 4 | import { IterableObj } from './merge'; 5 | import toPath from './toPath'; 6 | 7 | /** 8 | * Removes the property of the given object at the given path. 9 | * 10 | * @example 11 | * 12 | * unset({a: 1, b: 2}}, 'a') //=> true 13 | */ 14 | export default function unset(obj: T, path: string | unknown[]): T { 15 | const pathArr = toPath(path); 16 | let curObj: IterableObj = obj as IterableObj; 17 | 18 | if (isEmpty(pathArr) || !(isObj(obj) || isArr(obj))) { 19 | return obj; 20 | } 21 | 22 | for (let i = 0; i < pathArr.length; i++) { 23 | const prop = pathArr[i] as PropertyKey; 24 | 25 | if (i === pathArr.length - 1) { 26 | delete curObj[prop]; 27 | break; 28 | } 29 | 30 | curObj = curObj[prop] as IterableObj; 31 | 32 | if (!(isObj(curObj) || isArr(curObj))) { 33 | return obj; 34 | } 35 | } 36 | 37 | return obj as T; 38 | } 39 | -------------------------------------------------------------------------------- /packages/std/src/array/diff.ts: -------------------------------------------------------------------------------- 1 | import isEql from '../assert/isEql'; 2 | import isFn from '../types/isFn'; 3 | 4 | /** 5 | * It creates an array with the values of first, not included in the other arrays. 6 | * 7 | * @example 8 | * 9 | * diff([[1, "a"], [1, 2]]); // ['a'] 10 | */ 11 | export default function diff( 12 | collections: unknown[][] = [], 13 | by?: (val: unknown) => unknown 14 | ): unknown[] { 15 | const byFlag = isFn(by); 16 | 17 | return collections.slice(1).reduce( 18 | (acc, cur) => { 19 | const removeIdxs: number[] = []; 20 | for (const curVal of cur) { 21 | let idx = 0; 22 | for (const accVal of acc) { 23 | const v1 = byFlag ? by(curVal) : curVal; 24 | const v2 = byFlag ? by(accVal) : accVal; 25 | if (isEql(v1, v2)) { 26 | removeIdxs.push(idx); 27 | } 28 | 29 | idx += 1; 30 | } 31 | } 32 | 33 | return acc.filter((_item, i) => !removeIdxs.includes(i)); 34 | }, 35 | [...(collections[0] || [])] 36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /packages/std/src/object/mergeAll.ts: -------------------------------------------------------------------------------- 1 | import isArr from '../types/isArr'; 2 | import isObj from '../types/isObj'; 3 | 4 | type IterableObj = { 5 | [key: number | string]: unknown; 6 | }; 7 | 8 | /** 9 | * It deeply merges objects and concatenates the arrays if any present. 10 | * 11 | * @example 12 | * const a = { a: [1, 2], b: 0 }; 13 | * const b = { a: [3, 4], b: 5 }; 14 | * mergeAll(a, b) //=> {a: [1, 2, 3, 4], b: 5} 15 | */ 16 | export default function mergeAll(...objs: object[]): object { 17 | const filteredObjs = objs.filter((v) => isArr(v) || isObj(v)); 18 | const initialVal = isArr(filteredObjs[0]) ? [] : {}; 19 | 20 | return filteredObjs.reduce((acc: IterableObj, cur) => { 21 | if (isArr(cur) && isArr(acc)) { 22 | return [...acc, ...cur]; 23 | } 24 | 25 | for (const [key, val] of Object.entries(cur)) { 26 | if (isArr(val) || isObj(val)) { 27 | acc[key] = mergeAll(acc[key] as object, val); 28 | } else { 29 | acc[key] = val; 30 | } 31 | } 32 | return acc; 33 | }, initialVal); 34 | } 35 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isGenFn.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks if the given value is a [Generator Function](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/function*). 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isGenFn } from '@opentf/std'; 9 | 10 | isGenFn( 11 | val: unknown 12 | ): boolean 13 | ``` 14 | 15 | ## Examples 16 | 17 | ```ts 18 | isGenFn(function() {}) //=> false 19 | 20 | isGenFn({}) //=> false 21 | 22 | function* generator(i) { 23 | yield i; 24 | yield i + 10; 25 | } 26 | 27 | isGenFn(generator); //=> true 28 | 29 | async function* aGen(i) { 30 | yield i; 31 | yield i + 10; 32 | } 33 | 34 | isGenFn(aGen); //=> true 35 | 36 | const someObj = { 37 | *generator() { 38 | yield "a"; 39 | yield "b"; 40 | }, 41 | }; 42 | 43 | isGenFn(someObj.generator); //=> true 44 | ``` 45 | 46 | ## Try 47 | 48 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isPromise.spec.ts: -------------------------------------------------------------------------------- 1 | import { isPromise } from '../../src'; 2 | 3 | describe('Types > isPromise', () => { 4 | test('invalid cases', () => { 5 | expect(isPromise()).toBe(false); 6 | expect(isPromise(undefined)).toBe(false); 7 | expect(isPromise(null)).toBe(false); 8 | expect(isPromise(false)).toBe(false); 9 | expect(isPromise('')).toBe(false); 10 | expect(isPromise('then')).toBe(false); 11 | expect(isPromise(0)).toBe(false); 12 | expect(isPromise(1)).toBe(false); 13 | expect(isPromise({})).toBe(false); 14 | expect(isPromise({ then: true })).toBe(false); 15 | expect(isPromise([])).toBe(false); 16 | expect(isPromise(['then'])).toBe(false); 17 | }); 18 | 19 | test('valid cases', () => { 20 | expect(isPromise(Promise.resolve())).toBe(true); 21 | expect(isPromise(Promise.all([]))).toBe(true); 22 | expect(isPromise(Promise.race([]))).toBe(true); 23 | expect(isPromise(Promise.allSettled([]))).toBe(true); 24 | expect(isPromise({ then: function () {} })).toBe(true); 25 | }); 26 | }); 27 | -------------------------------------------------------------------------------- /packages/std/src/array/union.ts: -------------------------------------------------------------------------------- 1 | import isEql from '../assert/isEql'; 2 | import isFun from '../types/isFn'; 3 | import uniq from './uniq'; 4 | 5 | /** 6 | * Returns unique values in all the given collections. 7 | * 8 | * @example 9 | * 10 | * const setA = new Set([1, 2, 3, 4]); 11 | * const setB = new Set([2, 3, 5]); 12 | * const setC = new Set([2, 5, 3]); 13 | * union(setA, setB, setC) //=> [1, 2, 3, 4, 5] 14 | */ 15 | export default function union( 16 | collections: unknown[][] = [], 17 | by?: (val: unknown) => unknown 18 | ): unknown[] { 19 | const byFlag = isFun(by); 20 | const out = collections.reduce((acc, cur) => { 21 | for (const val of cur) { 22 | let flag = false; 23 | for (const val2 of acc) { 24 | const v1 = byFlag ? by(val) : val; 25 | const v2 = byFlag ? by(val2) : val2; 26 | if (isEql(v1, v2)) { 27 | flag = true; 28 | } 29 | } 30 | if (!flag) { 31 | acc.push(val); 32 | } 33 | } 34 | 35 | return acc; 36 | }, []); 37 | 38 | return uniq(out); 39 | } 40 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/pipeFn.spec.js: -------------------------------------------------------------------------------- 1 | import { pipeFn } from '../../src'; 2 | 3 | describe('Function > pipeFn', () => { 4 | test('empty pipe', () => { 5 | const fn = pipeFn(); 6 | expect(typeof fn).toBe('function'); 7 | expect(fn()).toBe(undefined); 8 | }); 9 | 10 | test('single args pipe fn with single function', () => { 11 | const fn = pipeFn(Math.abs); 12 | expect(typeof fn).toBe('function'); 13 | expect(fn(-5)).toBe(5); 14 | }); 15 | 16 | test('two args pipe fn with single function', () => { 17 | const fn = pipeFn(Math.pow); 18 | expect(typeof fn).toBe('function'); 19 | expect(fn(2, 3)).toBe(8); 20 | }); 21 | 22 | test('multiple args pipe fn with single function', () => { 23 | const fn = pipeFn(Math.max); 24 | expect(typeof fn).toBe('function'); 25 | expect(fn(2, 3, 5)).toBe(5); 26 | }); 27 | 28 | test('single args pipe fn with two functions', () => { 29 | const fn = pipeFn(Math.abs, Math.ceil); 30 | expect(typeof fn).toBe('function'); 31 | expect(fn(-1.235)).toBe(2); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /apps/docs/pages/Colors/rgbToHex.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Convert RGB colors into hexadecimal color values. 5 | 6 | 7 | It does not work with shorthand form & alpha param. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { rgbToHex } from '@opentf/std'; 14 | 15 | rgbToHex(rgb: [number, number, number]): string; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | rgbToHex([0, 0, 0]) //=> '#000000' 22 | 23 | rgbToHex([1, 1, 1]) //=> '#010101' 24 | 25 | rgbToHex([255, 255, 255]) //=> '#FFFFFF' 26 | 27 | rgbToHex([255, 255, 255]) //=> '#ffffff' 28 | 29 | rgbToHex([255, 0, 0]) //=> '#FF0000' 30 | 31 | rgbToHex([0, 255, 0]) //=> '#00FF00' 32 | 33 | rgbToHex([0, 0, 255]) //=> '#0000FF' 34 | 35 | rgbToHex([170, 170, 170]) //=> '#AAAAAA' 36 | 37 | rgbToHex([221, 221, 221]) //=> '#DDDDDD' 38 | 39 | rgbToHex([255, 133, 27]) //=> '#ff851b' 40 | ``` 41 | 42 | ## Try 43 | 44 | -------------------------------------------------------------------------------- /packages/std/src/array/drop.ts: -------------------------------------------------------------------------------- 1 | import isFn from '../types/isFn'; 2 | import isNull from '../types/isNull'; 3 | 4 | /** 5 | * Skips the given number of elements at the start of the given array. 6 | * 7 | * @example 8 | * drop([1, 2, 3, 4, 5], 3) //=> [4, 5] 9 | */ 10 | export default function drop( 11 | arr: T[], 12 | limit: number | null = 1, 13 | cb?: (val: T) => boolean 14 | ): Partial { 15 | if (!isNull(limit) && (!Number.isInteger(limit) || limit < 0)) { 16 | throw RangeError('The limit must be positive'); 17 | } 18 | 19 | const curLimit = isNull(limit) ? arr.length : limit; 20 | 21 | const a = []; 22 | let skipCount = 0; 23 | 24 | for (let i = 0; i < arr.length; i++) { 25 | const val = arr[i]; 26 | if (skipCount < curLimit) { 27 | if (isFn(cb)) { 28 | if (cb(val)) { 29 | skipCount += 1; 30 | } else { 31 | a.push(val); 32 | } 33 | continue; 34 | } 35 | 36 | skipCount += 1; 37 | continue; 38 | } 39 | 40 | a.push(val); 41 | } 42 | 43 | return a; 44 | } 45 | -------------------------------------------------------------------------------- /packages/std/__tests__/types/isJSON.spec.ts: -------------------------------------------------------------------------------- 1 | import { isJSON } from '../../src'; 2 | 3 | describe('Types > isJSON', () => { 4 | test('invalid cases', () => { 5 | expect(isJSON()).toBeFalsy(); 6 | expect(isJSON('')).toBeFalsy(); 7 | expect(isJSON('undefined')).toBeFalsy(); 8 | expect(isJSON('null')).toBeFalsy(); 9 | expect(isJSON('true')).toBeFalsy(); 10 | expect(isJSON('false')).toBeFalsy(); 11 | expect(isJSON('1')).toBeFalsy(); 12 | expect(isJSON('12345')).toBeFalsy(); 13 | expect(isJSON('abc')).toBeFalsy(); 14 | expect(isJSON('{a}')).toBeFalsy(); 15 | expect(isJSON('{a:}')).toBeFalsy(); 16 | expect(isJSON('{a:1}')).toBeFalsy(); 17 | expect(isJSON('{"a": undefined}')).toBeFalsy(); 18 | expect(isJSON('[]')).toBeFalsy(); 19 | }); 20 | 21 | test('valid cases', () => { 22 | expect(isJSON('{}')).toBeTruthy(); 23 | expect(isJSON('{"a":1}')).toBeTruthy(); 24 | expect( 25 | isJSON( 26 | '{"a": "abc", "b": true, "c": false, "d": [{"e": 1}, null, 5.0], "f": {}}' 27 | ) 28 | ).toBeTruthy(); 29 | }); 30 | }); 31 | -------------------------------------------------------------------------------- /apps/docs/pages/String/replaceAt.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Replace a character or string at the index position. 5 | 6 | ## Syntax 7 | 8 | ```ts 9 | import { replaceAt } from '@opentf/std'; 10 | 11 | replaceAt(str: string, index?: number, replaceStr?: string): string; 12 | ``` 13 | 14 | 15 | Default index = 0 16 | 17 | 18 | ## Examples 19 | 20 | ```ts 21 | replaceAt(); // Throws error 22 | 23 | replaceAt(""); //=> '' 24 | 25 | replaceAt("", 0); //=> '' 26 | 27 | replaceAt("", 0, "a"); //=> 'a' 28 | 29 | replaceAt("", 1, "abc"); //=> 'abc' 30 | 31 | replaceAt("a"); //=> '' 32 | 33 | replaceAt("abc"); //=> 'bc' 34 | 35 | replaceAt("abc", 1); //=> 'ac' 36 | 37 | replaceAt("abc", 5); //=> 'abc' 38 | 39 | replaceAt("abc", 1, ""); //=> 'ac' 40 | 41 | replaceAt("abc", 0, "z"); //=> 'zbc' 42 | 43 | replaceAt("iphone", 1, "P"); //=> 'iPhone' 44 | ``` 45 | 46 | ## Try 47 | 48 | -------------------------------------------------------------------------------- /packages/std/src/types/isTypedArr.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * Checks if the given value is a TypedArray. 3 | * 4 | * @example 5 | * 6 | * isTypedArr([]) //=> false 7 | * 8 | * isTypedArr(new Int8Array()) //=> true 9 | * 10 | * isTypedArr(new Float64Array()) //=> true 11 | */ 12 | 13 | export type TypedArray = 14 | | Int8Array 15 | | Uint8Array 16 | | Uint8ClampedArray 17 | | Int16Array 18 | | Uint16Array 19 | | Int32Array 20 | | Uint32Array 21 | | Float32Array 22 | | Float64Array 23 | | BigInt64Array 24 | | BigUint64Array; 25 | 26 | export default function isTypedArr(val: unknown): val is TypedArray { 27 | const typedArrClasses = [ 28 | '[object Int8Array]', 29 | '[object Uint8Array]', 30 | '[object Uint8ClampedArray]', 31 | '[object Int16Array]', 32 | '[object Uint16Array]', 33 | '[object Int32Array]', 34 | '[object Uint32Array]', 35 | '[object Float32Array]', 36 | '[object Float64Array]', 37 | '[object BigInt64Array]', 38 | '[object BigUint64Array]', 39 | ]; 40 | 41 | return typedArrClasses.includes(Object.prototype.toString.call(val)); 42 | } 43 | -------------------------------------------------------------------------------- /packages/std/__tests__/function/composeFn.spec.js: -------------------------------------------------------------------------------- 1 | import { composeFn } from '../../src'; 2 | 3 | describe('Function > composeFn', () => { 4 | test('empty compose', () => { 5 | const fn = composeFn(); 6 | expect(typeof fn).toBe('function'); 7 | expect(fn()).toBe(undefined); 8 | }); 9 | 10 | test('single args compose fn with single function', () => { 11 | const fn = composeFn(Math.abs); 12 | expect(typeof fn).toBe('function'); 13 | expect(fn(-5)).toBe(5); 14 | }); 15 | 16 | test('two args compose fn with single function', () => { 17 | const fn = composeFn(Math.pow); 18 | expect(typeof fn).toBe('function'); 19 | expect(fn(2, 3)).toBe(8); 20 | }); 21 | 22 | test('multiple args compose fn with single function', () => { 23 | const fn = composeFn(Math.max); 24 | expect(typeof fn).toBe('function'); 25 | expect(fn(2, 3, 5)).toBe(5); 26 | }); 27 | 28 | test('single args compose fn with two functions', () => { 29 | const fn = composeFn(Math.abs, Math.ceil); 30 | expect(typeof fn).toBe('function'); 31 | expect(fn(-1.235)).toBe(1); 32 | }); 33 | }); 34 | -------------------------------------------------------------------------------- /packages/std/__tests__/async/aPipe.spec.js: -------------------------------------------------------------------------------- 1 | import { aPipe, capitalize } from '../../src'; 2 | 3 | describe('Function > Pipe', () => { 4 | test('empty aPipe', async () => { 5 | await expect(aPipe()).resolves.toBe(undefined); 6 | }); 7 | 8 | test('returns passed value if no functions', async () => { 9 | await expect(aPipe(1)).resolves.toBe(1); 10 | }); 11 | 12 | test('single functions', async () => { 13 | await expect(aPipe(-1, Math.abs)).resolves.toBe(1); 14 | }); 15 | 16 | test('two functions', async () => { 17 | await expect( 18 | aPipe( 19 | 'guest', 20 | (s) => capitalize(s), 21 | (x) => new Promise((resolve) => resolve(`Welcome ${x}`)) 22 | ) 23 | ).resolves.toBe('Welcome Guest'); 24 | }); 25 | 26 | test('multiple functions', async () => { 27 | await expect( 28 | aPipe( 29 | 'guest', 30 | (s) => capitalize(s), 31 | (x) => new Promise((resolve) => resolve(`Welcome ${x}`)), 32 | (x) => new Promise((resolve) => resolve(`${x}...`)) 33 | ) 34 | ).resolves.toBe('Welcome Guest...'); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | # This workflow will do a clean install of node dependencies, cache/restore them, build the source code and run tests across different versions of node 2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions 3 | 4 | name: Build 5 | 6 | on: 7 | push: 8 | branches: [ main ] 9 | paths-ignore: 10 | - 'apps/website/**' 11 | pull_request: 12 | branches: [ main ] 13 | 14 | env: 15 | HUSKY: 0 16 | 17 | jobs: 18 | build: 19 | 20 | runs-on: ubuntu-latest 21 | 22 | strategy: 23 | matrix: 24 | node-version: [16.x, 18.x, 20.x] 25 | # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ 26 | 27 | steps: 28 | - uses: actions/checkout@v3 29 | - uses: pnpm/action-setup@v2 30 | with: 31 | version: 8 32 | - name: Use Node.js ${{ matrix.node-version }} 33 | uses: actions/setup-node@v3 34 | with: 35 | node-version: ${{ matrix.node-version }} 36 | cache: 'pnpm' 37 | - run: pnpm install 38 | - run: pnpm run ci -------------------------------------------------------------------------------- /apps/docs/pages/Array/compact.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Removes all the [falsy](https://developer.mozilla.org/en-US/docs/Glossary/Falsy) values in the given array. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts copy 13 | import { compact } from '@opentf/std'; 14 | 15 | compact(arr: T[] = []): Partial; 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | compact([undefined]) //=>[] 22 | 23 | compact([undefined, null]) //=>[] 24 | 25 | compact([undefined, null, 0]) //=>[] 26 | 27 | compact([undefined, null, 0, 1]) //=>[1] 28 | 29 | compact([undefined, null, 0, 1, -0, 2]) //=>[1, 2] 30 | 31 | compact([undefined, null, 0, 1, -0, 2, false, 3]) //=> [1, 2, 3]; 32 | 33 | compact([undefined, null, 0, 1, -0, 2, false, 3, true, NaN]) //=> [1, 2, 3, true] 34 | 35 | compact(['apple', '', 'Mango']) //=>['apple', 'Mango']); 36 | ``` 37 | 38 | ## Try 39 | 40 | 43 | -------------------------------------------------------------------------------- /apps/docs/pages/Async/aMap.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Array map with `Async` callback function. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | aMap( 9 | arr: T[], 10 | cb: (value: T, index: number) => Promise 11 | ): Promise 12 | ``` 13 | 14 | ## Usage 15 | 16 | ```ts 17 | import { aMap } from "@opentf/std"; 18 | 19 | aMap([], async (value, index) => {}); 20 | ``` 21 | 22 | ## Examples 23 | 24 | ```ts 25 | const arr = [1, 2, 3, 4, 5]; 26 | 27 | function multiply(n, i) { 28 | return new Promise((resolve) => { 29 | resolve(n * i); 30 | }); 31 | } 32 | 33 | const result = await aMap(arr, async (n, i) => await multiply(n, i)); 34 | console.log(result); // [0, 2, 6, 12, 20] 35 | ``` 36 | 37 | ## Try 38 | 39 | { 43 | resolve(n * i); 44 | }); 45 | } 46 | 47 | 48 | async function main() { 49 | const arr = [1, 2, 3, 4, 5]; 50 | const result = await aMap(arr, async (n, i) => await multiply(n, i)); 51 | log(result); 52 | } 53 | 54 | main(); 55 | `} /> -------------------------------------------------------------------------------- /packages/std/__tests__/array/arrReplace.spec.ts: -------------------------------------------------------------------------------- 1 | import { arrReplace } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('arrReplace', () => { 5 | expect(arrReplace()).toEqual([]); 6 | expect(arrReplace([])).toEqual([]); 7 | expect(arrReplace([1])).toEqual([1]); 8 | expect(arrReplace([1, 2, 3], null, null, 'a')).toEqual([1, 2, 'a']); 9 | expect(arrReplace([1, 2, 3], 0, null, 'a')).toEqual(['a', 2, 3]); 10 | expect(arrReplace([1, 2, 3], 1, null, 'a', 'b')).toEqual([1, 'a', 'b']); 11 | expect(arrReplace([1, 2, 3], 3, null, 'c')).toEqual([1, 2, 3, 'c']); 12 | expect(arrReplace([1, 2, 3], 5, null, 'c', 'd')).toEqual([ 13 | 1, 14 | 2, 15 | 3, 16 | 'c', 17 | 'd', 18 | ]); 19 | 20 | const months = ['Jan', 'Feb', 'Apr', 'May']; 21 | expect(arrReplace(months, 1, 1, 'Feb', 'Mar')).toEqual([ 22 | 'Jan', 23 | 'Feb', 24 | 'Mar', 25 | 'Apr', 26 | 'May', 27 | ]); 28 | expect(arrReplace(months, 1, null, 'Feb', 'Mar')).toEqual([ 29 | 'Jan', 30 | 'Feb', 31 | 'Mar', 32 | 'May', 33 | ]); 34 | }); 35 | }); 36 | -------------------------------------------------------------------------------- /apps/docs/pages/Async/aFilter.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Array filter with `Async` callback function. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | aFilter( 9 | arr: T[], 10 | cb: (value: T, index: number) => Promise 11 | ): Promise> 12 | ``` 13 | 14 | ## Usage 15 | 16 | ```ts 17 | import { aFilter } from "@opentf/std"; 18 | 19 | aFilter([], async (value, index) => {}); 20 | ``` 21 | 22 | ## Examples 23 | 24 | ```ts 25 | const arr = [1, 2, 3, 4, 5]; 26 | 27 | function isEven(n) { 28 | return new Promise((resolve) => { 29 | resolve(n % 2 === 0); 30 | }); 31 | } 32 | 33 | const filteredArr = await aFilter(arr, async (n) => await isEven(n)); 34 | 35 | console.log(filteredArr); //=> [2, 4] 36 | ``` 37 | 38 | ## Try 39 | 40 | { 44 | resolve(n % 2 === 0); 45 | }); 46 | } 47 | 48 | async function main() { 49 | const arr = [1, 2, 3, 4, 5]; 50 | const out = await aFilter(arr, async (n) => await isEven(n)); 51 | log(out); 52 | } 53 | 54 | main(); 55 | `} /> -------------------------------------------------------------------------------- /apps/docs/pages/Object/get.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Gets the value of an object at the given path. 5 | 6 | 7 | You can provide an optional default value to return if the given path does not exist. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { get } from '@opentf/std'; 14 | 15 | get( 16 | obj: object, 17 | path: string | unknown[], 18 | defVal?: unknown 19 | ): unknown 20 | ``` 21 | 22 | ## Examples 23 | 24 | ```ts 25 | get({}, '') //=> undefined 26 | 27 | get({}, '', undefined) //=> undefined 28 | 29 | get({}, '', null) //=> null 30 | 31 | get({}, 'a') //=> undefined 32 | 33 | get({ a: null }, 'a') //=> null 34 | 35 | get({ a: 1 }, 'a') //=> 1 36 | 37 | get({ user: { email: 'user@example.com' } }, 'user.email'); // 'user@example.com' 38 | 39 | get({ fruits: ['Apple', 'Mango', 'Orange'] }, 'fruits'); // ['Apple', 'Mango', 'Orange'] 40 | 41 | get({ a: [{ b: { c: 99 } }] }, 'a[0].b.c'); // 99 42 | ``` 43 | ## Try 44 | 45 | -------------------------------------------------------------------------------- /packages/std/src/object/set.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import isFn from '../types/isFn'; 3 | import isNum from '../types/isNum'; 4 | import { IterableObj } from './merge'; 5 | import toPath from './toPath'; 6 | 7 | /** 8 | * Sets the value to an object at the given path. 9 | * 10 | * @example 11 | * 12 | * set({}}, 'a.b', 1) //=> {a: {b: 1} } 13 | */ 14 | export default function set( 15 | obj: T, 16 | path: string | unknown[], 17 | value: unknown | ((val: unknown) => unknown) 18 | ): T { 19 | const pathArr = toPath(path); 20 | let curObj: IterableObj = obj as IterableObj; 21 | 22 | if (isEmpty(pathArr)) { 23 | return obj; 24 | } 25 | 26 | for (let i = 0; i < pathArr.length; i++) { 27 | const prop = pathArr[i] as PropertyKey; 28 | 29 | if (i === pathArr.length - 1) { 30 | const v = isFn(value) ? value(curObj[prop]) : value; 31 | curObj[prop] = v; 32 | break; 33 | } 34 | 35 | if (!curObj[prop]) { 36 | curObj[prop] = isNum(pathArr[i + 1], true) ? [] : {}; 37 | } 38 | 39 | curObj = curObj[prop] as IterableObj; 40 | } 41 | 42 | return obj as T; 43 | } 44 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/countBy.spec.ts: -------------------------------------------------------------------------------- 1 | import { countBy } from '../../src'; 2 | 3 | describe('Array', () => { 4 | test('countBy', () => { 5 | expect(countBy([])).toEqual({}); 6 | expect( 7 | countBy([1, 2, 3, 4, 5, 6, 7, 8, 9], (v) => 8 | v % 2 === 0 ? 'Even' : 'Odd' 9 | ) 10 | ).toEqual({ Even: 4, Odd: 5 }); 11 | 12 | expect(countBy(['Apple', 'Mango', 'Orange'], 'length')).toEqual({ 13 | '5': 2, 14 | '6': 1, 15 | }); 16 | 17 | const inventory = [ 18 | { name: 'asparagus', type: 'vegetables', qty: 5 }, 19 | { name: 'bananas', type: 'fruit', qty: 0 }, 20 | { name: 'goat', type: 'meat', qty: 23 }, 21 | { name: 'cherries', type: 'fruit', qty: 5 }, 22 | { name: 'fish', type: 'meat', qty: 22 }, 23 | ]; 24 | expect( 25 | countBy(inventory, ({ qty }) => (qty === 0 ? 'OutOfStock' : 'InStock')) 26 | ).toEqual({ OutOfStock: 1, InStock: 4 }); 27 | 28 | const letters = ['a', 'b', 'A', 'a', 'B', 'c']; 29 | 30 | expect(countBy(letters, (l) => l.toLowerCase())).toEqual({ 31 | a: 3, 32 | b: 2, 33 | c: 1, 34 | }); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /apps/docs/pages/Async/aResolvers.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Creates a promise with custom resolvers for `resolve` and `reject`. 5 | 6 | 7 | This is same as the new static method `Promise.withResolvers()`. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts 13 | import { aResolvers } from '@opentf/std'; 14 | 15 | const { promise, resolve, reject } = aResolvers(); 16 | ``` 17 | 18 | ## Examples 19 | 20 | ```ts 21 | const { promise, resolve, reject } = aResolvers() 22 | 23 | Math.random() > 0.5 ? resolve(console.log("ok")) : reject("not ok"); 24 | ``` 25 | 26 | ## Try 27 | 28 | 0.5 ? resolve(console.log("ok")) : reject("not ok"); 33 | `} /> 34 | 35 | ### Resources 36 | 37 | - [tc39/proposal-promise-with-resolvers](https://github.com/tc39/proposal-promise-with-resolvers) 38 | 39 | - [Promise.withResolvers()](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Promise/withResolvers) 40 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2021 Thanga Ganapathy 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. -------------------------------------------------------------------------------- /packages/std/__tests__/array/union.spec.ts: -------------------------------------------------------------------------------- 1 | import { union } from '../../src'; 2 | 3 | describe('Array > union', () => { 4 | test('two arrays', () => { 5 | const setA = [1, 2, 3]; 6 | const setB = [2, 3]; 7 | expect(union([setA, setB])).toEqual([1, 2, 3]); 8 | 9 | const evens = [2, 4, 6, 8]; 10 | const squares = [1, 4, 9]; 11 | expect(union([evens, squares])).toEqual([2, 4, 6, 8, 1, 9]); 12 | }); 13 | 14 | test('multiple arrays', () => { 15 | const setA = [1, 2, 3]; 16 | const setB = [2, 3]; 17 | const setC = [2, 3, 4, 5]; 18 | expect(union([setA, setB, setC])).toEqual([1, 2, 3, 4, 5]); 19 | }); 20 | 21 | test('two arrays with by fn', () => { 22 | expect(union([[2.1], [1.2, 2.3]], Math.floor)).toEqual([2.1, 1.2]); 23 | }); 24 | 25 | test('two array of objects', () => { 26 | const objects = [ 27 | { x: 1, y: 2 }, 28 | { x: 2, y: 1 }, 29 | ]; 30 | const others = [ 31 | { x: 1, y: 1 }, 32 | { x: 1, y: 2 }, 33 | ]; 34 | expect(union([objects, others])).toEqual([ 35 | { x: 1, y: 2 }, 36 | { x: 2, y: 1 }, 37 | { x: 1, y: 1 }, 38 | ]); 39 | }); 40 | }); 41 | -------------------------------------------------------------------------------- /packages/std/__tests__/assert/isEmpty.spec.ts: -------------------------------------------------------------------------------- 1 | import { isEmpty } from '../../src'; 2 | 3 | describe('Assert => isEmpty', () => { 4 | test('truthy', () => { 5 | expect(isEmpty('')).toBe(true); 6 | expect(isEmpty([])).toBe(true); 7 | expect(isEmpty({})).toBe(true); 8 | expect(isEmpty(new Map())).toBe(true); 9 | expect(isEmpty(new Set())).toBe(true); 10 | expect(isEmpty(new ArrayBuffer(0))).toBe(true); 11 | const arr = [,]; 12 | expect(isEmpty(arr, true)).toBe(true); 13 | }); 14 | 15 | test('falsy', () => { 16 | expect(isEmpty()).toBe(false); 17 | expect(isEmpty(undefined)).toBe(false); 18 | expect(isEmpty(null)).toBe(false); 19 | expect(isEmpty(1)).toBe(false); 20 | expect(isEmpty(1.5)).toBe(false); 21 | expect(isEmpty(1n)).toBe(false); 22 | expect(isEmpty(false)).toBe(false); 23 | expect(isEmpty(true)).toBe(false); 24 | expect(isEmpty(' ')).toBe(false); 25 | expect(isEmpty('a')).toBe(false); 26 | expect(isEmpty([1])).toBe(false); 27 | expect(isEmpty({ length: 0, size: 0, byteLength: 0 })).toBe(false); 28 | const arr = [,]; 29 | expect(isEmpty(arr)).toBe(false); 30 | }); 31 | }); 32 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/mode.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Calculates the `mode` value of the given array. 5 | 6 | 7 | Mode: The most frequent number—that is, the number that occurs the highest number of times. 8 |
9 | \- [Khan Academy](https://www.khanacademy.org/math/statistics-probability/summarizing-quantitative-data/mean-median-basics/a/mean-median-and-mode-review) 10 |
11 |
12 | 13 | ## Syntax 14 | 15 | ```ts 16 | import { mode } from '@opentf/std'; 17 | 18 | mode( 19 | arr: T[] = [], 20 | cb?: (val: T, index: number) => number 21 | ): number[] 22 | ``` 23 | 24 | ## Examples 25 | 26 | ```ts 27 | mode([1]) //=> [] 28 | 29 | mode([1, 2, 3, 4, 5]) //=> [] 30 | 31 | mode([4, 2]) //=> [] 32 | 33 | mode([4, 2, 3, 2, 2]) //=> [2] 34 | 35 | mode([0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 4]) //=> [1, 2] 36 | 37 | mode([{ n: 1 }, { n: 2 }, { n: 3 }, { n: 2 }], ({ n }) => n) //=> [2] 38 | 39 | ``` 40 | 41 | ## Try 42 | 43 | -------------------------------------------------------------------------------- /apps/docs/pages/Maths/median.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Calculates the `median` value of the given array. 5 | 6 | 7 | Median: The middle number; found by ordering all data points and picking out the one in the middle (or if there are two middle numbers, taking the mean of those two numbers). 8 |
9 | \- [Khan Academy](https://www.khanacademy.org/math/statistics-probability/summarizing-quantitative-data/mean-median-basics/a/mean-median-and-mode-review) 10 |
11 |
12 | 13 | ## Syntax 14 | 15 | ```ts 16 | import { median } from '@opentf/std'; 17 | 18 | median( 19 | arr: number[] = [], 20 | cb?: (val: number, index: number) => number 21 | ): number 22 | ``` 23 | 24 | ## Examples 25 | 26 | ```ts 27 | median([]) //=> NaN 28 | 29 | median([1]) //=> 1 30 | 31 | median([4, 1, 7]) //=> 1 32 | 33 | median([4, 2, 8]) //=> 2 34 | 35 | median([1, 4, 2, 5, 0]) //=> 2 36 | 37 | median([10, 20, 40, 50]) //=> 30 38 | ``` 39 | 40 | ## Try 41 | 42 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/max.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Returns the maximum value of the given array. 5 | 6 | 7 | If duplicate values are present in the array, then the first match will be returned. 8 | 9 | 10 | **Related** 11 | - [min](/Array/min) 12 | - [bounds](/Array/bounds) 13 | 14 | ## Syntax 15 | 16 | ```ts copy 17 | import { max } from '@opentf/std'; 18 | 19 | max( 20 | arr: T[] = [], 21 | by: (val: T) => number = (x: T) => x as number 22 | ): T | null 23 | ``` 24 | 25 | ## Examples 26 | 27 | ```ts 28 | max([]) //=> null 29 | 30 | max([1, undefined, 2, null, 3]) //=> 3 31 | 32 | max([1, 2, 3, 4, 5]) //=> 5 33 | 34 | const arr = [ 35 | { 36 | name: 'x', 37 | age: 10, 38 | }, 39 | { 40 | name: 'y', 41 | age: 16, 42 | }, 43 | { 44 | name: 'z', 45 | age: 13, 46 | }, 47 | { name: 'y2', age: 16 }, 48 | ]; 49 | max(arr, (o) => o.age)) 50 | //=> 51 | // { 52 | // name: 'y', 53 | // age: 16, 54 | // } 55 | ``` 56 | 57 | ## Try 58 | 59 | 63 | -------------------------------------------------------------------------------- /packages/std/__tests__/array/max.spec.ts: -------------------------------------------------------------------------------- 1 | import { max } from '../../src'; 2 | 3 | describe('Array > max', () => { 4 | test('empty array', () => { 5 | expect(max([])).toBe(null); 6 | }); 7 | 8 | test('falsy array', () => { 9 | expect(max([undefined, null])).toBe(null); 10 | expect(max([1, undefined, 2, null, 3])).toBe(3); 11 | }); 12 | 13 | test('number array', () => { 14 | expect(max([1, 2, 3, 4, 5])).toBe(5); 15 | expect(max([10, 21, 37, 14, 15])).toBe(37); 16 | expect(max([100.12, 100.21, 37.52, 14.17, 15.26])).toBe(100.21); 17 | }); 18 | 19 | test('string array', () => { 20 | expect(max(['a', 'b', 'c', 'z', 'd'])).toBe('z'); 21 | expect(max(['apple', 'mango', 'grapes'])).toBe('mango'); 22 | }); 23 | 24 | test('array of objects', () => { 25 | const arr = [ 26 | { 27 | name: 'x', 28 | age: 10, 29 | }, 30 | { 31 | name: 'y', 32 | age: 16, 33 | }, 34 | { 35 | name: 'z', 36 | age: 13, 37 | }, 38 | { name: 'y2', age: 16 }, 39 | ]; 40 | expect(max(arr, (f) => f.age)).toEqual({ 41 | name: 'y', 42 | age: 16, 43 | }); 44 | }); 45 | }); 46 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/arrRm.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Removes items at the given index from the given array. 5 | 6 | 7 | Immutable: This does not mutate the given array. 8 | 9 | 10 | ## Syntax 11 | 12 | ```ts copy 13 | import { arrRm } from '@opentf/std'; 14 | 15 | arrRm( 16 | arr: T[] = [], 17 | index?: number, 18 | count: number = 1 19 | ) 20 | ``` 21 | 22 | ## Examples 23 | 24 | ```ts 25 | arrRm([]) // => []); 26 | 27 | arrRm([1]) // => []); 28 | 29 | arrRm([1, 2]) // => [1]); 30 | 31 | arrRm([1, 2], 1) // => [1]); 32 | 33 | arrRm([1, 2], 1, 1) // => [1]); 34 | 35 | arrRm([1, 2, 3, 4, 5], -1) // => [1, 2, 3, 4]); 36 | 37 | arrRm([1, 2, 3, 4, 5], -1, 1) // => [1, 2, 3, 4]); 38 | 39 | arrRm([1, 2, 3, 4, 5], -1, 3) // => [1, 2, 3, 4]); 40 | 41 | arrRm([1, 2, 3, 4, 5], -2, 2) // => [1, 2, 3]); 42 | 43 | const myFish = ['angel', 'clown', 'mandarin', 'sturgeon']; 44 | arrRm(myFish, 2, Infinity) // => ['angel', 'clown']); 45 | ``` 46 | 47 | ## Try 48 | 49 | 53 | -------------------------------------------------------------------------------- /packages/std/src/string/camelCase.ts: -------------------------------------------------------------------------------- 1 | import capitalize from './capitalize'; 2 | import replaceAt from './replaceAt'; 3 | 4 | function camelCase(str: string): string { 5 | let out; 6 | const res = str.match(/[a-z0-9]+/gi); 7 | 8 | const wordCase = (word: string) => { 9 | const regexp = new RegExp(/[A-Z]+/g); 10 | let match; 11 | 12 | while ((match = regexp.exec(word)) !== null) { 13 | if (regexp.lastIndex && regexp.lastIndex < word.length) { 14 | word = 15 | word.substring(0, match.index) + 16 | capitalize(word.substring(match.index, regexp.lastIndex - 1)) + 17 | word.substring(regexp.lastIndex - 1); 18 | } else { 19 | return word.substring(0, match.index) + capitalize(match[0]); 20 | } 21 | } 22 | 23 | return word; 24 | }; 25 | 26 | if (res) { 27 | for (let i = 0; i < res.length; i++) { 28 | if (res[i].match(/[A-Z]+/g)) { 29 | res[i] = wordCase(res[i]); 30 | } else { 31 | res[i] = capitalize(res[i]); 32 | } 33 | } 34 | out = res.join(''); 35 | 36 | return replaceAt(out, 0, out[0].toLowerCase()); 37 | } 38 | 39 | return str; 40 | } 41 | 42 | export default camelCase; 43 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/bounds.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Returns a tuple of the min & max values of the given array. 5 | 6 | 7 | If duplicate values are present in the array, then the first match will be returned. 8 | 9 | 10 | **Related** 11 | - [min](/Array/min) 12 | - [max](/Array/max) 13 | 14 | ## Syntax 15 | 16 | ```ts copy 17 | import { bounds } from '@opentf/std'; 18 | 19 | bounds( 20 | arr: T[] = [], 21 | by: (val: T) => number = (x: T) => x as number 22 | ) 23 | ``` 24 | 25 | ## Examples 26 | 27 | ```ts 28 | bounds([1, 2, 3, 4, 5]) //=> [1, 5] 29 | 30 | const arr = [ 31 | { 32 | name: 'x', 33 | age: 10, 34 | }, 35 | { 36 | name: 'y', 37 | age: 16, 38 | }, 39 | { 40 | name: 'z', 41 | age: 13, 42 | }, 43 | { name: 'y2', age: 16 }, 44 | ]; 45 | bounds(arr, (o) => o.age) 46 | //=> 47 | // [ 48 | // { 49 | // name: 'x', 50 | // age: 10, 51 | // }, 52 | // { 53 | // name: 'y', 54 | // age: 16, 55 | // }, 56 | // ] 57 | ``` 58 | 59 | ## Try 60 | 61 | 65 | -------------------------------------------------------------------------------- /packages/std/src/object/toSet.ts: -------------------------------------------------------------------------------- 1 | import isEmpty from '../assert/isEmpty'; 2 | import isFn from '../types/isFn'; 3 | import isNum from '../types/isNum'; 4 | import clone from './clone'; 5 | import { IterableObj } from './merge'; 6 | import toPath from './toPath'; 7 | 8 | /** 9 | * Sets the value to an object at the given path & returns new object. 10 | * 11 | * @example 12 | * 13 | * set({}}, 'a.b', 1) //=> {a: {b: 1} } 14 | */ 15 | export default function toSet( 16 | obj: T, 17 | path: string | unknown[], 18 | value: unknown | ((val: unknown) => unknown) 19 | ): T { 20 | const pathArr = toPath(path); 21 | const cObj = clone(obj); 22 | let curObj: IterableObj = cObj as IterableObj; 23 | 24 | if (isEmpty(pathArr)) { 25 | return obj; 26 | } 27 | 28 | for (let i = 0; i < pathArr.length; i++) { 29 | const prop = pathArr[i] as PropertyKey; 30 | 31 | if (i === pathArr.length - 1) { 32 | const v = isFn(value) ? value(curObj[prop]) : value; 33 | curObj[prop] = v; 34 | break; 35 | } 36 | 37 | if (!curObj[prop]) { 38 | curObj[prop] = isNum(pathArr[i + 1], true) ? [] : {}; 39 | } 40 | 41 | curObj = curObj[prop] as IterableObj; 42 | } 43 | 44 | return cObj as T; 45 | } 46 | -------------------------------------------------------------------------------- /apps/docs/pages/Types/isJSON.mdx: -------------------------------------------------------------------------------- 1 | import REPL from "../../components/REPL"; 2 | 3 | > Checks whether the given string is a valid [JSON](https://json.org/) object. 4 | 5 | ## Syntax 6 | 7 | ```ts 8 | import { isJSON } from '@opentf/std'; 9 | 10 | isJSON(str: string): boolean; 11 | ``` 12 | 13 | ## Examples 14 | 15 | ```ts 16 | // Falsy cases 17 | // *********** 18 | 19 | isJSON(""); //=> false 20 | 21 | isJSON("undefined"); //=> false 22 | 23 | isJSON("null"); //=> false 24 | 25 | isJSON("true"); //=> false 26 | 27 | isJSON("false"); //=> false 28 | 29 | isJSON("1"); //=> false 30 | 31 | isJSON("12345"); //=> false 32 | 33 | isJSON("abc"); //=> false 34 | 35 | isJSON("{a}"); //=> false 36 | 37 | isJSON("{a:}"); //=> false 38 | 39 | isJSON("{a:1}"); //=> false 40 | 41 | isJSON('{"a": undefined}'); //=> false 42 | 43 | isJSON("[]"); //=> false 44 | 45 | // Truthy cases 46 | // ************ 47 | 48 | isJSON("{}"); //=> true 49 | 50 | isJSON('{"a":1}'); //=> true 51 | 52 | isJSON( 53 | '{"a": "abc", "b": true, "c": false, "d": [{"e": 1}, null, 5.0], "f": {}}' 54 | ); //=> true 55 | ``` 56 | 57 | ## Try 58 | 59 | -------------------------------------------------------------------------------- /apps/docs/pages/Array/min.mdx: -------------------------------------------------------------------------------- 1 | import { Callout } from "nextra/components"; 2 | import REPL from "../../components/REPL"; 3 | 4 | > Returns the minimum value of the given array. 5 | 6 | 7 | If duplicate values are present in the array, then the first match will be returned. 8 | 9 | 10 | **Related** 11 | - [max](/Array/max) 12 | - [bounds](/Array/bounds) 13 | 14 | ## Syntax 15 | 16 | ```ts copy 17 | import { min } from '@opentf/std'; 18 | 19 | min( 20 | arr: T[] = [], 21 | by: (val: T) => number = (x: T) => x as number 22 | ): T | null 23 | ``` 24 | 25 | ## Examples 26 | 27 | ```ts 28 | max([]) //=> null 29 | 30 | max([1, undefined, 2, null, 3]) //=> 1 31 | 32 | min([1, 2, -3, 4, 5]) //=> -3 33 | 34 | const arr = [ 35 | { 36 | name: 'x', 37 | age: 10, 38 | }, 39 | { 40 | name: 'x2', 41 | age: 10, 42 | }, 43 | { 44 | name: 'y', 45 | age: 16, 46 | }, 47 | { 48 | name: 'z', 49 | age: 13, 50 | }, 51 | { name: 'y2', age: 16 }, 52 | ]; 53 | min(arr, (f) => f.age) 54 | //=> 55 | // { 56 | // name: 'x', 57 | // age: 10, 58 | // } 59 | ``` 60 | 61 | ## Try 62 | 63 | 67 | --------------------------------------------------------------------------------