@rbxts/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/README.md +27 -0
- package/out/index.d.ts +23 -0
- package/out/init.luau +104 -0
- package/package.json +40 -0
package/README.md
ADDED
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# @rbxts/diff
|
|
2
|
+
|
|
3
|
+
[](https://github.com/R-unic/diff/actions/workflows)
|
|
4
|
+
[](https://coveralls.io/github/R-unic/diff)
|
|
5
|
+
|
|
6
|
+
Calculate diffs between objects and apply diffs to objects
|
|
7
|
+
|
|
8
|
+
## Example
|
|
9
|
+
|
|
10
|
+
```ts
|
|
11
|
+
import { createDiff, applyDiff } from "@rbxts/diff";
|
|
12
|
+
|
|
13
|
+
interface Foo {
|
|
14
|
+
readonly blah?: string;
|
|
15
|
+
readonly bar: {
|
|
16
|
+
readonly baz: number;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
const a: Foo = { blah: "yas", bar: { baz: 420 } };
|
|
21
|
+
const b: Foo = { bar: { baz: 69 } };
|
|
22
|
+
const diff = createDiff(a, b);
|
|
23
|
+
print(diff) // { changed = { bar = { baz = 69 } }, removed = { blah = true } }
|
|
24
|
+
|
|
25
|
+
const newObject = applyDiff(a, diff); // this will turn a into b
|
|
26
|
+
print(newObject) // { bar = { baz = 69 } }
|
|
27
|
+
```
|
package/out/index.d.ts
ADDED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
type GenericRecord = Record<string | number, unknown>;
|
|
2
|
+
type Primitive = string | number | boolean | undefined;
|
|
3
|
+
type Length<T> = T extends {
|
|
4
|
+
length: infer N extends number;
|
|
5
|
+
} ? N : never;
|
|
6
|
+
type IsTuple<T> = T extends readonly unknown[] ? Length<T> extends never ? false : true : false;
|
|
7
|
+
type NonSymbolKeys<T> = Exclude<keyof T, symbol>;
|
|
8
|
+
type DeepPartial<T> = T extends Primitive ? T : T extends readonly (infer U)[] ? IsTuple<T> extends true ? {
|
|
9
|
+
readonly [K in keyof T]?: DeepPartial<T[K]>;
|
|
10
|
+
} : readonly DeepPartial<U>[] : T extends object ? {
|
|
11
|
+
readonly [K in NonSymbolKeys<T>]?: DeepPartial<T[K]>;
|
|
12
|
+
} : T;
|
|
13
|
+
type RemovalTag<T> = true | (T extends object ? DeepKeys<T> : never);
|
|
14
|
+
type DeepKeys<T> = T extends readonly (infer U)[] ? readonly (RemovalTag<U> | undefined)[] : {
|
|
15
|
+
readonly [K in NonSymbolKeys<T>]?: RemovalTag<T[K]>;
|
|
16
|
+
};
|
|
17
|
+
export interface Diff<T> {
|
|
18
|
+
readonly changed?: DeepPartial<T>;
|
|
19
|
+
readonly removed?: DeepKeys<T>;
|
|
20
|
+
}
|
|
21
|
+
export declare function createDiff<T extends GenericRecord | unknown[]>(oldData: T, newData: T): Diff<T>;
|
|
22
|
+
export declare function applyDiff<T extends {}>(base: T, diff: Diff<T>): T;
|
|
23
|
+
export {};
|
package/out/init.luau
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
-- Compiled with roblox-ts v3.0.0
|
|
2
|
+
local function createDiff(oldData, newData)
|
|
3
|
+
if oldData == newData then
|
|
4
|
+
return {}
|
|
5
|
+
end
|
|
6
|
+
local _oldData = oldData
|
|
7
|
+
local _arg0 = type(_oldData) == "table"
|
|
8
|
+
assert(_arg0, "attempt to create diff of non-table objects")
|
|
9
|
+
local _newData = newData
|
|
10
|
+
local _arg0_1 = type(_newData) == "table"
|
|
11
|
+
assert(_arg0_1, "attempt to create diff of non-table objects")
|
|
12
|
+
local changed = {}
|
|
13
|
+
local removed = {}
|
|
14
|
+
for key in pairs(oldData) do
|
|
15
|
+
if newData[key] ~= nil then
|
|
16
|
+
continue
|
|
17
|
+
end
|
|
18
|
+
removed[key] = true
|
|
19
|
+
end
|
|
20
|
+
for key, newValue in pairs(newData) do
|
|
21
|
+
local oldValue = oldData[key]
|
|
22
|
+
if oldValue == nil then
|
|
23
|
+
changed[key] = newValue
|
|
24
|
+
continue
|
|
25
|
+
end
|
|
26
|
+
if (not (type(oldValue) == "table") or not (type(newValue) == "table")) and oldValue ~= newValue then
|
|
27
|
+
changed[key] = newValue
|
|
28
|
+
continue
|
|
29
|
+
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
|
|
36
|
+
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
|
|
47
|
+
end
|
|
48
|
+
return {
|
|
49
|
+
changed = if changedCount > 0 then changed else nil,
|
|
50
|
+
removed = if removedCount > 0 then removed else nil,
|
|
51
|
+
}
|
|
52
|
+
end
|
|
53
|
+
local function applyDiff(base, diff)
|
|
54
|
+
local _base = base
|
|
55
|
+
local _arg0 = type(_base) == "table"
|
|
56
|
+
assert(_arg0, "attempt to apply diff to non-table object")
|
|
57
|
+
local result = table.clone(base)
|
|
58
|
+
if diff.removed ~= nil then
|
|
59
|
+
for key, value in pairs(diff.removed) do
|
|
60
|
+
if value == true then
|
|
61
|
+
result[key] = nil
|
|
62
|
+
continue
|
|
63
|
+
end
|
|
64
|
+
local _exp = base[key]
|
|
65
|
+
local _object = {}
|
|
66
|
+
local _left = "changed"
|
|
67
|
+
local _result = diff.changed
|
|
68
|
+
if _result ~= nil then
|
|
69
|
+
_result = _result[key]
|
|
70
|
+
end
|
|
71
|
+
_object[_left] = _result
|
|
72
|
+
local _left_1 = "removed"
|
|
73
|
+
local _result_1 = diff.removed
|
|
74
|
+
if _result_1 ~= nil then
|
|
75
|
+
_result_1 = _result_1[key]
|
|
76
|
+
end
|
|
77
|
+
_object[_left_1] = _result_1
|
|
78
|
+
result[key] = applyDiff(_exp, _object)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
if diff.changed ~= nil then
|
|
82
|
+
for key, value in pairs(diff.changed) do
|
|
83
|
+
local baseValue = base[key]
|
|
84
|
+
if not (type(value) == "table") or not (type(baseValue) == "table") then
|
|
85
|
+
result[key] = value
|
|
86
|
+
continue
|
|
87
|
+
end
|
|
88
|
+
local _removed = diff.removed
|
|
89
|
+
if _removed ~= nil then
|
|
90
|
+
_removed = _removed[key]
|
|
91
|
+
end
|
|
92
|
+
local removed = _removed
|
|
93
|
+
result[key] = applyDiff(baseValue, {
|
|
94
|
+
changed = value,
|
|
95
|
+
removed = removed,
|
|
96
|
+
})
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
return result
|
|
100
|
+
end
|
|
101
|
+
return {
|
|
102
|
+
createDiff = createDiff,
|
|
103
|
+
applyDiff = applyDiff,
|
|
104
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@rbxts/diff",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Calculate diffs between objects and apply diffs to objects",
|
|
5
|
+
"author": "runicly",
|
|
6
|
+
"main": "out/init.lua",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"setup-rokit": "rokit trust lune-org/lune && rokit trust rojo-rbx/rojo && rokit install",
|
|
9
|
+
"build": "npm run setup-rokit && rbxtsc ",
|
|
10
|
+
"dev": "npm run build -- -w",
|
|
11
|
+
"prepublishOnly": "npm test",
|
|
12
|
+
"test": "npm run build && npm run build -- -p tests && rojo build tests -o tests/test-environment.rbxl && lune run tests tests/test-environment.rbxl",
|
|
13
|
+
"coverage": "nyc report && lune run fix-lcov-paths"
|
|
14
|
+
},
|
|
15
|
+
"keywords": [
|
|
16
|
+
"roblox",
|
|
17
|
+
"rbxts",
|
|
18
|
+
"diff"
|
|
19
|
+
],
|
|
20
|
+
"repository": {
|
|
21
|
+
"type": "git",
|
|
22
|
+
"url": "git+https://github.com/R-unic/diff.git"
|
|
23
|
+
},
|
|
24
|
+
"license": "ISC",
|
|
25
|
+
"types": "out/index.d.ts",
|
|
26
|
+
"files": [
|
|
27
|
+
"out",
|
|
28
|
+
"!**/*.tsbuildinfo"
|
|
29
|
+
],
|
|
30
|
+
"publishConfig": {
|
|
31
|
+
"access": "public"
|
|
32
|
+
},
|
|
33
|
+
"devDependencies": {
|
|
34
|
+
"@rbxts/compiler-types": "^3.0.0-types.0",
|
|
35
|
+
"@rbxts/types": "^1.0.919",
|
|
36
|
+
"nyc": "^17.1.0",
|
|
37
|
+
"roblox-ts": "=3.0.0",
|
|
38
|
+
"typescript": "=5.5.3"
|
|
39
|
+
}
|
|
40
|
+
}
|