@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 ADDED
@@ -0,0 +1,27 @@
1
+ # @rbxts/diff
2
+
3
+ [![CI Status](https://github.com/R-unic/diff/actions/workflows/test.yml/badge.svg)](https://github.com/R-unic/diff/actions/workflows)
4
+ [![Coverage Status](https://coveralls.io/repos/github/R-unic/diff/badge.svg?branch=master)](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
+ }