@rbxts/diff 1.0.0 → 1.0.2

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/out/index.d.ts CHANGED
@@ -7,17 +7,52 @@ type IsTuple<T> = T extends readonly unknown[] ? Length<T> extends never ? false
7
7
  type NonSymbolKeys<T> = Exclude<keyof T, symbol>;
8
8
  type DeepPartial<T> = T extends Primitive ? T : T extends readonly (infer U)[] ? IsTuple<T> extends true ? {
9
9
  readonly [K in keyof T]?: DeepPartial<T[K]>;
10
- } : readonly DeepPartial<U>[] : T extends object ? {
10
+ } : readonly DeepPartial<U>[] : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<DeepPartial<K>, DeepPartial<V>> : T extends object ? {
11
11
  readonly [K in NonSymbolKeys<T>]?: DeepPartial<T[K]>;
12
12
  } : T;
13
13
  type RemovalTag<T> = true | (T extends object ? DeepKeys<T> : never);
14
- type DeepKeys<T> = T extends readonly (infer U)[] ? readonly (RemovalTag<U> | undefined)[] : {
14
+ type DeepKeys<T> = T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<K, RemovalTag<V> | undefined> : T extends readonly (infer U)[] ? readonly (RemovalTag<U> | undefined)[] : {
15
15
  readonly [K in NonSymbolKeys<T>]?: RemovalTag<T[K]>;
16
16
  };
17
17
  export interface Diff<T> {
18
18
  readonly changed?: DeepPartial<T>;
19
19
  readonly removed?: DeepKeys<T>;
20
20
  }
21
- export declare function createDiff<T extends GenericRecord | unknown[]>(oldData: T, newData: T): Diff<T>;
21
+ export interface DiffOptions<K> {
22
+ readonly equals?: (a: unknown, b: unknown) => boolean;
23
+ readonly ignoreKeys?: K[];
24
+ }
25
+ /**
26
+ * Creates a diff object by comparing two data structures.
27
+ *
28
+ * @param oldData - The original data object
29
+ * @param newData - The new data object to compare against
30
+ * @param options - Configuration options for diff generation
31
+ * @param options.equals - Custom equality function for comparing values (default: `===`)
32
+ * @param options.ignoreKeys - Array of keys to exclude from diff comparison (shallow, root level only)
33
+ * @returns A Diff object containing changed and removed keys, or an empty object if no differences
34
+ *
35
+ * @example
36
+ * const diff = createDiff(
37
+ * { a: 1, b: 2 },
38
+ * { a: 1, b: 3, c: 4 }
39
+ * );
40
+ * // Returns: { changed: { b: 3, c: 4 } }
41
+ */
42
+ export declare function createDiff<T extends {}>(oldData: T, newData: T, { equals, ignoreKeys }?: DiffOptions<T extends GenericRecord ? keyof T : unknown>): Diff<T>;
43
+ /**
44
+ * Applies a diff to a base object and returns the modified result.
45
+ *
46
+ * @param base - The base object to apply the diff to
47
+ * @param diff - The diff object containing changes and removals
48
+ * @returns A new object with the diff applied to the base
49
+ *
50
+ * @example
51
+ * const result = applyDiff(
52
+ * { a: 1, b: 2, c: 3 },
53
+ * { changed: { b: 5 }, removed: { c: true } }
54
+ * );
55
+ * // Returns: { a: 1, b: 5 }
56
+ */
22
57
  export declare function applyDiff<T extends {}>(base: T, diff: Diff<T>): T;
23
58
  export {};
package/out/init.luau CHANGED
@@ -1,8 +1,52 @@
1
1
  -- Compiled with roblox-ts v3.0.0
2
- local function createDiff(oldData, newData)
2
+ local function isEmpty(record)
3
+ for _element, _element_1 in pairs(record) do
4
+ local _ = { _element, _element_1 }
5
+ return false
6
+ end
7
+ return true
8
+ end
9
+ --[[
10
+ *
11
+ * Creates a diff object by comparing two data structures.
12
+ *
13
+ * @param oldData - The original data object
14
+ * @param newData - The new data object to compare against
15
+ * @param options - Configuration options for diff generation
16
+ * @param options.equals - Custom equality function for comparing values (default: `===`)
17
+ * @param options.ignoreKeys - Array of keys to exclude from diff comparison (shallow, root level only)
18
+ * @returns A Diff object containing changed and removed keys, or an empty object if no differences
19
+ *
20
+ * @example
21
+ * const diff = createDiff(
22
+ * { a: 1, b: 2 },
23
+ * { a: 1, b: 3, c: 4 }
24
+ * );
25
+ * // Returns: { changed: { b: 3, c: 4 } }
26
+
27
+ ]]
28
+ local function createDiff(oldData, newData, _param)
29
+ if _param == nil then
30
+ _param = {}
31
+ end
32
+ local equals = _param.equals
33
+ if equals == nil then
34
+ equals = function(a, b)
35
+ return a == b
36
+ end
37
+ end
38
+ local ignoreKeys = _param.ignoreKeys
39
+ if ignoreKeys == nil then
40
+ ignoreKeys = {}
41
+ end
3
42
  if oldData == newData then
4
43
  return {}
5
44
  end
45
+ local _set = {}
46
+ for _, _v in ignoreKeys do
47
+ _set[_v] = true
48
+ end
49
+ local keyIgnoreSet = _set
6
50
  local _oldData = oldData
7
51
  local _arg0 = type(_oldData) == "table"
8
52
  assert(_arg0, "attempt to create diff of non-table objects")
@@ -11,45 +55,58 @@ local function createDiff(oldData, newData)
11
55
  assert(_arg0_1, "attempt to create diff of non-table objects")
12
56
  local changed = {}
13
57
  local removed = {}
14
- for key in pairs(oldData) do
58
+ for key in oldData do
59
+ if keyIgnoreSet[key] ~= nil then
60
+ continue
61
+ end
15
62
  if newData[key] ~= nil then
16
63
  continue
17
64
  end
18
65
  removed[key] = true
19
66
  end
20
- for key, newValue in pairs(newData) do
21
- local oldValue = oldData[key]
22
- if oldValue == nil then
23
- changed[key] = newValue
67
+ for key, newValue in newData do
68
+ if keyIgnoreSet[key] ~= nil then
24
69
  continue
25
70
  end
26
- if (not (type(oldValue) == "table") or not (type(newValue) == "table")) and oldValue ~= newValue then
27
- changed[key] = newValue
71
+ local oldValue = oldData[key]
72
+ if type(oldValue) == "table" and type(newValue) == "table" then
73
+ local childDiff = createDiff(oldValue, newValue, {
74
+ equals = equals,
75
+ })
76
+ if childDiff.changed ~= nil then
77
+ changed[key] = childDiff.changed
78
+ end
79
+ if childDiff.removed ~= nil then
80
+ removed[key] = childDiff.removed
81
+ end
28
82
  continue
29
83
  end
30
- local childDiff = createDiff(oldValue, newValue)
31
- if childDiff.changed ~= nil then
32
- changed[key] = childDiff.changed or newValue
33
- end
34
- if childDiff.removed ~= nil then
35
- removed[key] = childDiff.removed
84
+ if equals(oldValue, newValue) then
85
+ continue
36
86
  end
37
- end
38
- local changedCount = 0
39
- local removedCount = 0
40
- for _element, _element_1 in pairs(changed) do
41
- local _ = { _element, _element_1 }
42
- changedCount += 1
43
- end
44
- for _element, _element_1 in pairs(removed) do
45
- local _ = { _element, _element_1 }
46
- removedCount += 1
87
+ changed[key] = newValue
47
88
  end
48
89
  return {
49
- changed = if changedCount > 0 then changed else nil,
50
- removed = if removedCount > 0 then removed else nil,
90
+ changed = if isEmpty(changed) then nil else changed,
91
+ removed = if isEmpty(removed) then nil else removed,
51
92
  }
52
93
  end
94
+ --[[
95
+ *
96
+ * Applies a diff to a base object and returns the modified result.
97
+ *
98
+ * @param base - The base object to apply the diff to
99
+ * @param diff - The diff object containing changes and removals
100
+ * @returns A new object with the diff applied to the base
101
+ *
102
+ * @example
103
+ * const result = applyDiff(
104
+ * { a: 1, b: 2, c: 3 },
105
+ * { changed: { b: 5 }, removed: { c: true } }
106
+ * );
107
+ * // Returns: { a: 1, b: 5 }
108
+
109
+ ]]
53
110
  local function applyDiff(base, diff)
54
111
  local _base = base
55
112
  local _arg0 = type(_base) == "table"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/diff",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "Calculate diffs between objects and apply diffs to objects",
5
5
  "author": "runicly",
6
6
  "main": "out/init.lua",