@potmot/diff 0.0.0 → 0.0.1

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/README.md CHANGED
@@ -23,3 +23,266 @@ yarn add @potmot/diff
23
23
  ```bash
24
24
  pnpm add @potmot/diff
25
25
  ```
26
+
27
+ ## 使用方法
28
+
29
+ ### 1. deepEquals - 深度相等比较
30
+
31
+ 用于深度比较两个值是否相等,支持对象、数组和嵌套结构。
32
+
33
+ ```typescript
34
+ import { deepEquals } from '@potmot/diff';
35
+
36
+ // 基本类型比较
37
+ deepEquals(1, 1); // true
38
+ deepEquals('hello', 'world'); // false
39
+
40
+ // 对象比较
41
+ deepEquals({ a: 1, b: 2 }, { a: 1, b: 2 }); // true
42
+ deepEquals({ a: 1 }, { a: 1, b: 2 }); // false
43
+
44
+ // 嵌套对象比较
45
+ deepEquals({ a: { b: { c: 1 } } }, { a: { b: { c: 1 } } }); // true
46
+
47
+ // 数组比较
48
+ deepEquals([1, 2, 3], [1, 2, 3]); // true
49
+ deepEquals([1, 2], [1, 2, 3]); // false
50
+ ```
51
+
52
+ ### 2. objectDiff - 对象差异分析
53
+
54
+ 比较两个对象的差异,返回新增、删除和更新的属性。
55
+
56
+ ```typescript
57
+ import { objectDiff } from '@potmot/diff';
58
+
59
+ // 基本使用
60
+ const oldObj = { a: 1, b: 2, c: 3 };
61
+ const newObj = { a: 1, b: 4, d: 5 };
62
+
63
+ const result = objectDiff(oldObj, newObj);
64
+ /*
65
+ result = {
66
+ type: 'object',
67
+ deleted: {
68
+ c: { propertyName: 'c', value: 3 }
69
+ },
70
+ added: {
71
+ d: { propertyName: 'd', value: 5 }
72
+ },
73
+ updated: {
74
+ b: {
75
+ propertyName: 'b',
76
+ prevValue: 2,
77
+ nextValue: 4,
78
+ diff: undefined
79
+ }
80
+ }
81
+ }
82
+ */
83
+
84
+ // 嵌套对象比较
85
+ const oldUser = {
86
+ name: 'John',
87
+ address: {
88
+ city: 'Beijing',
89
+ zip: '100000'
90
+ }
91
+ };
92
+
93
+ const newUser = {
94
+ name: 'John',
95
+ address: {
96
+ city: 'Shanghai',
97
+ zip: '100000'
98
+ }
99
+ };
100
+
101
+ const diff = objectDiff(oldUser, newUser);
102
+ /*
103
+ diff = {
104
+ type: 'object',
105
+ updated: {
106
+ address: {
107
+ propertyName: 'address',
108
+ prevValue: { city: 'Beijing', zip: '100000' },
109
+ nextValue: { city: 'Shanghai', zip: '100000' },
110
+ diff: {
111
+ type: 'object',
112
+ updated: {
113
+ city: {
114
+ propertyName: 'city',
115
+ prevValue: 'Beijing',
116
+ nextValue: 'Shanghai',
117
+ diff: undefined
118
+ }
119
+ }
120
+ }
121
+ }
122
+ }
123
+ }
124
+ */
125
+
126
+ // 处理 null/undefined
127
+ objectDiff(null, { a: 1 }); // 所有属性都是新增
128
+ objectDiff({ a: 1 }, null); // 所有属性都是删除
129
+ ```
130
+
131
+ ### 3. arrayDiff - 数组差异分析
132
+
133
+ 比较两个数组的差异,支持元素新增、删除、更新和移动检测。
134
+
135
+ ```typescript
136
+ import { arrayDiff } from '@potmot/diff';
137
+
138
+ // 定义匹配函数(用于识别同一元素)
139
+ const matchById = (a, b) => a.id === b.id;
140
+
141
+ const oldList = [
142
+ { id: 1, name: 'Item 1', value: 'A' },
143
+ { id: 2, name: 'Item 2', value: 'B' },
144
+ { id: 3, name: 'Item 3', value: 'C' }
145
+ ];
146
+
147
+ const newList = [
148
+ { id: 2, name: 'Item 2', value: 'B' }, // 相等
149
+ { id: 1, name: 'Item 1', value: 'A Updated' }, // 更新
150
+ { id: 4, name: 'Item 4', value: 'D' } // 新增
151
+ // id: 3 被删除
152
+ ];
153
+
154
+ const result = arrayDiff(oldList, newList, [matchById]);
155
+ /*
156
+ result = {
157
+ type: 'array',
158
+ added: [
159
+ { data: { id: 4, name: 'Item 4', value: 'D' }, nextIndex: 2 }
160
+ ],
161
+ updated: [
162
+ {
163
+ prevData: { id: 1, name: 'Item 1', value: 'A' },
164
+ prevIndex: 0,
165
+ nextData: { id: 1, name: 'Item 1', value: 'A Updated' },
166
+ nextIndex: 1,
167
+ diff: {
168
+ type: 'object',
169
+ updated: {
170
+ value: {
171
+ propertyName: 'value',
172
+ prevValue: 'A',
173
+ nextValue: 'A Updated',
174
+ diff: undefined
175
+ }
176
+ }
177
+ }
178
+ }
179
+ ],
180
+ deleted: [
181
+ { data: { id: 3, name: 'Item 3', value: 'C' }, prevIndex: 2 }
182
+ ],
183
+ moved: [
184
+ { data: { id: 2, name: 'Item 2', value: 'B' }, prevIndex: 1, nextIndex: 0 }
185
+ ],
186
+ equals: []
187
+ }
188
+ */
189
+ ```
190
+
191
+ ### 4. 高级用法
192
+
193
+ #### 多条件匹配
194
+
195
+ ```typescript
196
+ // 使用多个匹配函数进行更精确的对比
197
+ const matchByNameAndValue = [
198
+ (a, b) => a.name === b.name,
199
+ (a, b) => a.value === b.value
200
+ ];
201
+
202
+ const result = arrayDiff(oldList, newList, matchByNameAndValue);
203
+ ```
204
+
205
+ #### 自定义深度比较函数
206
+
207
+ ```typescript
208
+ // 为 objectDiff 提供自定义的深度比较函数
209
+ const customDeepMatch = [
210
+ (a, b) => {
211
+ // 如果都有 name 属性,则通过 name 判断是否相等
212
+ if ('name' in a && 'name' in b) {
213
+ return a.name === b.name;
214
+ }
215
+ return false;
216
+ }
217
+ ];
218
+
219
+ const result = objectDiff(oldObj, newObj, customDeepMatch);
220
+ ```
221
+
222
+ #### 循环引用处理
223
+
224
+ ```typescript
225
+ // 自动检测和处理循环引用
226
+ const obj1 = { a: 1 };
227
+ obj1.self = obj1; // 循环引用
228
+
229
+ const obj2 = { a: 2 };
230
+ obj2.self = obj2; // 循环引用
231
+
232
+ const result = objectDiff(obj1, obj2);
233
+ // {
234
+ // type: 'object',
235
+ // updated: {
236
+ // a: { propertyName: 'a', prevValue: 1, nextValue: 2, diff: undefined },
237
+ // self: {
238
+ // propertyName: 'self',
239
+ // prevValue: obj1,
240
+ // nextValue: obj2,
241
+ // diff: { type: 'circular reference' }
242
+ // }
243
+ // }
244
+ // }
245
+ ```
246
+
247
+ ## API 参考
248
+
249
+ ### deepEquals(a: any, b: any): boolean
250
+
251
+ 深度比较两个值是否相等。
252
+
253
+ **参数:**
254
+ - `a` - 第一个值
255
+ - `b` - 第二个值
256
+
257
+ **返回:** `boolean` - 如果两个值深度相等则返回 `true`
258
+
259
+ ---
260
+
261
+ ### objectDiff<T, U>(oldVal: T | undefined | null, newVal: U | undefined | null, deepMatchFnList?: Function[]): ObjectDiff | CircularReferenceDiff
262
+
263
+ 比较两个对象的差异。
264
+
265
+ **参数:**
266
+ - `oldVal` - 原始对象
267
+ - `newVal` - 新对象
268
+ - `deepMatchFnList` - 可选,自定义深度比较函数列表,默认匹配函数为`deepEquals`
269
+
270
+ **返回:** `ObjectDiff | CircularReferenceDiff` - 差异结果对象
271
+
272
+ ---
273
+
274
+ ### arrayDiff<T>(prevList: T[], nextList: T[], matchFnList: Function[], deepMatchFnList?: Function[]): ArrayDiff
275
+
276
+ 比较两个数组的差异。
277
+
278
+ **参数:**
279
+ - `prevList` - 原始数组
280
+ - `nextList` - 新数组
281
+ - `matchFnList` - 匹配函数列表,用于识别同一元素
282
+ - `deepMatchFnList` - 可选,自定义深度比较函数列表,默认匹配函数为`deepEquals`
283
+
284
+ **返回:** `ArrayDiff` - 差异结果对象,包含 `added`、`updated`、`deleted`、`moved`、`equals` 数组
285
+
286
+ ## 许可证
287
+
288
+ MIT
package/dist/index.d.ts CHANGED
@@ -1,3 +1,4 @@
1
+ export type { CircularReferenceDiff, ObjectDiff, PropertyAddedDiffItem, PropertyDeletedDiffItem, PropertyUpdatedDiffItem, ArrayDiff, ArrayAddedDiffItem, ArrayUpdatedDiffItem, ArrayDeletedDiffItem, ArrayMovedDiffItem, ArrayEqualsDiffItem, } from './type/DiffItem';
1
2
  export { deepEquals } from './deepEquals';
