@rbxts/replion 1.0.18 → 1.0.20
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 +1 -1
- package/package.json +1 -1
- package/src/BaseReplion.lua +94 -17
- package/src/Client.lua +58 -105
- package/src/Server.lua +37 -54
- package/src/Shared.lua +0 -7
- package/src/index.d.ts +6 -1
package/README.md
CHANGED
package/package.json
CHANGED
package/src/BaseReplion.lua
CHANGED
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
export type GenericDataTable = { [string]: any };
|
|
3
|
-
|
|
4
2
|
local isTypeScriptEnv = script.Parent.Name == 'src';
|
|
5
3
|
local dependencies = if isTypeScriptEnv then script.Parent.Parent.Parent else script.Parent.Parent;
|
|
6
4
|
local Shared = require(script.Parent.Shared);
|
|
7
5
|
local Signal = require(isTypeScriptEnv and dependencies['sleitnick-signal'] or dependencies.Signal);
|
|
8
6
|
|
|
7
|
+
export type GenericDataTable = { [string]: any };
|
|
8
|
+
export type Observer = (newValue: any, oldValue: any) -> ();
|
|
9
|
+
|
|
9
10
|
local BaseReplion = {};
|
|
10
11
|
BaseReplion.__index = BaseReplion;
|
|
11
12
|
|
|
@@ -14,7 +15,7 @@ function BaseReplion.new(data: GenericDataTable)
|
|
|
14
15
|
|
|
15
16
|
self.data = data;
|
|
16
17
|
|
|
17
|
-
self.
|
|
18
|
+
self._signalRoot = {};
|
|
18
19
|
self._allSignal = Signal.new();
|
|
19
20
|
|
|
20
21
|
return self;
|
|
@@ -25,32 +26,108 @@ function BaseReplion:get(path: { string }?)
|
|
|
25
26
|
return Shared.getNestedValue(self.data, path);
|
|
26
27
|
end;
|
|
27
28
|
|
|
28
|
-
function BaseReplion:
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
function BaseReplion:_pruneSignalTree(path: {string})
|
|
30
|
+
local stack = {self._signalRoot};
|
|
31
|
+
local current = self._signalRoot;
|
|
32
|
+
|
|
33
|
+
for _, key in path do
|
|
34
|
+
current = current[key];
|
|
35
|
+
if not current then return; end;
|
|
36
|
+
table.insert(stack, current);
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
for i = #path, 1, -1 do
|
|
40
|
+
local key = path[i];
|
|
41
|
+
local node = stack[i + 1];
|
|
42
|
+
local parent = stack[i];
|
|
43
|
+
|
|
44
|
+
local hasListeners = (node._refCount or 0) > 0;
|
|
45
|
+
local hasChildren = false;
|
|
46
|
+
|
|
47
|
+
if not hasListeners then
|
|
48
|
+
for k in node do
|
|
49
|
+
if k == '_signal' then continue; end;
|
|
50
|
+
if k == '_refCount' then continue; end;
|
|
51
|
+
hasChildren = true;
|
|
52
|
+
break;
|
|
53
|
+
end;
|
|
54
|
+
end;
|
|
55
|
+
|
|
56
|
+
if not hasListeners and not hasChildren then
|
|
57
|
+
parent[key] = nil;
|
|
58
|
+
else
|
|
59
|
+
break;
|
|
60
|
+
end;
|
|
32
61
|
end;
|
|
62
|
+
end;
|
|
33
63
|
|
|
34
|
-
|
|
35
|
-
if not
|
|
36
|
-
|
|
64
|
+
function BaseReplion:subscribe(path: { string }?, callback: Observer)
|
|
65
|
+
if (not path) or (#path == 0) then
|
|
66
|
+
local connection = self._allSignal:Connect(callback);
|
|
67
|
+
return function()
|
|
68
|
+
connection:Disconnect()
|
|
69
|
+
end;
|
|
37
70
|
end;
|
|
38
71
|
|
|
39
|
-
local
|
|
72
|
+
local current = self._signalRoot;
|
|
73
|
+
for _, key in path do
|
|
74
|
+
if not current[key] then current[key] = {}; end;
|
|
75
|
+
current = current[key];
|
|
76
|
+
end;
|
|
77
|
+
|
|
78
|
+
if not current._signal then
|
|
79
|
+
current._signal = Signal.new();
|
|
80
|
+
current._refCount = 0;
|
|
81
|
+
end;
|
|
82
|
+
|
|
83
|
+
local connection = current._signal:Connect(callback);
|
|
84
|
+
current._refCount = (current._refCount or 0) + 1;
|
|
40
85
|
|
|
41
|
-
task.spawn(callback, initialValue, nil);
|
|
42
|
-
local connection = self._signals[signalKey]:Connect(callback);
|
|
43
86
|
return function()
|
|
44
87
|
connection:Disconnect();
|
|
88
|
+
|
|
89
|
+
if current._refCount then
|
|
90
|
+
current._refCount -= 1;
|
|
91
|
+
end;
|
|
92
|
+
|
|
93
|
+
if current._refCount <= 0 then
|
|
94
|
+
if current._signal then
|
|
95
|
+
current._signal:Destroy();
|
|
96
|
+
current._signal = nil;
|
|
97
|
+
end;
|
|
98
|
+
current._refCount = nil;
|
|
99
|
+
self:_pruneSignalTree(path);
|
|
100
|
+
end
|
|
101
|
+
end;
|
|
102
|
+
end;
|
|
103
|
+
|
|
104
|
+
function BaseReplion:observe(path: { string }?, callback: Observer)
|
|
105
|
+
if path then
|
|
106
|
+
local initialValue = Shared.getNestedValue(self.data, path);
|
|
107
|
+
task.spawn(callback, initialValue, nil);
|
|
108
|
+
else
|
|
109
|
+
task.spawn(callback, self.data, nil);
|
|
45
110
|
end;
|
|
111
|
+
|
|
112
|
+
return self:subscribe(path, callback);
|
|
46
113
|
end;
|
|
47
114
|
|
|
48
115
|
function BaseReplion:destroy()
|
|
49
116
|
self._allSignal:Destroy();
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
117
|
+
|
|
118
|
+
local function destroyTree(node)
|
|
119
|
+
if node._signal then
|
|
120
|
+
node._signal:Destroy();
|
|
121
|
+
end;
|
|
122
|
+
for k, v in node do
|
|
123
|
+
if k == '_signal' then continue; end;
|
|
124
|
+
if k == '_refCount' then continue; end;
|
|
125
|
+
if typeof(v) ~= 'table' then continue; end;
|
|
126
|
+
destroyTree(v);
|
|
127
|
+
end;
|
|
128
|
+
end;
|
|
129
|
+
destroyTree(self._signalRoot)
|
|
130
|
+
table.clear(self._signalRoot);
|
|
54
131
|
end;
|
|
55
132
|
|
|
56
133
|
return BaseReplion;
|
package/src/Client.lua
CHANGED
|
@@ -5,23 +5,8 @@ local BaseReplion = require(script.Parent.BaseReplion)
|
|
|
5
5
|
local Shared = require(script.Parent.Shared);
|
|
6
6
|
local Signal = require(isTypeScriptEnv and dependencies['sleitnick-signal'] or dependencies.Signal);
|
|
7
7
|
|
|
8
|
-
type Observer = (newValue: any, oldValue: any) -> ();
|
|
9
|
-
type Deletion = { path: { string }, oldTable: any };
|
|
10
|
-
|
|
11
8
|
local remote = script.Parent:WaitForChild(Shared.REMOTE_NAME) :: RemoteEvent;
|
|
12
9
|
|
|
13
|
-
local function deepMergeAndApply(target: any, updates: any)
|
|
14
|
-
for key, value in updates do
|
|
15
|
-
if value == Shared.NIL_SENTINEL then
|
|
16
|
-
target[key] = nil;
|
|
17
|
-
elseif typeof(value) == 'table' and typeof(target[key]) == 'table' then
|
|
18
|
-
deepMergeAndApply(target[key], value);
|
|
19
|
-
else
|
|
20
|
-
target[key] = value;
|
|
21
|
-
end;
|
|
22
|
-
end;
|
|
23
|
-
end;
|
|
24
|
-
|
|
25
10
|
local Client = {};
|
|
26
11
|
Client.__index = Client;
|
|
27
12
|
|
|
@@ -49,7 +34,7 @@ function Client.waitForReplion(channel: string)
|
|
|
49
34
|
return replion;
|
|
50
35
|
end;
|
|
51
36
|
|
|
52
|
-
function Client.new(channel: string, data:
|
|
37
|
+
function Client.new(channel: string, data: BaseReplion.GenericDataTable)
|
|
53
38
|
local self = setmetatable({}, Client);
|
|
54
39
|
|
|
55
40
|
self.channel = channel;
|
|
@@ -63,103 +48,71 @@ function Client:get(path: { string }?)
|
|
|
63
48
|
return self._base:get(path);
|
|
64
49
|
end;
|
|
65
50
|
|
|
66
|
-
function Client:
|
|
67
|
-
return self._base:
|
|
51
|
+
function Client:subscribe(path: { string }?, callback: BaseReplion.Observer)
|
|
52
|
+
return self._base:subscribe(path, callback);
|
|
68
53
|
end;
|
|
69
54
|
|
|
70
|
-
function Client:
|
|
71
|
-
|
|
72
|
-
local currentVal = target[k];
|
|
73
|
-
local newPath = table.clone(path);
|
|
74
|
-
table.insert(newPath, k);
|
|
75
|
-
|
|
76
|
-
if v == Shared.NIL_SENTINEL or (typeof(currentVal) == 'table' and typeof(v) ~= 'table') then
|
|
77
|
-
if typeof(currentVal) == 'table' then
|
|
78
|
-
table.insert(out, { path = newPath, oldTable = currentVal });
|
|
79
|
-
end;
|
|
80
|
-
elseif typeof(v) == 'table' and typeof(currentVal) == 'table' then
|
|
81
|
-
self:_collectDeletions(currentVal, v, newPath, out);
|
|
82
|
-
end;
|
|
83
|
-
end;
|
|
55
|
+
function Client:observe(path: { string }?, callback: BaseReplion.Observer)
|
|
56
|
+
return self._base:observe(path, callback);
|
|
84
57
|
end;
|
|
85
58
|
|
|
86
|
-
function Client:
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
if
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
59
|
+
function Client:_fireRecursive(signalNode: any, newValue: any, oldValue: any)
|
|
60
|
+
if not signalNode then return; end;
|
|
61
|
+
|
|
62
|
+
if signalNode._signal then
|
|
63
|
+
signalNode._signal:Fire(newValue, oldValue);
|
|
64
|
+
end;
|
|
65
|
+
|
|
66
|
+
for key, childNode in signalNode do
|
|
67
|
+
if key == '_signal' then continue; end;
|
|
68
|
+
if key == '_refCount' then continue; end;
|
|
69
|
+
|
|
70
|
+
local newChild = if typeof(newValue) == 'table' then newValue[key] else nil;
|
|
71
|
+
local oldChild = if typeof(oldValue) == 'table' then oldValue[key] else nil;
|
|
72
|
+
|
|
73
|
+
if newChild ~= nil or oldChild ~= nil then
|
|
74
|
+
self:_fireRecursive(childNode, newChild, oldChild);
|
|
75
|
+
end;
|
|
76
|
+
end;
|
|
103
77
|
end;
|
|
104
78
|
|
|
105
|
-
function Client:
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
79
|
+
function Client:_applyUpdatesRecursive(target: any, updates: any, signalNode: any)
|
|
80
|
+
local anyChanged = false;
|
|
81
|
+
|
|
82
|
+
for key, updateVal in updates do
|
|
83
|
+
local currentVal = target[key];
|
|
84
|
+
local nextSignalNode = if signalNode then signalNode[key] else nil;
|
|
85
|
+
|
|
86
|
+
local finalVal = updateVal;
|
|
87
|
+
if finalVal == Shared.NIL_SENTINEL then finalVal = nil; end;
|
|
88
|
+
|
|
89
|
+
if typeof(finalVal) == 'table' and typeof(currentVal) == 'table' then
|
|
90
|
+
if self:_applyUpdatesRecursive(currentVal, finalVal, nextSignalNode) then
|
|
91
|
+
anyChanged = true;
|
|
92
|
+
|
|
93
|
+
if nextSignalNode and nextSignalNode._signal then
|
|
94
|
+
nextSignalNode._signal:Fire(currentVal, currentVal);
|
|
95
|
+
end;
|
|
96
|
+
end;
|
|
97
|
+
else
|
|
98
|
+
if currentVal ~= finalVal then
|
|
99
|
+
target[key] = finalVal;
|
|
100
|
+
anyChanged = true;
|
|
101
|
+
|
|
102
|
+
if nextSignalNode then
|
|
103
|
+
self:_fireRecursive(nextSignalNode, finalVal, currentVal);
|
|
104
|
+
end;
|
|
105
|
+
end;
|
|
106
|
+
end;
|
|
107
|
+
end;
|
|
108
|
+
|
|
109
|
+
return anyChanged;
|
|
124
110
|
end;
|
|
125
111
|
|
|
126
|
-
function Client:_applyUpdates(updates:
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
local oldData = table.clone(self._base.data); -- Note: Shallow copy instead of deep copy.
|
|
131
|
-
|
|
132
|
-
deepMergeAndApply(self._base.data, updates);
|
|
133
|
-
|
|
134
|
-
local anyChanged = false;
|
|
135
|
-
|
|
136
|
-
for _, item in deletions do
|
|
137
|
-
self:_notifyDeepDeletion(item.path, item.oldTable);
|
|
138
|
-
end;
|
|
139
|
-
|
|
140
|
-
for key, newValue in updates do
|
|
141
|
-
local oldValue = oldData[key];
|
|
142
|
-
|
|
143
|
-
-- If it's a table, we assume it changed if it's in the updates list.
|
|
144
|
-
if typeof(newValue) == 'table' then
|
|
145
|
-
anyChanged = true;
|
|
146
|
-
local signal = self._base._signals[key];
|
|
147
|
-
if signal then
|
|
148
|
-
signal:Fire(self._base.data[key], self._base.data[key]); -- Warning: Sends improper 'old' argument due to shallow copy optimization.
|
|
149
|
-
end;
|
|
150
|
-
self:_notifyRecursiveUpdates({key}, newValue);
|
|
151
|
-
elseif self._base.data[key] ~= oldValue then
|
|
152
|
-
anyChanged = true;
|
|
153
|
-
local signal = self._base._signals[key];
|
|
154
|
-
if signal then
|
|
155
|
-
signal:Fire(self._base.data[key], oldValue);
|
|
156
|
-
end;
|
|
157
|
-
end;
|
|
158
|
-
end;
|
|
159
|
-
|
|
160
|
-
if anyChanged then
|
|
161
|
-
self._base._allSignal:Fire(self._base.data, updates);
|
|
162
|
-
end;
|
|
112
|
+
function Client:_applyUpdates(updates: BaseReplion.GenericDataTable)
|
|
113
|
+
local changed = self:_applyUpdatesRecursive(self._base.data, updates, self._base._signalRoot);
|
|
114
|
+
if not changed then return; end;
|
|
115
|
+
self._base._allSignal:Fire(self._base.data, updates);
|
|
163
116
|
end;
|
|
164
117
|
|
|
165
118
|
function Client:destroy()
|
package/src/Server.lua
CHANGED
|
@@ -10,9 +10,8 @@ local Sift = require(isTypeScriptEnv and dependencies.sift.out or dependencies.S
|
|
|
10
10
|
type ServerConfig = {
|
|
11
11
|
channel: string;
|
|
12
12
|
replicateTo: Player?;
|
|
13
|
-
data:
|
|
13
|
+
data: BaseReplion.GenericDataTable;
|
|
14
14
|
};
|
|
15
|
-
type Observer = (newValue: any, oldValue: any) -> ();
|
|
16
15
|
|
|
17
16
|
local remote = script.Parent:FindFirstChild(Shared.REMOTE_NAME) :: RemoteEvent;
|
|
18
17
|
if not remote then
|
|
@@ -62,7 +61,6 @@ Server._globalReplions = {} :: { [string]: Replion };
|
|
|
62
61
|
function Server._getPlayerReplion(player: Player, channel: string)
|
|
63
62
|
local playerReplions = Server._activeReplions[player];
|
|
64
63
|
if not playerReplions then return nil; end;
|
|
65
|
-
|
|
66
64
|
return playerReplions[channel];
|
|
67
65
|
end;
|
|
68
66
|
|
|
@@ -79,7 +77,7 @@ function Server.new(config: ServerConfig)
|
|
|
79
77
|
|
|
80
78
|
self._base = BaseReplion.new(Sift.Dictionary.copyDeep(config.data));
|
|
81
79
|
|
|
82
|
-
self._queuedUpdates = {} ::
|
|
80
|
+
self._queuedUpdates = {} :: BaseReplion.GenericDataTable;
|
|
83
81
|
self._isQueued = false;
|
|
84
82
|
self._destroyed = false;
|
|
85
83
|
|
|
@@ -97,7 +95,11 @@ function Server.new(config: ServerConfig)
|
|
|
97
95
|
return self;
|
|
98
96
|
end;
|
|
99
97
|
|
|
100
|
-
function Server:
|
|
98
|
+
function Server:subscribe(path: { string }?, callback: BaseReplion.Observer)
|
|
99
|
+
return self._base:subscribe(path, callback);
|
|
100
|
+
end;
|
|
101
|
+
|
|
102
|
+
function Server:observe(path: { string }?, callback: BaseReplion.Observer)
|
|
101
103
|
return self._base:observe(path, callback);
|
|
102
104
|
end;
|
|
103
105
|
|
|
@@ -105,75 +107,56 @@ function Server:get(path: { string }?)
|
|
|
105
107
|
return self._base:get(path);
|
|
106
108
|
end;
|
|
107
109
|
|
|
108
|
-
function Server:_notifyDeep(
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
if typeof(newValue) == 'table' then
|
|
112
|
-
for k, v in newValue do
|
|
113
|
-
local nextPath = table.clone(currentPath);
|
|
114
|
-
table.insert(nextPath, k);
|
|
115
|
-
|
|
116
|
-
local nextOld = if typeof(oldValue) == 'table' then oldValue[k] else nil;
|
|
117
|
-
|
|
118
|
-
local signalKey = Shared.getSignalKey(nextPath);
|
|
119
|
-
local signal = signals[signalKey];
|
|
120
|
-
if signal then
|
|
121
|
-
signal:Fire(v, nextOld);
|
|
122
|
-
end;
|
|
123
|
-
|
|
124
|
-
self:_notifyDeep(nextPath, v, nextOld);
|
|
125
|
-
end;
|
|
126
|
-
end;
|
|
110
|
+
function Server:_notifyDeep(signalNode: any, newValue: any, oldValue: any)
|
|
111
|
+
if not signalNode then return; end;
|
|
127
112
|
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
113
|
+
if signalNode._signal then
|
|
114
|
+
signalNode._signal:Fire(newValue, oldValue);
|
|
115
|
+
end;
|
|
131
116
|
|
|
132
|
-
|
|
133
|
-
|
|
117
|
+
for key, childNode in signalNode do
|
|
118
|
+
if key == '_signal' then continue; end;
|
|
119
|
+
if key == '_refCount' then continue; end;
|
|
134
120
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
if signal then
|
|
138
|
-
signal:Fire(nil, v);
|
|
139
|
-
end;
|
|
121
|
+
local nextNew = if typeof(newValue) == 'table' then newValue[key] else nil;
|
|
122
|
+
local nextOld = if typeof(oldValue) == 'table' then oldValue[key] else nil;
|
|
140
123
|
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
124
|
+
if nextNew ~= nil or nextOld ~= nil then
|
|
125
|
+
self:_notifyDeep(childNode, nextNew, nextOld);
|
|
126
|
+
end;
|
|
127
|
+
end;
|
|
144
128
|
end;
|
|
145
129
|
|
|
146
130
|
function Server:set(path: { string }, value: any)
|
|
147
131
|
if self._destroyed then return; end;
|
|
148
132
|
|
|
149
|
-
local topKey = path[1];
|
|
150
|
-
|
|
151
133
|
local oldValue = Shared.getNestedValue(self._base.data, path);
|
|
152
134
|
local newValue = if typeof(value) == 'function' then value(oldValue) else value;
|
|
153
135
|
if oldValue == newValue then return; end;
|
|
154
136
|
|
|
155
|
-
local oldTop = self._base.data[topKey];
|
|
156
|
-
|
|
157
137
|
setNestedValue(self._base.data, path, newValue);
|
|
158
138
|
queueNestedUpdate(self._queuedUpdates, path, newValue);
|
|
159
139
|
self:_scheduleUpdatesFlush();
|
|
160
140
|
|
|
161
141
|
do
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if topSignal then
|
|
165
|
-
topSignal:Fire(self._base.data[topKey], oldTop);
|
|
166
|
-
end;
|
|
142
|
+
local rootKey = path[1];
|
|
143
|
+
local currentSignalNode = self._base._signalRoot;
|
|
167
144
|
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
145
|
+
local rootSignalNode = if currentSignalNode then currentSignalNode[rootKey] else nil;
|
|
146
|
+
|
|
147
|
+
for _, key in path do
|
|
148
|
+
if not currentSignalNode then break; end;
|
|
149
|
+
currentSignalNode = currentSignalNode[key];
|
|
150
|
+
end;
|
|
151
|
+
|
|
152
|
+
if rootSignalNode and rootSignalNode ~= currentSignalNode and rootSignalNode._signal then
|
|
153
|
+
local rootValue = self._base.data[rootKey];
|
|
154
|
+
rootSignalNode._signal:Fire(rootValue, rootValue);
|
|
155
|
+
end;
|
|
175
156
|
|
|
176
|
-
|
|
157
|
+
if currentSignalNode then
|
|
158
|
+
self:_notifyDeep(currentSignalNode, newValue, oldValue);
|
|
159
|
+
end;
|
|
177
160
|
|
|
178
161
|
local thisUpdate = {};
|
|
179
162
|
setNestedValue(thisUpdate, path, newValue);
|
package/src/Shared.lua
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
--!strict
|
|
2
|
-
export type GenericDataTable = { [string]: any };
|
|
3
|
-
|
|
4
2
|
local Shared = {};
|
|
5
3
|
|
|
6
4
|
Shared.REMOTE_NAME = 'ReplionNetwork';
|
|
@@ -15,9 +13,4 @@ function Shared.getNestedValue(root: any, path: { string })
|
|
|
15
13
|
return current;
|
|
16
14
|
end;
|
|
17
15
|
|
|
18
|
-
function Shared.getSignalKey(key: string | { string })
|
|
19
|
-
if typeof(key) == 'string' then return key; end;
|
|
20
|
-
return table.concat(key, '\0');
|
|
21
|
-
end;
|
|
22
|
-
|
|
23
16
|
return Shared;
|
package/src/index.d.ts
CHANGED
|
@@ -6,7 +6,6 @@ declare namespace Replion {
|
|
|
6
6
|
type Path<T> = T extends object
|
|
7
7
|
? { [K in keyof T & string]: [K] | [K, ...Path<T[K]>] }[keyof T & string]
|
|
8
8
|
: never;
|
|
9
|
-
|
|
10
9
|
/**
|
|
11
10
|
* Resolves the type of the value at a specific path P within object T.
|
|
12
11
|
*/
|
|
@@ -30,6 +29,12 @@ declare namespace Replion {
|
|
|
30
29
|
get(): T;
|
|
31
30
|
get<P extends Path<T>>(path: P): PathValue<T, P>;
|
|
32
31
|
|
|
32
|
+
subscribe(key: undefined, callback: (newValue: T, oldValue: Partial<T>) => void): Cleanup;
|
|
33
|
+
subscribe<P extends Path<T>>(
|
|
34
|
+
path: P,
|
|
35
|
+
callback: (newValue: PathValue<T, P>, oldValue: PathValue<T, P> | undefined) => void,
|
|
36
|
+
): Cleanup;
|
|
37
|
+
|
|
33
38
|
observe(key: undefined, callback: (newValue: T, oldValue: Partial<T>) => void): Cleanup;
|
|
34
39
|
observe<P extends Path<T>>(
|
|
35
40
|
path: P,
|