@jay-framework/json-patch 0.9.0 → 0.10.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,29 +1,35 @@
1
- declare const ADD = "add";
2
- declare const REPLACE = "replace";
3
- declare const REMOVE = "remove";
4
- declare const MOVE = "move";
5
- type JSONPointer = (string | number)[];
6
- interface JSONPatchAdd {
1
+ type Prev = [never, 0, 1, 2, 3, 4, 5, 6, 7, ...0[]];
2
+ type Paths<T, Depth extends number = 7> = Depth extends 0 ? never : T extends object ? {
3
+ [K in keyof T]: K extends string | number ? T[K] extends any[] ? [K] | [K, number] | (T[K][number] extends object ? [K, number, ...Paths<T[K][number], Prev[Depth]>] : never) : T[K] extends object ? [K] | [K, ...Paths<T[K], Prev[Depth]>] : [K] : never;
4
+ }[keyof T] : never;
5
+ declare const ADD: "add";
6
+ declare const REPLACE: "replace";
7
+ declare const REMOVE: "remove";
8
+ declare const MOVE: "move";
9
+ type IsAny<T> = 0 extends 1 & T ? true : false;
10
+ type IsUnknown<T> = unknown extends T ? (T extends unknown ? true : false) : false;
11
+ type JSONPointer<T = unknown> = IsAny<T> extends true ? (string | number)[] : IsUnknown<T> extends true ? (string | number)[] : [T] extends [never] ? (string | number)[] : Paths<T> extends never ? (string | number)[] : Paths<T>;
12
+ interface JSONPatchAdd<T = unknown> {
7
13
  op: typeof ADD;
8
- path: JSONPointer;
14
+ path: JSONPointer<T>;
9
15
  value: any;
10
16
  }
11
- interface JSONPatchReplace {
17
+ interface JSONPatchReplace<T = unknown> {
12
18
  op: typeof REPLACE;
13
- path: JSONPointer;
19
+ path: JSONPointer<T>;
14
20
  value: any;
15
21
  }
16
- interface JSONPatchRemove {
22
+ interface JSONPatchRemove<T = unknown> {
17
23
  op: typeof REMOVE;
18
- path: JSONPointer;
24
+ path: JSONPointer<T>;
19
25
  }
20
- interface JSONPatchMove {
26
+ interface JSONPatchMove<T = unknown> {
21
27
  op: typeof MOVE;
22
- from: JSONPointer;
23
- path: JSONPointer;
28
+ from: JSONPointer<T>;
29
+ path: JSONPointer<T>;
24
30
  }
25
- type JSONPatchOperation = JSONPatchAdd | JSONPatchReplace | JSONPatchRemove | JSONPatchMove;
26
- type JSONPatch = JSONPatchOperation[];
31
+ type JSONPatchOperation<T = unknown> = JSONPatchAdd<T> | JSONPatchReplace<T> | JSONPatchRemove<T> | JSONPatchMove<T>;
32
+ type JSONPatch<T = unknown> = JSONPatchOperation<T>[];
27
33
 
28
34
  type MeasureOfChange = number;
29
35
  type DataFields = number;
@@ -33,6 +39,6 @@ type ArrayContext = {
33
39
  type ArrayContexts = [JSONPointer, ArrayContext][];
34
40
  declare function diff<T>(newValue: T, oldValue: T, contexts?: ArrayContexts, path?: JSONPointer): [JSONPatch, MeasureOfChange, DataFields];
35
41
 
36
- declare function patch<T>(target: T, jsonPatch: JSONPatch, level?: number): T;
42
+ declare function patch<T>(target: T, jsonPatch: JSONPatch<T>, level?: number): T;
37
43
 
38
44
  export { ADD, type ArrayContexts, type JSONPatch, type JSONPatchAdd, type JSONPatchMove, type JSONPatchOperation, type JSONPatchRemove, type JSONPatchReplace, type JSONPointer, MOVE, REMOVE, REPLACE, diff, patch };
package/dist/index.js CHANGED
@@ -113,41 +113,51 @@ function validateMove({ from, path }) {
113
113
  function patch(target, jsonPatch, level = 0) {
114
114
  const copy = Array.isArray(target) ? [...target] : { ...target };
115
115
  let equalCount = 0;
116
- const patchesGroupedByProp = jsonPatch.reduce((prev, patchOperation) => {
117
- const pathItem = patchOperation.path[level];
116
+ const patchesGroupedByProp = {};
117
+ for (const patchOperation of jsonPatch) {
118
+ const path = patchOperation.path;
119
+ const pathItem = path[level];
118
120
  const op = patchOperation.op;
119
- if (patchOperation.path.length - 1 === level) {
121
+ if (path.length - 1 === level) {
120
122
  if (op === REPLACE || op === ADD) {
121
- if (Array.isArray(copy) && op === ADD)
122
- copy.splice(pathItem, 0, patchOperation.value);
123
- else if (copy[pathItem] === patchOperation.value)
123
+ if (Array.isArray(copy) && op === ADD) {
124
+ copy.splice(
125
+ pathItem,
126
+ 0,
127
+ patchOperation.value
128
+ );
129
+ } else if (copy[pathItem] === patchOperation.value) {
124
130
  equalCount += 1;
125
- else
131
+ } else {
126
132
  copy[pathItem] = patchOperation.value;
133
+ }
127
134
  } else if (op === REMOVE) {
128
135
  if (Array.isArray(copy))
129
136
  copy.splice(pathItem, 1);
130
137
  else
131
138
  delete copy[pathItem];
132
139
  } else if (op === MOVE && Array.isArray(copy) && validateMove(patchOperation)) {
133
- let [item] = copy.splice(patchOperation.from[level], 1);
140
+ const fromPath = patchOperation.from;
141
+ const [item] = copy.splice(fromPath[level], 1);
134
142
  copy.splice(pathItem, 0, item);
135
143
  }
136
- } else if (!prev[pathItem])
137
- prev[pathItem] = [patchOperation];
138
- else
139
- prev[pathItem].push(patchOperation);
140
- return prev;
141
- }, {});
142
- Object.keys(patchesGroupedByProp).forEach((key) => {
144
+ } else if (!patchesGroupedByProp[pathItem]) {
145
+ patchesGroupedByProp[pathItem] = [patchOperation];
146
+ } else {
147
+ patchesGroupedByProp[pathItem].push(patchOperation);
148
+ }
149
+ }
150
+ for (const key of Object.keys(patchesGroupedByProp)) {
143
151
  if (copy[key]) {
152
+ const targetVal = target[key];
144
153
  const patched = patch(copy[key], patchesGroupedByProp[key], level + 1);
145
- if (target[key] === patched)
154
+ if (targetVal === patched) {
146
155
  equalCount += patchesGroupedByProp[key].length;
147
- else
148
- copy[key] = patch(copy[key], patchesGroupedByProp[key], level + 1);
156
+ } else {
157
+ copy[key] = patched;
158
+ }
149
159
  }
150
- });
160
+ }
151
161
  if (equalCount === jsonPatch.length)
152
162
  return target;
153
163
  else
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jay-framework/json-patch",
3
- "version": "0.9.0",
3
+ "version": "0.10.0",
4
4
  "type": "module",
5
5
  "license": "Apache-2.0",
6
6
  "main": "./dist/index.js",
@@ -20,10 +20,10 @@
20
20
  "test:watch": "vitest"
21
21
  },
22
22
  "dependencies": {
23
- "@jay-framework/list-compare": "^0.9.0"
23
+ "@jay-framework/list-compare": "^0.10.0"
24
24
  },
25
25
  "devDependencies": {
26
- "@jay-framework/dev-environment": "^0.9.0",
26
+ "@jay-framework/dev-environment": "^0.10.0",
27
27
  "@types/node": "^20.11.5",
28
28
  "rimraf": "^5.0.5",
29
29
  "tsup": "^8.0.1",