2
3
  export { arrayDiff } from './arrayDiff';
3
4
  export { objectDiff } from './objectDiff';
package/dist/index.js CHANGED
@@ -10,21 +10,21 @@ const j = (t, e) => {
10
10
  if (Array.isArray(t) && Array.isArray(e)) {
11
11
  if (t.length !== e.length)
12
12
  return !1;
13
- for (let o = 0; o < t.length; o++)
14
- if (!j(t[o], e[o]))
13
+ for (let c = 0; c < t.length; c++)
14
+ if (!j(t[c], e[c]))
15
15
  return !1;
16
16
  return !0;
17
17
  }
18
18
  if (Array.isArray(t) || Array.isArray(e))
19
19
  return !1;
20
- const i = Object.keys(t), s = Object.keys(e);
21
- if (i.length !== s.length)
20
+ const y = Object.keys(t), u = Object.keys(e);
21
+ if (y.length !== u.length)
22
22
  return !1;
23
- for (const o of i)
24
- if (!s.includes(o) || !j(t[o], e[o]))
23
+ for (const c of y)
24
+ if (!u.includes(c) || !j(t[c], e[c]))
25
25
  return !1;
26
26
  return !0;
27
- }, v = (t, e, i = [j], s = /* @__PURE__ */ new WeakSet(), o = /* @__PURE__ */ new WeakSet()) => {
27
+ }, l = (t, e, y = [j], u = /* @__PURE__ */ new WeakSet(), c = /* @__PURE__ */ new WeakSet()) => {
28
28
  if ((t == null || Object.keys(t).length === 0) && (e == null || Object.keys(e).length === 0))
29
29
  return { type: "object" };
30
30
  if (t == null || typeof t != "object") {
@@ -48,47 +48,53 @@ const j = (t, e) => {
48
48
  }), { type: "object", deleted: r };
49
49
  }
