Skip to content

Commit 1226b8a

Browse files
authored
Merge pull request #26 from jg-rp/json-patch-fix
Fix move and copy to end of array with JSON Patch
2 parents 99aa9d6 + 73d570b commit 1226b8a

File tree

7 files changed

+2406
-3473
lines changed

7 files changed

+2406
-3473
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
# JSON P3 Change Log
22

3+
## Version 1.3.5 (unreleased)
4+
5+
**Fixes**
6+
7+
- Fixed a JSON Patch bug where we would not allow moving or copying to the end of an array using the special JSON Pointer token `-`.
8+
39
## Version 1.3.4
410

511
**Fixes**

package-lock.json

Lines changed: 2344 additions & 3443 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "json-p3",
3-
"version": "1.3.4",
3+
"version": "1.3.5",
44
"author": "James Prior",
55
"license": "MIT",
66
"description": "JSONPath, JSON Pointer and JSON Patch",
@@ -37,43 +37,43 @@
3737
"dist/**/*"
3838
],
3939
"devDependencies": {
40-
"@babel/cli": "^7.23.4",
41-
"@babel/core": "^7.23.7",
42-
"@babel/preset-env": "^7.23.7",
43-
"@babel/preset-typescript": "^7.23.3",
40+
"@babel/cli": "^7.25.9",
41+
"@babel/core": "^7.26.0",
42+
"@babel/preset-env": "^7.26.0",
43+
"@babel/preset-typescript": "^7.26.0",
4444
"@jest/globals": "^29.7.0",
4545
"@rollup/plugin-babel": "^6.0.4",
46-
"@rollup/plugin-commonjs": "^25.0.7",
47-
"@rollup/plugin-node-resolve": "^15.2.3",
48-
"@rollup/plugin-replace": "^5.0.5",
46+
"@rollup/plugin-commonjs": "^25.0.8",
47+
"@rollup/plugin-node-resolve": "^15.3.0",
48+
"@rollup/plugin-replace": "^5.0.7",
4949
"@rollup/plugin-terser": "^0.4.4",
50-
"@rollup/plugin-typescript": "^11.1.5",
51-
"@types/jest": "^29.5.11",
52-
"@typescript-eslint/eslint-plugin": "^6.17.0",
53-
"@typescript-eslint/parser": "^6.17.0",
54-
"eslint": "^8.56.0",
50+
"@rollup/plugin-typescript": "^11.1.6",
51+
"@types/jest": "^29.5.14",
52+
"@typescript-eslint/eslint-plugin": "^8.17.0",
53+
"@typescript-eslint/parser": "^8.17.0",
54+
"eslint": "^8.57.1",
5555
"eslint-config-prettier": "^9.1.0",
56-
"eslint-plugin-escompat": "^3.4.0",
56+
"eslint-plugin-escompat": "^3.11.4",
5757
"eslint-plugin-eslint-comments": "^3.2.0",
5858
"eslint-plugin-filenames": "^1.3.2",
59-
"eslint-plugin-github": "^4.10.1",
59+
"eslint-plugin-github": "^4.10.2",
6060
"eslint-plugin-i18n-text": "^1.0.1",
61-
"eslint-plugin-import": "^2.29.1",
61+
"eslint-plugin-import": "^2.31.0",
6262
"eslint-plugin-jsdoc": "^47.0.2",
63-
"eslint-plugin-n": "^16.6.1",
64-
"eslint-plugin-no-only-tests": "^3.1.0",
63+
"eslint-plugin-n": "^16.6.2",
64+
"eslint-plugin-no-only-tests": "^3.3.0",
6565
"eslint-plugin-node": "^11.1.0",
66-
"eslint-plugin-prettier": "^5.1.2",
67-
"eslint-plugin-promise": "^6.1.1",
66+
"eslint-plugin-prettier": "^5.2.1",
67+
"eslint-plugin-promise": "^6.6.0",
6868
"eslint-plugin-sonarjs": "^0.23.0",
6969
"eslint-plugin-tsdoc": "^0.2.17",
7070
"iregexp-check": "^0.1.1",
7171
"jest": "^29.7.0",
72-
"prettier": "^3.1.1",
73-
"rollup": "^4.9.2",
74-
"ts-jest": "^29.1.1",
75-
"tslib": "^2.6.2",
76-
"typescript": "^5.3.3"
72+
"prettier": "^3.4.2",
73+
"rollup": "^4.28.0",
74+
"ts-jest": "^29.2.5",
75+
"tslib": "^2.8.1",
76+
"typescript": "^5.7.2"
7777
},
7878
"keywords": [
7979
"JSON",

src/patch/patch.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -243,7 +243,11 @@ export class OpMove implements Op {
243243
}
244244

245245
if (isArray(destParent)) {
246-
destParent.splice(Number(destTarget), 0, sourceObj);
246+
if (destTarget === "-") {
247+
destParent.push(sourceObj);
248+
} else {
249+
destParent.splice(Number(destTarget), 0, sourceObj);
250+
}
247251
} else if (isObject(destParent)) {
248252
destParent[destTarget] = sourceObj;
249253
} else {
@@ -298,12 +302,16 @@ export class OpCopy implements Op {
298302
}
299303

300304
if (isArray(destParent)) {
301-
destParent.splice(Number(destTarget), 0, this.deepCopy(sourceObj));
305+
if (destTarget === "-") {
306+
destParent.push(this.deepCopy(sourceObj));
307+
} else {
308+
destParent.splice(Number(destTarget), 0, this.deepCopy(sourceObj));
309+
}
302310
} else if (isObject(destParent)) {
303311
destParent[destTarget] = this.deepCopy(sourceObj);
304312
} else {
305313
throw new JSONPatchError(
306-
`unexpected operation on '${typeof parent}' (${this.name}:${index})`,
314+
`unexpected operation on '${typeof destParent}' (${this.name}:${index})`,
307315
);
308316
}
309317

src/path/lru_cache.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,10 @@ export class LRUCache<K, V> extends Map<K, V> {
2626
if (this.has(key)) {
2727
this.delete(key);
2828
} else if (this.size >= this.maxSize) {
29-
this.delete(this.first());
29+
const first = this.first();
30+
if (first !== undefined) {
31+
this.delete(first);
32+
}
3033
}
3134
return super.set(key, value);
3235
}

tests/patch/patch.test.ts

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -142,4 +142,19 @@ describe("JSON Patch", () => {
142142
'"bar/" pointers must start with a slash or be the empty string (add:0)',
143143
);
144144
});
145+
test("move, end of array", () => {
146+
const data = { foo: { bar: [1, 2, 3] }, a: "b" };
147+
const patch = new JSONPatch().move("/a", "/foo/bar/-");
148+
expect(patch.apply(data)).toStrictEqual({
149+
foo: { bar: [1, 2, 3, "b"] },
150+
});
151+
});
152+
test("copy, end of array", () => {
153+
const data = { foo: { bar: [1, 2, 3] }, a: "b" };
154+
const patch = new JSONPatch().copy("/a", "/foo/bar/-");
155+
expect(patch.apply(data)).toStrictEqual({
156+
foo: { bar: [1, 2, 3, "b"] },
157+
a: "b",
158+
});
159+
});
145160
});

0 commit comments

Comments
 (0)