@quenty/tie 10.6.0 → 10.7.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +19 -0
  2. package/README.md +4 -0
  3. package/package.json +16 -15
  4. package/src/Shared/Members/Methods/TieMethodDefinition.lua +44 -0
  5. package/src/Shared/{Implementation → Members/Methods}/TieMethodImplementation.lua +4 -5
  6. package/src/Shared/Members/Methods/TieMethodInterfaceUtils.lua +58 -0
  7. package/src/Shared/{Interface → Members/Properties}/TiePropertyChangedSignalConnection.lua +1 -1
  8. package/src/Shared/Members/Properties/TiePropertyDefinition.lua +58 -0
  9. package/src/Shared/{Interface → Members/Properties}/TiePropertyInterface.lua +42 -59
  10. package/src/Shared/Members/Signals/TieSignalConnection.lua +63 -0
  11. package/src/Shared/Members/Signals/TieSignalDefinition.lua +38 -0
  12. package/src/Shared/{Implementation → Members/Signals}/TieSignalImplementation.lua +29 -15
  13. package/src/Shared/Members/Signals/TieSignalInterface.lua +90 -0
  14. package/src/Shared/Members/TieMemberDefinition.lua +104 -0
  15. package/src/Shared/Members/TieMemberInterface.lua +94 -0
  16. package/src/Shared/Realms/TieRealmUtils.lua +41 -0
  17. package/src/Shared/{Definition/Types → Realms}/TieRealms.lua +3 -4
  18. package/src/Shared/Services/TieRealmService.lua +31 -0
  19. package/src/Shared/TieDefinition.lua +708 -0
  20. package/src/Shared/TieImplementation.lua +167 -0
  21. package/src/Shared/TieInterface.lua +129 -0
  22. package/src/Shared/{Encoding → Utils}/TieUtils.lua +4 -1
  23. package/test/modules/Server/Action/Action.lua +4 -7
  24. package/test/modules/Server/Door.lua +5 -10
  25. package/test/scripts/Server/ServerMain.server.lua +3 -3
  26. package/src/Shared/Definition/TieDefinition.lua +0 -507
  27. package/src/Shared/Definition/TieMethodDefinition.lua +0 -61
  28. package/src/Shared/Definition/TiePropertyDefinition.lua +0 -64
  29. package/src/Shared/Definition/TieSignalDefinition.lua +0 -59
  30. package/src/Shared/Definition/Types/TieRealmUtils.lua +0 -60
  31. package/src/Shared/Implementation/TieImplementation.lua +0 -129
  32. package/src/Shared/Interface/TieInterface.lua +0 -122
  33. package/src/Shared/Interface/TieInterfaceUtils.lua +0 -70
  34. package/src/Shared/Interface/TieMethodInterfaceUtils.lua +0 -43
  35. package/src/Shared/Interface/TieSignalConnection.lua +0 -89
  36. package/src/Shared/Interface/TieSignalInterface.lua +0 -61
  37. /package/src/Shared/{Implementation → Members/Properties}/TiePropertyImplementation.lua +0 -0
  38. /package/src/Shared/{Implementation → Members/Properties}/TiePropertyImplementationUtils.lua +0 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,25 @@
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.7.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/tie@10.6.0...@quenty/tie@10.7.0) (2024-09-12)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Tie signal implementation fix ([8dc23bb](https://github.com/Quenty/NevermoreEngine/commit/8dc23bb8300598431a58b273ee2382ee90e76243))
12
+ * TODO FIX THIS ([3731acd](https://github.com/Quenty/NevermoreEngine/commit/3731acdf4cf888bdac55157670fc61d6a6ba7c3d))
13
+
14
+
15
+ ### Features
16
+
17
+ * Add tuple package and fix tie signal ([134f90c](https://github.com/Quenty/NevermoreEngine/commit/134f90c03b265b9d2232198475ca27f4d5e87071))
18
+ * Allow default values to be defined for TiePropertyDefinition ([89112f1](https://github.com/Quenty/NevermoreEngine/commit/89112f15ffdc8c637681ba9f4e7aa1c60e2c7e23))
19
+ * Unedited all changes ([60e64e3](https://github.com/Quenty/NevermoreEngine/commit/60e64e3efce17c10c4b8965871187d231b338dd4))
20
+
21
+
22
+
23
+
24
+
6
25
  # [10.6.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/tie@10.5.0...@quenty/tie@10.6.0) (2024-08-09)
7
26
 
8
27
  **Note:** Version bump only for package @quenty/tie
package/README.md CHANGED
@@ -32,3 +32,7 @@ This package does two things. First of all, it basically automates the creation
32
32
  1. Support tagged ties with
33
33
  1. Ensure ties can be queried via CollectionService
34
34
  1. Allow client implementation of server-based ties
35
+
36
+ ## Realms
37
+
38
+ 1. By default everything is a "shared" realm
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/tie",
3
- "version": "10.6.0",
3
+ "version": "10.7.0",
4
4
  "description": "Tie allows interfaces to be defined between Lua OOP and Roblox objects.",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -28,27 +28,28 @@
28
28
  "Quenty"
29
29
  ],
30
30
  "dependencies": {
31
- "@quenty/attributeutils": "^14.4.0",
32
- "@quenty/baseobject": "^10.3.0",
33
- "@quenty/brio": "^14.4.0",
34
- "@quenty/collectionserviceutils": "^8.4.0",
35
- "@quenty/instanceutils": "^13.4.0",
36
- "@quenty/loader": "^10.3.0",
37
- "@quenty/maid": "^3.2.0",
38
- "@quenty/rx": "^13.4.0",
39
- "@quenty/statestack": "^14.5.0",
31
+ "@quenty/attributeutils": "^14.5.0",
32
+ "@quenty/baseobject": "^10.4.0",
33
+ "@quenty/brio": "^14.5.0",
34
+ "@quenty/collectionserviceutils": "^8.5.0",
35
+ "@quenty/instanceutils": "^13.5.0",
36
+ "@quenty/loader": "^10.4.0",
37
+ "@quenty/maid": "^3.3.0",
38
+ "@quenty/rx": "^13.5.0",
39
+ "@quenty/statestack": "^14.6.0",
40
40
  "@quenty/string": "^3.2.0",
41
41
  "@quenty/symbol": "^3.1.0",
42
42
  "@quenty/table": "^3.5.0",
43
- "@quenty/valuebaseutils": "^13.4.0",
44
- "@quenty/valueobject": "^13.4.0"
43
+ "@quenty/tuple": "^1.1.0",
44
+ "@quenty/valuebaseutils": "^13.5.0",
45
+ "@quenty/valueobject": "^13.5.0"
45
46
  },
46
47
  "devDependencies": {
47
- "@quenty/promise": "^10.3.0",
48
- "@quenty/signal": "^7.3.0"
48
+ "@quenty/promise": "^10.4.0",
49
+ "@quenty/signal": "^7.4.0"
49
50
  },
50
51
  "publishConfig": {
51
52
  "access": "public"
52
53
  },
53
- "gitHead": "ba466bdbc05c42fb607cf5e228c16339201d21d7"
54
+ "gitHead": "fb172906f3ee725269ec1e5f4daf9dca227e729d"
54
55
  }
@@ -0,0 +1,44 @@
1
+ --[=[
2
+ @class TieMethodDefinition
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local TieMethodImplementation = require("TieMethodImplementation")
8
+ local TieMethodInterfaceUtils = require("TieMethodInterfaceUtils")
9
+ local TieMemberDefinition = require("TieMemberDefinition")
10
+ local TieRealmUtils = require("TieRealmUtils")
11
+
12
+ local TieMethodDefinition = setmetatable({}, TieMemberDefinition)
13
+ TieMethodDefinition.ClassName = "TieMethodDefinition"
14
+ TieMethodDefinition.__index = TieMethodDefinition
15
+
16
+ function TieMethodDefinition.new(tieDefinition, methodName, memberTieRealm)
17
+ assert(TieRealmUtils.isTieRealm(memberTieRealm), "Bad memberTieRealm")
18
+
19
+ local self = setmetatable(TieMemberDefinition.new(tieDefinition, methodName, memberTieRealm), TieMethodDefinition)
20
+
21
+ return self
22
+ end
23
+
24
+ function TieMethodDefinition:GetFriendlyName()
25
+ return string.format("%s:%s()", self._tieDefinition:GetName(), self._memberName)
26
+ end
27
+
28
+ function TieMethodDefinition:Implement(implParent: Instance, initialValue, actualSelf, tieRealm)
29
+ assert(typeof(implParent) == "Instance", "Bad implParent")
30
+ assert(actualSelf, "No actualSelf")
31
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
32
+
33
+ return TieMethodImplementation.new(self, implParent, initialValue, actualSelf)
34
+ end
35
+
36
+ function TieMethodDefinition:GetInterface(implParent: Instance, aliasSelf, tieRealm)
37
+ assert(typeof(implParent) == "Instance", "Bad implParent")
38
+ assert(aliasSelf, "No aliasSelf")
39
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
40
+
41
+ return TieMethodInterfaceUtils.get(aliasSelf, self, implParent, nil, tieRealm)
42
+ end
43
+
44
+ return TieMethodDefinition
@@ -11,18 +11,17 @@ local TieMethodImplementation = setmetatable({}, BaseObject)
11
11
  TieMethodImplementation.ClassName = "TieMethodImplementation"
12
12
  TieMethodImplementation.__index = TieMethodImplementation
13
13
 
14
- function TieMethodImplementation.new(memberDefinition, folder, initialValue, actualSelf)
14
+ function TieMethodImplementation.new(memberDefinition, parent, initialValue, actualSelf)
15
15
  local self = setmetatable(BaseObject.new(), TieMethodImplementation)
16
16
 
17
17
  self._memberDefinition = assert(memberDefinition, "No memberDefinition")
18
- self._folder = assert(folder, "No folder")
18
+ self._parent = assert(parent, "No parent")
19
19
  self._actualSelf = assert(actualSelf, "No actualSelf")
20
20
 
21
- self._bindableFunction = Instance.new("BindableFunction")
21
+ self._bindableFunction = self._maid:Add(Instance.new("BindableFunction"))
22
22
  self._bindableFunction.Name = memberDefinition:GetMemberName()
23
23
  self._bindableFunction.Archivable = false
24
- self._bindableFunction.Parent = self._folder
25
- self._maid:GiveTask(self._bindableFunction)
24
+ self._bindableFunction.Parent = self._parent
26
25
 
27
26
  self:SetImplementation(initialValue)
28
27
 
@@ -0,0 +1,58 @@
1
+ --[=[
2
+ @class TieMethodInterfaceUtils
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local TieUtils = require("TieUtils")
8
+ local TieRealmUtils = require("TieRealmUtils")
9
+
10
+ local TieMethodInterfaceUtils = {}
11
+
12
+ function TieMethodInterfaceUtils.get(aliasSelf, tieMethodDefinition, implParent, adornee, interfaceTieRealm)
13
+ assert(TieRealmUtils.isTieRealm(interfaceTieRealm), "Bad interfaceTieRealm")
14
+
15
+ local tieDefinition = tieMethodDefinition:GetTieDefinition()
16
+
17
+ return function(firstArg, ...)
18
+ if firstArg ~= aliasSelf then
19
+ error(string.format("Must call methods with self as first parameter (Hint use `%s:%s()` instead of `%s.%s()`)",
20
+ tieDefinition:GetName(),
21
+ tieMethodDefinition:GetMemberName(),
22
+ tieDefinition:GetName(),
23
+ tieMethodDefinition:GetMemberName()))
24
+ end
25
+
26
+ if implParent and adornee then
27
+ if implParent.Parent ~= adornee then
28
+ error("implParent is not a parent of the adornee")
29
+ end
30
+ elseif implParent then
31
+ implParent = implParent
32
+ elseif adornee then
33
+ -- Search the adornee (rip this is SO slow)
34
+
35
+ local validContainerNameSet = tieDefinition:GetValidContainerNameSet(interfaceTieRealm)
36
+ for containerName, _ in pairs(validContainerNameSet) do
37
+ local found = adornee:FindFirstChild(containerName)
38
+ if found then
39
+ local bindableFunction = found:FindFirstChild(tieMethodDefinition:GetMemberName())
40
+ if bindableFunction then
41
+ return TieUtils.decode(bindableFunction:Invoke(TieUtils.encode(...)))
42
+ end
43
+ end
44
+ end
45
+
46
+ error(string.format("No implemented for %s on %q", tieMethodDefinition:GetFriendlyName(), implParent:GetFullName()))
47
+ end
48
+
49
+ local bindableFunction = implParent:FindFirstChild(tieMethodDefinition:GetMemberName())
50
+ if not bindableFunction then
51
+ error(string.format("No implemented for %s on %q", tieMethodDefinition:GetFriendlyName(), implParent:GetFullName()))
52
+ end
53
+
54
+ return TieUtils.decode(bindableFunction:Invoke(TieUtils.encode(...)))
55
+ end;
56
+ end
57
+
58
+ return TieMethodInterfaceUtils
@@ -31,7 +31,7 @@ function TiePropertyChangedSignalConnection:__index(index)
31
31
  elseif TiePropertyChangedSignalConnection[index] then
32
32
  return TiePropertyChangedSignalConnection[index]
33
33
  else
34
- error(("Bad index %q for TiePropertyChangedSignalConnection"):format(tostring(index)))
34
+ error(string.format("Bad index %q for TiePropertyChangedSignalConnection", tostring(index)))
35
35
  end
36
36
  end
37
37
 
@@ -0,0 +1,58 @@
1
+ --[=[
2
+ @class TiePropertyDefinition
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local TiePropertyImplementation = require("TiePropertyImplementation")
8
+ local TiePropertyInterface = require("TiePropertyInterface")
9
+ local TieMemberDefinition = require("TieMemberDefinition")
10
+ local TieRealmUtils = require("TieRealmUtils")
11
+
12
+ local TiePropertyDefinition = setmetatable({}, TieMemberDefinition)
13
+ TiePropertyDefinition.ClassName = "TiePropertyDefinition"
14
+ TiePropertyDefinition.__index = TiePropertyDefinition
15
+
16
+ function TiePropertyDefinition.new(tieDefinition, propertyName: string, defaultValue: any, memberTieRealm)
17
+ assert(TieRealmUtils.isTieRealm(memberTieRealm), "Bad memberTieRealm")
18
+
19
+ local self = setmetatable(TieMemberDefinition.new(tieDefinition, propertyName, memberTieRealm), TiePropertyDefinition)
20
+
21
+ self._defaultValue = defaultValue
22
+
23
+ return self
24
+ end
25
+
26
+ function TiePropertyDefinition:GetDefaultValue()
27
+ return self._defaultValue
28
+ end
29
+
30
+ function TiePropertyDefinition:IsRequiredForImplementation(currentRealm)
31
+ -- Override
32
+ if getmetatable(TiePropertyDefinition).IsRequiredForImplementation(self, currentRealm) then
33
+ if self:GetDefaultValue() ~= nil then
34
+ return false
35
+ end
36
+
37
+ return true
38
+ end
39
+
40
+ return false
41
+ end
42
+
43
+ function TiePropertyDefinition:Implement(implParent: Instance, initialValue, _actualSelf, tieRealm)
44
+ assert(typeof(implParent) == "Instance", "Bad implParent")
45
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
46
+
47
+ return TiePropertyImplementation.new(self, implParent, initialValue, tieRealm)
48
+ end
49
+
50
+ function TiePropertyDefinition:GetInterface(implParent: Instance, _actualSelf, tieRealm)
51
+ assert(typeof(implParent) == "Instance", "Bad implParent")
52
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
53
+
54
+ return TiePropertyInterface.new(implParent, nil, self, tieRealm)
55
+ end
56
+
57
+
58
+ return TiePropertyDefinition
@@ -4,37 +4,30 @@
4
4
 
5
5
  local require = require(script.Parent.loader).load(script)
6
6
 
7
+ local AttributeUtils = require("AttributeUtils")
8
+ local AttributeValue = require("AttributeValue")
7
9
  local Maid = require("Maid")
8
10
  local Observable = require("Observable")
9
11
  local Rx = require("Rx")
10
12
  local RxBrioUtils = require("RxBrioUtils")
11
13
  local RxInstanceUtils = require("RxInstanceUtils")
12
14
  local String = require("String")
13
- local TieInterfaceUtils = require("TieInterfaceUtils")
15
+ local Symbol = require("Symbol")
14
16
  local TiePropertyChangedSignalConnection = require("TiePropertyChangedSignalConnection")
15
17
  local TiePropertyImplementationUtils = require("TiePropertyImplementationUtils")
16
18
  local TieUtils = require("TieUtils")
17
19
  local ValueBaseUtils = require("ValueBaseUtils")
18
20
  local ValueObject = require("ValueObject")
19
- local AttributeUtils = require("AttributeUtils")
20
- local AttributeValue = require("AttributeValue")
21
- local Symbol = require("Symbol")
21
+ local TieMemberInterface = require("TieMemberInterface")
22
22
 
23
23
  local UNSET_VALUE = Symbol.named("unsetValue")
24
24
 
25
- local TiePropertyInterface = {}
25
+ local TiePropertyInterface = setmetatable({}, TieMemberInterface)
26
26
  TiePropertyInterface.ClassName = "TiePropertyInterface"
27
27
  TiePropertyInterface.__index = TiePropertyInterface
28
28
 
29
- function TiePropertyInterface.new(folder, adornee, memberDefinition)
30
- local self = setmetatable({}, TiePropertyInterface)
31
-
32
- assert(folder or adornee, "Folder or adornee required")
33
-
34
- self._folder = folder
35
- self._adornee = adornee
36
- self._memberDefinition = assert(memberDefinition, "No memberDefinition")
37
- self._tieDefinition = self._memberDefinition:GetTieDefinition()
29
+ function TiePropertyInterface.new(implParent, adornee, memberDefinition, interfaceTieRealm)
30
+ local self = setmetatable(TieMemberInterface.new(implParent, adornee, memberDefinition, interfaceTieRealm), TiePropertyInterface)
38
31
 
39
32
  return self
40
33
  end
@@ -84,17 +77,13 @@ function TiePropertyInterface:Observe()
84
77
  })
85
78
  end
86
79
 
87
- function TiePropertyInterface:_getFolder()
88
- return TieInterfaceUtils.getFolder(self._tieDefinition, self._folder, self._adornee)
89
- end
90
-
91
80
  function TiePropertyInterface:_findValueBase()
92
- local folder = self:_getFolder()
93
- if not folder then
81
+ local implParent = self:GetImplParent()
82
+ if not implParent then
94
83
  return nil
95
84
  end
96
85
 
97
- local implementation = folder:FindFirstChild(self._memberDefinition:GetMemberName())
86
+ local implementation = implParent:FindFirstChild(self._memberDefinition:GetMemberName())
98
87
  if not implementation then
99
88
  return nil
100
89
  end
@@ -112,21 +101,20 @@ end
112
101
  function TiePropertyInterface:_getValueBaseOrError()
113
102
  local valueBase = self:_findValueBase()
114
103
  if not valueBase then
115
- error(("%s.%s is not implemented for %s"):format(
116
- self._tieDefinition:GetContainerName(),
117
- self._memberDefinition:GetMemberName(),
104
+ error(string.format("%s.%s is not implemented for %s",
105
+ self._memberDefinition:GetFriendlyName(),
118
106
  self:_getFullName()))
119
107
  end
120
108
  return valueBase
121
109
  end
122
110
 
123
111
  function TiePropertyInterface:_getFullName()
124
- if self._folder then
125
- return self._folder:GetFullName()
112
+ if self._implParent then
113
+ return self._implParent:GetFullName()
126
114
  elseif self._adornee then
127
115
  return self._adornee:GetFullName()
128
116
  else
129
- error("[TiePropertyInterface] - Either folder or adornee should be defined")
117
+ error("[TiePropertyInterface] - Either implParent or adornee should be defined")
130
118
  end
131
119
  end
132
120
 
@@ -135,8 +123,7 @@ function TiePropertyInterface:_getChangedEvent()
135
123
  Connect = function(_, callback)
136
124
  assert(type(callback) == "function", "Bad callback")
137
125
  return TiePropertyChangedSignalConnection.new(function(connMaid)
138
- local valueObject = ValueObject.new(nil)
139
- connMaid:GiveTask(valueObject)
126
+ local valueObject = connMaid:Add(ValueObject.new(nil) )
140
127
 
141
128
  connMaid:GiveTask(self:Observe():Subscribe(function(value)
142
129
  valueObject.Value = value
@@ -154,7 +141,7 @@ local IMPLEMENTATION_TYPES = {
154
141
  none = "none";
155
142
  }
156
143
 
157
- function TiePropertyInterface:_observeFromFolder(folder)
144
+ function TiePropertyInterface:_observeFromImplParent(implParent)
158
145
  return Observable.new(function(sub)
159
146
  local memberName = self._memberDefinition:GetMemberName()
160
147
  local topMaid = Maid.new()
@@ -169,11 +156,11 @@ function TiePropertyInterface:_observeFromFolder(folder)
169
156
  end
170
157
 
171
158
  -- Prioritize attributes first
172
- local currentAttribute = folder:GetAttribute(memberName)
159
+ local currentAttribute = implParent:GetAttribute(memberName)
173
160
  if currentAttribute ~= nil then
174
161
  if lastImplementationType ~= IMPLEMENTATION_TYPES.attribute then
175
162
  lastImplementationType = IMPLEMENTATION_TYPES.attribute
176
- sub:Fire(AttributeValue.new(folder, memberName))
163
+ sub:Fire(AttributeValue.new(implParent, memberName))
177
164
  end
178
165
 
179
166
  return
@@ -210,7 +197,7 @@ function TiePropertyInterface:_observeFromFolder(folder)
210
197
  end
211
198
 
212
199
  -- Subscribe to named children
213
- topMaid:GiveTask(RxInstanceUtils.observeChildrenOfNameBrio(folder, "Instance", self._memberDefinition:GetMemberName())
200
+ topMaid:GiveTask(RxInstanceUtils.observeChildrenOfNameBrio(implParent, "Instance", self._memberDefinition:GetMemberName())
214
201
  :Subscribe(function(brio)
215
202
  if brio:IsDead() then
216
203
  return
@@ -233,7 +220,7 @@ function TiePropertyInterface:_observeFromFolder(folder)
233
220
  update()
234
221
  end))
235
222
 
236
- topMaid:GiveTask(folder:GetAttributeChangedSignal(memberName):Connect(update))
223
+ topMaid:GiveTask(implParent:GetAttributeChangedSignal(memberName):Connect(update))
237
224
  update()
238
225
 
239
226
  return topMaid
@@ -241,25 +228,21 @@ function TiePropertyInterface:_observeFromFolder(folder)
241
228
  end
242
229
 
243
230
  function TiePropertyInterface:_observeValueBaseBrio()
244
- return self:_observeFolderBrio():Pipe({
245
- RxBrioUtils.switchMapBrio(function(folder)
246
- return self:_observeFromFolder(folder)
231
+ return self:ObserveImplParentBrio():Pipe({
232
+ RxBrioUtils.switchMapBrio(function(implParent)
233
+ return self:_observeFromImplParent(implParent)
247
234
  end);
248
235
  RxBrioUtils.onlyLastBrioSurvives();
249
236
  })
250
237
  end
251
238
 
252
- function TiePropertyInterface:_observeFolderBrio()
253
- return TieInterfaceUtils.observeFolderBrio(self._tieDefinition, self._folder, self._adornee)
254
- end
255
-
256
239
  function TiePropertyInterface:__index(index)
257
240
  if TiePropertyInterface[index] then
258
241
  return TiePropertyInterface[index]
259
242
  elseif index == "Value" then
260
- local folder = self:_getFolder()
261
- if folder then
262
- local currentAttributeValue = folder:GetAttribute(self._memberDefinition:GetMemberName())
243
+ local implParent = self:GetImplParent()
244
+ if implParent then
245
+ local currentAttributeValue = implParent:GetAttribute(self._memberDefinition:GetMemberName())
263
246
  if currentAttributeValue ~= nil then
264
247
  return currentAttributeValue
265
248
  end
@@ -269,51 +252,51 @@ function TiePropertyInterface:__index(index)
269
252
  return valueBase.Value
270
253
  elseif index == "Changed" then
271
254
  return self:_getChangedEvent()
272
- elseif index == "_adornee" or index == "_folder" or index == "_memberDefinition" or index == "_tieDefinition" then
255
+ elseif index == "_adornee" or index == "_implParent" or index == "_memberDefinition" or index == "_tieDefinition" then
273
256
  return rawget(self, index)
274
257
  else
275
- error(("Bad index %q for TiePropertyInterface"):format(tostring(index)))
258
+ error(string.format("Bad index %q for TiePropertyInterface", tostring(index)))
276
259
  end
277
260
  end
278
261
 
279
262
  function TiePropertyInterface:__newindex(index, value)
280
- if index == "_adornee" or index == "_folder" or index == "_memberDefinition" or index == "_tieDefinition" then
263
+ if index == "_adornee" or index == "_implParent" or index == "_memberDefinition" or index == "_tieDefinition" then
281
264
  rawset(self, index, value)
282
265
  elseif index == "Value" then
283
266
  local className = ValueBaseUtils.getClassNameFromType(typeof(value))
284
267
  if not className then
285
- error(("[TiePropertyImplementation] - Bad implementation value type %q, cannot set"):format(typeof(value)))
268
+ error(string.format("[TiePropertyImplementation] - Bad implementation value type %q, cannot set", typeof(value)))
286
269
  end
287
270
 
288
271
  local valueBase = self:_findValueBase()
289
272
  if type(valueBase) == "table" or (typeof(valueBase) == "Instance" and valueBase.ClassName == className) then
290
273
  valueBase.Value = value
291
274
  elseif AttributeUtils.isValidAttributeType(typeof(value)) and value ~= nil then
292
- local folder = self:_getFolder()
293
- if folder then
294
- folder:SetAttribute(self._memberDefinition:GetMemberName(), value)
275
+ local implParent = self:GetImplParent()
276
+ if implParent then
277
+ implParent:SetAttribute(self._memberDefinition:GetMemberName(), value)
295
278
 
296
279
  -- Remove existing as needed
297
- local current = folder:FindFirstChild(self._memberDefinition:GetMemberName())
280
+ local current = implParent:FindFirstChild(self._memberDefinition:GetMemberName())
298
281
  if current then
299
282
  current:Destroy()
300
283
  end
301
284
  return
302
285
  end
303
286
  else
304
- local folder = self:_getFolder()
305
- if folder then
306
- local copy = TiePropertyImplementationUtils.changeToClassIfNeeded(self._memberDefinition, folder, className)
287
+ local implParent = self:GetImplParent()
288
+ if implParent then
289
+ local copy = TiePropertyImplementationUtils.changeToClassIfNeeded(self._memberDefinition, implParent, className)
307
290
  copy.Value = value
308
- copy.Parent = folder
291
+ copy.Parent = implParent
309
292
  else
310
- error(("[TiePropertyImplementation] - No folder for %q"):format(self._memberDefinition:GetMemberName()))
293
+ error(string.format("[TiePropertyImplementation] - No implParent for %q", self._memberDefinition:GetMemberName()))
311
294
  end
312
295
  end
313
296
  elseif index == "Changed" then
314
- error(("Cannot assign %q for TiePropertyInterface"):format(tostring(index)))
297
+ error(string.format("Cannot assign %q for TiePropertyInterface", tostring(index)))
315
298
  else
316
- error(("Bad index %q for TiePropertyInterface"):format(tostring(index)))
299
+ error(string.format("Bad index %q for TiePropertyInterface", tostring(index)))
317
300
  end
318
301
  end
319
302
 
@@ -0,0 +1,63 @@
1
+ --[=[
2
+ @class TieSignalConnection
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local Maid = require("Maid")
8
+ local TieUtils = require("TieUtils")
9
+
10
+ local TieSignalConnection = {}
11
+ TieSignalConnection.ClassName = "TieSignalConnection"
12
+ TieSignalConnection.__index = TieSignalConnection
13
+
14
+ function TieSignalConnection.new(tieSignalInterface, callback)
15
+ local self = setmetatable({}, TieSignalConnection)
16
+
17
+ self._maid = Maid.new()
18
+ self._connected = true
19
+
20
+ self._tieSignalInterface = assert(tieSignalInterface, "No tieSignalInterface")
21
+ self._callback = assert(callback, "No callback")
22
+
23
+ self:_connect()
24
+
25
+ return self
26
+ end
27
+
28
+ function TieSignalConnection:Disconnect()
29
+ self:Destroy()
30
+ end
31
+
32
+ function TieSignalConnection:_connect()
33
+ self._maid:GiveTask(self._tieSignalInterface:ObserveBindableEventBrio():Subscribe(function(brio)
34
+ if brio:IsDead() then
35
+ return
36
+ end
37
+
38
+ local maid, bindableEvent = brio:ToMaidAndValue()
39
+ maid:GiveTask(bindableEvent.Event:Connect(function(...)
40
+ task.spawn(self._callback, TieUtils.decode(...))
41
+ end))
42
+ end))
43
+ end
44
+
45
+ function TieSignalConnection:__index(index)
46
+ if index == "_tieSignalInterface" then
47
+ return rawget(self, index)
48
+ elseif index == "IsConnected" then
49
+ return self._connected
50
+ elseif TieSignalConnection[index] then
51
+ return TieSignalConnection[index]
52
+ else
53
+ error(string.format("Bad index %q for TieSignalConnection", tostring(index)))
54
+ end
55
+ end
56
+
57
+ function TieSignalConnection:Destroy()
58
+ self._connected = false
59
+ self._maid:DoCleaning()
60
+ -- Avoid setting the metatable so calling methods is always valid
61
+ end
62
+
63
+ return TieSignalConnection
@@ -0,0 +1,38 @@
1
+ --[=[
2
+ @class TieSignalDefinition
3
+ ]=]
4
+
5
+ local require = require(script.Parent.loader).load(script)
6
+
7
+ local TieMemberDefinition = require("TieMemberDefinition")
8
+ local TieSignalImplementation = require("TieSignalImplementation")
9
+ local TieSignalInterface = require("TieSignalInterface")
10
+ local TieRealmUtils = require("TieRealmUtils")
11
+
12
+ local TieSignalDefinition = setmetatable({}, TieMemberDefinition)
13
+ TieSignalDefinition.ClassName = "TieSignalDefinition"
14
+ TieSignalDefinition.__index = TieSignalDefinition
15
+
16
+ function TieSignalDefinition.new(tieDefinition, signalName, memberTieRealm)
17
+ assert(TieRealmUtils.isTieRealm(memberTieRealm), "Bad memberTieRealm")
18
+
19
+ local self = setmetatable(TieMemberDefinition.new(tieDefinition, signalName, memberTieRealm), TieSignalDefinition)
20
+
21
+ return self
22
+ end
23
+
24
+ function TieSignalDefinition:Implement(implParent: Instance, initialValue, _actualSelf, tieRealm)
25
+ assert(typeof(implParent) == "Instance", "Bad implParent")
26
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
27
+
28
+ return TieSignalImplementation.new(self, implParent, initialValue, tieRealm)
29
+ end
30
+
31
+ function TieSignalDefinition:GetInterface(implParent: Instance, _actualSelf, tieRealm)
32
+ assert(typeof(implParent) == "Instance", "Bad implParent")
33
+ assert(TieRealmUtils.isTieRealm(tieRealm), "Bad tieRealm")
34
+
35
+ return TieSignalInterface.new(implParent, nil, self, tieRealm)
36
+ end
37
+
38
+ return TieSignalDefinition