50
50
  if (typeof t == "object") {
51
- if (s.has(t))
51
+ if (u.has(t))
52
52
  return { type: "circular reference" };
53
- s.add(t);
53
+ u.add(t);
54
54
  }
55
55
  if (typeof e == "object") {
56
- if (o.has(e))
56
+ if (c.has(e))
57
57
  return { type: "circular reference" };
58
- o.add(e);
58
+ c.add(e);
59
59
  }
60
- const p = { type: "object" }, c = {};
60
+ const h = { type: "object" }, i = {};
61
61
  for (const r in t)
62
- r in e || (c[r] = {
62
+ r in e || (i[r] = {
63
63
  propertyName: r,
64
64
  value: t[r]
65
65
  });
66
- Object.keys(c).length > 0 && (p.deleted = c);
67
- const a = {};
66
+ Object.keys(i).length > 0 && (h.deleted = i);
67
+ const p = {};
68
68
  for (const r in e)
69
- r in t || (a[r] = {
69
+ r in t || (p[r] = {
70
70
  propertyName: r,
71
71
  value: e[r]
72
72
  });
73
- Object.keys(a).length > 0 && (p.added = a);
74
- const h = {};
73
+ Object.keys(p).length > 0 && (h.added = p);
74
+ const a = {};
75
75
  for (const r in t)
76
76
  if (r in e) {
77
77
  const f = r, n = r;
78
78
  if (!j(t[f], e[n])) {
79
- const y = t[f], d = e[n];
80
- let u;
81
- Array.isArray(y) && Array.isArray(d) ? u = x(y, d, i, i) : typeof y == "object" && typeof d == "object" && y !== null && d !== null && y !== void 0 && d !== void 0 && (u = v(y, d, i, s, o)), h[r] = {
79
+ const s = t[f], d = e[n];
80
+ let o;
81
+ Array.isArray(s) && Array.isArray(d) ? o = x(s, d, y, y) : s !== null && d !== null && s !== void 0 && d !== void 0 && typeof s == "object" && typeof d == "object" && (o = l(
82
+ s,
83
+ d,
84
+ y,
85
+ u,
86
+ c
87
+ )), a[r] = {
82
88
  propertyName: r,
83
89
  prevValue: t[f],
84
90
  nextValue: e[n],
85
- diff: u
91
+ diff: o
86
92
  };
87
93
  }
88
94
  }
89
- return Object.keys(h).length > 0 && (p.updated = h), p;
90
- }, x = (t, e, i, s = [j], o = /* @__PURE__ */ new WeakSet(), p = /* @__PURE__ */ new WeakSet()) => {
91
- const c = {
95
+ return Object.keys(a).length > 0 && (h.updated = a), h;
96
+ }, x = (t, e, y, u = [j], c = /* @__PURE__ */ new WeakSet(), h = /* @__PURE__ */ new WeakSet()) => {
97
+ const i = {
92
98
  type: "array",
93
99
  added: [],
94
100
  updated: [],
@@ -97,54 +103,60 @@ const j = (t, e) => {
97
103
  equals: []
98
104
  };
99
105
  if (!t && !e)
100
- return c;
106
+ return i;
101
107
  if (!t)
102
108
  return e?.forEach((r, f) => {
103
- c.added.push({ data: r, nextIndex: f });
104
- }), c;
109
+ i.added.push({ data: r, nextIndex: f });
110
+ }), i;
105
111
  if (!e)
106
112
  return t?.forEach((r, f) => {
107
- c.deleted.push({ data: r, prevIndex: f });
108
- }), c;
109
- const a = new Set(t.map((r, f) => ({ item: r, index: f }))), h = new Set(e.map((r, f) => ({ item: r, index: f })));
110
- for (const r of i)
111
- for (const f of a) {
112
- const { item: n, index: y } = f;
113
+ i.deleted.push({ data: r, prevIndex: f });
114
+ }), i;
115
+ const p = new Set(t.map((r, f) => ({ item: r, index: f }))), a = new Set(e.map((r, f) => ({ item: r, index: f })));
116
+ for (const r of y)
117
+ for (const f of p) {
118
+ const { item: n, index: s } = f;
113
119
  let d;
114
- for (const u of h)
115
- r(n, u.item) && (d = u);
120
+ for (const o of a)
121
+ r(n, o.item) && (d = o);
116
122
  if (d !== void 0) {
117
- const { item: u, index: k } = d;
118
- if (j(n, u))
119
- y === k ? c.equals.push({
120
- data: u,
121
- index: k
122
- }) : c.moved.push({
123
- data: u,
124
- prevIndex: y,
125
- nextIndex: k
123
+ const { item: o, index: v } = d;
124
+ if (j(n, o))
125
+ s === v ? i.equals.push({
126
+ data: o,
127
+ index: v
128
+ }) : i.moved.push({
129
+ data: o,
130
+ prevIndex: s,
131
+ nextIndex: v
126
132
  });
127
133
  else {
128
- const A = Array.isArray(n) && Array.isArray(u) ? x(n, u, s, s, o, p) : typeof n == "object" && typeof u == "object" ? v(n, u, s, o, p) : void 0;
129
- c.updated.push({
134
+ let k;
135
+ Array.isArray(n) && Array.isArray(o) ? k = x(n, o, u, u) : n !== null && o !== null && n !== void 0 && o !== void 0 && typeof n == "object" && typeof o == "object" && (k = l(
136
+ n,
137
+ o,
138
+ u,
139
+ c,
140
+ h
141
+ )), i.updated.push({
130
142
  prevData: n,
131
- prevIndex: y,
132
- nextData: u,
133
- nextIndex: k,
134
- diff: A
143
+ prevIndex: s,
144
+ nextData: o,
145
+ nextIndex: v,
146
+ diff: k
135
147
  });
136
148
  }
137
- a.delete(f), h.delete(d);
149
+ p.delete(f), a.delete(d);
138
150
  }
139
151
  }
140
- return a.forEach(({ item: r, index: f }) => {
141
- c.deleted.push({ data: r, prevIndex: f });
142
- }), h.forEach(({ item: r, index: f }) => {
143
- c.added.push({ data: r, nextIndex: f });
144
- }), c;
152
+ return p.forEach(({ item: r, index: f }) => {
153
+ i.deleted.push({ data: r, prevIndex: f });
154
+ }), a.forEach(({ item: r, index: f }) => {
155
+ i.added.push({ data: r, nextIndex: f });
156
+ }), i;
145
157
  };
146
158
  export {
147
159
  x as arrayDiff,
148
160
  j as deepEquals,
149
- v as objectDiff
161
+ l as objectDiff
150
162
  };
@@ -1 +1 @@
1
- (function(p,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(p=typeof globalThis<"u"?globalThis:p||self,u(p["@potmot/diff"]={}))})(this,(function(p){"use strict";const u=(t,e)=>{if(t===e)return!0;if(t===null||e===null||t===void 0||e===void 0)return t===e;if(typeof t!=typeof e)return!1;if(typeof t!="object")return t===e;if(Array.isArray(t)&&Array.isArray(e)){if(t.length!==e.length)return!1;for(let o=0;o<t.length;o++)if(!u(t[o],e[o]))return!1;return!0}if(Array.isArray(t)||Array.isArray(e))return!1;const a=Object.keys(t),s=Object.keys(e);if(a.length!==s.length)return!1;for(const o of a)if(!s.includes(o)||!u(t[o],e[o]))return!1;return!0},v=(t,e,a=[u],s=new WeakSet,o=new WeakSet)=>{if((t==null||Object.keys(t).length===0)&&(e==null||Object.keys(e).length===0))return{type:"object"};if(t==null||typeof t!="object"){const r={};return e!=null&&typeof e=="object"&&Object.keys(e).forEach(f=>{const n=f;r[n]={propertyName:n,value:e[n]}}),{type:"object",added:r}}if(e==null||typeof e!="object"){const r={};return Object.keys(t).forEach(f=>{const n=f;r[n]={propertyName:n,value:t[n]}}),{type:"object",deleted:r}}if(typeof t=="object"){if(s.has(t))return{type:"circular reference"};s.add(t)}if(typeof e=="object"){if(o.has(e))return{type:"circular reference"};o.add(e)}const h={type:"object"},i={};for(const r in t)r in e||(i[r]={propertyName:r,value:t[r]});Object.keys(i).length>0&&(h.deleted=i);const j={};for(const r in e)r in t||(j[r]={propertyName:r,value:e[r]});Object.keys(j).length>0&&(h.added=j);const k={};for(const r in t)if(r in e){const f=r,n=r;if(!u(t[f],e[n])){const y=t[f],c=e[n];let d;Array.isArray(y)&&Array.isArray(c)?d=l(y,c,a,a):typeof y=="object"&&typeof c=="object"&&y!==null&&c!==null&&y!==void 0&&c!==void 0&&(d=v(y,c,a,s,o)),k[r]={propertyName:r,prevValue:t[f],nextValue:e[n],diff:d}}}return Object.keys(k).length>0&&(h.updated=k),h},l=(t,e,a,s=[u],o=new WeakSet,h=new WeakSet)=>{const i={type:"array",added:[],updated:[],deleted:[],moved:[],equals:[]};if(!t&&!e)return i;if(!t)return e?.forEach((r,f)=>{i.added.push({data:r,nextIndex:f})}),i;if(!e)return t?.forEach((r,f)=>{i.deleted.push({data:r,prevIndex:f})}),i;const j=new Set(t.map((r,f)=>({item:r,index:f}))),k=new Set(e.map((r,f)=>({item:r,index:f})));for(const r of a)for(const f of j){const{item:n,index:y}=f;let c;for(const d of k)r(n,d.item)&&(c=d);if(c!==void 0){const{item:d,index:m}=c;if(u(n,d))y===m?i.equals.push({data:d,index:m}):i.moved.push({data:d,prevIndex:y,nextIndex:m});else{const b=Array.isArray(n)&&Array.isArray(d)?l(n,d,s,s,o,h):typeof n=="object"&&typeof d=="object"?v(n,d,s,o,h):void 0;i.updated.push({prevData:n,prevIndex:y,nextData:d,nextIndex:m,diff:b})}j.delete(f),k.delete(c)}}return j.forEach(({item:r,index:f})=>{i.deleted.push({data:r,prevIndex:f})}),k.forEach(({item:r,index:f})=>{i.added.push({data:r,nextIndex:f})}),i};p.arrayDiff=l,p.deepEquals=u,p.objectDiff=v,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
1
+ (function(p,u){typeof exports=="object"&&typeof module<"u"?u(exports):typeof define=="function"&&define.amd?define(["exports"],u):(p=typeof globalThis<"u"?globalThis:p||self,u(p["@potmot/diff"]={}))})(this,(function(p){"use strict";const u=(t,e)=>{if(t===e)return!0;if(t===null||e===null||t===void 0||e===void 0)return t===e;if(typeof t!=typeof e)return!1;if(typeof t!="object")return t===e;if(Array.isArray(t)&&Array.isArray(e)){if(t.length!==e.length)return!1;for(let d=0;d<t.length;d++)if(!u(t[d],e[d]))return!1;return!0}if(Array.isArray(t)||Array.isArray(e))return!1;const a=Object.keys(t),s=Object.keys(e);if(a.length!==s.length)return!1;for(const d of a)if(!s.includes(d)||!u(t[d],e[d]))return!1;return!0},k=(t,e,a=[u],s=new WeakSet,d=new WeakSet)=>{if((t==null||Object.keys(t).length===0)&&(e==null||Object.keys(e).length===0))return{type:"object"};if(t==null||typeof t!="object"){const r={};return e!=null&&typeof e=="object"&&Object.keys(e).forEach(f=>{const n=f;r[n]={propertyName:n,value:e[n]}}),{type:"object",added:r}}if(e==null||typeof e!="object"){const r={};return Object.keys(t).forEach(f=>{const n=f;r[n]={propertyName:n,value:t[n]}}),{type:"object",deleted:r}}if(typeof t=="object"){if(s.has(t))return{type:"circular reference"};s.add(t)}if(typeof e=="object"){if(d.has(e))return{type:"circular reference"};d.add(e)}const l={type:"object"},i={};for(const r in t)r in e||(i[r]={propertyName:r,value:t[r]});Object.keys(i).length>0&&(l.deleted=i);const h={};for(const r in e)r in t||(h[r]={propertyName:r,value:e[r]});Object.keys(h).length>0&&(l.added=h);const j={};for(const r in t)if(r in e){const f=r,n=r;if(!u(t[f],e[n])){const y=t[f],c=e[n];let o;Array.isArray(y)&&Array.isArray(c)?o=m(y,c,a,a):y!==null&&c!==null&&y!==void 0&&c!==void 0&&typeof y=="object"&&typeof c=="object"&&(o=k(y,c,a,s,d)),j[r]={propertyName:r,prevValue:t[f],nextValue:e[n],diff:o}}}return Object.keys(j).length>0&&(l.updated=j),l},m=(t,e,a,s=[u],d=new WeakSet,l=new WeakSet)=>{const i={type:"array",added:[],updated:[],deleted:[],moved:[],equals:[]};if(!t&&!e)return i;if(!t)return e?.forEach((r,f)=>{i.added.push({data:r,nextIndex:f})}),i;if(!e)return t?.forEach((r,f)=>{i.deleted.push({data:r,prevIndex:f})}),i;const h=new Set(t.map((r,f)=>({item:r,index:f}))),j=new Set(e.map((r,f)=>({item:r,index:f})));for(const r of a)for(const f of h){const{item:n,index:y}=f;let c;for(const o of j)r(n,o.item)&&(c=o);if(c!==void 0){const{item:o,index:v}=c;if(u(n,o))y===v?i.equals.push({data:o,index:v}):i.moved.push({data:o,prevIndex:y,nextIndex:v});else{let b;Array.isArray(n)&&Array.isArray(o)?b=m(n,o,s,s):n!==null&&o!==null&&n!==void 0&&o!==void 0&&typeof n=="object"&&typeof o=="object"&&(b=k(n,o,s,d,l)),i.updated.push({prevData:n,prevIndex:y,nextData:o,nextIndex:v,diff:b})}h.delete(f),j.delete(c)}}return h.forEach(({item:r,index:f})=>{i.deleted.push({data:r,prevIndex:f})}),j.forEach(({item:r,index:f})=>{i.added.push({data:r,nextIndex:f})}),i};p.arrayDiff=m,p.deepEquals=u,p.objectDiff=k,Object.defineProperty(p,Symbol.toStringTag,{value:"Module"})}));
@@ -1,8 +1,8 @@
1
1
  export type CircularReferenceDiff = {
2
- type: "circular reference";
2
+ type: 'circular reference';
3
3
  };
4
4
  export type ObjectDiff<T extends Record<string, unknown>, U extends Record<string, unknown> = T> = {
5
- type: "object";
5
+ type: 'object';
6
6
  updated?: {
7
7
  [K in keyof T & keyof U]?: PropertyUpdatedDiffItem<T, U, K>;
8
8
  };
@@ -21,11 +21,11 @@ export type PropertyDeletedDiffItem<T extends Record<string, unknown>, K extends
21
21
  propertyName: K;
22
22
  value: T[K];
23
23
  };
24
- export type PropertyUpdatedDiffItem<T extends Record<string, unknown>, U extends Record<string, unknown> = T, K extends (keyof T & keyof U) = (keyof T & keyof U)> = {
24
+ export type PropertyUpdatedDiffItem<T extends Record<string, unknown>, U extends Record<string, unknown> = T, K extends keyof T & keyof U = keyof T & keyof U> = {
25
25
  propertyName: K;
26
26
  prevValue: T[K];
27
27
  nextValue: U[K];
28
- diff?: (T[K] & U[K]) extends Array<infer Item> | ReadonlyArray<infer Item> ? ArrayDiff<Item> : (T[K] & U[K]) extends Record<string, unknown> ? ObjectDiff<T[K] & U[K], T[K] & U[K]> | CircularReferenceDiff : never;
28
+ diff?: T[K] & U[K] extends Array<infer Item> | ReadonlyArray<infer Item> ? ArrayDiff<Item> : T[K] & U[K] extends Record<string, unknown> ? ObjectDiff<T[K] & U[K], T[K] & U[K]> | CircularReferenceDiff : never;
29
29
  };
30
30
  export type ArrayAddedDiffItem<T> = {
31
31
  data: T;
@@ -52,7 +52,7 @@ export type ArrayEqualsDiffItem<T> = {
52
52
  index: number;
53
53
  };
54
54
  export type ArrayDiff<T> = {
55
- type: "array";
55
+ type: 'array';
56
56
  added: ArrayAddedDiffItem<T>[];
57
57
  updated: ArrayUpdatedDiffItem<T>[];
58
58
  deleted: ArrayDeletedDiffItem<T>[];
package/package.json CHANGED
@@ -1,9 +1,11 @@
1
1
  {
2
2
  "name": "@potmot/diff",
3
3
  "private": false,
4
- "version": "0.0.0",
4
+ "version": "0.0.1",
5
5
  "description": "Lightweight deep diff tool for JavaScript objects and arrays.",
6
- "keywords": ["diff"],
6
+ "keywords": [
7
+ "diff"
8
+ ],
7
9
  "homepage": "https://github.com/pot-mot/diff/blob/main/README.md",
8
10
  "repository": {
9
11
  "type": "git",
@@ -37,14 +39,24 @@
37
39
  },
38
40
  "scripts": {
39
41
  "build": "tsc & vite build",
40
- "test": "vitest run"
42
+ "test": "vitest run",
43
+ "lint:pritter": "prettier --write src/"
44
+ },
45
+ "lint-staged": {
46
+ "*.{js,ts,vue,json,css}": [
47
+ "prettier --write"
48
+ ]
41
49
  },
42
50
  "devDependencies": {
43
51
  "@tsconfig/node22": "^22.0.5",
44
52
  "@types/node": "^25.2.3",
53
+ "@vitest/coverage-v8": "3.2.4",
54
+ "husky": "^9.1.7",
55
+ "lint-staged": "^16.2.7",
56
+ "prettier": "^3.8.1",
45
57
  "typescript": "~5.9.3",
46
58
  "vite": "^7.3.1",
47
59
  "vite-plugin-dts": "^4.5.4",
48
- "vitest": "^4.0.18"
60
+ "vitest": "^3.2.4"
49
61
  }
50
62
  }