@quenty/binder 9.0.0-canary.ff9fb44.0 → 9.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/CHANGELOG.md CHANGED
@@ -3,7 +3,126 @@
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
- # [9.0.0-canary.ff9fb44.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.16.0...@quenty/binder@9.0.0-canary.ff9fb44.0) (2023-06-03)
6
+ # [9.0.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.27.0...@quenty/binder@9.0.0) (2023-10-11)
7
+
8
+
9
+ ### Bug Fixes
10
+
11
+ * Binder has warning about constructing other binders ([3729779](https://github.com/Quenty/NevermoreEngine/commit/37297794d59310a53a3659a406f1e6e266460283))
12
+
13
+
14
+
15
+
16
+
17
+ # [8.27.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.26.0...@quenty/binder@8.27.0) (2023-09-21)
18
+
19
+ **Note:** Version bump only for package @quenty/binder
20
+
21
+
22
+
23
+
24
+
25
+ # [8.26.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.25.0...@quenty/binder@8.26.0) (2023-09-04)
26
+
27
+ **Note:** Version bump only for package @quenty/binder
28
+
29
+
30
+
31
+
32
+
33
+ # [8.25.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.24.0...@quenty/binder@8.25.0) (2023-08-23)
34
+
35
+
36
+ ### Features
37
+
38
+ * Add Binder:ObserveAllBrio() ([f68cccc](https://github.com/Quenty/NevermoreEngine/commit/f68cccc8b74acf770ca16888d31c0bb82436d3b0))
39
+
40
+
41
+
42
+
43
+
44
+ # [8.24.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.23.0...@quenty/binder@8.24.0) (2023-08-01)
45
+
46
+ **Note:** Version bump only for package @quenty/binder
47
+
48
+
49
+
50
+
51
+
52
+ # [8.23.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.22.0...@quenty/binder@8.23.0) (2023-07-28)
53
+
54
+ **Note:** Version bump only for package @quenty/binder
55
+
56
+
57
+
58
+
59
+
60
+ # [8.22.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.21.0...@quenty/binder@8.22.0) (2023-07-23)
61
+
62
+ **Note:** Version bump only for package @quenty/binder
63
+
64
+
65
+
66
+
67
+
68
+ # [8.21.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.20.0...@quenty/binder@8.21.0) (2023-07-15)
69
+
70
+
71
+ ### Features
72
+
73
+ * Add Binder:Create() API surface ([0e78a1c](https://github.com/Quenty/NevermoreEngine/commit/0e78a1ce69e2469f61059b641b2000ddd0c7d758))
74
+
75
+
76
+
77
+
78
+
79
+ # [8.20.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.19.1...@quenty/binder@8.20.0) (2023-07-10)
80
+
81
+ **Note:** Version bump only for package @quenty/binder
82
+
83
+
84
+
85
+
86
+
87
+ ## [8.19.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.19.0...@quenty/binder@8.19.1) (2023-06-24)
88
+
89
+ **Note:** Version bump only for package @quenty/binder
90
+
91
+
92
+
93
+
94
+
95
+ # [8.19.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.18.1...@quenty/binder@8.19.0) (2023-06-24)
96
+
97
+ **Note:** Version bump only for package @quenty/binder
98
+
99
+
100
+
101
+
102
+
103
+ ## [8.18.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.18.0...@quenty/binder@8.18.1) (2023-06-23)
104
+
105
+
106
+ ### Bug Fixes
107
+
108
+ * Fix binder args failing in no-arg non-service-provided interface ([36f3417](https://github.com/Quenty/NevermoreEngine/commit/36f3417debd56f478fea591133f78d2a0c521dab))
109
+
110
+
111
+
112
+
113
+
114
+ # [8.18.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.17.0...@quenty/binder@8.18.0) (2023-06-17)
115
+
116
+
117
+ ### Features
118
+
119
+ * Binders can be initialized by the ServiceBag directly instead of requireing a BinderProvider ([28ce17f](https://github.com/Quenty/NevermoreEngine/commit/28ce17fe254b7fdce115132244ca1a6e8693d24b))
120
+
121
+
122
+
123
+
124
+
125
+ # [8.17.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/binder@8.16.0...@quenty/binder@8.17.0) (2023-06-05)
7
126
 
8
127
  **Note:** Version bump only for package @quenty/binder
9
128
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/binder",
3
- "version": "9.0.0-canary.ff9fb44.0",
3
+ "version": "9.0.0",
4
4
  "description": "Utility object to Bind a class to Roblox object, and associated helper methods",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -25,18 +25,19 @@
25
25
  "Quenty"
26
26
  ],
27
27
  "dependencies": {
28
- "@quenty/baseobject": "6.2.1",
29
- "@quenty/brio": "8.13.0",
30
- "@quenty/instanceutils": "7.14.0",
31
- "@quenty/linkutils": "7.14.0",
32
- "@quenty/loader": "6.2.1",
33
- "@quenty/maid": "2.5.0",
34
- "@quenty/promise": "6.5.0",
35
- "@quenty/signal": "2.4.0",
36
- "@quenty/valueobject": "7.14.0"
28
+ "@quenty/baseobject": "^7.0.0",
29
+ "@quenty/brio": "^9.0.0",
30
+ "@quenty/instanceutils": "^8.0.0",
31
+ "@quenty/linkutils": "^8.0.0",
32
+ "@quenty/loader": "^7.0.0",
33
+ "@quenty/maid": "^2.6.0",
34
+ "@quenty/promise": "^7.0.0",
35
+ "@quenty/rx": "^8.0.0",
36
+ "@quenty/signal": "^3.0.0",
37
+ "@quenty/valueobject": "^8.0.0"
37
38
  },
38
39
  "publishConfig": {
39
40
  "access": "public"
40
41
  },
41
- "gitHead": "ff9fb44bc6867fe6ac15ea58a744a028212c8601"
42
+ "gitHead": "fdeae46099587019ec5fc15317dc673aed379400"
42
43
  }
@@ -31,8 +31,10 @@ local CollectionService = game:GetService("CollectionService")
31
31
 
32
32
  local Maid = require("Maid")
33
33
  local MaidTaskUtils = require("MaidTaskUtils")
34
- local Signal = require("Signal")
34
+ local Observable = require("Observable")
35
35
  local promiseBoundClass = require("promiseBoundClass")
36
+ local Signal = require("Signal")
37
+ local Brio = require("Brio")
36
38
 
37
39
  local Binder = {}
38
40
  Binder.__index = Binder
@@ -65,12 +67,22 @@ Binder.ClassName = "Binder"
65
67
  @return Binder<T>
66
68
  ]=]
67
69
  function Binder.new(tagName, constructor, ...)
70
+ assert(type(tagName) == "string", "Bad tagName")
71
+
68
72
  local self = setmetatable({}, Binder)
69
73
 
70
74
  self._tagName = assert(tagName, "Bad argument 'tagName', expected string")
71
75
  self._constructor = assert(constructor, "Bad argument 'constructor', expected table or function")
76
+ self._defaultClassType = "Folder"
77
+ self.ServiceName = self._tagName .. "Binder"
72
78
 
73
- self:Init(...)
79
+ if Binder.isBinder(self._constructor) then
80
+ error("Cannot make a binder that constructs another binder")
81
+ end
82
+
83
+ if select("#", ...) > 0 then
84
+ self._args = { ... }
85
+ end
74
86
 
75
87
  return self
76
88
  end
@@ -107,6 +119,11 @@ end
107
119
  @param ... any
108
120
  ]=]
109
121
  function Binder:Init(...)
122
+ if self._initialized then
123
+ return
124
+ end
125
+
126
+ self._initialized = true
110
127
  self._maid = Maid.new()
111
128
 
112
129
  self._instToClass = {} -- [inst] = class
@@ -114,22 +131,50 @@ function Binder:Init(...)
114
131
  self._pendingInstSet = {} -- [inst] = true
115
132
 
116
133
  self._listeners = {} -- [inst] = callback
117
- self._args = {...}
134
+
135
+ if select("#", ...) > 0 then
136
+ if not self._args then
137
+ self._args = {...}
138
+ elseif not self:_argsMatch(...) then
139
+ warn("[Binder.Init] - Non-matching args from :Init() and .new()")
140
+ end
141
+ elseif not self._args then
142
+ -- Binder.new() would have captured args if we had them
143
+ self._args = {}
144
+ end
118
145
 
119
146
  self._maid._warning = task.delay(5, function()
120
147
  warn(("Binder %q is not loaded. Call :Start() on it!"):format(self._tagName))
121
148
  end)
122
149
  end
123
150
 
151
+ function Binder:_argsMatch(...)
152
+ if #self._args ~= select("#", ...) then
153
+ return false
154
+ end
155
+
156
+ for index, value in pairs({...}) do
157
+ if self._args[index] ~= value then
158
+ return false
159
+ end
160
+ end
161
+
162
+ return true
163
+ end
164
+
124
165
  --[=[
125
166
  Listens for new instances and connects to the GetInstanceAddedSignal() and removed signal!
126
167
  ]=]
127
168
  function Binder:Start()
128
- if self._loaded then
169
+ if not self._initialized then
170
+ self:Init()
171
+ end
172
+
173
+ if self._started then
129
174
  return
130
175
  end
131
176
  self._maid._warning = nil
132
- self._loaded = true
177
+ self._started = true
133
178
 
134
179
  for _, inst in pairs(CollectionService:GetTagged(self._tagName)) do
135
180
  task.spawn(self._add, self, inst)
@@ -161,9 +206,95 @@ function Binder:GetConstructor()
161
206
  return self._constructor
162
207
  end
163
208
 
209
+ --[=[
210
+ Observes the current value of the instance
211
+
212
+ @param instance Instance
213
+ @return Observable<T | nil>
214
+ ]=]
215
+ function Binder:Observe(instance)
216
+ assert(typeof(instance) == "Instance", "Bad instance")
217
+
218
+ return Observable.new(function(sub)
219
+ local maid = Maid.new()
220
+
221
+ maid:GiveTask(self:ObserveInstance(instance, function(...)
222
+ sub:Fire(...)
223
+ end))
224
+ sub:Fire(self:Get(instance))
225
+
226
+ return maid
227
+ end)
228
+ end
229
+
230
+ --[=[
231
+ Observes all entries in the binder
232
+
233
+ @return Observable<Brio<T>>
234
+ ]=]
235
+ function Binder:ObserveAllBrio()
236
+ return Observable.new(function(sub)
237
+ local maid = Maid.new()
238
+
239
+ local function handleNewClass(class)
240
+ local brio = Brio.new(class)
241
+ maid[class] = brio
242
+
243
+ sub:Fire(brio)
244
+ end
245
+
246
+ maid:GiveTask(self:GetClassAddedSignal():Connect(handleNewClass))
247
+
248
+ for _, item in pairs(self:GetAll()) do
249
+ handleNewClass(item)
250
+ end
251
+
252
+ maid:GiveTask(self:GetClassRemovingSignal():Connect(function(class)
253
+ maid[class] = nil
254
+ end))
255
+
256
+ return maid
257
+ end)
258
+ end
259
+
260
+ --[=[
261
+ Observes a bound class on a given instance.
262
+
263
+ @param instance Instance
264
+ @return Observable<Brio<T>>
265
+ ]=]
266
+ function Binder:ObserveBrio(instance)
267
+ assert(typeof(instance) == "Instance", "Bad instance")
268
+
269
+ return Observable.new(function(sub)
270
+ local maid = Maid.new()
271
+
272
+ local function handleClassChanged(class)
273
+ if class then
274
+ local brio = Brio.new(class)
275
+ maid._lastBrio = brio
276
+
277
+ sub:Fire(brio)
278
+ else
279
+ maid._lastBrio = nil
280
+ end
281
+ end
282
+
283
+ maid:GiveTask(self:ObserveInstance(instance, handleClassChanged))
284
+ handleClassChanged(self:Get(instance))
285
+
286
+ return maid
287
+ end)
288
+ end
289
+
164
290
  --[=[
165
291
  Fired when added, and then after removal, but before destroy!
166
292
 
293
+ :::info
294
+ This is before [Rx] so it doesn't follow the same Rx pattern. See [Binder.Observe] for
295
+ an [Rx] compatible interface.
296
+ :::
297
+
167
298
  @param inst Instance
168
299
  @param callback function
169
300
  @return function -- Cleanup function
@@ -318,6 +449,28 @@ function Binder:Bind(inst)
318
449
  return self:Get(inst)
319
450
  end
320
451
 
452
+ --[=[
453
+ Tags the instance with the tag for the binder
454
+
455
+ @param inst Instance
456
+ ]=]
457
+ function Binder:Tag(inst)
458
+ assert(typeof(inst) == "Instance", "Bad inst")
459
+
460
+ CollectionService:AddTag(inst, self._tagName)
461
+ end
462
+
463
+ --[=[
464
+ Untags the instance with the tag for the binder
465
+
466
+ @param inst Instance
467
+ ]=]
468
+ function Binder:Untag(inst)
469
+ assert(typeof(inst) == "Instance", "Bad inst")
470
+
471
+ CollectionService:RemoveTag(inst, self._tagName)
472
+ end
473
+
321
474
  --[=[
322
475
  Unbinds the instance by removing the tag.
323
476
 
@@ -389,6 +542,24 @@ function Binder:Promise(inst, cancelToken)
389
542
  return promiseBoundClass(self, inst, cancelToken)
390
543
  end
391
544
 
545
+ --[=[
546
+ Creates a new class tagged with this binder's instance
547
+
548
+ @param className string | nil
549
+ @return Instance
550
+ ]=]
551
+ function Binder:Create(className)
552
+ assert(type(className) == "string" or className == nil, "Bad className")
553
+
554
+ local instance = Instance.new(className or self._defaultClassType)
555
+ instance.Name = self._tagName
556
+ instance.Archivable = false
557
+
558
+ self:Tag(instance)
559
+
560
+ return instance
561
+ end
562
+
392
563
  function Binder:_add(inst)
393
564
  assert(typeof(inst) == "Instance", "Argument 'inst' is not an Instance")
394
565