@quenty/tie 10.8.0 → 10.10.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/CHANGELOG.md CHANGED
@@ -3,6 +3,31 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ # [10.10.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/tie@10.9.0...@quenty/tie@10.10.0) (2024-10-04)
7
+
8
+
9
+ ### Features
10
+
11
+ * Use configuration instead of folder. While this forces a datamodel event to fire, it means we scan less classes on the client, and it's easier to see in the explorer ([06a342f](https://github.com/Quenty/NevermoreEngine/commit/06a342f5726282c46174ddec3dc7f54eeb768c46))
12
+ * Use RxSignal for the TiePropertyInterface ([5ea04b8](https://github.com/Quenty/NevermoreEngine/commit/5ea04b85402e994f13a81a9b32e5971e1a262eb5))
13
+
14
+
15
+ ### Performance Improvements
16
+
17
+ * TieImplementation uses Folder on client instead of camera, which results in a memory improvement ([bc55d76](https://github.com/Quenty/NevermoreEngine/commit/bc55d76fd296c8923e47c3830145c8e75d8a7b69))
18
+
19
+
20
+
21
+
22
+
23
+ # [10.9.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/tie@10.8.0...@quenty/tie@10.9.0) (2024-09-25)
24
+
25
+ **Note:** Version bump only for package @quenty/tie
26
+
27
+
28
+
29
+
30
+
6
31
  # [10.8.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/tie@10.7.0...@quenty/tie@10.8.0) (2024-09-25)
7
32
 
8
33
  **Note:** Version bump only for package @quenty/tie
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/tie",
3
- "version": "10.8.0",
3
+ "version": "10.10.0",
4
4
  "description": "Tie allows interfaces to be defined between Lua OOP and Roblox objects.",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,28 +28,29 @@
28
28
  "Quenty"
29
29
  ],
30
30
  "dependencies": {
31
- "@quenty/attributeutils": "^14.6.0",
32
- "@quenty/baseobject": "^10.5.0",
33
- "@quenty/brio": "^14.6.0",
34
- "@quenty/collectionserviceutils": "^8.6.0",
35
- "@quenty/instanceutils": "^13.6.0",
36
- "@quenty/loader": "^10.5.0",
37
- "@quenty/maid": "^3.3.0",
38
- "@quenty/rx": "^13.6.0",
39
- "@quenty/statestack": "^14.7.0",
31
+ "@quenty/attributeutils": "^14.8.0",
32
+ "@quenty/baseobject": "^10.6.0",
33
+ "@quenty/brio": "^14.8.0",
34
+ "@quenty/collectionserviceutils": "^8.8.0",
35
+ "@quenty/instanceutils": "^13.8.0",
36
+ "@quenty/loader": "^10.6.0",
37
+ "@quenty/maid": "^3.4.0",
38
+ "@quenty/rx": "^13.8.0",
39
+ "@quenty/rxsignal": "^7.8.0",
40
+ "@quenty/statestack": "^14.9.0",
40
41
  "@quenty/string": "^3.3.0",
41
- "@quenty/symbol": "^3.1.0",
42
+ "@quenty/symbol": "^3.2.0",
42
43
  "@quenty/table": "^3.5.0",
43
- "@quenty/tuple": "^1.2.0",
44
- "@quenty/valuebaseutils": "^13.6.0",
45
- "@quenty/valueobject": "^13.6.0"
44
+ "@quenty/tuple": "^1.3.0",
45
+ "@quenty/valuebaseutils": "^13.8.0",
46
+ "@quenty/valueobject": "^13.8.0"
46
47
  },
47
48
  "devDependencies": {
48
- "@quenty/promise": "^10.5.0",
49
- "@quenty/signal": "^7.5.0"
49
+ "@quenty/promise": "^10.6.0",
50
+ "@quenty/signal": "^7.7.0"
50
51
  },
51
52
  "publishConfig": {
52
53
  "access": "public"
53
54
  },
54
- "gitHead": "41715b15e2b48b2d22ff4f5277a8d4b7a0d32ef3"
55
+ "gitHead": "035abfa088c854a73e1c65b350267eaa17669646"
55
56
  }
@@ -11,14 +11,13 @@ local Observable = require("Observable")
11
11
  local Rx = require("Rx")
12
12
  local RxBrioUtils = require("RxBrioUtils")
13
13
  local RxInstanceUtils = require("RxInstanceUtils")
14
+ local RxSignal = require("RxSignal")
14
15
  local String = require("String")
15
16
  local Symbol = require("Symbol")
16
- local TiePropertyChangedSignalConnection = require("TiePropertyChangedSignalConnection")
17
+ local TieMemberInterface = require("TieMemberInterface")
17
18
  local TiePropertyImplementationUtils = require("TiePropertyImplementationUtils")
18
19
  local TieUtils = require("TieUtils")
19
20
  local ValueBaseUtils = require("ValueBaseUtils")
20
- local ValueObject = require("ValueObject")
21
- local TieMemberInterface = require("TieMemberInterface")
22
21
 
23
22
  local UNSET_VALUE = Symbol.named("unsetValue")
24
23
 
@@ -48,18 +47,22 @@ end
48
47
  function TiePropertyInterface:Observe()
49
48
  return self:_observeValueBaseBrio():Pipe({
50
49
  Rx.switchMap(function(brio)
51
- if brio:IsDead() then
52
- return Rx.of(nil)
53
- end
54
- local valueBase = brio:GetValue()
55
- if not valueBase then
56
- return Rx.of(nil)
57
- end
58
-
59
50
  return Observable.new(function(sub)
60
- local maid = Maid.new()
51
+ if brio:IsDead() then
52
+ sub:Fire(nil)
53
+ sub:Complete()
54
+ return
55
+ end
56
+
57
+ local valueBase = brio:GetValue()
58
+ if not valueBase then
59
+ sub:Fire(nil)
60
+ sub:Complete()
61
+ return
62
+ end
63
+
64
+ local maid = brio:ToMaid()
61
65
 
62
- sub:Fire(valueBase.Value)
63
66
  maid:GiveTask(valueBase.Changed:Connect(function()
64
67
  sub:Fire(valueBase.Value)
65
68
  end))
@@ -70,6 +73,8 @@ function TiePropertyInterface:Observe()
70
73
  end
71
74
  end))
72
75
 
76
+ sub:Fire(valueBase.Value)
77
+
73
78
  return maid
74
79
  end)
75
80
  end);
@@ -119,21 +124,9 @@ function TiePropertyInterface:_getFullName()
119
124
  end
120
125
 
121
126
  function TiePropertyInterface:_getChangedEvent()
122
- return {
123
- Connect = function(_, callback)
124
- assert(type(callback) == "function", "Bad callback")
125
- return TiePropertyChangedSignalConnection.new(function(connMaid)
126
- local valueObject = connMaid:Add(ValueObject.new(nil) )
127
-
128
- connMaid:GiveTask(self:Observe():Subscribe(function(value)
129
- valueObject.Value = value
130
- end))
131
-
132
- -- After observing, so we can emit only changes.
133
- connMaid:GiveTask(valueObject.Changed:Connect(callback))
134
- end)
135
- end;
136
- }
127
+ return RxSignal.new(self:Observe():Pipe({
128
+ Rx.skip(1)
129
+ }))
137
130
  end
138
131
 
139
132
  local IMPLEMENTATION_TYPES = {
@@ -196,29 +189,29 @@ function TiePropertyInterface:_observeFromImplParent(implParent)
196
189
  end
197
190
  end
198
191
 
199
- -- Subscribe to named children
200
- topMaid:GiveTask(RxInstanceUtils.observeChildrenOfNameBrio(implParent, "Instance", self._memberDefinition:GetMemberName())
201
- :Subscribe(function(brio)
202
- if brio:IsDead() then
203
- return
204
- end
205
-
206
- local innerMaid = brio:ToMaid()
207
- local child = brio:GetValue()
192
+ -- Subscribe to named children, assuming no name changes...
193
+ topMaid:GiveTask(RxInstanceUtils.observeChildrenBrio(implParent, function(value)
194
+ return value.Name == memberName
195
+ end):Subscribe(function(brio)
196
+ if brio:IsDead() then
197
+ return
198
+ end
208
199
 
209
- innerMaid:GiveTask(function()
210
- local index = table.find(validNamedChildren, child)
200
+ local innerMaid, child = brio:ToMaidAndValue()
211
201
 
212
- if index then
213
- table.remove(validNamedChildren, index)
214
- end
202
+ innerMaid:GiveTask(function()
203
+ local index = table.find(validNamedChildren, child)
215
204
 
216
- update()
217
- end)
205
+ if index then
206
+ table.remove(validNamedChildren, index)
207
+ end
218
208
 
219
- table.insert(validNamedChildren, child)
220
209
  update()
221
- end))
210
+ end)
211
+
212
+ table.insert(validNamedChildren, child)
213
+ update()
214
+ end))
222
215
 
223
216
  topMaid:GiveTask(implParent:GetAttributeChangedSignal(memberName):Connect(update))
224
217
  update()
@@ -89,6 +89,7 @@ function TieDefinition.new(definitionName, members)
89
89
  local self = setmetatable({}, TieDefinition)
90
90
 
91
91
  self._definitionName = assert(definitionName, "No definitionName")
92
+ self._validContainerNameSetWeakCache = setmetatable({}, {__mode = "kv"})
92
93
  self._memberMap = {}
93
94
  self._defaultTieRealm = TieRealms.SHARED
94
95
 
@@ -156,8 +157,41 @@ function TieDefinition:GetImplementations(adornee: Instance, tieRealm)
156
157
  return implementations
157
158
  end
158
159
 
159
- function TieDefinition:GetImplClass()
160
- return "Camera"
160
+ function TieDefinition:GetNewImplClass(tieRealm)
161
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
162
+
163
+ if tieRealm == TieRealms.CLIENT then
164
+ return "Configuration"
165
+ else
166
+ return "Camera"
167
+ end
168
+ end
169
+
170
+ local IMPL_CLIENT_SET = table.freeze({
171
+ ["Configuration"] = true;
172
+ })
173
+
174
+ local IMPL_SERVER_SET = table.freeze({
175
+ ["Camera"] = true;
176
+ })
177
+
178
+ local IMPL_SHARED_SET = table.freeze({
179
+ ["Camera"] = true;
180
+ ["Configuration"] = true;
181
+ })
182
+
183
+ function TieDefinition:GetImplClassSet(tieRealm)
184
+
185
+ if tieRealm == TieRealms.CLIENT then
186
+ -- Shared implements both...
187
+ return IMPL_CLIENT_SET
188
+ elseif tieRealm == TieRealms.SERVER then
189
+ return IMPL_SERVER_SET
190
+ elseif tieRealm == TieRealms.SHARED then
191
+ return IMPL_SHARED_SET
192
+ else
193
+ error("Unknwon tieRealm")
194
+ end
161
195
  end
162
196
 
163
197
  function TieDefinition:GetImplementationParents(adornee, tieRealm)
@@ -464,10 +498,11 @@ function TieDefinition:ObserveValidContainerChildrenBrio(adornee, tieRealm)
464
498
  assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
465
499
 
466
500
  local validContainerNameSet = self:GetValidContainerNameSet(tieRealm)
501
+ local validImplClassSet = self:GetImplClassSet(tieRealm)
467
502
 
468
503
  return RxInstanceUtils.observeChildrenBrio(adornee, function(value)
469
504
  -- Just assume our name doesn't change
470
- return value:IsA(self:GetImplClass()) and validContainerNameSet[value.Name] and true or false
505
+ return validImplClassSet[value.ClassName] and validContainerNameSet[value.Name] and true or false
471
506
  end)
472
507
  end
473
508
 
@@ -597,26 +632,34 @@ end
597
632
  ]=]
598
633
  function TieDefinition:GetValidContainerNameSet(tieRealm)
599
634
  -- TODO: Still generate unique datamodel key here?
635
+ if self._validContainerNameSetWeakCache[tieRealm] then
636
+ return self._validContainerNameSetWeakCache[tieRealm]
637
+ end
600
638
 
601
639
  if tieRealm == TieRealms.CLIENT then
602
640
  -- Shared implements both...
603
- return {
641
+ self._validContainerNameSetWeakCache[tieRealm] = table.freeze({
604
642
  [self._definitionName .. "Client"] = true;
605
643
  [self._definitionName .. "Shared"] = true;
606
- }
644
+ })
645
+ return self._validContainerNameSetWeakCache[tieRealm]
607
646
  elseif tieRealm == TieRealms.SERVER then
608
- return {
647
+ self._validContainerNameSetWeakCache[tieRealm] = table.freeze({
609
648
  [self._definitionName] = true;
610
649
  [self._definitionName .. "Shared"] = true;
611
- }
650
+ })
651
+ return self._validContainerNameSetWeakCache[tieRealm]
612
652
  elseif tieRealm == TieRealms.SHARED then
613
653
  -- Technically on the implementation shared is very strict,
614
654
  -- but we allow any calls here for discovery
615
- return {
655
+ self._validContainerNameSetWeakCache[tieRealm] = table.freeze({
616
656
  [self._definitionName] = true;
617
657
  [self._definitionName .. "Client"] = true;
618
658
  [self._definitionName .. "Shared"] = true;
619
- }
659
+ })
660
+ return self._validContainerNameSetWeakCache[tieRealm]
661
+ else
662
+ error("Unknwon tieRealm")
620
663
  end
621
664
  end
622
665
 
@@ -27,7 +27,7 @@ function TieImplementation.new(tieDefinition, adornee, implementer, implementati
27
27
  self._actualSelf = implementer or {}
28
28
  self._implementationTieRealm = assert(implementationTieRealm, "Bad implementationTieRealm")
29
29
 
30
- self._implParent = self._maid:Add(Instance.new(tieDefinition:GetImplClass()))
30
+ self._implParent = self._maid:Add(Instance.new(tieDefinition:GetNewImplClass(implementationTieRealm)))
31
31
  self._implParent.Archivable = false
32
32
 
33
33
  self._memberImplementations = {}
@@ -1,44 +0,0 @@
1
- --[=[
2
- @class TiePropertyChangedSignalConnection
3
- ]=]
4
-
5
- local require = require(script.Parent.loader).load(script)
6
-
7
- local Maid = require("Maid")
8
-
9
- local TiePropertyChangedSignalConnection = {}
10
- TiePropertyChangedSignalConnection.ClassName = "TiePropertyChangedSignalConnection"
11
- TiePropertyChangedSignalConnection.__index = TiePropertyChangedSignalConnection
12
-
13
- function TiePropertyChangedSignalConnection.new(connect)
14
- local self = setmetatable({}, TiePropertyChangedSignalConnection)
15
-
16
- self._maid = Maid.new()
17
-
18
- self._connected = true
19
- connect(self._maid)
20
-
21
- return self
22
- end
23
-
24
- function TiePropertyChangedSignalConnection:Disconnect()
25
- self:Destroy()
26
- end
27
-
28
- function TiePropertyChangedSignalConnection:__index(index)
29
- if index == "IsConnected" then
30
- return self._connected
31
- elseif TiePropertyChangedSignalConnection[index] then
32
- return TiePropertyChangedSignalConnection[index]
33
- else
34
- error(string.format("Bad index %q for TiePropertyChangedSignalConnection", tostring(index)))
35
- end
36
- end
37
-
38
- function TiePropertyChangedSignalConnection:Destroy()
39
- self._connected = false
40
- self._maid:DoCleaning()
41
- -- Avoid setting the metatable so calling methods is always valid
42
- end
43
-
44
- return TiePropertyChangedSignalConnection