-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
618b75a
commit f0ce82f
Showing
5 changed files
with
293 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -17,7 +17,6 @@ coverage | |
|
||
# Compiled | ||
build/Release | ||
dist | ||
|
||
# Dependency directory | ||
node_modules | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.omitPaths = exports.getPaths = exports.revert = exports.diffPaths = exports.diffValues = exports.diff = void 0; | ||
const _ = __importStar(require("lodash")); | ||
const utils_1 = require("./utils"); | ||
function diff(original, current) { | ||
const { addedAndChanged, deletedAndChanged } = _getPaths(original, current); | ||
return { | ||
left: (0, utils_1.compact)(deletedAndChanged.values), | ||
right: (0, utils_1.compact)(addedAndChanged.values), | ||
}; | ||
} | ||
exports.diff = diff; | ||
function diffValues(original, current) { | ||
const { changedPaths, addedPaths, deletedPaths } = _getPaths(original, current); | ||
return { | ||
changed: (0, utils_1.getObjectValues)(current, changedPaths), | ||
added: (0, utils_1.getObjectValues)(current, addedPaths), | ||
deleted: (0, utils_1.getObjectValues)(original, deletedPaths), | ||
}; | ||
} | ||
exports.diffValues = diffValues; | ||
function diffPaths(original, current) { | ||
const { changedPaths, addedPaths, deletedPaths } = _getPaths(original, current); | ||
return { | ||
changed: changedPaths, | ||
added: addedPaths, | ||
deleted: deletedPaths, | ||
}; | ||
} | ||
exports.diffPaths = diffPaths; | ||
function revert(dest, src, customizer) { | ||
const srcPaths = (0, utils_1.getObjectPaths)(src, '', _.isArray(src)); | ||
return srcPaths.reduce((result, path) => { | ||
const destValue = _.get(dest, path); | ||
const srcValue = _.get(src, path); | ||
const value = customizer(destValue, srcValue); | ||
_.set(result, path, value); | ||
return result; | ||
}, {}); | ||
} | ||
exports.revert = revert; | ||
function getPaths(obj) { | ||
return (0, utils_1.getObjectPaths)(obj, '', _.isArray(obj)); | ||
} | ||
exports.getPaths = getPaths; | ||
function omitPaths(obj, excludedPaths) { | ||
const includedPaths = getPaths(obj).filter((path) => { | ||
const isIgnored = excludedPaths.some((ignoredPath) => { | ||
if (_.startsWith(ignoredPath, '*.')) { | ||
return _.endsWith(path, _.trimStart(ignoredPath, '*.')); | ||
} | ||
if (_.endsWith(ignoredPath, '.*')) { | ||
return _.startsWith(path, _.trimEnd(ignoredPath, '.*')); | ||
} | ||
return ignoredPath === path; | ||
}); | ||
return !isIgnored; | ||
}); | ||
return (0, utils_1.getObjectValues)(obj, includedPaths); | ||
} | ||
exports.omitPaths = omitPaths; | ||
function _getPaths(original, current) { | ||
const addedAndChanged = (0, utils_1.getObjectsDiff)(current, original); | ||
const deletedAndChanged = (0, utils_1.getObjectsDiff)(original, current); | ||
const changedPaths = _.intersection(addedAndChanged.paths, deletedAndChanged.paths); | ||
const addedPaths = _.difference(addedAndChanged.paths, changedPaths); | ||
const deletedPaths = _.difference(deletedAndChanged.paths, changedPaths); | ||
return { | ||
addedAndChanged, | ||
deletedAndChanged, | ||
changedPaths, | ||
addedPaths, | ||
deletedPaths, | ||
}; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,65 @@ | ||
{ | ||
"name": "o2diff", | ||
"version": "4.0.2", | ||
"description": "Returns the difference between two objects", | ||
"main": "dist/index.js", | ||
"typings": "index.d.ts", | ||
"files": [ | ||
"dist", | ||
"index.d.ts" | ||
], | ||
"engines": { | ||
"node": ">=16", | ||
"npm": ">=7" | ||
}, | ||
"scripts": { | ||
"prepare": "husky install", | ||
"prepublish": "pnpm build", | ||
"start": "ts-node-dev --rs --cls ./index.ts", | ||
"clean": "rm -rf ./dist", | ||
"build": "pnpm clean && pnpm tsc --project tsconfig.dist.json && cp package.json dist/package.json", | ||
"prettify": "prettier --write \"src/**/*.ts\" \"test/**/*.ts\"", | ||
"format": "pnpm lint && pnpm prettify", | ||
"lint": "eslint ./src ./test --ext .ts --fix", | ||
"test": "NODE_ENV=test mocha", | ||
"coverage": "nyc npm test", | ||
"coverage-gh": "nyc --reporter=lcov npm test && codecov" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/AlexanderMac/o2diff.git" | ||
}, | ||
"keywords": [ | ||
"object", | ||
"diff", | ||
"difference", | ||
"compare", | ||
"changes" | ||
], | ||
"author": "Alexander Mac", | ||
"license": "MIT", | ||
"bugs": { | ||
"url": "https://github.com/AlexanderMac/o2diff/issues" | ||
}, | ||
"homepage": "https://github.com/AlexanderMac/o2diff#readme", | ||
"dependencies": { | ||
"lodash": "^4.17.21" | ||
}, | ||
"devDependencies": { | ||
"@types/lodash": "^4.14.199", | ||
"@types/mocha": "^10.0.2", | ||
"@types/node": "^20.7.2", | ||
"@typescript-eslint/eslint-plugin": "^6.7.3", | ||
"@typescript-eslint/parser": "^6.7.3", | ||
"eslint": "^8.50.0", | ||
"eslint-plugin-simple-import-sort": "^10.0.0", | ||
"husky": "^8.0.3", | ||
"lint-staged": "^14.0.1", | ||
"mocha": "^10.2.0", | ||
"nyc": "^15.1.0", | ||
"prettier": "^3.0.3", | ||
"should": "^13.2.3", | ||
"ts-node-dev": "^2.0.0", | ||
"typescript": "^5.2.2" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,118 @@ | ||
"use strict"; | ||
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
var desc = Object.getOwnPropertyDescriptor(m, k); | ||
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { | ||
desc = { enumerable: true, get: function() { return m[k]; } }; | ||
} | ||
Object.defineProperty(o, k2, desc); | ||
}) : (function(o, m, k, k2) { | ||
if (k2 === undefined) k2 = k; | ||
o[k2] = m[k]; | ||
})); | ||
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { | ||
Object.defineProperty(o, "default", { enumerable: true, value: v }); | ||
}) : function(o, v) { | ||
o["default"] = v; | ||
}); | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
if (mod && mod.__esModule) return mod; | ||
var result = {}; | ||
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); | ||
__setModuleDefault(result, mod); | ||
return result; | ||
}; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.compact = exports.convertSpecial = exports.isSimplePrimitive = exports.getObjectValues = exports.getObjectsDiff = exports.getObjectPaths = void 0; | ||
const _ = __importStar(require("lodash")); | ||
function getObjectPaths(obj, curPath = '', isArray = false) { | ||
let paths = []; | ||
_.each(obj, (val, key) => { | ||
val = convertSpecial(val); | ||
const newPath = isArray ? `${curPath}[${key}]` : `${curPath}.${key}`; | ||
if (isSimplePrimitive(val)) { | ||
paths.push(newPath); | ||
} | ||
else if (_.isArray(val)) { | ||
paths = paths.concat(getObjectPaths(val, newPath, true)); | ||
} | ||
else { | ||
paths = paths.concat(getObjectPaths(val, newPath)); | ||
} | ||
}); | ||
if (!curPath) { | ||
paths = paths.map((path) => _.trimStart(path, '.')); | ||
} | ||
return paths; | ||
} | ||
exports.getObjectPaths = getObjectPaths; | ||
function getObjectsDiff(left, right) { | ||
const leftPaths = getObjectPaths(left); | ||
const reducer = { | ||
values: {}, | ||
paths: [], | ||
}; | ||
return leftPaths.reduce((result, path) => { | ||
const leftVal = convertSpecial(_.get(left, path)); | ||
const rightVal = convertSpecial(_.get(right, path)); | ||
if (!_.isEqual(leftVal, rightVal)) { | ||
_.set(result.values, path, leftVal); | ||
result.paths.push(path); | ||
} | ||
return result; | ||
}, reducer); | ||
} | ||
exports.getObjectsDiff = getObjectsDiff; | ||
function getObjectValues(obj, paths) { | ||
const values = paths.reduce((result, path) => { | ||
const val = convertSpecial(_.get(obj, path)); | ||
_.set(result, path, val); | ||
return result; | ||
}, {}); | ||
return compact(values); | ||
} | ||
exports.getObjectValues = getObjectValues; | ||
function isSimplePrimitive(val) { | ||
return (_.isNil(val) || | ||
_.isBoolean(val) || | ||
_.isNumber(val) || | ||
_.isString(val) || | ||
_.isDate(val) || | ||
_.isSymbol(val) || | ||
_.isRegExp(val)); | ||
} | ||
exports.isSimplePrimitive = isSimplePrimitive; | ||
function convertSpecial(val) { | ||
if (val && val.constructor.name === 'ObjectID') { | ||
return val.toString(); | ||
} | ||
return val; | ||
} | ||
exports.convertSpecial = convertSpecial; | ||
function compact(obj) { | ||
obj = convertSpecial(obj); | ||
if (isSimplePrimitive(obj)) { | ||
return obj; | ||
} | ||
if (_.isArray(obj)) { | ||
return _.compact(obj); | ||
} | ||
const result = {}; | ||
_.each(obj, (objItem, objKey) => { | ||
objItem = convertSpecial(objItem); | ||
if (isSimplePrimitive(objItem)) { | ||
result[objKey] = objItem; | ||
} | ||
else if (_.isArray(objItem)) { | ||
result[objKey] = _.filter(objItem, (v) => !_.isNil(v)); | ||
_.each(result[objKey], (arrItem, arrIndex) => { | ||
result[objKey][arrIndex] = compact(arrItem); | ||
}); | ||
} | ||
else { | ||
result[objKey] = compact(objItem); | ||
} | ||
}); | ||
return result; | ||
} | ||
exports.compact = compact; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
<!DOCTYPE html> | ||
<html> | ||
<head> | ||
<meta http-equiv="Content-type" content="text/html; charset=utf-8"> | ||
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; style-src 'unsafe-inline'; img-src data:; connect-src 'self'"> | ||
<title>o2diff Demo</title> | ||
</head> | ||
<body> | ||
|
||
</body> | ||
</html> |