@rbxts/replion 1.0.7 → 1.0.9

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 CHANGED
@@ -2,4 +2,4 @@
2
2
 
3
3
  ## Install
4
4
  Install with [wally](https://wally.run/):\
5
- `Replion = "shouxtech/replion@1.0.7"`
5
+ `Replion = "shouxtech/replion@1.0.9"`
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@rbxts/replion",
3
- "version": "1.0.7",
3
+ "version": "1.0.9",
4
4
  "description": "",
5
5
  "main": "src/init.lua",
6
6
  "scripts": {},
@@ -25,4 +25,4 @@
25
25
  "@rbxts/sift": "^0.0.11",
26
26
  "@rbxts/sleitnick-signal": "^1.0.8"
27
27
  }
28
- }
28
+ }
package/src/Server.lua CHANGED
@@ -5,12 +5,14 @@ local isTypeScriptEnv = script.Parent.Name == 'src';
5
5
  local dependencies = if isTypeScriptEnv then script.Parent.Parent.Parent else script.Parent.Parent;
6
6
  local Shared = require(script.Parent.Shared);
7
7
  local Sift = require(isTypeScriptEnv and dependencies.sift.out or dependencies.Sift);
8
+ local Signal = require(isTypeScriptEnv and dependencies['sleitnick-signal'] or dependencies.Signal);
8
9
 
9
10
  type ServerConfig = {
10
11
  channel: string;
11
12
  replicateTo: Player?;
12
13
  data: Shared.GenericDataTable;
13
14
  };
15
+ type Observer = (newValue: any, oldValue: any) -> ();
14
16
 
15
17
  local remote = script.Parent:FindFirstChild(Shared.REMOTE_NAME) :: RemoteEvent;
16
18
  if not remote then
@@ -19,7 +21,7 @@ if not remote then
19
21
  remote.Parent = script.Parent;
20
22
  end;
21
23
 
22
- local function setNestedValue(root: any, path: {string}, value: any)
24
+ local function setNestedValue(root: any, path: { string }, value: any)
23
25
  local current = root;
24
26
  for i = 1, #path - 1 do
25
27
  local key = path[i];
@@ -35,7 +37,7 @@ local function setNestedValue(root: any, path: {string}, value: any)
35
37
  return oldValue;
36
38
  end;
37
39
 
38
- local function queueNestedUpdate(queue: any, path: {string}, value: any)
40
+ local function queueNestedUpdate(queue: any, path: { string }, value: any)
39
41
  local current = queue;
40
42
  for i = 1, #path - 1 do
41
43
  local key = path[i];
@@ -76,6 +78,9 @@ function Server.new(config: ServerConfig)
76
78
  self.channel = config.channel;
77
79
  self.data = Sift.Dictionary.copyDeep(config.data);
78
80
 
81
+ self._signals = {} :: { [string]: any };
82
+ self._allSignal = Signal.new();
83
+
79
84
  self._queuedUpdates = {} :: Shared.GenericDataTable;
80
85
  self._isQueued = false;
81
86
  self._destroyed = false;
@@ -94,19 +99,46 @@ function Server.new(config: ServerConfig)
94
99
  return self;
95
100
  end;
96
101
 
102
+ function Server:observe(key: string?, callback: Observer)
103
+ if not key then
104
+ task.spawn(callback, self.data, nil);
105
+ return self._allSignal:Connect(callback);
106
+ end;
107
+
108
+ if not self._signals[key] then
109
+ self._signals[key] = Signal.new();
110
+ end;
111
+
112
+ task.spawn(callback, self.data[key], nil);
113
+ return self._signals[key]:Connect(callback);
114
+ end;
115
+
97
116
  function Server:set(key: string | {string}, value: any)
98
117
  if self._destroyed then return; end;
99
118
 
100
119
  local path = if typeof(key) == 'table' then key else {key};
101
- local oldValue = Shared.getNestedValue(self.data, path);
120
+ local topKey = path[1];
102
121
 
122
+ local oldValue = Shared.getNestedValue(self.data, path);
103
123
  local newValue = if typeof(value) == 'function' then value(oldValue) else value;
104
-
105
124
  if oldValue == newValue then return; end;
106
125
 
126
+ local oldTop = self.data[topKey];
127
+
107
128
  setNestedValue(self.data, path, newValue);
108
129
  queueNestedUpdate(self._queuedUpdates, path, newValue);
109
130
  self:_scheduleUpdatesFlush();
131
+
132
+ do
133
+ local signal = self._signals[topKey];
134
+ if signal then
135
+ signal:Fire(self.data[topKey], oldTop);
136
+ end;
137
+
138
+ local thisUpdate = {};
139
+ setNestedValue(thisUpdate, path, newValue);
140
+ self._allSignal:Fire(self.data, thisUpdate);
141
+ end;
110
142
  end;
111
143
 
112
144
  function Server:get(key: (string | {string})?)
@@ -123,6 +155,12 @@ function Server:destroy()
123
155
  self.data = {};
124
156
  self._queuedUpdates = {};
125
157
 
158
+ self._allSignal:Destroy();
159
+ for _, signal in self._signals do
160
+ signal:Destroy();
161
+ end;
162
+ self._signals = {};
163
+
126
164
  if self.player then
127
165
  local playerReplions = self._activeReplions[self.player];
128
166
  if not playerReplions then return; end;
@@ -149,7 +187,6 @@ function Server:_flushUpdates()
149
187
  self._isQueued = false;
150
188
 
151
189
  local updates = self._queuedUpdates;
152
-
153
190
  local nUpdates = Sift.Dictionary.count(updates);
154
191
  if nUpdates == 0 then return; end;
155
192
 
package/src/Shared.lua CHANGED
@@ -6,7 +6,7 @@ local Shared = {};
6
6
  Shared.REMOTE_NAME = 'ReplionNetwork';
7
7
  Shared.NIL_SENTINEL = '\0\0__NIL__\0\0';
8
8
 
9
- function Shared.getNestedValue(root: any, path: {string})
9
+ function Shared.getNestedValue(root: any, path: { string })
10
10
  local current = root;
11
11
  for _, key in path do
12
12
  if typeof(current) ~= 'table' then return nil; end;
package/src/index.d.ts CHANGED
@@ -21,7 +21,7 @@ declare namespace Replion {
21
21
  }
22
22
 
23
23
  class Client<T extends object> {
24
- static waitForReplion<T extends object>(channel: string): Client<T>;
24
+ static waitForReplion: <T extends object>(channel: string) => Client<T>;
25
25
 
26
26
  get(): T;
27
27
  get<K extends keyof T>(key: K): T[K];