Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
wraithgar authored and lukekarrys committed Mar 28, 2022
1 parent 0f1cd60 commit da377ee
Show file tree
Hide file tree
Showing 8 changed files with 241 additions and 53 deletions.
17 changes: 17 additions & 0 deletions node_modules/just-diff-apply/index.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
// Definitions by: Eddie Atkinson <https://github.com/eddie-atkinson>

type Operation = "add" | "replace" | "remove";

type DiffOps = Array<{
op: Operation;
path: Array<string | number>;
value?: any;
}>;
type PathConverter = (path: string) => string[];

export function diffApply<T extends object>(
obj: T,
diff: DiffOps,
pathConverter?: PathConverter
): T;
export const jsonPatchPathConverter: PathConverter;
78 changes: 67 additions & 11 deletions node_modules/just-diff-apply/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ module.exports = {
var REMOVE = 'remove';
var REPLACE = 'replace';
var ADD = 'add';
var MOVE = 'move';

function diffApply(obj, diff, pathConverter) {
if (!obj || typeof obj != 'object') {
Expand All @@ -62,44 +63,99 @@ function diffApply(obj, diff, pathConverter) {
var thisDiff = diff[i];
var subObject = obj;
var thisOp = thisDiff.op;
var thisPath = thisDiff.path;
if (pathConverter) {
thisPath = pathConverter(thisPath);
if (!Array.isArray(thisPath)) {
throw new Error('pathConverter must return an array');

var thisPath = transformPath(pathConverter, thisDiff.path);
var thisFromPath = thisDiff.from && transformPath(pathConverter, thisDiff.from);
var toPath, toPathCopy, lastToProp, subToObject, valueToMove;

if (thisFromPath) {
// MOVE only, "fromPath" is effectively path and "path" is toPath
toPath = thisPath;
thisPath = thisFromPath;

toPathCopy = toPath.slice();
lastToProp = toPathCopy.pop();
prototypeCheck(lastToProp);
if (lastToProp == null) {
return false;
}
} else {
if (!Array.isArray(thisPath)) {
throw new Error('diff path must be an array, consider supplying a path converter');

var thisToProp;
while (((thisToProp = toPathCopy.shift())) != null) {
prototypeCheck(thisToProp);
if (!(thisToProp in subToObject)) {
subToObject[thisToProp] = {};
}
subToObject = subToObject[thisToProp];
}
}

var pathCopy = thisPath.slice();
var lastProp = pathCopy.pop();
prototypeCheck(lastProp);
if (lastProp == null) {
return false;
}

var thisProp;
while (((thisProp = pathCopy.shift())) != null) {
prototypeCheck(thisProp);
if (!(thisProp in subObject)) {
subObject[thisProp] = {};
}
subObject = subObject[thisProp];
}
if (thisOp === REMOVE || thisOp === REPLACE) {
if (thisOp === REMOVE || thisOp === REPLACE || thisOp === MOVE) {
var path = thisOp === MOVE ? thisDiff.from : thisDiff.path;
if (!subObject.hasOwnProperty(lastProp)) {
throw new Error(['expected to find property', thisDiff.path, 'in object', obj].join(' '));
throw new Error(['expected to find property', path, 'in object', obj].join(' '));
}
}
if (thisOp === REMOVE) {
if (thisOp === REMOVE || thisOp === MOVE) {
if (thisOp === MOVE) {
valueToMove = subObject[lastProp];
}
Array.isArray(subObject) ? subObject.splice(lastProp, 1) : delete subObject[lastProp];
}
if (thisOp === REPLACE || thisOp === ADD) {
subObject[lastProp] = thisDiff.value;
}

if (thisOp === MOVE) {
subObject[lastToProp] = valueToMove;
}
}
return subObject;
}

function transformPath(pathConverter, thisPath) {
if(pathConverter) {
thisPath = pathConverter(thisPath);
if(!Array.isArray(thisPath)) {
throw new Error([
'pathConverter must return an array, returned:',
thisPath,
].join(' '));
}
} else {
if(!Array.isArray(thisPath)) {
throw new Error([
'diff path',
thisPath,
'must be an array, consider supplying a path converter']
.join(' '));
}
}
return thisPath;
}

function jsonPatchPathConverter(stringPath) {
return stringPath.split('/').slice(1);
}

function prototypeCheck(prop) {
// coercion is intentional to catch prop values like `['__proto__']`
if (prop == '__proto__' || prop == 'constructor' || prop == 'prototype') {
throw new Error('setting of prototype values not supported');
}
}
25 changes: 13 additions & 12 deletions node_modules/just-diff-apply/index.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -65,36 +65,30 @@ function diffApply(obj, diff, pathConverter) {
}
} else {
if (!Array.isArray(thisPath)) {
throw new Error(
'diff path must be an array, consider supplying a path converter'
);
throw new Error('diff path must be an array, consider supplying a path converter');
}
}
var pathCopy = thisPath.slice();
var lastProp = pathCopy.pop();
prototypeCheck(lastProp);
if (lastProp == null) {
return false;
}
var thisProp;
while ((thisProp = pathCopy.shift()) != null) {
while (((thisProp = pathCopy.shift())) != null) {
prototypeCheck(thisProp);
if (!(thisProp in subObject)) {
subObject[thisProp] = {};
}
subObject = subObject[thisProp];
}
if (thisOp === REMOVE || thisOp === REPLACE) {
if (!subObject.hasOwnProperty(lastProp)) {
throw new Error(
['expected to find property', thisDiff.path, 'in object', obj].join(
' '
)
);
throw new Error(['expected to find property', thisDiff.path, 'in object', obj].join(' '));
}
}
if (thisOp === REMOVE) {
Array.isArray(subObject)
? subObject.splice(lastProp, 1)
: delete subObject[lastProp];
Array.isArray(subObject) ? subObject.splice(lastProp, 1) : delete subObject[lastProp];
}
if (thisOp === REPLACE || thisOp === ADD) {
subObject[lastProp] = thisDiff.value;
Expand All @@ -107,4 +101,11 @@ function jsonPatchPathConverter(stringPath) {
return stringPath.split('/').slice(1);
}

function prototypeCheck(prop) {
// coercion is intentional to catch prop values like `['__proto__']`
if (prop == '__proto__' || prop == 'constructor' || prop == 'prototype') {
throw new Error('setting of prototype values not supported');
}
}

export {diffApply, jsonPatchPathConverter};
108 changes: 108 additions & 0 deletions node_modules/just-diff-apply/index.tests.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import * as diffObj from "./index";

const { diffApply, jsonPatchPathConverter } = diffObj;
const obj1 = {
a: 2,
b: 3,
c: {
d: 5
}
};
const arr1 = [1, "bee"];

const objOps: diffObj.DiffOps = [
{
op: "replace",
path: ["a"],
value: 10
},
{
op: "remove",
path: ["b"]
},
{
op: "add",
path: ["e"],
value: 15
},
{
op: "remove",
path: ["c", "d"]
}
];

const arrOps: diffObj.DiffOps = [
{
op: "replace",
path: [1],
value: 10
},
{
op: "remove",
path: [2]
},
{
op: "add",
path: [7],
value: 15
}
];

//OK
diffApply(obj1, objOps);
diffApply(obj1, []);
diffApply(arr1, arrOps);
diffApply(arr1, []);
diffApply(obj1, objOps, jsonPatchPathConverter);
diffApply(arr1, arrOps, jsonPatchPathConverter);

// not OK
// @ts-expect-error
diffApply(obj1);
// @ts-expect-error
diffApply(arr2);
// @ts-expect-error
diffApply("a");
// @ts-expect-error
diffApply(true);

// @ts-expect-error
diffApply(obj1, 1);
// @ts-expect-error
diffApply(3, arr2);
// @ts-expect-error
diffApply(obj1, "a");
// @ts-expect-error
diffApply("b", arr2);

// @ts-expect-error
diffApply(obj1, [{ op: "delete", path: ["a"] }]);
// @ts-expect-error
diffApply(obj1, [{ op: "delete", path: ["a"] }], jsonPatchPathConverter);
// @ts-expect-error
diffApply(obj1, "a", jsonPatchPathConverter);
// @ts-expect-error
diffApply(obj1, ["a", "b", "c"], jsonPatchPathConverter);

// @ts-expect-error
diff("a", jsonPatchPathConverter);
// @ts-expect-error
diff(true, jsonPatchPathConverter);

// @ts-expect-error
diff(obj1, 1, jsonPatchPathConverter);
// @ts-expect-error
diff(3, arr2, jsonPatchPathConverter);
// @ts-expect-error
diff(obj1, "a", jsonPatchPathConverter);
// @ts-expect-error
diff("b", arr2, jsonPatchPathConverter);

// @ts-expect-error
diff(obj1, obj2, "a");
// @ts-expect-error
diff(arr1, arr2, 1);
// @ts-expect-error
diff(obj1, arr1, "bee");
// @ts-expect-error
diff(obj2, arr2, "nope");
3 changes: 2 additions & 1 deletion node_modules/just-diff-apply/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "just-diff-apply",
"version": "4.0.1",
"version": "5.2.0",
"description": "Apply a diff to an object. Optionally supports jsonPatch protocol",
"main": "index.js",
"module": "index.mjs",
Expand All @@ -10,6 +10,7 @@
"default": "./index.mjs"
}
},
"types": "index.d.ts",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"build": "rollup -c"
Expand Down
29 changes: 17 additions & 12 deletions node_modules/parse-conflict-json/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "parse-conflict-json",
"version": "2.0.1",
"version": "2.0.2",
"description": "Parse a JSON string that has git merge conflicts, resolving if possible",
"author": "GitHub Inc.",
"license": "ISC",
Expand All @@ -11,34 +11,39 @@
"preversion": "npm test",
"postversion": "npm publish",
"postpublish": "git push origin --follow-tags",
"lint": "eslint '**/*.js'",
"postlint": "npm-template-check",
"lint": "eslint \"**/*.js\"",
"postlint": "template-oss-check",
"lintfix": "npm run lint -- --fix",
"prepublishOnly": "git push origin --follow-tags",
"posttest": "npm run lint"
"posttest": "npm run lint",
"template-oss-apply": "template-oss-apply --force"
},
"tap": {
"check-coverage": true
},
"devDependencies": {
"@npmcli/template-oss": "^2.3.1",
"tap": "^15.1.5"
"@npmcli/eslint-config": "^3.0.1",
"@npmcli/template-oss": "3.2.0",
"tap": "^16.0.1"
},
"dependencies": {
"json-parse-even-better-errors": "^2.3.1",
"just-diff": "^5.0.1",
"just-diff-apply": "^4.0.1"
"just-diff-apply": "^5.2.0"
},
"repository": {
"type": "git",
"url": "git+https://github.com/npm/parse-conflict-json.git"
"url": "https://github.com/npm/parse-conflict-json.git"
},
"files": [
"bin",
"lib"
"bin/",
"lib/"
],
"templateVersion": "2.3.1",
"engines": {
"node": "^12.13.0 || ^14.15.0 || >=16"
"node": "^12.13.0 || ^14.15.0 || >=16.0.0"
},
"templateOSS": {
"//@npmcli/template-oss": "This file is partially managed by @npmcli/template-oss. Edits may be overwritten.",
"version": "3.2.0"
}
}
Loading

0 comments on commit da377ee

Please sign in to comment.