├── .husky ├── .gitignore ├── pre-push ├── pre-commit └── commit-msg ├── docs ├── .nojekyll ├── assets │ └── img │ │ └── favicon.png ├── _sidebar.md ├── isEmpty.md ├── curry.md ├── applyTo.md ├── pipe.md ├── compose.md ├── index.html ├── uniq.md └── README.md ├── .npmrc ├── .gitattributes ├── .prettierignore ├── .eslintignore ├── logo.png ├── banner.jpg ├── commitlint.config.js ├── .prettierrc.json ├── config ├── webpack.prod.js ├── webpack.dev.js └── webpack.common.js ├── .gitignore ├── babel.config.js ├── tsconfig.json ├── src ├── index.ts ├── __tests__ │ ├── applyTo.test.ts │ ├── curry.test.ts │ ├── pipe.test.ts │ ├── compose.test.ts │ ├── isEmpty.test.ts │ └── uniq.test.ts ├── applyTo.ts ├── isEmpty.ts ├── pipe.ts ├── compose.ts ├── curry.ts └── uniq.ts ├── .editorconfig ├── jest.config.js ├── .eslintrc.js ├── .github └── workflows │ └── ci.yml ├── LICENSE ├── package.json └── README.md /.husky/.gitignore: -------------------------------------------------------------------------------- 1 | _ -------------------------------------------------------------------------------- /docs/.nojekyll: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | legacy-peer-deps=true 2 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js text eol=lf 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | coverage 2 | node_modules 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | coverage 4 | -------------------------------------------------------------------------------- /logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helderberto/maximus/HEAD/logo.png -------------------------------------------------------------------------------- /banner.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helderberto/maximus/HEAD/banner.jpg -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run validate 5 | -------------------------------------------------------------------------------- /commitlint.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { extends: ['@commitlint/config-conventional'] }; 2 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npm run lint-staged 5 | -------------------------------------------------------------------------------- /.husky/commit-msg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | . "$(dirname "$0")/_/husky.sh" 3 | 4 | npx commitlint --edit $1 5 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "trailingComma": "all", 3 | "singleQuote": true, 4 | "printWidth": 120 5 | } 6 | -------------------------------------------------------------------------------- /docs/assets/img/favicon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/helderberto/maximus/HEAD/docs/assets/img/favicon.png -------------------------------------------------------------------------------- /config/webpack.prod.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'production', 6 | devtool: 'source-map', 7 | }); 8 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | *.log 4 | tmp/ 5 | *.tern-port 6 | node_modules/ 7 | npm-debug.log* 8 | yarn-debug.log* 9 | yarn-error.log* 10 | *.tsbuildinfo 11 | .npm 12 | .eslintcache 13 | /coverage/ 14 | dist 15 | -------------------------------------------------------------------------------- /babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [ 3 | [ 4 | '@babel/preset-env', 5 | { 6 | targets: { 7 | node: 'current', 8 | }, 9 | }, 10 | ], 11 | ], 12 | }; 13 | -------------------------------------------------------------------------------- /config/webpack.dev.js: -------------------------------------------------------------------------------- 1 | const { merge } = require('webpack-merge'); 2 | const common = require('./webpack.common'); 3 | 4 | module.exports = merge(common, { 5 | mode: 'development', 6 | devtool: 'inline-source-map', 7 | }); 8 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist", 4 | "declaration": true, 5 | "rootDir": "./src", 6 | "strict": true, 7 | "target": "es5", 8 | "module": "commonjs" 9 | }, 10 | "include": ["src"] 11 | } 12 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | /* istanbul ignore file */ 2 | export { pipe } from './pipe'; 3 | export { compose } from './compose'; 4 | export { curry } from './curry'; 5 | export { applyTo } from './applyTo'; 6 | export { isEmpty } from './isEmpty'; 7 | export { uniq } from './uniq'; 8 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # This file is for unifying the coding style for different editors and IDEs 2 | # editorconfig.org 3 | 4 | root = true 5 | 6 | [*] 7 | charset = utf-8 8 | end_of_line = lf 9 | indent_size = 2 10 | indent_style = space 11 | insert_final_newline = true 12 | trim_trailing_whitespace = true 13 | -------------------------------------------------------------------------------- /docs/_sidebar.md: -------------------------------------------------------------------------------- 1 | - Getting started 2 | 3 | - [Why Maximus?](/#why-maximus) 4 | - [Install](/#install) 5 | - [Usage](/#usage) 6 | - [Contribute](/#contribute) 7 | 8 | - Function 9 | 10 | - [applyTo](applyTo.md) 11 | - [curry](curry.md) 12 | - [compose](compose.md) 13 | - [isEmpty](isEmpty.md) 14 | - [uniq](uniq.md) 15 | - [pipe](pipe.md) 16 | -------------------------------------------------------------------------------- /jest.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | preset: 'ts-jest', 3 | testEnvironment: 'node', 4 | collectCoverage: true, 5 | testRegex: '/src/__tests__/.*(\\.|/)(test|spec)\\.ts?$', 6 | roots: ['/src'], 7 | coverageDirectory: 'coverage', 8 | collectCoverageFrom: ['/**/*.ts'], 9 | testPathIgnorePatterns: ['/node_modules/', 'dist'], 10 | }; 11 | -------------------------------------------------------------------------------- /src/__tests__/applyTo.test.ts: -------------------------------------------------------------------------------- 1 | import { applyTo } from '..'; 2 | 3 | describe('applyTo', () => { 4 | it('should validate applying simple function', () => { 5 | const increment = jest.fn((x) => x + 1); 6 | const result = applyTo(1, increment); 7 | expect(result).toEqual(2); 8 | const result2 = applyTo(1)(increment); 9 | expect(result2).toEqual(2); 10 | }); 11 | }); 12 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | parser: '@babel/eslint-parser', 3 | env: { 4 | browser: true, 5 | es2020: true, 6 | node: true, 7 | jest: true, 8 | }, 9 | extends: ['standard', 'prettier'], 10 | plugins: ['prettier', 'standard'], 11 | parserOptions: { 12 | sourceType: 'module', 13 | }, 14 | rules: { 15 | 'prettier/prettier': 'error', 16 | }, 17 | }; 18 | -------------------------------------------------------------------------------- /src/__tests__/curry.test.ts: -------------------------------------------------------------------------------- 1 | import { curry } from '..'; 2 | 3 | describe('curry', () => { 4 | it('should validate curried numbers', () => { 5 | const sum = (a: number, b: number, c: number) => a + b + c; 6 | const curriedSum = curry(sum); 7 | 8 | expect(curriedSum(2)(2, 2)).toEqual(6); 9 | }); 10 | 11 | it('should test with more arguments', () => { 12 | const add = curry((n1: number, n2: number) => n1 + n2); 13 | 14 | expect(add(1, 2, 3)).toEqual(3); 15 | }); 16 | }); 17 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: ci 2 | on: [pull_request] 3 | 4 | jobs: 5 | build: 6 | runs-on: ubuntu-latest 7 | steps: 8 | - name: Checkout Repository 9 | uses: actions/checkout@v2 10 | 11 | - name: Setup Node 12 | uses: actions/setup-node@v1 13 | with: 14 | node-version: 14.x 15 | 16 | - name: Install dependencies 17 | run: npm ci 18 | 19 | - name: Validate 20 | run: npm run validate 21 | 22 | - name: Build 23 | run: npm run build 24 | -------------------------------------------------------------------------------- /docs/isEmpty.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## isEmpty ⇒ Boolean 4 | 5 | It checks if value is empty 6 | 7 | **Kind**: global constant\ 8 | **Returns**: Boolean - returns boolean if value is empty\ 9 | **Category**: Function 10 | 11 | | Type | Description | 12 | | ---------------- | ------------------- | 13 | | any | value to be checked | 14 | 15 | **Example** 16 | 17 | ```js 18 | isEmpty(''); //=> true 19 | isEmpty({}); //=> true 20 | isEmpty([]); //=> true 21 | isEmpty(); //=> true 22 | ``` 23 | -------------------------------------------------------------------------------- /src/applyTo.ts: -------------------------------------------------------------------------------- 1 | import { curry } from './curry'; 2 | 3 | type Func = (arg: T) => R; 4 | 5 | /** 6 | * 7 | * Takes a value and applies it to a function 8 | * 9 | * @category Function 10 | * @param {*} value - the value that will be applied 11 | * @param {Function} function - the function that will receive the value 12 | * @returns {*} the return of applied function with the value 13 | * 14 | * @example 15 | * const increment = x => 1 16 | * applyTo(1, increment) // => 2 17 | */ 18 | 19 | export const applyTo = curry((value: T, fn: Func): R => fn(value)); 20 | -------------------------------------------------------------------------------- /src/isEmpty.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * It checks if value is empty 3 | * 4 | * @category Function 5 | * @param {any} - value to be checked 6 | * @returns {Boolean} returns boolean if value is empty 7 | * 8 | * @example 9 | * isEmpty('') //=> true 10 | * isEmpty({}) //=> true 11 | * isEmpty([]) //=> true 12 | * isEmpty() //=> true 13 | */ 14 | export const isEmpty = (value: any): boolean => { 15 | return ( 16 | value === null || 17 | value === '' || 18 | typeof value === 'undefined' || 19 | (typeof value === 'object' && Object.keys(value).length === 0) 20 | ); 21 | }; 22 | -------------------------------------------------------------------------------- /docs/curry.md: -------------------------------------------------------------------------------- 1 | ## curry(fn) ⇒ function 2 | 3 | A function that takes multiple arguments and returns a curried method. 4 | 5 | **Kind**: global function\ 6 | **Returns**: function - the curried method with arguments\ 7 | **Category**: Function 8 | 9 | | Param | Type | Description | 10 | | ----- | --------------------- | --------------------- | 11 | | fn | function | the function to curry | 12 | 13 | **Example** 14 | 15 | ```js 16 | const sum = (a, b, c) => a + b + c; 17 | const curriedSum = curry(sum); 18 | curriedSum(1)(2, 3); //=> 6 19 | ``` 20 | -------------------------------------------------------------------------------- /src/__tests__/pipe.test.ts: -------------------------------------------------------------------------------- 1 | import { pipe } from '..'; 2 | 3 | describe('pipe', () => { 4 | const increment = jest.fn((x) => x + 1); 5 | const double = jest.fn((x) => x * 2); 6 | 7 | afterEach(() => { 8 | jest.clearAllMocks(); 9 | }); 10 | 11 | it('should validate pipe result', () => { 12 | const result = pipe(increment, double)(1); 13 | expect(result).toEqual(4); 14 | }); 15 | 16 | it('should validate each function is called once', () => { 17 | pipe(increment, double)(1); 18 | expect(increment).toHaveBeenCalledTimes(1); 19 | expect(double).toHaveBeenCalledTimes(1); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/__tests__/compose.test.ts: -------------------------------------------------------------------------------- 1 | import { compose } from '..'; 2 | 3 | describe('compose', () => { 4 | const increment = jest.fn((x) => x + 1); 5 | const double = jest.fn((x) => x * 2); 6 | 7 | afterEach(() => { 8 | jest.clearAllMocks(); 9 | }); 10 | 11 | it('should validate pipe result', () => { 12 | const result = compose(increment, double)(1); 13 | expect(result).toEqual(3); 14 | }); 15 | 16 | it('should validate each function is called once', () => { 17 | compose(increment, double)(1); 18 | expect(increment).toHaveBeenCalledTimes(1); 19 | expect(double).toHaveBeenCalledTimes(1); 20 | }); 21 | }); 22 | -------------------------------------------------------------------------------- /src/pipe.ts: -------------------------------------------------------------------------------- 1 | import { applyTo } from './applyTo'; 2 | 3 | type Func = (arg: T) => R; 4 | 5 | /** 6 | * 7 | * Pipe takes HOCs and returns a function that combines them, from the left to the right 8 | * 9 | * @category Function 10 | * @param {...Function} functions - the functions to compose 11 | * @returns {Function} the composed function 12 | * 13 | * @example 14 | * const increment = x => 1 15 | * const double = x => x * 2 16 | * const incrementAndDouble = pipe(increment, double) 17 | * incrementAndDouble(1) //=> 4 18 | */ 19 | export const pipe = 20 | (...functions: Func[]): Func => 21 | (value: T): R => 22 | functions.reduce(applyTo, value); 23 | -------------------------------------------------------------------------------- /src/compose.ts: -------------------------------------------------------------------------------- 1 | import { applyTo } from './applyTo'; 2 | 3 | type Func = (arg: T) => R; 4 | 5 | /** 6 | * 7 | * Compose takes HOCs and returns a function that combines them from the right to the left 8 | * 9 | * @category Function 10 | * @param {...Function} functions - the functions to compose 11 | * @returns {Function} the composed function 12 | * 13 | * @example 14 | * const increment = x => 1 15 | * const double = x => x * 2 16 | * const doubleAndIncrement = compose(increment, double) 17 | * doubleAndIncrement(1) //=> 3 18 | */ 19 | export const compose = 20 | (...functions: Func[]): Func => 21 | (value: T): R => 22 | functions.reduceRight(applyTo, value); 23 | -------------------------------------------------------------------------------- /docs/applyTo.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## applyTo ⇒ \* 4 | 5 | Takes a value and applies it to a function 6 | 7 | **Kind**: global constant\ 8 | **Returns**: \* - the return of applied function with the value\ 9 | **Category**: Function 10 | 11 | | Param | Type | Description | 12 | | -------- | --------------------- | ---------------------------------------- | 13 | | value | \* | the value that will be applied | 14 | | function | function | the function that will receive the value | 15 | 16 | **Example** 17 | 18 | ```js 19 | const increment = (x) => 1; 20 | applyTo(1, increment); // => 2 21 | ``` 22 | -------------------------------------------------------------------------------- /docs/pipe.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## pipe(...functions) ⇒ function 4 | 5 | Pipe takes HOCs and returns a function that combines them, from the left to the right 6 | 7 | **Kind**: global function 8 | **Returns**: function - the composed function 9 | **Category**: Function 10 | 11 | | Param | Type | Description | 12 | | ------------ | --------------------- | ------------------------ | 13 | | ...functions | function | the functions to compose | 14 | 15 | **Example** 16 | 17 | ```js 18 | const increment = (x) => 1; 19 | const double = (x) => x * 2; 20 | const incrementAndDouble = pipe(increment, double); 21 | incrementAndDouble(1); //=> 4 22 | ``` 23 | -------------------------------------------------------------------------------- /docs/compose.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## compose(...functions) ⇒ function 4 | 5 | Compose takes HOCs and returns a function that combines them from the right to the left 6 | 7 | **Kind**: global function\ 8 | **Returns**: function - the composed function\ 9 | **Category**: Function 10 | 11 | | Param | Type | Description | 12 | | ------------ | --------------------- | ------------------------ | 13 | | ...functions | function | the functions to compose | 14 | 15 | **Example** 16 | 17 | ```js 18 | const increment = (x) => 1; 19 | const double = (x) => x * 2; 20 | const doubleAndIncrement = compose(increment, double); 21 | doubleAndIncrement(1); //=> 3 22 | ``` 23 | -------------------------------------------------------------------------------- /src/curry.ts: -------------------------------------------------------------------------------- 1 | type Func = (...args: any[]) => any; 2 | 3 | /** 4 | * A function that takes multiple arguments and returns a curried method. 5 | * 6 | * @category Function 7 | * @param {Function} fn - the function to curry 8 | * @returns {Function} the curried method with arguments 9 | * 10 | * @example 11 | * const sum = (a, b, c) => a + b + c 12 | * const curriedSum = curry(sum) 13 | * curriedSum(1)(2, 3) //=> 6 14 | */ 15 | export const curry = (fn: Func): Func => 16 | function curried(this: any, ...args: any[]): Func { 17 | if (args.length >= fn.length) { 18 | return fn.apply(this, args); 19 | } 20 | return function (this: any, ..._args: any[]): any { 21 | return curried.apply(this, args.concat(_args)); 22 | }; 23 | }; 24 | -------------------------------------------------------------------------------- /src/uniq.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * Remove duplicated items from an array 4 | * 5 | * @category Function 6 | * @param {string | Array} key - Object key to compare and remove it from the original array or an Array that will be removed duplicated items 7 | * @param {Array} arr - An array 8 | * @returns {Array} - New array without the duplicated items 9 | */ 10 | 11 | export const uniq = (key: string | T[]): T[] | ((arr: { [key: string]: any }[]) => { [key: string]: any }[]) => { 12 | if (Array.isArray(key)) { 13 | return Array.from(new Set(key)); 14 | } 15 | return (arr: { [key: string]: any }[]) => 16 | Array.from( 17 | arr.reduce((acc, item) => item && item[key as string] && acc.set(item[key as string], item), new Map()).values(), 18 | ); 19 | }; 20 | -------------------------------------------------------------------------------- /config/webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 3 | 4 | module.exports = { 5 | entry: { 6 | mxs: './src/index', 7 | }, 8 | output: { 9 | path: path.resolve(__dirname, '..', 'dist'), 10 | filename: '[name].js', 11 | library: 'MXS', 12 | libraryTarget: 'umd', 13 | globalObject: 'this', 14 | }, 15 | module: { 16 | rules: [ 17 | { 18 | test: /\.tsx?$/, 19 | exclude: /node_modules/, 20 | use: { 21 | loader: 'ts-loader', 22 | }, 23 | }, 24 | { 25 | test: /\.js$/, 26 | exclude: /node_modules/, 27 | use: { 28 | loader: 'swc-loader', 29 | }, 30 | }, 31 | ], 32 | }, 33 | resolve: { 34 | extensions: ['.tsx', '.ts', '.js'], 35 | }, 36 | plugins: [new CleanWebpackPlugin()], 37 | }; 38 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Maximus 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. 22 | -------------------------------------------------------------------------------- /docs/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Maximus 6 | 7 | 8 | 9 | 13 | 14 | 15 | 16 |
17 | 18 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/__tests__/isEmpty.test.ts: -------------------------------------------------------------------------------- 1 | import { isEmpty } from '..'; 2 | 3 | describe('isEmpty', () => { 4 | it('should return true if value is undefined', () => { 5 | expect(isEmpty(undefined)).toBeTruthy(); 6 | }); 7 | 8 | it('should return true if value is null', () => { 9 | expect(isEmpty(null)).toBeTruthy(); 10 | }); 11 | 12 | it('should return true if value is an empty string', () => { 13 | expect(isEmpty('')).toBeTruthy(); 14 | }); 15 | 16 | it('should return true if value is an empty object', () => { 17 | expect(isEmpty({})).toBeTruthy(); 18 | }); 19 | 20 | it('should return false if value is a non-empty string', () => { 21 | expect(isEmpty('not empty')).toBeFalsy(); 22 | }); 23 | 24 | it('should return false if value is a non-empty object', () => { 25 | expect(isEmpty({ key: 'value' })).toBeFalsy(); 26 | }); 27 | 28 | it('should return false if value is a number', () => { 29 | expect(isEmpty(42)).toBeFalsy(); 30 | }); 31 | 32 | it('should return false if value is a boolean', () => { 33 | expect(isEmpty(true)).toBeFalsy(); 34 | expect(isEmpty(false)).toBeFalsy(); 35 | }); 36 | }); 37 | -------------------------------------------------------------------------------- /docs/uniq.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | ## uniq(key|arr) ⇒ (arr) ⇒ [Array] 4 | 5 | Uniq can take an array as first argument and will remove the duplicated items and return a new array without duplication. But in case you want to remove duplicated objects from an array you sould pass the object key in the first argument and then uniq will return a function that accept an array as argument. 6 | 7 | **Kind**: global function\ 8 | **Returns**: Array - new arry without duplications\ 9 | **Category**: Function 10 | 11 | | Param | Type | Description | 12 | | ----- | ------------------- | ------------------------------- | 13 | | key | string | key to match duplicated objects | 14 | | arr | array | the array with duplicated items | 15 | 16 | **Example** 17 | 18 | Simple array case 19 | 20 | ```js 21 | const arr = [1, 2, 1, 3, 4, 1, 5]; 22 | const newArr = uniq(arr); // [1,2,3,4,5] 23 | ``` 24 | 25 | Case with array of objects 26 | 27 | ```js 28 | const arr = [ 29 | { id: 1, name: 'paul' }, 30 | { id: 2, name: 'paul' }, 31 | { id: 1, name: 'maximus' }, 32 | { id: 3, name: 'anne' }, 33 | ]; 34 | const uniqById = uniq('id'); 35 | const newArray = uniqById(arr); //[{id:1,name:'maximus'},{id:2,name:'paul'}{id:3,name:'anne'}] 36 | ``` 37 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 |
2 |

