diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index f1c3b88..c0f2010 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -24,7 +24,7 @@ jobs: uses: actions/setup-node@v1 with: node-version: ${{ matrix.node-version }} - - run: yarn + - run: yarn - run: yarn workspaces run build - run: yarn workspaces run test # You may pin to the exact commit or the version. @@ -32,4 +32,4 @@ jobs: - uses: codecov/codecov-action@v1.0.13 with: # Comma-separated list of files to upload - files: ./packages/url-manager/coverage/coverage-final.json # optional + files: ./packages/url-manager/coverage/coverage-final.json,./packages/object-util/coverage/coverage-final.json # optional diff --git a/packages/object-util/.babelrc b/packages/object-util/.babelrc new file mode 100644 index 0000000..c4bf74f --- /dev/null +++ b/packages/object-util/.babelrc @@ -0,0 +1,10 @@ +{ + "presets": [ + ["@babel/preset-env", { + "targets": { + "node": "current" + } + }], + "@babel/preset-typescript" + ] +} diff --git a/packages/object-util/.gitignore b/packages/object-util/.gitignore new file mode 100644 index 0000000..782d4a6 --- /dev/null +++ b/packages/object-util/.gitignore @@ -0,0 +1,2 @@ +/dist/ +coverage diff --git a/packages/object-util/.npmignore b/packages/object-util/.npmignore new file mode 100644 index 0000000..b873d06 --- /dev/null +++ b/packages/object-util/.npmignore @@ -0,0 +1,13 @@ +node_modules +src +test +.babelrc +.eslintrc.js +.gitignore +.npmignore +tsconfig.* +webpack.config.js +yarn-error.log +coverage +__tests__ +jest.config.js diff --git a/packages/object-util/__tests__/index.test.ts b/packages/object-util/__tests__/index.test.ts new file mode 100644 index 0000000..ee8ccdf --- /dev/null +++ b/packages/object-util/__tests__/index.test.ts @@ -0,0 +1,92 @@ +/// + +import { objectSize, objectToArray, objectMap, objectSort, cloneObject, objectEqual } from '../src/ObjectUtil' + + +describe('Basic tests', () => { + it('shoud return length of the object', () => { + const obj = { + index0: true, + index1: false, + index2: false, + index3: false, + index4: false, + index5: false, + index6: false, + index7: false, + index8: false, + index9: false, + index10: false + } + expect(objectSize(obj)).toBe(11) + }) + + it('should convert the object to an array', () => { + const obj = { + pouet: 'first', + toto: 'second' + } + expect(objectToArray(obj)).toEqual(['first', 'second']) + }) + + it('should run through the object', () => { + const obj = { + pouet: 'first', + toto: 'second' + } + expect(objectMap(obj, (value, index) => { + return [index, value] + })).toEqual([['pouet', 'first'],['toto','second']]) + }) + + it('should sort the object', () => { + const obj = { + b: 'first', + a: 'second' + } + expect(objectSort(obj)).toEqual({ + a: 'second', + b: 'first' + }) + }) + + it('should clone the object', () => { + const obj = { + pouet: 'first', + toto: 'second' + } + const clone = cloneObject(obj) + expect(clone).toEqual(obj) + clone.pouet = 'third' + expect(clone).not.toEqual(obj) + }) + + it('should deeply clone the object', () => { + const obj = { + pouet: {is: 'first'}, + toto: 'second' + } + const clone = cloneObject(obj) + expect(clone).toEqual(obj) + clone.toto = 'third' + expect(clone).not.toEqual(obj) + }) +}); + +describe('Object Equal Test', () => { + it('should be equal', () => { + expect(objectEqual({pouet: true}, {pouet: true})).toBe(true) + }) + it('should not be equal', () => { + expect(objectEqual({pouet: true}, {pouet: false})).toBe(false) + }) + it('should be deeply equal', () => { + expect(objectEqual({pouet: {is: true}}, {pouet: {is: true}})).toBe(true) + }) + it('should not be deeply equal', () => { + expect(objectEqual({pouet: {is: true}}, {pouet: {is: false}})).toBe(false) + }) + it('should not be differently equal', () => { + expect(objectEqual({pouet: true}, {})).toBe(false) + }) +}) diff --git a/packages/object-util/jest.config.js b/packages/object-util/jest.config.js new file mode 100644 index 0000000..3c46609 --- /dev/null +++ b/packages/object-util/jest.config.js @@ -0,0 +1,18 @@ +module.exports = { + globals: { + 'ts-jest': { + tsConfig: 'tsconfig.test.json' + }, + "transform": { + ".(ts|tsx)": " ../../node_modules/ts-jest/preprocessor.js" + }, + "testRegex": "(/__tests__/.*|\\.(test|spec))\\.(ts|tsx|js)$", + "testResultsProcessor": "../../node_modules/ts-jest/coverageprocessor.js", + "collectCoverageFrom": ["src/URLManager.ts"], + "moduleFileExtensions": [ + "ts", + "tsx", + "js" + ], + }, +} diff --git a/packages/object-util/package.json b/packages/object-util/package.json new file mode 100644 index 0000000..a6febbe --- /dev/null +++ b/packages/object-util/package.json @@ -0,0 +1,31 @@ +{ + "name": "@dzeio/object-util", + "version": "0.0.1", + "description": "some Function to make work on objects easier", + "repository": "https://github.com/dzeiocom/libs.git", + "author": "Aviortheking", + "license": "MIT", + "main": "./dist/URLManager.js", + "browser": "./dist/browser.js", + "types": "./dist/URLManager.d.ts", + "devDependencies": { + "@babel/core": "^7.11.4", + "@babel/preset-env": "^7.11.0", + "@babel/preset-typescript": "^7.10.4", + "@types/chai": "^4.2.12", + "@types/jest": "^26.0.10", + "babel-loader": "^8.1.0", + "codecov": "^3.7.2", + "jest": "^26.4.2", + "ts-loader": "^8.0.3", + "ts-node": "^9.0.0", + "typescript": "^4.0.2", + "webpack": "^4.44.1", + "webpack-cli": "^3.3.12" + }, + "scripts": { + "prepublishOnly": "yarn build", + "build": "webpack --mode=\"production\" && tsc", + "test": "jest --coverage" + } +} diff --git a/packages/object-util/src/ObjectUtil.ts b/packages/object-util/src/ObjectUtil.ts new file mode 100644 index 0000000..d4f496d --- /dev/null +++ b/packages/object-util/src/ObjectUtil.ts @@ -0,0 +1,103 @@ +export const objectMap = (items: Record, fn: (el: T, key: string) => J) => { + const list: Array = [] + objectLoop(items, (item, key) => { + list.push(fn(item, key)) + }) + return list +} + +export const objectLoop = (items: Record, fn: (el: T, key: string) => void | boolean) => { + let res: void | boolean + for (const key in items) { + if (!Object.prototype.hasOwnProperty.call(items, key)) { + continue + } + res = fn(items[key], key) + if (typeof res === 'boolean' && !res) { + return res + } + } + return res +} + +export function objectToArray(obj: Record): Array { + return Object.values(obj) +} + +export function objectSize(obj: Record) { + return Object.keys(obj).length +} + +export function objectSort>(obj: Record, fn?: (a: string, b: string) => number): T { + const ordered: any = {}; + for (const key of Object.keys(obj).sort(fn)) { + ordered[key] = obj[key] + } + return ordered +} + +export function cloneObject>(obj: T): T { + const clone: T = {} as any + objectLoop(obj, (value, key) => { + if (typeof value === 'object' && value != null) { + clone[key as Extract] = cloneObject(value) + return + } + clone[key as Extract] = value + }) + return clone +} + +export function objectSet(obj: Record, path: Array, value: any) { + let pointer = obj + for (let index = 0; index < path.length; index++) { + const key = path[index] + if ((!Object.prototype.hasOwnProperty.call(pointer, key)) && (index+1) < path.length) { + const key1 = path[index + 1] + if (typeof key1 === 'number') { + pointer[key] = [] + } else { + pointer[key] = {} + } + } + + // if last index + if ((index+1) === path.length) { + pointer[key] = value + if (value === undefined) { + delete pointer[key] + } + break + } + // move pointer to new key + pointer = pointer[key] + } +} + +export function objectEqual(x: Record, y: Record): boolean { + const res = objectLoop(x, (item, key) => { + if (!(key in y)) { + return false + } + const item2 = y[key] + if (typeof item === 'object' && typeof item2 === 'object') { + return objectEqual(item, item2) + } + return item === item2 + }) + if (typeof res !== 'boolean') { + return true + } + return res +} + +export default { + objectMap, + objectLoop, + objectToArray, + objectSize, + objectSort, + cloneObject, + objectSet, + objectEqual +} diff --git a/packages/object-util/src/index.ts b/packages/object-util/src/index.ts new file mode 100644 index 0000000..90342c7 --- /dev/null +++ b/packages/object-util/src/index.ts @@ -0,0 +1,9 @@ +import ObjectUtil from './ObjectUtil' + +ObjectUtil.objectLoop(ObjectUtil, (fn, key) => { + // @ts-expect-error + window[key as any] = fn +}) + +// @ts-expect-error +window.ObjectUtil = ObjectUtil diff --git a/packages/object-util/tsconfig.json b/packages/object-util/tsconfig.json new file mode 100644 index 0000000..7bc1d43 --- /dev/null +++ b/packages/object-util/tsconfig.json @@ -0,0 +1,9 @@ +{ + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "dist" + }, + "files": [ + "src/ObjectUtil.ts" + ] +} diff --git a/packages/object-util/tsconfig.test.json b/packages/object-util/tsconfig.test.json new file mode 100644 index 0000000..67ae45c --- /dev/null +++ b/packages/object-util/tsconfig.test.json @@ -0,0 +1,6 @@ +{ + "compilerOptions": { + "target": "es5", + "esModuleInterop": true + } +} diff --git a/packages/object-util/webpack.config.js b/packages/object-util/webpack.config.js new file mode 100644 index 0000000..6273b45 --- /dev/null +++ b/packages/object-util/webpack.config.js @@ -0,0 +1,17 @@ +module.exports = { + entry: './src/index', + output: { + path: __dirname, + filename: './dist/browser.js', + }, + resolve: { + extensions: ['.js', '.ts'], + }, + module: { + rules: [ + { + test: /\.ts$/, use: ['babel-loader', 'ts-loader'], exclude: /node_modules/ + } + ] + } +}