@sandboxed/diff 1.0.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/LICENSE +7 -0
- package/README.md +127 -0
- package/docs/config.md +165 -0
- package/docs/utils.md +76 -0
- package/lib/index.cjs +687 -0
- package/lib/index.cjs.map +1 -0
- package/lib/index.d.ts +87 -0
- package/lib/index.js +660 -0
- package/lib/index.js.map +1 -0
- package/package.json +68 -0
package/lib/index.cjs
ADDED
|
@@ -0,0 +1,687 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
ChangeType: () => ChangeType,
|
|
24
|
+
default: () => index_default
|
|
25
|
+
});
|
|
26
|
+
module.exports = __toCommonJS(index_exports);
|
|
27
|
+
|
|
28
|
+
// src/utils/constants.ts
|
|
29
|
+
var Iterables = /* @__PURE__ */ new Set([Object, Array, Set, Map]);
|
|
30
|
+
var ChangeType = /* @__PURE__ */ ((ChangeType2) => {
|
|
31
|
+
ChangeType2["ADD"] = "add";
|
|
32
|
+
ChangeType2["UPDATE"] = "update";
|
|
33
|
+
ChangeType2["REMOVE"] = "remove";
|
|
34
|
+
ChangeType2["NOOP"] = "noop";
|
|
35
|
+
return ChangeType2;
|
|
36
|
+
})(ChangeType || {});
|
|
37
|
+
var DefaultPathHints = {
|
|
38
|
+
map: "__MAP__",
|
|
39
|
+
set: "__SET__"
|
|
40
|
+
};
|
|
41
|
+
var MAX_DEPTH = 50;
|
|
42
|
+
var MAX_KEYS = 1e3;
|
|
43
|
+
var ITERATION_TIMEOUT_CHECK = 1e3;
|
|
44
|
+
var MAX_TIMEOUT_MS = 1e3;
|
|
45
|
+
var REDACTED = "*****";
|
|
46
|
+
|
|
47
|
+
// src/utils/fns.ts
|
|
48
|
+
function isPrimitive(value) {
|
|
49
|
+
return value !== Object(value);
|
|
50
|
+
}
|
|
51
|
+
function getRawValue(value) {
|
|
52
|
+
if (isPrimitive(value) && typeof value !== "symbol") return value;
|
|
53
|
+
return value.toString();
|
|
54
|
+
}
|
|
55
|
+
function isNullOrUndefined(value) {
|
|
56
|
+
return value === null || value === void 0;
|
|
57
|
+
}
|
|
58
|
+
function isCustomClassInstance(object) {
|
|
59
|
+
if (isNullOrUndefined(object) || typeof object !== "object" || !object.constructor) {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
return !object.constructor?.toString?.().includes("[native code]");
|
|
63
|
+
}
|
|
64
|
+
function emptyShellClone(object) {
|
|
65
|
+
if (isCustomClassInstance(object)) {
|
|
66
|
+
return Object.create(Object.getPrototypeOf(object));
|
|
67
|
+
}
|
|
68
|
+
if (isObject(object)) {
|
|
69
|
+
return /* @__PURE__ */ Object.create(null);
|
|
70
|
+
}
|
|
71
|
+
return new object.constructor();
|
|
72
|
+
}
|
|
73
|
+
function getWrapper(obj) {
|
|
74
|
+
let wrapper = ["{", "}"];
|
|
75
|
+
if (Array.isArray(obj)) {
|
|
76
|
+
wrapper = ["[", "]"];
|
|
77
|
+
} else if (isCustomClassInstance(obj)) {
|
|
78
|
+
wrapper = [`${obj.constructor.name} {`, "}"];
|
|
79
|
+
} else if (obj instanceof Map) {
|
|
80
|
+
wrapper = [`Map (${obj.size}) {`, "}"];
|
|
81
|
+
} else if (obj instanceof Set) {
|
|
82
|
+
wrapper = ["Set [", "]"];
|
|
83
|
+
}
|
|
84
|
+
return wrapper;
|
|
85
|
+
}
|
|
86
|
+
function getRef(value) {
|
|
87
|
+
return `ref<${value?.constructor?.name || typeof value}>`;
|
|
88
|
+
}
|
|
89
|
+
function isObject(obj) {
|
|
90
|
+
return obj !== null && typeof obj === "object" && (Object.getPrototypeOf(obj) === Object.prototype || Object.getPrototypeOf(obj) === null);
|
|
91
|
+
}
|
|
92
|
+
function areObjects(a, b) {
|
|
93
|
+
return isObject(a) && isObject(b);
|
|
94
|
+
}
|
|
95
|
+
function getEnumerableKeys(obj) {
|
|
96
|
+
return [...Object.keys(obj), ...Object.getOwnPropertySymbols(obj)];
|
|
97
|
+
}
|
|
98
|
+
function isIterable(obj) {
|
|
99
|
+
return Iterables.has(obj?.constructor) || isObject(obj) || isCustomClassInstance(obj);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// src/diff/shared.ts
|
|
103
|
+
function lastPathValue(changeType, value) {
|
|
104
|
+
return { deleted: changeType === "remove" /* REMOVE */, value };
|
|
105
|
+
}
|
|
106
|
+
function includeDiffType(type, config) {
|
|
107
|
+
return config.include?.includes?.(type) && !config.exclude?.includes?.(type);
|
|
108
|
+
}
|
|
109
|
+
function shouldRedactValue(key, config) {
|
|
110
|
+
const rawKey = getRawValue(key);
|
|
111
|
+
return config.redactKeys?.includes?.(rawKey);
|
|
112
|
+
}
|
|
113
|
+
function createReplacer(config) {
|
|
114
|
+
const seen = /* @__PURE__ */ new WeakSet();
|
|
115
|
+
return function replacer(k, v) {
|
|
116
|
+
if (v && typeof v === "object") {
|
|
117
|
+
if (seen.has(v)) return "[Circular]";
|
|
118
|
+
seen.add(v);
|
|
119
|
+
}
|
|
120
|
+
if (v instanceof Set) {
|
|
121
|
+
return `Set ${JSON.stringify([...v.values()], replacer)}`;
|
|
122
|
+
}
|
|
123
|
+
if (v instanceof Map) {
|
|
124
|
+
const entries = [...v.entries()];
|
|
125
|
+
const stringified = entries.map(
|
|
126
|
+
([key, value]) => `${JSON.stringify(key, replacer)}: ${JSON.stringify(shouldRedactValue(key, config) ? REDACTED : value, replacer)}`
|
|
127
|
+
).join(", ");
|
|
128
|
+
return `Map (${entries.length}) { ${stringified} }`;
|
|
129
|
+
}
|
|
130
|
+
if (v instanceof Function) {
|
|
131
|
+
return `Function ${v.name || "(anonymous)"}`;
|
|
132
|
+
}
|
|
133
|
+
if (typeof v === "symbol") {
|
|
134
|
+
return v.toString();
|
|
135
|
+
}
|
|
136
|
+
if (typeof v === "bigint") {
|
|
137
|
+
return `BigInt(${v.toString()})`;
|
|
138
|
+
}
|
|
139
|
+
return shouldRedactValue(k, config) ? REDACTED : v;
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
function stringify(obj, config) {
|
|
143
|
+
return JSON.stringify(obj, createReplacer(config));
|
|
144
|
+
}
|
|
145
|
+
function getObjectChangeResult(lhs, rhs, depth, key, parsedKey, config, path) {
|
|
146
|
+
const isLhsMap = lhs instanceof Map;
|
|
147
|
+
const isRhsMap = rhs instanceof Map;
|
|
148
|
+
let valueInLhs = lhs?.[key];
|
|
149
|
+
let valueInRhs = rhs?.[key];
|
|
150
|
+
let keyInLhs = Object.hasOwn(lhs, key);
|
|
151
|
+
let keyInRhs = Object.hasOwn(rhs, key);
|
|
152
|
+
if (isLhsMap) {
|
|
153
|
+
valueInLhs = lhs.get(key);
|
|
154
|
+
keyInLhs = lhs.has(key);
|
|
155
|
+
}
|
|
156
|
+
if (isRhsMap) {
|
|
157
|
+
valueInRhs = rhs.get(key);
|
|
158
|
+
keyInRhs = rhs.has(key);
|
|
159
|
+
}
|
|
160
|
+
const redactValue = shouldRedactValue(key, config);
|
|
161
|
+
const rawValueInLhs = getRawValue(valueInLhs);
|
|
162
|
+
const rawValueInRhs = getRawValue(valueInRhs);
|
|
163
|
+
const formattedValueInLhs = JSON.stringify(
|
|
164
|
+
redactValue ? REDACTED : rawValueInLhs,
|
|
165
|
+
createReplacer(config)
|
|
166
|
+
);
|
|
167
|
+
const formattedValueInRhs = JSON.stringify(
|
|
168
|
+
redactValue ? REDACTED : rawValueInRhs,
|
|
169
|
+
createReplacer(config)
|
|
170
|
+
);
|
|
171
|
+
let type = "noop" /* NOOP */;
|
|
172
|
+
let formattedValue = formattedValueInRhs;
|
|
173
|
+
let pathValue = valueInRhs;
|
|
174
|
+
if (!keyInLhs && keyInRhs) {
|
|
175
|
+
type = "add" /* ADD */;
|
|
176
|
+
} else if (keyInLhs && !keyInRhs) {
|
|
177
|
+
type = "remove" /* REMOVE */;
|
|
178
|
+
formattedValue = formattedValueInLhs;
|
|
179
|
+
pathValue = valueInLhs;
|
|
180
|
+
} else if (config.strict ? rawValueInLhs !== rawValueInRhs : rawValueInLhs != rawValueInRhs) {
|
|
181
|
+
type = "update" /* UPDATE */;
|
|
182
|
+
}
|
|
183
|
+
const result = [];
|
|
184
|
+
if (includeDiffType(type, config)) {
|
|
185
|
+
if (type === "update" /* UPDATE */ && !config.showUpdatedOnly) {
|
|
186
|
+
result.push({
|
|
187
|
+
type: "remove" /* REMOVE */,
|
|
188
|
+
str: `${JSON.stringify(parsedKey, createReplacer(config))}: ${formattedValueInLhs},`,
|
|
189
|
+
depth,
|
|
190
|
+
path: [...path, lastPathValue("remove" /* REMOVE */, valueInLhs)]
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
result.push({
|
|
194
|
+
type,
|
|
195
|
+
str: `${JSON.stringify(parsedKey, createReplacer(config))}: ${formattedValue},`,
|
|
196
|
+
depth,
|
|
197
|
+
path: [...path, lastPathValue(type, pathValue)]
|
|
198
|
+
});
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
function getPathHint(config, type) {
|
|
203
|
+
if (typeof config.pathHints === "object") {
|
|
204
|
+
const hint = config.pathHints[type];
|
|
205
|
+
if (typeof hint === "string") return hint;
|
|
206
|
+
}
|
|
207
|
+
return null;
|
|
208
|
+
}
|
|
209
|
+
function buildResult(rhs, result, depth, initialChangeType, parent, path, config) {
|
|
210
|
+
if (!includeDiffType(initialChangeType, config)) return result;
|
|
211
|
+
const parentDepth = depth - 1;
|
|
212
|
+
const [open, close] = getWrapper(rhs);
|
|
213
|
+
return [
|
|
214
|
+
{
|
|
215
|
+
type: initialChangeType,
|
|
216
|
+
str: parentDepth > 0 ? `${stringify(parent, config)}: ${open}` : open,
|
|
217
|
+
depth: parentDepth,
|
|
218
|
+
path
|
|
219
|
+
},
|
|
220
|
+
...result,
|
|
221
|
+
{
|
|
222
|
+
type: initialChangeType,
|
|
223
|
+
str: parentDepth > 0 ? `${close},` : close,
|
|
224
|
+
depth: parentDepth,
|
|
225
|
+
path
|
|
226
|
+
}
|
|
227
|
+
];
|
|
228
|
+
}
|
|
229
|
+
function timeoutSecurityCheck(startedAt, config) {
|
|
230
|
+
if (Date.now() - startedAt > config.timeout) {
|
|
231
|
+
throw new Error("Diff took too much time! Aborting.");
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
function maxKeysSecurityCheck(size, config) {
|
|
235
|
+
if (size > config.maxKeys) {
|
|
236
|
+
throw new Error("Object is too big to continue! Aborting.");
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// src/diff/diffObjects.ts
|
|
241
|
+
function diffObjects({
|
|
242
|
+
recursiveDiff: recursiveDiff2,
|
|
243
|
+
lhs,
|
|
244
|
+
rhs,
|
|
245
|
+
config,
|
|
246
|
+
depth,
|
|
247
|
+
parent,
|
|
248
|
+
seen,
|
|
249
|
+
initialChangeType,
|
|
250
|
+
path,
|
|
251
|
+
startedAt
|
|
252
|
+
}) {
|
|
253
|
+
const result = [];
|
|
254
|
+
const lhsKeys = getEnumerableKeys(lhs);
|
|
255
|
+
maxKeysSecurityCheck(lhsKeys.length, config);
|
|
256
|
+
const rhsKeys = getEnumerableKeys(rhs);
|
|
257
|
+
maxKeysSecurityCheck(rhsKeys.length, config);
|
|
258
|
+
const keys = /* @__PURE__ */ new Set([...lhsKeys, ...rhsKeys]);
|
|
259
|
+
let i = 0;
|
|
260
|
+
for (const key of keys) {
|
|
261
|
+
if (i++ % ITERATION_TIMEOUT_CHECK === 0) {
|
|
262
|
+
timeoutSecurityCheck(startedAt, config);
|
|
263
|
+
}
|
|
264
|
+
const lhsValue = Array.isArray(lhs) ? lhs[key] : lhs?.[key];
|
|
265
|
+
const rhsValue = Array.isArray(rhs) ? rhs[key] : rhs?.[key];
|
|
266
|
+
const numericKey = typeof key !== "symbol" ? Number(key) : NaN;
|
|
267
|
+
const parsedKey = isNaN(numericKey) ? key : numericKey;
|
|
268
|
+
const updatedPath = [...path, parsedKey];
|
|
269
|
+
if (isIterable(lhsValue) || isIterable(rhsValue)) {
|
|
270
|
+
result.push(
|
|
271
|
+
...recursiveDiff2({
|
|
272
|
+
lhs: lhsValue,
|
|
273
|
+
rhs: rhsValue,
|
|
274
|
+
config,
|
|
275
|
+
depth: depth + 1,
|
|
276
|
+
parent: parsedKey,
|
|
277
|
+
seen,
|
|
278
|
+
initialChangeType,
|
|
279
|
+
path: updatedPath,
|
|
280
|
+
startedAt
|
|
281
|
+
})
|
|
282
|
+
);
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
result.push(
|
|
286
|
+
...getObjectChangeResult(
|
|
287
|
+
lhs,
|
|
288
|
+
rhs,
|
|
289
|
+
depth,
|
|
290
|
+
key,
|
|
291
|
+
parsedKey,
|
|
292
|
+
config,
|
|
293
|
+
updatedPath
|
|
294
|
+
)
|
|
295
|
+
);
|
|
296
|
+
}
|
|
297
|
+
return buildResult(
|
|
298
|
+
rhs,
|
|
299
|
+
result,
|
|
300
|
+
depth,
|
|
301
|
+
initialChangeType,
|
|
302
|
+
parent,
|
|
303
|
+
path,
|
|
304
|
+
config
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
var diffObjects_default = diffObjects;
|
|
308
|
+
|
|
309
|
+
// src/diff/diffSets.ts
|
|
310
|
+
function diffSets({
|
|
311
|
+
recursiveDiff: recursiveDiff2,
|
|
312
|
+
lhs,
|
|
313
|
+
rhs,
|
|
314
|
+
config,
|
|
315
|
+
depth,
|
|
316
|
+
parent,
|
|
317
|
+
seen,
|
|
318
|
+
initialChangeType,
|
|
319
|
+
path,
|
|
320
|
+
startedAt
|
|
321
|
+
}) {
|
|
322
|
+
const result = [];
|
|
323
|
+
maxKeysSecurityCheck(lhs.size, config);
|
|
324
|
+
maxKeysSecurityCheck(rhs.size, config);
|
|
325
|
+
const mergedSet = /* @__PURE__ */ new Set([...lhs, ...rhs]);
|
|
326
|
+
let i = 0;
|
|
327
|
+
for (const value of mergedSet) {
|
|
328
|
+
if (i++ % ITERATION_TIMEOUT_CHECK === 0) {
|
|
329
|
+
timeoutSecurityCheck(startedAt, config);
|
|
330
|
+
}
|
|
331
|
+
const existsInLhs = lhs.has(value);
|
|
332
|
+
const existsInRhs = rhs.has(value);
|
|
333
|
+
const hint = getPathHint(config, "set");
|
|
334
|
+
const updatedPath = [...path];
|
|
335
|
+
if (hint) {
|
|
336
|
+
updatedPath.push(hint);
|
|
337
|
+
}
|
|
338
|
+
if (isIterable(value)) {
|
|
339
|
+
result.push(
|
|
340
|
+
...recursiveDiff2({
|
|
341
|
+
lhs: existsInLhs ? value : void 0,
|
|
342
|
+
rhs: existsInRhs ? value : void 0,
|
|
343
|
+
config,
|
|
344
|
+
depth: depth + 1,
|
|
345
|
+
parent: getRef(value),
|
|
346
|
+
seen,
|
|
347
|
+
initialChangeType,
|
|
348
|
+
path: updatedPath,
|
|
349
|
+
startedAt
|
|
350
|
+
})
|
|
351
|
+
);
|
|
352
|
+
continue;
|
|
353
|
+
}
|
|
354
|
+
let type = "noop" /* NOOP */;
|
|
355
|
+
if (existsInLhs && !existsInRhs) {
|
|
356
|
+
type = "remove" /* REMOVE */;
|
|
357
|
+
} else if (!existsInLhs && existsInRhs) {
|
|
358
|
+
type = "add" /* ADD */;
|
|
359
|
+
}
|
|
360
|
+
if (includeDiffType(type, config)) {
|
|
361
|
+
result.push({
|
|
362
|
+
type,
|
|
363
|
+
str: `${JSON.stringify(value)},`,
|
|
364
|
+
depth,
|
|
365
|
+
path: [...updatedPath, lastPathValue(type, value)]
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
return buildResult(
|
|
370
|
+
rhs,
|
|
371
|
+
result,
|
|
372
|
+
depth,
|
|
373
|
+
initialChangeType,
|
|
374
|
+
parent,
|
|
375
|
+
path,
|
|
376
|
+
config
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
var diffSets_default = diffSets;
|
|
380
|
+
|
|
381
|
+
// src/diff/diffMaps.ts
|
|
382
|
+
function diffMaps({
|
|
383
|
+
recursiveDiff: recursiveDiff2,
|
|
384
|
+
lhs,
|
|
385
|
+
rhs,
|
|
386
|
+
config,
|
|
387
|
+
depth,
|
|
388
|
+
parent,
|
|
389
|
+
seen,
|
|
390
|
+
initialChangeType,
|
|
391
|
+
path,
|
|
392
|
+
startedAt
|
|
393
|
+
}) {
|
|
394
|
+
const result = [];
|
|
395
|
+
maxKeysSecurityCheck(lhs.size, config);
|
|
396
|
+
maxKeysSecurityCheck(rhs.size, config);
|
|
397
|
+
const mergedMapKeys = /* @__PURE__ */ new Set([...lhs.keys(), ...rhs.keys()]);
|
|
398
|
+
let i = 0;
|
|
399
|
+
for (const key of mergedMapKeys) {
|
|
400
|
+
if (i++ % ITERATION_TIMEOUT_CHECK === 0) {
|
|
401
|
+
timeoutSecurityCheck(startedAt, config);
|
|
402
|
+
}
|
|
403
|
+
const keyInLhs = lhs.has(key);
|
|
404
|
+
const keyInRhs = rhs.has(key);
|
|
405
|
+
const lhsValue = keyInLhs ? lhs.get(key) : null;
|
|
406
|
+
const rhsValue = keyInRhs ? rhs.get(key) : null;
|
|
407
|
+
const hint = getPathHint(config, "map");
|
|
408
|
+
const pathUpdate = hint ? [hint, key] : [key];
|
|
409
|
+
const updatedPath = [...path, ...pathUpdate];
|
|
410
|
+
if (isIterable(lhsValue) || isIterable(rhsValue)) {
|
|
411
|
+
result.push(
|
|
412
|
+
...recursiveDiff2({
|
|
413
|
+
lhs: lhsValue,
|
|
414
|
+
rhs: rhsValue,
|
|
415
|
+
config,
|
|
416
|
+
depth: depth + 1,
|
|
417
|
+
parent: key,
|
|
418
|
+
seen,
|
|
419
|
+
initialChangeType,
|
|
420
|
+
path: updatedPath,
|
|
421
|
+
startedAt
|
|
422
|
+
})
|
|
423
|
+
);
|
|
424
|
+
continue;
|
|
425
|
+
}
|
|
426
|
+
result.push(
|
|
427
|
+
...getObjectChangeResult(lhs, rhs, depth, key, key, config, updatedPath)
|
|
428
|
+
);
|
|
429
|
+
}
|
|
430
|
+
return buildResult(
|
|
431
|
+
rhs,
|
|
432
|
+
result,
|
|
433
|
+
depth,
|
|
434
|
+
initialChangeType,
|
|
435
|
+
parent,
|
|
436
|
+
path,
|
|
437
|
+
config
|
|
438
|
+
);
|
|
439
|
+
}
|
|
440
|
+
var diffMaps_default = diffMaps;
|
|
441
|
+
|
|
442
|
+
// src/diff/diffConstructors.ts
|
|
443
|
+
function diffConstructors({
|
|
444
|
+
recursiveDiff: recursiveDiff2,
|
|
445
|
+
lhs,
|
|
446
|
+
rhs,
|
|
447
|
+
config,
|
|
448
|
+
depth,
|
|
449
|
+
parent,
|
|
450
|
+
seen,
|
|
451
|
+
initialChangeType,
|
|
452
|
+
path,
|
|
453
|
+
startedAt
|
|
454
|
+
}) {
|
|
455
|
+
let modLhs = lhs;
|
|
456
|
+
let modRhs = rhs;
|
|
457
|
+
let defaultChangeType = initialChangeType;
|
|
458
|
+
if (isObject(rhs) || rhs?.constructor) {
|
|
459
|
+
modLhs = emptyShellClone(rhs);
|
|
460
|
+
defaultChangeType = "add" /* ADD */;
|
|
461
|
+
} else if (isObject(lhs) || lhs?.constructor) {
|
|
462
|
+
modRhs = emptyShellClone(lhs);
|
|
463
|
+
defaultChangeType = "remove" /* REMOVE */;
|
|
464
|
+
} else {
|
|
465
|
+
throw new Error("Edge case raised, I don't know how to handle this input");
|
|
466
|
+
}
|
|
467
|
+
return recursiveDiff2({
|
|
468
|
+
lhs: modLhs,
|
|
469
|
+
rhs: modRhs,
|
|
470
|
+
config,
|
|
471
|
+
depth,
|
|
472
|
+
parent,
|
|
473
|
+
seen,
|
|
474
|
+
initialChangeType: defaultChangeType,
|
|
475
|
+
path,
|
|
476
|
+
startedAt
|
|
477
|
+
});
|
|
478
|
+
}
|
|
479
|
+
var diffConstructors_default = diffConstructors;
|
|
480
|
+
|
|
481
|
+
// src/diff/index.ts
|
|
482
|
+
function recursiveDiff({
|
|
483
|
+
lhs,
|
|
484
|
+
rhs,
|
|
485
|
+
config,
|
|
486
|
+
depth,
|
|
487
|
+
parent,
|
|
488
|
+
seen,
|
|
489
|
+
initialChangeType,
|
|
490
|
+
path,
|
|
491
|
+
startedAt
|
|
492
|
+
}) {
|
|
493
|
+
if (depth > config.maxDepth) {
|
|
494
|
+
throw new Error("Max depth exceeded!");
|
|
495
|
+
}
|
|
496
|
+
timeoutSecurityCheck(startedAt, config);
|
|
497
|
+
const lhsSeen = seen.get(lhs) ?? 0;
|
|
498
|
+
const rhsSeen = seen.get(rhs) ?? 0;
|
|
499
|
+
if (lhsSeen > 1 || rhsSeen > 1) {
|
|
500
|
+
if (!includeDiffType(initialChangeType, config)) return [];
|
|
501
|
+
return [
|
|
502
|
+
{
|
|
503
|
+
type: initialChangeType,
|
|
504
|
+
str: `${stringify(parent, config)}: [Circular],`,
|
|
505
|
+
depth: depth - 1,
|
|
506
|
+
path
|
|
507
|
+
}
|
|
508
|
+
];
|
|
509
|
+
}
|
|
510
|
+
if (typeof lhs === "object" && lhs !== null) seen.set(lhs, lhsSeen + 1);
|
|
511
|
+
if (typeof rhs === "object" && rhs !== null) seen.set(rhs, rhsSeen + 1);
|
|
512
|
+
const args = {
|
|
513
|
+
recursiveDiff,
|
|
514
|
+
lhs,
|
|
515
|
+
rhs,
|
|
516
|
+
config,
|
|
517
|
+
depth,
|
|
518
|
+
parent,
|
|
519
|
+
seen,
|
|
520
|
+
initialChangeType,
|
|
521
|
+
path,
|
|
522
|
+
startedAt
|
|
523
|
+
};
|
|
524
|
+
if (isPrimitive(lhs) && isPrimitive(rhs)) {
|
|
525
|
+
if (config.strict ? lhs === rhs : lhs == rhs) {
|
|
526
|
+
return [];
|
|
527
|
+
}
|
|
528
|
+
const parentDepth = depth - 1;
|
|
529
|
+
const lhsValue = JSON.stringify(lhs, createReplacer(config));
|
|
530
|
+
const rhsValue = JSON.stringify(rhs, createReplacer(config));
|
|
531
|
+
const result = [];
|
|
532
|
+
if (includeDiffType("update" /* UPDATE */, config)) {
|
|
533
|
+
if (!config.showUpdatedOnly) {
|
|
534
|
+
result.push({
|
|
535
|
+
type: "remove" /* REMOVE */,
|
|
536
|
+
str: `${lhsValue}`,
|
|
537
|
+
depth: parentDepth,
|
|
538
|
+
path: [...path, lastPathValue("remove" /* REMOVE */, lhs)]
|
|
539
|
+
});
|
|
540
|
+
}
|
|
541
|
+
result.push({
|
|
542
|
+
type: "update" /* UPDATE */,
|
|
543
|
+
str: `${rhsValue}`,
|
|
544
|
+
depth: parentDepth,
|
|
545
|
+
path: [...path, lastPathValue("update" /* UPDATE */, rhs)]
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
return result;
|
|
549
|
+
}
|
|
550
|
+
if (!areObjects(lhs, rhs) && // Skips for Object.create(null) vs {}
|
|
551
|
+
(lhs?.constructor !== rhs?.constructor || isNullOrUndefined(lhs) && rhs || lhs && isNullOrUndefined(rhs))) {
|
|
552
|
+
return diffConstructors_default(args);
|
|
553
|
+
}
|
|
554
|
+
if (lhs instanceof Set && rhs instanceof Set) {
|
|
555
|
+
return diffSets_default(args);
|
|
556
|
+
}
|
|
557
|
+
if (lhs instanceof Map && rhs instanceof Map) {
|
|
558
|
+
return diffMaps_default(args);
|
|
559
|
+
}
|
|
560
|
+
return diffObjects_default(args);
|
|
561
|
+
}
|
|
562
|
+
var diff_default = recursiveDiff;
|
|
563
|
+
|
|
564
|
+
// src/utils/toDiffString.ts
|
|
565
|
+
var ANSI_RESET = "\x1B[0m";
|
|
566
|
+
function colorWrapper(color) {
|
|
567
|
+
return (str) => `${color}${str}${ANSI_RESET}`;
|
|
568
|
+
}
|
|
569
|
+
var ansiColors = {
|
|
570
|
+
["remove" /* REMOVE */]: colorWrapper("\x1B[31m"),
|
|
571
|
+
["add" /* ADD */]: colorWrapper("\x1B[32m"),
|
|
572
|
+
["update" /* UPDATE */]: colorWrapper("\x1B[33m"),
|
|
573
|
+
["noop" /* NOOP */]: colorWrapper("")
|
|
574
|
+
};
|
|
575
|
+
function toDiffString(diff2, config) {
|
|
576
|
+
const defaultConfig = {
|
|
577
|
+
withColors: true,
|
|
578
|
+
colors: ansiColors,
|
|
579
|
+
wrapper: [],
|
|
580
|
+
indentSize: 2,
|
|
581
|
+
symbols: {
|
|
582
|
+
["add" /* ADD */]: "+",
|
|
583
|
+
["remove" /* REMOVE */]: "-",
|
|
584
|
+
["update" /* UPDATE */]: "!",
|
|
585
|
+
["noop" /* NOOP */]: ""
|
|
586
|
+
}
|
|
587
|
+
};
|
|
588
|
+
const mergedConfig = {
|
|
589
|
+
...defaultConfig,
|
|
590
|
+
...config,
|
|
591
|
+
colors: {
|
|
592
|
+
...defaultConfig.colors,
|
|
593
|
+
...config?.colors
|
|
594
|
+
},
|
|
595
|
+
symbols: {
|
|
596
|
+
...defaultConfig.symbols,
|
|
597
|
+
...config?.symbols
|
|
598
|
+
}
|
|
599
|
+
};
|
|
600
|
+
const diffString = diff2.map(({ type, str, depth }, index) => {
|
|
601
|
+
let symbolString = mergedConfig.symbols[type];
|
|
602
|
+
if (index > 0 && index < diff2.length - 1 && !symbolString.length) {
|
|
603
|
+
symbolString = ` ${mergedConfig.symbols[type]}`;
|
|
604
|
+
}
|
|
605
|
+
let buildStr = `${symbolString}${" ".repeat(depth * mergedConfig.indentSize)}${str}`;
|
|
606
|
+
if (mergedConfig.withColors) {
|
|
607
|
+
buildStr = mergedConfig.colors[type](buildStr);
|
|
608
|
+
}
|
|
609
|
+
return buildStr;
|
|
610
|
+
}).join("\n");
|
|
611
|
+
const [open = "", close = ""] = mergedConfig.wrapper || [];
|
|
612
|
+
return `${open ? `${open}
|
|
613
|
+
` : ""}${diffString}${close ? `
|
|
614
|
+
${close}` : ""}`;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
// src/index.ts
|
|
618
|
+
function diff(lhs, rhs, config) {
|
|
619
|
+
const defaultConfig = {
|
|
620
|
+
include: [
|
|
621
|
+
"add" /* ADD */,
|
|
622
|
+
"remove" /* REMOVE */,
|
|
623
|
+
"update" /* UPDATE */,
|
|
624
|
+
"noop" /* NOOP */
|
|
625
|
+
],
|
|
626
|
+
exclude: [],
|
|
627
|
+
strict: true,
|
|
628
|
+
showUpdatedOnly: false,
|
|
629
|
+
pathHints: {
|
|
630
|
+
map: DefaultPathHints.map,
|
|
631
|
+
set: DefaultPathHints.set
|
|
632
|
+
},
|
|
633
|
+
maxDepth: MAX_DEPTH,
|
|
634
|
+
maxKeys: MAX_KEYS,
|
|
635
|
+
timeout: MAX_TIMEOUT_MS,
|
|
636
|
+
redactKeys: [
|
|
637
|
+
"password",
|
|
638
|
+
"secret",
|
|
639
|
+
"token",
|
|
640
|
+
"Symbol(password)",
|
|
641
|
+
"Symbol(secret)",
|
|
642
|
+
"Symbol(token)"
|
|
643
|
+
]
|
|
644
|
+
};
|
|
645
|
+
const mergedConfig = {
|
|
646
|
+
...defaultConfig,
|
|
647
|
+
...config
|
|
648
|
+
};
|
|
649
|
+
if (!mergedConfig.maxDepth) mergedConfig.maxDepth = MAX_DEPTH;
|
|
650
|
+
if (!mergedConfig.maxKeys) mergedConfig.maxKeys = MAX_KEYS;
|
|
651
|
+
if (!mergedConfig.timeout) mergedConfig.timeout = MAX_TIMEOUT_MS;
|
|
652
|
+
mergedConfig.include = Array.isArray(mergedConfig.include) ? mergedConfig.include : [mergedConfig.include];
|
|
653
|
+
mergedConfig.exclude = Array.isArray(mergedConfig.exclude) ? mergedConfig.exclude : [mergedConfig.exclude];
|
|
654
|
+
const diffResult = diff_default({
|
|
655
|
+
lhs,
|
|
656
|
+
rhs,
|
|
657
|
+
config: mergedConfig,
|
|
658
|
+
depth: 1,
|
|
659
|
+
parent: null,
|
|
660
|
+
seen: /* @__PURE__ */ new WeakMap(),
|
|
661
|
+
initialChangeType: "noop" /* NOOP */,
|
|
662
|
+
path: [],
|
|
663
|
+
startedAt: Date.now()
|
|
664
|
+
});
|
|
665
|
+
const areEqual = diffResult.every(
|
|
666
|
+
(result) => result.type === "noop" /* NOOP */
|
|
667
|
+
);
|
|
668
|
+
Object.defineProperty(diffResult, "toDiffString", {
|
|
669
|
+
value: (diffStringConfig) => toDiffString(diffResult, diffStringConfig),
|
|
670
|
+
enumerable: false,
|
|
671
|
+
writable: false,
|
|
672
|
+
configurable: false
|
|
673
|
+
});
|
|
674
|
+
Object.defineProperty(diffResult, "equal", {
|
|
675
|
+
value: areEqual,
|
|
676
|
+
enumerable: false,
|
|
677
|
+
writable: false,
|
|
678
|
+
configurable: false
|
|
679
|
+
});
|
|
680
|
+
return diffResult;
|
|
681
|
+
}
|
|
682
|
+
var index_default = diff;
|
|
683
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
684
|
+
0 && (module.exports = {
|
|
685
|
+
ChangeType
|
|
686
|
+
});
|
|
687
|
+
//# sourceMappingURL=index.cjs.map
|