⚔️ Maximus

3 | 4 |

Lightweight functional JavaScript utilities

5 | 6 |

The acronym "MXS" is used in this project to refer to the package name "Maximus"

7 | 8 |

InstallDocumentationContribute

9 | 10 | [![js-standard-style](https://img.shields.io/badge/code%20style-standard-brightgreen.svg)](http://standardjs.com) 11 | 12 | Maximus Banner 13 |
14 | 15 | ## Why Maximus? 16 | 17 | We noticed that there are several packages that provide functionalities using functional programming, the Maximus objective is not to overlay robust tools like [Ramda](https://ramdajs.com/) and [Lodash](https://lodash.com/), but for cases where you don't need everything that is offered in these great and appreciated packages. 18 | 19 | Some utilities are repeated in the projects we work on and are commonly necessary to rewrite or copy-paste. 20 | 21 | Based on this, we aim to focus on small utilities to facilitate the use of functional approach, manipulation of Arrays and Objects. 22 | 23 | ## Install 24 | 25 | Using NPM: 26 | 27 | ```sh 28 | $ npm i --save mxs 29 | ``` 30 | 31 | In Node.js: 32 | 33 | ```javascript 34 | const MXS = require('mxs'); 35 | ``` 36 | 37 | Directly in the browser: 38 | 39 | ```html 40 | 41 | ``` 42 | 43 | ## Usage 44 | 45 | ```javascript 46 | import * as MXS from 'mxs'; 47 | 48 | const result = MXS.compose( 49 | (withMiddleName) => `${withMiddleName} Meridius`, 50 | (name) => `${name} Décimus`, 51 | )('Maximus'); 52 | 53 | console.log(result); // => 'Maximus Décimus Meridius' 54 | ``` 55 | 56 | ## Contribute 57 | 58 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 59 | 60 | Please make sure to update tests as appropriate. 61 | 62 | ## License 63 | 64 | [MIT License](LICENSE) © Maximus 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mxs", 3 | "version": "0.10.1", 4 | "description": "⚔️ Lightweight functional JavaScript utilities", 5 | "main": "dist/mxs.js", 6 | "module": "dist/mxs.js", 7 | "types": "dist/index.d.ts", 8 | "scripts": { 9 | "lint": "eslint src --max-warnings=0", 10 | "lint:fix": "npm run lint --fix", 11 | "format": "prettier --write 'src/**/*.{js,md,json}'", 12 | "build": "tsc && webpack --config config/webpack.prod.js", 13 | "build:dev": "tsc && webpack --watch --progress --config config/webpack.dev.js", 14 | "test": "jest", 15 | "test:watch": "npm test --watch --maxWorkers=50%", 16 | "test:ci": "npm test --coverage", 17 | "postpublish": "npm run build", 18 | "docs:serve": "docsify serve ./docs -P 3000", 19 | "generate-fn-md": "jsdoc2md", 20 | "validate": "npm run lint && npm test" 21 | }, 22 | "lint-staged": { 23 | "src/**/*.{js,json,md}": [ 24 | "prettier --write ." 25 | ], 26 | "src/**/*": [ 27 | "npm lint --fix", 28 | "npm test --findRelatedTests --bail" 29 | ] 30 | }, 31 | "repository": "git@github.com:helderburato/maximus.git", 32 | "author": "Helder Burato Berto (https://helderburato.com)", 33 | "keywords": [ 34 | "maximus", 35 | "mx", 36 | "functional", 37 | "utils", 38 | "utilities", 39 | "lightweight", 40 | "fp" 41 | ], 42 | "files": [ 43 | "dist/", 44 | "LICENSE", 45 | "README.md" 46 | ], 47 | "devDependencies": { 48 | "@babel/core": "^7.16.12", 49 | "@babel/eslint-parser": "^7.16.5", 50 | "@babel/preset-env": "^7.16.11", 51 | "@commitlint/cli": "^18.4.4", 52 | "@commitlint/config-conventional": "^16.0.0", 53 | "@swc/core": "^1.2.133", 54 | "@types/jest": "^29.5.11", 55 | "@types/node": "^20.11.0", 56 | "babel-jest": "^27.4.6", 57 | "clean-webpack-plugin": "^4.0.0-alpha.0", 58 | "docsify-cli": "^4.4.2", 59 | "eslint": "^8.7.0", 60 | "eslint-config-prettier": "^8.1.0", 61 | "eslint-config-standard": "^16.0.2", 62 | "eslint-plugin-import": "^2.25.4", 63 | "eslint-plugin-node": "^11.1.0", 64 | "eslint-plugin-prettier": "^4.0.0", 65 | "eslint-plugin-promise": "^6.0.0", 66 | "eslint-plugin-standard": "^5.0.0", 67 | "faker": "^5.4.0", 68 | "husky": "^7.0.4", 69 | "jest": "^29.7.0", 70 | "jsdoc-to-markdown": "^7.1.0", 71 | "lint-staged": "12.3.2", 72 | "prettier": "^2.5.1", 73 | "swc-loader": "^0.1.15", 74 | "ts-jest": "^29.1.1", 75 | "ts-loader": "^9.5.1", 76 | "typescript": "^5.3.3", 77 | "webpack": "^5.67.0", 78 | "webpack-cli": "^4.9.2", 79 | "webpack-merge": "^5.7.3" 80 | }, 81 | "license": "MIT" 82 | } 83 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 |

⚔️ Maximus

3 | 4 |

Lightweight functional JavaScript utilities

5 | 6 |

The acronym "MXS" is used in this project to refer to the package name "Maximus"

7 | 8 |

InstallDocumentationContribute

9 | 10 | 27 | 28 | Maximus Banner 29 |
30 | 31 | ## Why Maximus? 32 | 33 | We noticed that there are several packages that provide functionalities using functional programming, the Maximus objective is not to overlay robust tools like [Ramda](https://ramdajs.com/) and [Lodash](https://lodash.com/), but for cases where you don't need everything that is offered in these great and appreciated packages. 34 | 35 | Some utilities are repeated in the projects we work on and are commonly necessary to rewrite or copy-paste. 36 | 37 | Based on this, we aim to focus on small utilities to facilitate the use of functional approach, manipulation of Arrays and Objects. 38 | 39 | ## Install 40 | 41 | Using NPM or Yarn: 42 | 43 | ```sh 44 | $ npm i --save mxs OR yarn add mxs 45 | ``` 46 | 47 | In Node.js: 48 | 49 | ```javascript 50 | const MXS = require('mxs) 51 | ``` 52 | 53 | Directly in the browser: 54 | 55 | ```html 56 | 57 | ``` 58 | 59 | ## Usage 60 | 61 | ```javascript 62 | import * as MXS from 'mxs'; 63 | 64 | const result = MXS.compose( 65 | (withMiddleName) => `${withMiddleName} Meridius`, 66 | (name) => `${name} Décimus`, 67 | )('Maximus'); 68 | 69 | console.log(result); // => 'Maximus Décimus Meridius' 70 | ``` 71 | 72 | ## Contribute 73 | 74 | Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change. 75 | 76 | Please make sure to update tests as appropriate. 77 | 78 | ## License 79 | 80 | [MIT License](LICENSE) © Maximus 81 | -------------------------------------------------------------------------------- /src/__tests__/uniq.test.ts: -------------------------------------------------------------------------------- 1 | import { uniq } from '..'; 2 | 3 | describe('uniq', () => { 4 | it('should remove duplicated obejct items from the array and return a new array', () => { 5 | const uniqById = uniq('id'); 6 | const array = [ 7 | { 8 | id: 1, 9 | first_name: 'Philippe', 10 | last_name: 'Demogeot', 11 | email: 'pdemogeot0@vkontakte.ru', 12 | }, 13 | { 14 | id: 2, 15 | first_name: 'Myranda', 16 | last_name: 'Arnaud', 17 | email: 'marnaud1@weather.com', 18 | }, 19 | { 20 | id: 3, 21 | first_name: 'Laurel', 22 | last_name: 'Loosemore', 23 | email: 'lloosemore2@abc.net.au', 24 | }, 25 | { 26 | id: 1, 27 | first_name: 'Cammy', 28 | last_name: 'Heyworth', 29 | email: 'cheyworth3@elpais.com', 30 | }, 31 | { 32 | id: 5, 33 | first_name: 'Jodi', 34 | last_name: 'Calfe', 35 | email: 'jcalfe4@jiathis.com', 36 | }, 37 | { 38 | id: 1, 39 | first_name: 'Patrizio', 40 | last_name: 'Dockrell', 41 | email: 'pdockrell5@github.io', 42 | }, 43 | { 44 | id: 7, 45 | first_name: 'Jana', 46 | last_name: 'Bartholomieu', 47 | email: 'jbartholomieu6@alibaba.com', 48 | }, 49 | { 50 | id: 1, 51 | first_name: 'Bronny', 52 | last_name: 'Fanner', 53 | email: 'bfanner7@craigslist.org', 54 | }, 55 | { 56 | id: 9, 57 | first_name: 'Nessa', 58 | last_name: 'Flook', 59 | email: 'nflook8@pinterest.com', 60 | }, 61 | { 62 | id: 1, 63 | first_name: 'Martelle', 64 | last_name: 'Macon', 65 | email: 'mmacon9@theatlantic.com', 66 | }, 67 | ]; 68 | const expected = [ 69 | { 70 | email: 'mmacon9@theatlantic.com', 71 | first_name: 'Martelle', 72 | id: 1, 73 | last_name: 'Macon', 74 | }, 75 | { 76 | email: 'marnaud1@weather.com', 77 | first_name: 'Myranda', 78 | id: 2, 79 | last_name: 'Arnaud', 80 | }, 81 | { 82 | email: 'lloosemore2@abc.net.au', 83 | first_name: 'Laurel', 84 | id: 3, 85 | last_name: 'Loosemore', 86 | }, 87 | { 88 | email: 'jcalfe4@jiathis.com', 89 | first_name: 'Jodi', 90 | id: 5, 91 | last_name: 'Calfe', 92 | }, 93 | { 94 | email: 'jbartholomieu6@alibaba.com', 95 | first_name: 'Jana', 96 | id: 7, 97 | last_name: 'Bartholomieu', 98 | }, 99 | { 100 | email: 'nflook8@pinterest.com', 101 | first_name: 'Nessa', 102 | id: 9, 103 | last_name: 'Flook', 104 | }, 105 | ]; 106 | expect((uniqById as (arr: { [key: string]: any; }[]) => { [key: string]: any; }[])(array)).toEqual(expected); 107 | }); 108 | 109 | it('should remove duplicated array items and return a new array', () => { 110 | const array = [ 111 | 'name1', 112 | 'name2', 113 | 'name3', 114 | 'name1', 115 | 'name4', 116 | 'name1', 117 | 'name5', 118 | 'name6', 119 | 'name6', 120 | 'name8', 121 | 'name7', 122 | 'name8', 123 | ]; 124 | const expected = ['name1', 'name2', 'name3', 'name4', 'name5', 'name6', 'name8', 'name7']; 125 | expect(uniq(array)).toEqual(expected); 126 | }); 127 | }); 128 | --------------------------------------------------------------------------------