@quenty/settings 11.53.2 → 11.54.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,26 @@
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
+ # [11.54.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/settings@11.53.3...@quenty/settings@11.54.0) (2026-07-14)
7
+
8
+ ### Bug Fixes
9
+
10
+ - add [@within](https://github.com/within) for moonwave on SettingDefinitionProvider \_\_index; cast Tie :Implement receiver ([388e3f8](https://github.com/Quenty/NevermoreEngine/commit/388e3f8c658b14d991b2328776d6cac5b11501c0))
11
+ - cast Tie interface at :Implement sites to dodge flaky symlink-nominal analyze errors ([17f54f8](https://github.com/Quenty/NevermoreEngine/commit/17f54f87c6d449386570b8a409175dc2d6d02016))
12
+ - **lint:** resolve selene unused-self and Rx shadowing from --!strict conversions ([3f4a085](https://github.com/Quenty/NevermoreEngine/commit/3f4a085911808146f10a2435efbe9e89dff8edff))
13
+ - **settings:** cast cmdr handle to dodge flaky symlink-nominal analyze error ([bdaf1b4](https://github.com/Quenty/NevermoreEngine/commit/bdaf1b45f24882af05f40a941f48eb5b125eac84))
14
+ - **settings:** cast cmdr service handle for strict CmdrServiceClient ([18b38b3](https://github.com/Quenty/NevermoreEngine/commit/18b38b3d4ceb3f1c9476015f545822a78f34747f))
15
+
16
+ ### Features
17
+
18
+ - **settings:** convert package to --!strict ([5a93f97](https://github.com/Quenty/NevermoreEngine/commit/5a93f9791f9dcdc4843c3ada174ddc130e071104))
19
+
20
+ ## [11.53.3](https://github.com/Quenty/NevermoreEngine/compare/@quenty/settings@11.53.2...@quenty/settings@11.53.3) (2026-06-15)
21
+
22
+ ### Bug Fixes
23
+
24
+ - Async guard ([7b793d9](https://github.com/Quenty/NevermoreEngine/commit/7b793d91973d137b18c0eac95b99ca27796b7a89))
25
+
6
26
  ## [11.53.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/settings@11.53.1...@quenty/settings@11.53.2) (2026-06-03)
7
27
 
8
28
  **Note:** Version bump only for package @quenty/settings
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/settings",
3
- "version": "11.53.2",
3
+ "version": "11.54.0",
4
4
  "description": "Centralized player settings service",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -30,11 +30,11 @@
30
30
  "dependencies": {
31
31
  "@quenty/attributeutils": "14.30.1",
32
32
  "@quenty/baseobject": "10.13.0",
33
- "@quenty/binder": "14.36.1",
33
+ "@quenty/binder": "14.37.0",
34
34
  "@quenty/brio": "14.30.1",
35
35
  "@quenty/canceltoken": "11.19.1",
36
- "@quenty/cmdrservice": "13.45.2",
37
- "@quenty/datastore": "13.39.1",
36
+ "@quenty/cmdrservice": "13.46.0",
37
+ "@quenty/datastore": "13.40.0",
38
38
  "@quenty/ducktype": "5.11.0",
39
39
  "@quenty/enumutils": "3.4.6",
40
40
  "@quenty/instanceutils": "13.30.1",
@@ -42,14 +42,14 @@
42
42
  "@quenty/loader": "10.11.0",
43
43
  "@quenty/maid": "3.9.0",
44
44
  "@quenty/nevermore-test-runner": "1.4.0",
45
- "@quenty/observablecollection": "12.38.1",
46
- "@quenty/playerbinder": "14.36.1",
45
+ "@quenty/observablecollection": "12.39.0",
46
+ "@quenty/playerbinder": "14.37.0",
47
47
  "@quenty/playerutils": "8.32.1",
48
48
  "@quenty/promise": "10.18.1",
49
49
  "@quenty/remotefunctionutils": "10.18.1",
50
50
  "@quenty/remoting": "12.32.1",
51
51
  "@quenty/rx": "13.28.3",
52
- "@quenty/rxbinderutils": "14.36.1",
52
+ "@quenty/rxbinderutils": "14.37.0",
53
53
  "@quenty/rxsignal": "7.28.3",
54
54
  "@quenty/servicebag": "11.18.1",
55
55
  "@quenty/signal": "7.13.1",
@@ -58,12 +58,12 @@
58
58
  "@quenty/symbol": "3.5.2",
59
59
  "@quenty/table": "3.9.2",
60
60
  "@quenty/throttle": "10.12.2",
61
- "@quenty/tie": "10.40.1",
61
+ "@quenty/tie": "10.41.0",
62
62
  "@quenty/valueobject": "13.31.1",
63
63
  "@quentystudios/jest-lua": "3.10.0-quenty.2"
64
64
  },
65
65
  "publishConfig": {
66
66
  "access": "public"
67
67
  },
68
- "gitHead": "1acafc712ce34f5dbaa70bb23b16da95e9cd3f82"
68
+ "gitHead": "13f0162f4971a77378e55e9b7236aea94f0dd3a8"
69
69
  }
@@ -28,14 +28,32 @@ local ValueObject = require("ValueObject")
28
28
 
29
29
  local UNSET_VALUE = Symbol.named("unsetValue")
30
30
 
31
- local PlayerSettingsClient = setmetatable({}, PlayerSettingsBase)
31
+ local PlayerSettingsClient = {}
32
32
  PlayerSettingsClient.ClassName = "PlayerSettingsClient"
33
33
  PlayerSettingsClient.__index = PlayerSettingsClient
34
+ -- Runtime inheritance only. Typing the metatable target as `any` keeps the old solver from
35
+ -- chasing the full PlayerSettingsBase type here, which otherwise overflows its complexity
36
+ -- budget ("Code is too complex"). The inherited surface is supplied structurally below.
37
+ setmetatable(PlayerSettingsClient :: any, PlayerSettingsBase)
38
+
39
+ -- Only the dynamic remoting member this class touches.
40
+ type RemotingLike = {
41
+ RequestUpdateSettings: any,
42
+ }
43
+
44
+ -- Minimal structural surface inherited from PlayerSettingsBase that this class uses. See the
45
+ -- setmetatable note above for why we don't intersect PlayerSettingsBase.PlayerSettingsBase.
46
+ type PlayerSettingsBaseLike = {
47
+ _obj: Folder,
48
+ _maid: Maid.Maid,
49
+ GetPlayer: (self: any) -> Player?,
50
+ Destroy: (self: any) -> (),
51
+ }
34
52
 
35
53
  export type PlayerSettingsClient =
36
54
  typeof(setmetatable(
37
55
  {} :: {
38
- _remoting: Remoting.Remoting,
56
+ _remoting: RemotingLike,
39
57
  _pendingReplicationDataInTransit: ValueObject.ValueObject<any>,
40
58
  _toReplicate: { [any]: any? }?,
41
59
  _toReplicateCallbacks: { [string]: { [any]: any } },
@@ -44,7 +62,7 @@ export type PlayerSettingsClient =
44
62
  },
45
63
  {} :: typeof({ __index = PlayerSettingsClient })
46
64
  ))
47
- & PlayerSettingsBase.PlayerSettingsBase
65
+ & PlayerSettingsBaseLike
48
66
 
49
67
  --[=[
50
68
  See [SettingsBindersClient] and [SettingsServiceClient] on how to properly use this class.
@@ -58,7 +76,7 @@ function PlayerSettingsClient.new(folder: Folder, serviceBag: ServiceBag.Service
58
76
  setmetatable(PlayerSettingsBase.new(folder, serviceBag) :: any, PlayerSettingsClient)
59
77
 
60
78
  if self:GetPlayer() == Players.LocalPlayer then
61
- self._remoting = self._maid:Add(Remoting.new(self._obj, "PlayerSettings", Remoting.Realms.CLIENT))
79
+ self._remoting = self._maid:Add(Remoting.new(self._obj, "PlayerSettings", Remoting.Realms.CLIENT)) :: any
62
80
 
63
81
  self._toReplicate = nil
64
82
  self._toReplicateCallbacks = {}
@@ -74,7 +92,7 @@ function PlayerSettingsClient.new(folder: Folder, serviceBag: ServiceBag.Service
74
92
  self:_sendSettings()
75
93
  end, { leading = true, trailing = true }))
76
94
 
77
- self._maid:GiveTask(PlayerSettingsInterface.Client:Implement(self._obj, self))
95
+ self._maid:GiveTask((PlayerSettingsInterface :: any).Client:Implement(self._obj, self))
78
96
  end
79
97
 
80
98
  return self
@@ -99,7 +117,7 @@ function PlayerSettingsClient.GetValue<T>(self: PlayerSettingsClient, settingNam
99
117
  return PlayerSettingsUtils.decodeForNetwork(pending[settingName])
100
118
  end
101
119
 
102
- return getmetatable(PlayerSettingsClient).GetValue(self, settingName, defaultValue)
120
+ return (getmetatable(PlayerSettingsClient :: any) :: any).GetValue(self, settingName, defaultValue)
103
121
  end
104
122
 
105
123
  --[=[
@@ -116,7 +134,11 @@ function PlayerSettingsClient.ObserveValue<T>(
116
134
  ): Observable.Observable<T>
117
135
  assert(type(settingName) == "string", "Bad settingName")
118
136
 
119
- local baseObservable = getmetatable(PlayerSettingsClient).ObserveValue(self, settingName, defaultValue)
137
+ local baseObservable = (getmetatable(PlayerSettingsClient :: any) :: any).ObserveValue(
138
+ self,
139
+ settingName,
140
+ defaultValue
141
+ )
120
142
 
121
143
  -- We need to register our own replication checkers...
122
144
  return Observable.new(function(sub)
@@ -167,7 +167,7 @@ end
167
167
  function SettingsServiceClient._setupCmdr(self: SettingsServiceClient)
168
168
  local cmdrServiceClient = self._serviceBag:GetService(require("CmdrServiceClient"))
169
169
 
170
- self._maid:GivePromise(cmdrServiceClient:PromiseCmdr()):Then(function(cmdr)
170
+ self._maid:GivePromise((cmdrServiceClient :: any):PromiseCmdr()):Then(function(cmdr)
171
171
  SettingsCmdrUtils.registerSettingDefinition(cmdr, self._serviceBag)
172
172
  end)
173
173
  end
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  Provides commands involving player settings
4
4
 
@@ -15,8 +15,18 @@ local SettingsCmdrUtils = require("SettingsCmdrUtils")
15
15
  local SettingsCmdrService = {}
16
16
  SettingsCmdrService.ServiceName = "SettingsCmdrService"
17
17
 
18
- function SettingsCmdrService:Init(serviceBag: ServiceBag.ServiceBag)
19
- assert(not self._serviceBag, "Already initialized")
18
+ export type SettingsCmdrService = typeof(setmetatable(
19
+ {} :: {
20
+ _serviceBag: ServiceBag.ServiceBag,
21
+ _maid: Maid.Maid,
22
+ _cmdrService: any,
23
+ _settingService: any,
24
+ },
25
+ {} :: typeof({ __index = SettingsCmdrService })
26
+ ))
27
+
28
+ function SettingsCmdrService.Init(self: SettingsCmdrService, serviceBag: ServiceBag.ServiceBag): ()
29
+ assert(not (self :: any)._serviceBag, "Already initialized")
20
30
  self._serviceBag = assert(serviceBag, "No serviceBag")
21
31
  self._maid = Maid.new()
22
32
 
@@ -24,11 +34,11 @@ function SettingsCmdrService:Init(serviceBag: ServiceBag.ServiceBag)
24
34
  self._settingService = self._serviceBag:GetService(require("SettingsService"))
25
35
  end
26
36
 
27
- function SettingsCmdrService:Start()
37
+ function SettingsCmdrService.Start(self: SettingsCmdrService): ()
28
38
  self:_setupCommands()
29
39
  end
30
40
 
31
- function SettingsCmdrService:_setupCommands()
41
+ function SettingsCmdrService._setupCommands(self: SettingsCmdrService): ()
32
42
  self._maid:GivePromise(self._cmdrService:PromiseCmdr()):Then(function(cmdr)
33
43
  SettingsCmdrUtils.registerSettingDefinition(cmdr, self._serviceBag)
34
44
  end)
@@ -65,7 +75,7 @@ function SettingsCmdrService:_setupCommands()
65
75
  end)
66
76
  end
67
77
 
68
- function SettingsCmdrService:Destroy()
78
+ function SettingsCmdrService.Destroy(self: SettingsCmdrService): ()
69
79
  self._maid:DoCleaning()
70
80
  end
71
81
 
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  @class PlayerHasSettings
4
4
  ]=]
@@ -22,34 +22,37 @@ export type PlayerHasSettings =
22
22
  typeof(setmetatable(
23
23
  {} :: {
24
24
  _serviceBag: ServiceBag.ServiceBag,
25
- _playerSettingsBinder: PlayerSettings.PlayerSettings,
25
+ _playerSettingsBinder: any,
26
26
  _playerDataStoreService: PlayerDataStoreService.PlayerDataStoreService,
27
+ _settings: Folder?,
27
28
  },
28
29
  {} :: typeof({ __index = PlayerHasSettings })
29
30
  ))
30
31
  & BaseObject.BaseObject
31
32
 
32
- function PlayerHasSettings.new(player: Player, serviceBag)
33
- local self = setmetatable(BaseObject.new(player), PlayerHasSettings)
33
+ function PlayerHasSettings.new(player: Player, serviceBag: ServiceBag.ServiceBag): PlayerHasSettings
34
+ local self: PlayerHasSettings = setmetatable(BaseObject.new(player) :: any, PlayerHasSettings)
34
35
 
35
36
  self._serviceBag = assert(serviceBag, "No serviceBag")
36
37
  self._playerSettingsBinder = self._serviceBag:GetService(PlayerSettings)
37
- self._playerDataStoreService = self._serviceBag:GetService(PlayerDataStoreService)
38
+ self._playerDataStoreService = self._serviceBag:GetService(PlayerDataStoreService) :: any
38
39
 
39
40
  self:_promiseLoadSettings()
40
41
 
41
42
  return self
42
43
  end
43
44
 
44
- function PlayerHasSettings:_promiseLoadSettings()
45
+ function PlayerHasSettings._promiseLoadSettings(self: PlayerHasSettings): ()
45
46
  self._settings = PlayerSettingsUtils.create()
46
47
  self._maid:GiveTask(function()
47
- self._settings:Destroy()
48
+ if self._settings then
49
+ self._settings:Destroy()
50
+ end
48
51
  self._settings = nil
49
52
  end)
50
53
 
51
- self._maid
52
- :GivePromise(self._playerDataStoreService:PromiseDataStore(self._obj))
54
+ local loadPromise = self._maid:GivePromise(self._playerDataStoreService:PromiseDataStore(self._obj :: Player));
55
+ (loadPromise :: any)
53
56
  :Then(function(dataStore)
54
57
  -- Ensure we've fully loaded before we parent.
55
58
  -- This should ensure the cache is mostly instant.
@@ -57,6 +60,10 @@ function PlayerHasSettings:_promiseLoadSettings()
57
60
  local subStore = dataStore:GetSubStore("settings")
58
61
 
59
62
  return dataStore:Load("settings", {}):Then(function(settings)
63
+ if not self._settings then
64
+ return
65
+ end
66
+
60
67
  for settingName, value in settings do
61
68
  local attributeName = PlayerSettingsUtils.getAttributeName(settingName)
62
69
  self._settings:SetAttribute(attributeName, PlayerSettingsUtils.encodeForAttribute(value))
@@ -78,11 +85,15 @@ function PlayerHasSettings:_promiseLoadSettings()
78
85
  end)
79
86
  end
80
87
 
81
- function PlayerHasSettings:_handleAttributeChanged(subStore, attributeName)
88
+ function PlayerHasSettings._handleAttributeChanged(self: PlayerHasSettings, subStore: any, attributeName: string): ()
82
89
  if not PlayerSettingsUtils.isSettingAttribute(attributeName) then
83
90
  return
84
91
  end
85
92
 
93
+ if not self._settings then
94
+ return
95
+ end
96
+
86
97
  -- Write the new value
87
98
  local settingName = PlayerSettingsUtils.getSettingName(attributeName)
88
99
  if not DataStoreStringUtils.isValidUTF8(settingName) then
@@ -105,4 +116,4 @@ function PlayerHasSettings:_handleAttributeChanged(subStore, attributeName)
105
116
  subStore:Store(settingName, newValue)
106
117
  end
107
118
 
108
- return PlayerBinder.new("PlayerHasSettings", PlayerHasSettings)
119
+ return PlayerBinder.new("PlayerHasSettings", PlayerHasSettings :: any) :: PlayerBinder.PlayerBinder<PlayerHasSettings>
@@ -6,7 +6,10 @@
6
6
  local require = require(script.Parent.loader).load(script)
7
7
 
8
8
  local Binder = require("Binder")
9
+ local Brio = require("Brio")
9
10
  local DataStoreStringUtils = require("DataStoreStringUtils")
11
+ local Maid = require("Maid")
12
+ local Observable = require("Observable")
10
13
  local PlayerSettingsBase = require("PlayerSettingsBase")
11
14
  local PlayerSettingsConstants = require("PlayerSettingsConstants")
12
15
  local PlayerSettingsInterface = require("PlayerSettingsInterface")
@@ -15,20 +18,44 @@ local Remoting = require("Remoting")
15
18
  local ServiceBag = require("ServiceBag")
16
19
  local SettingsDataService = require("SettingsDataService")
17
20
 
18
- local PlayerSettings = setmetatable({}, PlayerSettingsBase)
21
+ local PlayerSettings = {}
19
22
  PlayerSettings.ClassName = "PlayerSettings"
20
23
  PlayerSettings.__index = PlayerSettings
24
+ -- Runtime inheritance only. Typing the metatable target as `any` keeps the old solver from
25
+ -- chasing the full PlayerSettingsBase type here, which otherwise overflows its complexity
26
+ -- budget ("Code is too complex"). The inherited surface is supplied structurally below.
27
+ setmetatable(PlayerSettings :: any, PlayerSettingsBase)
28
+
29
+ -- Minimal structural surface of SettingsDataService that this class actually uses. Embedding
30
+ -- the full SettingsDataService metatable type blows up the old solver, so we type only what
31
+ -- we call here.
32
+ type SettingsDataServiceLike = {
33
+ ObserveRegisteredDefinitionsBrio: (self: SettingsDataServiceLike) -> Observable.Observable<Brio.Brio<any>>,
34
+ }
35
+
36
+ -- Only the dynamic remoting member this class touches.
37
+ type RemotingLike = {
38
+ RequestUpdateSettings: any,
39
+ }
40
+
41
+ -- Minimal structural surface inherited from PlayerSettingsBase that this class uses. See the
42
+ -- setmetatable note above for why we don't intersect PlayerSettingsBase.PlayerSettingsBase.
43
+ type PlayerSettingsBaseLike = {
44
+ _obj: Folder,
45
+ _maid: Maid.Maid,
46
+ GetPlayer: (self: any) -> Player?,
47
+ }
21
48
 
22
49
  export type PlayerSettings =
23
50
  typeof(setmetatable(
24
51
  {} :: {
25
52
  _serviceBag: ServiceBag.ServiceBag,
26
- _remoting: Remoting.Remoting,
27
- _settingsDataService: SettingsDataService.SettingsDataService,
53
+ _remoting: RemotingLike,
54
+ _settingsDataService: SettingsDataServiceLike,
28
55
  },
29
56
  {} :: typeof({ __index = PlayerSettings })
30
57
  ))
31
- & PlayerSettingsBase.PlayerSettingsBase
58
+ & PlayerSettingsBaseLike
32
59
 
33
60
  export type SettingsMap = { [string]: any }
34
61
 
@@ -49,7 +76,7 @@ function PlayerSettings.new(folder: Folder, serviceBag: ServiceBag.ServiceBag):
49
76
  self:EnsureInitialized(value:GetSettingName(), value:GetDefaultValue())
50
77
  end))
51
78
 
52
- self._maid:GiveTask(PlayerSettingsInterface.Server:Implement(self._obj, self))
79
+ self._maid:GiveTask((PlayerSettingsInterface :: any).Server:Implement(self._obj, self))
53
80
 
54
81
  return self
55
82
  end
@@ -78,7 +105,7 @@ function PlayerSettings.EnsureInitialized<T>(self: PlayerSettings, settingName:
78
105
  end
79
106
 
80
107
  function PlayerSettings._setupRemoting(self: PlayerSettings): ()
81
- self._remoting = self._maid:Add(Remoting.new(self._obj, "PlayerSettings", Remoting.Realms.SERVER))
108
+ self._remoting = self._maid:Add(Remoting.new(self._obj, "PlayerSettings", Remoting.Realms.SERVER)) :: any
82
109
 
83
110
  self._maid:Add(self._remoting.RequestUpdateSettings:Bind(function(player: Player, settingsMap: SettingsMap)
84
111
  assert(self:GetPlayer() == player, "Bad player")
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  Provides a service for managing centralized player settings. See [SettingsDataService] for the data service.
4
4
 
@@ -7,14 +7,27 @@
7
7
 
8
8
  local require = require(script.Parent.loader).load(script)
9
9
 
10
+ local Brio = require("Brio")
10
11
  local Maid = require("Maid")
12
+ local Observable = require("Observable")
13
+ local Promise = require("Promise")
11
14
  local ServiceBag = require("ServiceBag")
15
+ local SettingsDataService = require("SettingsDataService")
12
16
 
13
17
  local SettingsService = {}
14
18
  SettingsService.ServiceName = "SettingsService"
15
19
 
16
- function SettingsService:Init(serviceBag: ServiceBag.ServiceBag)
17
- assert(not self._serviceBag, "Already initialized")
20
+ export type SettingsService = typeof(setmetatable(
21
+ {} :: {
22
+ _serviceBag: ServiceBag.ServiceBag,
23
+ _maid: Maid.Maid,
24
+ _settingsDataService: SettingsDataService.SettingsDataService,
25
+ },
26
+ {} :: typeof({ __index = SettingsService })
27
+ ))
28
+
29
+ function SettingsService.Init(self: SettingsService, serviceBag: ServiceBag.ServiceBag): ()
30
+ assert(not (self :: any)._serviceBag, "Already initialized")
18
31
  self._serviceBag = assert(serviceBag, "No serviceBag")
19
32
  self._maid = Maid.new()
20
33
 
@@ -23,7 +36,7 @@ function SettingsService:Init(serviceBag: ServiceBag.ServiceBag)
23
36
  self._serviceBag:GetService((require :: any)("SettingsCmdrService"))
24
37
 
25
38
  -- Internal
26
- self._settingsDataService = self._serviceBag:GetService(require("SettingsDataService"))
39
+ self._settingsDataService = self._serviceBag:GetService(require("SettingsDataService")) :: any
27
40
 
28
41
  -- Binders
29
42
  self._serviceBag:GetService(require("PlayerHasSettings"))
@@ -36,7 +49,10 @@ end
36
49
  @param player Player
37
50
  @return Observable<Brio<PlayerSettings>>
38
51
  ]=]
39
- function SettingsService:ObservePlayerSettingsBrio(player: Player)
52
+ function SettingsService.ObservePlayerSettingsBrio(
53
+ self: SettingsService,
54
+ player: Player
55
+ ): Observable.Observable<Brio.Brio<any>>
40
56
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
41
57
 
42
58
  return self._settingsDataService:ObservePlayerSettingsBrio(player)
@@ -48,7 +64,7 @@ end
48
64
  @param player Player
49
65
  @return Observable<PlayerSettings>
50
66
  ]=]
51
- function SettingsService:ObservePlayerSettings(player: Player)
67
+ function SettingsService.ObservePlayerSettings(self: SettingsService, player: Player): Observable.Observable<any>
52
68
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
53
69
 
54
70
  return self._settingsDataService:ObservePlayerSettings(player)
@@ -60,7 +76,7 @@ end
60
76
  @param player Player
61
77
  @return PlayerSettings
62
78
  ]=]
63
- function SettingsService:GetPlayerSettings(player: Player)
79
+ function SettingsService.GetPlayerSettings(self: SettingsService, player: Player): any
64
80
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
65
81
 
66
82
  return self._settingsDataService:GetPlayerSettings(player)
@@ -73,7 +89,11 @@ end
73
89
  @param cancelToken CancelToken?
74
90
  @return Promise<PlayerSettings>
75
91
  ]=]
76
- function SettingsService:PromisePlayerSettings(player: Player, cancelToken)
92
+ function SettingsService.PromisePlayerSettings(
93
+ self: SettingsService,
94
+ player: Player,
95
+ cancelToken: any?
96
+ ): Promise.Promise<any>
77
97
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
78
98
 
79
99
  return self._settingsDataService:PromisePlayerSettings(player, cancelToken)
@@ -82,7 +102,7 @@ end
82
102
  --[=[
83
103
  Cleans up the settings service
84
104
  ]=]
85
- function SettingsService:Destroy()
105
+ function SettingsService.Destroy(self: SettingsService): ()
86
106
  self._maid:DoCleaning()
87
107
  end
88
108
 
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  @class SettingsCmdrUtils
4
4
  ]=]
@@ -10,10 +10,10 @@ local SettingsDataService = require("SettingsDataService")
10
10
 
11
11
  local SettingsCmdrUtils = {}
12
12
 
13
- function SettingsCmdrUtils.registerSettingDefinition(cmdr, serviceBag: ServiceBag.ServiceBag)
13
+ function SettingsCmdrUtils.registerSettingDefinition(cmdr: any, serviceBag: ServiceBag.ServiceBag): ()
14
14
  assert(ServiceBag.isServiceBag(serviceBag), "Bad serviceBag")
15
15
 
16
- local settingsDataService = serviceBag:GetService(SettingsDataService)
16
+ local settingsDataService: any = serviceBag:GetService(SettingsDataService)
17
17
 
18
18
  local settingDefinitionType = {
19
19
  Transform = function(text)
@@ -81,7 +81,9 @@ function SettingDefinition.Init<T>(self: SettingDefinition<T>, serviceBag: Servi
81
81
  self._serviceBag = assert(serviceBag, "No serviceBag")
82
82
 
83
83
  local settingsDataService = self._serviceBag:GetService(SettingsDataService)
84
- self._maid:GiveTask(settingsDataService:RegisterSettingDefinition(self))
84
+ -- Same SettingsDataService type resolved via two symlink require paths reads as
85
+ -- nominally distinct to the old solver; cast the receiver to dodge the false mismatch.
86
+ self._maid:GiveTask((settingsDataService :: any):RegisterSettingDefinition(self))
85
87
  end
86
88
 
87
89
  --[=[
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  Provides settings in bulk, and can be initialized by a [ServiceBag]. See [SettingDefinition] for
4
4
  more details on how to use this.
@@ -36,6 +36,17 @@ SettingDefinitionProvider.ClassName = "SettingDefinitionProvider"
36
36
  SettingDefinitionProvider.ServiceName = "SettingDefinitionProvider"
37
37
  SettingDefinitionProvider.__index = SettingDefinitionProvider
38
38
 
39
+ export type SettingDefinitionProvider = typeof(setmetatable(
40
+ {} :: {
41
+ _settingDefinitionList: { SettingDefinition.SettingDefinition<any> },
42
+ _lookup: { [string]: SettingDefinition.SettingDefinition<any> },
43
+ _maid: Maid.Maid,
44
+ _serviceBag: ServiceBag.ServiceBag,
45
+ _initializedDefinitionLookup: { [any]: SettingDefinition.SettingDefinition<any> },
46
+ },
47
+ {} :: typeof({ __index = SettingDefinitionProvider })
48
+ ))
49
+
39
50
  --[=[
40
51
  Constructs a new provider with a list of [SettingDefinition]'s.
41
52
 
@@ -68,8 +79,8 @@ SettingDefinitionProvider.__index = SettingDefinitionProvider
68
79
  @param settingDefinitions { SettingDefinition }
69
80
  @return SettingDefinitionProvider
70
81
  ]=]
71
- function SettingDefinitionProvider.new(settingDefinitions)
72
- local self = setmetatable({}, SettingDefinitionProvider)
82
+ function SettingDefinitionProvider.new(settingDefinitions: { [any]: any }): SettingDefinitionProvider
83
+ local self: SettingDefinitionProvider = setmetatable({} :: any, SettingDefinitionProvider)
73
84
 
74
85
  self._settingDefinitionList = {}
75
86
  self._lookup = {}
@@ -78,7 +89,7 @@ function SettingDefinitionProvider.new(settingDefinitions)
78
89
  if type(key) == "number" then
79
90
  assert(SettingDefinition.isSettingDefinition(key), "Bad settingDefinition")
80
91
 
81
- self:_addSettingDefinition(key)
92
+ self:_addSettingDefinition(key :: any)
82
93
  elseif type(key) == "string" then
83
94
  if SettingDefinition.isSettingDefinition(value) then
84
95
  self:_addSettingDefinition(value)
@@ -94,7 +105,10 @@ function SettingDefinitionProvider.new(settingDefinitions)
94
105
  return self
95
106
  end
96
107
 
97
- function SettingDefinitionProvider:_addSettingDefinition(settingDefinition)
108
+ function SettingDefinitionProvider._addSettingDefinition(
109
+ self: SettingDefinitionProvider,
110
+ settingDefinition: SettingDefinition.SettingDefinition<any>
111
+ ): ()
98
112
  assert(SettingDefinition.isSettingDefinition(settingDefinition), "Bad settingDefinition")
99
113
 
100
114
  table.insert(self._settingDefinitionList, settingDefinition)
@@ -106,9 +120,9 @@ end
106
120
 
107
121
  @param serviceBag ServiceBag
108
122
  ]=]
109
- function SettingDefinitionProvider:Init(serviceBag: ServiceBag.ServiceBag)
123
+ function SettingDefinitionProvider.Init(self: SettingDefinitionProvider, serviceBag: ServiceBag.ServiceBag): ()
110
124
  assert(serviceBag, "No serviceBag")
111
- assert(not self._maid, "Already initialized")
125
+ assert(not (self :: any)._maid, "Already initialized")
112
126
 
113
127
  self._maid = Maid.new()
114
128
  self._serviceBag = assert(serviceBag, "No serviceBag")
@@ -117,18 +131,20 @@ function SettingDefinitionProvider:Init(serviceBag: ServiceBag.ServiceBag)
117
131
 
118
132
  -- Register our setting definitions
119
133
  for _, settingDefinition in self._settingDefinitionList do
120
- local initialized = self._serviceBag:GetService(settingDefinition)
121
- self._initializedDefinitionLookup[settingDefinition] = initialized
134
+ local rawSettingDefinition = settingDefinition :: any
135
+ local initialized = self._serviceBag:GetService(rawSettingDefinition)
136
+ self._initializedDefinitionLookup[rawSettingDefinition] = initialized
122
137
 
123
138
  -- Store lookup to overcome metatable lookup
124
- self[settingDefinition:GetSettingName()] = initialized
139
+ local rawSelf = self :: any
140
+ rawSelf[rawSettingDefinition:GetSettingName()] = initialized
125
141
  end
126
142
  end
127
143
 
128
144
  --[=[
129
145
  Starts the provider. Empty.
130
146
  ]=]
131
- function SettingDefinitionProvider:Start()
147
+ function SettingDefinitionProvider.Start(_self: SettingDefinitionProvider): ()
132
148
  -- Empty, to prevent us from erroring on service bag init
133
149
  end
134
150
 
@@ -137,7 +153,9 @@ end
137
153
 
138
154
  @return { SettingDefinition }
139
155
  ]=]
140
- function SettingDefinitionProvider:GetSettingDefinitions()
156
+ function SettingDefinitionProvider.GetSettingDefinitions(
157
+ self: SettingDefinitionProvider
158
+ ): { SettingDefinition.SettingDefinition<any> }
141
159
  if self._serviceBag then
142
160
  local copy = table.clone(self._settingDefinitionList)
143
161
 
@@ -171,8 +189,9 @@ end
171
189
 
172
190
  @param index string
173
191
  @return SettingDefinition
192
+ @within SettingDefinitionProvider
174
193
  ]=]
175
- function SettingDefinitionProvider:__index(index)
194
+ (SettingDefinitionProvider :: any).__index = function(self: any, index: any)
176
195
  if index == nil then
177
196
  error("[SettingDefinitionProvider] - Cannot index provider with nil value")
178
197
  elseif SettingDefinitionProvider[index] then
@@ -186,7 +205,7 @@ function SettingDefinitionProvider:__index(index)
186
205
  then
187
206
  return rawget(self, index)
188
207
  elseif type(index) == "string" then
189
- local lookup = rawget(self, "_lookup")
208
+ local lookup = rawget(self, "_lookup") :: any
190
209
  local settingDefinition = lookup[index]
191
210
  if not settingDefinition then
192
211
  error(string.format("Bad index %q into SettingDefinitionProvider", tostring(index)))
@@ -208,7 +227,10 @@ end
208
227
  @param settingName string
209
228
  @return SettingDefinition
210
229
  ]=]
211
- function SettingDefinitionProvider:Get(settingName: string)
230
+ function SettingDefinitionProvider.Get(
231
+ self: SettingDefinitionProvider,
232
+ settingName: string
233
+ ): SettingDefinition.SettingDefinition<any>?
212
234
  assert(type(settingName) == "string", "Bad settingName")
213
235
 
214
236
  local found = self._lookup[settingName]
@@ -226,7 +248,7 @@ end
226
248
  --[=[
227
249
  Cleans up the setting registration
228
250
  ]=]
229
- function SettingDefinitionProvider:Destroy()
251
+ function SettingDefinitionProvider.Destroy(self: SettingDefinitionProvider): ()
230
252
  self._maid:DoCleaning()
231
253
  end
232
254
 
@@ -1,4 +1,4 @@
1
- --!nonstrict
1
+ --!strict
2
2
  --[=[
3
3
  Shared between client and server, letting us centralize definitions in one place.
4
4
 
@@ -9,21 +9,29 @@ local require = require(script.Parent.loader).load(script)
9
9
 
10
10
  local Players = game:GetService("Players")
11
11
 
12
+ local Brio = require("Brio")
12
13
  local Maid = require("Maid")
14
+ local Observable = require("Observable")
13
15
  local ObservableMap = require("ObservableMap")
14
16
  local ObservableSet = require("ObservableSet")
15
17
  local PlayerSettingsInterface = require("PlayerSettingsInterface")
18
+ local Promise = require("Promise")
16
19
  local Rx = require("Rx")
17
20
  local RxBrioUtils = require("RxBrioUtils")
18
21
  local RxInstanceUtils = require("RxInstanceUtils")
19
22
  local ServiceBag = require("ServiceBag")
20
23
 
21
24
  local SettingsDataService = {}
25
+ SettingsDataService.ServiceName = "SettingsDataService"
22
26
 
23
27
  export type SettingsDataService = typeof(setmetatable(
24
28
  {} :: {
25
29
  _serviceBag: ServiceBag.ServiceBag,
26
30
  _maid: Maid.Maid,
31
+ _tieRealmService: any,
32
+ _settingDefinitions: ObservableSet.ObservableSet<any>,
33
+ _playerSettingsCacheMap: ObservableMap.ObservableMap<Player, any>,
34
+ _hydratedPlayersMaid: Maid.Maid,
27
35
  },
28
36
  {} :: typeof({ __index = SettingsDataService })
29
37
  ))
@@ -33,8 +41,8 @@ export type SettingsDataService = typeof(setmetatable(
33
41
 
34
42
  @param serviceBag ServiceBag
35
43
  ]=]
36
- function SettingsDataService:Init(serviceBag: ServiceBag.ServiceBag)
37
- assert(not self._serviceBag, "Already initialized")
44
+ function SettingsDataService.Init(self: SettingsDataService, serviceBag: ServiceBag.ServiceBag): ()
45
+ assert(not (self :: any)._serviceBag, "Already initialized")
38
46
  self._serviceBag = assert(serviceBag, "No serviceBag")
39
47
  self._maid = Maid.new()
40
48
 
@@ -45,23 +53,28 @@ function SettingsDataService:Init(serviceBag: ServiceBag.ServiceBag)
45
53
  self._settingDefinitions = self._maid:Add(ObservableSet.new())
46
54
  end
47
55
 
48
- function SettingsDataService:_getPlayerSettingsCacheMap()
56
+ function SettingsDataService._getPlayerSettingsCacheMap(
57
+ self: SettingsDataService
58
+ ): ObservableMap.ObservableMap<Player, any>
49
59
  -- Avoid hydrating
50
60
  if self._playerSettingsCacheMap then
51
61
  return self._playerSettingsCacheMap
52
62
  end
53
63
 
54
- self._playerSettingsCacheMap = self._maid:Add(ObservableMap.new())
64
+ self._playerSettingsCacheMap = self._maid:Add(ObservableMap.new() :: ObservableMap.ObservableMap<Player, any>)
55
65
  self._hydratedPlayersMaid = self._maid:Add(Maid.new())
56
66
 
57
67
  self._maid:GiveTask(Players.PlayerRemoving:Connect(function(player: Player)
58
68
  self._hydratedPlayersMaid[player] = nil
59
69
  end))
60
70
 
61
- return self._playerSettingsCacheMap
71
+ return (self._playerSettingsCacheMap :: any) :: ObservableMap.ObservableMap<Player, any>
62
72
  end
63
73
 
64
- function SettingsDataService:_getPlayerSettingsMapForPlayer(player: Player)
74
+ function SettingsDataService._getPlayerSettingsMapForPlayer(
75
+ self: SettingsDataService,
76
+ player: Player
77
+ ): ObservableMap.ObservableMap<Player, any>
65
78
  local playerSettingsCacheMap = self:_getPlayerSettingsCacheMap()
66
79
 
67
80
  if self._hydratedPlayersMaid[player] then
@@ -75,19 +88,19 @@ function SettingsDataService:_getPlayerSettingsMapForPlayer(player: Player)
75
88
  return playerSettingsCacheMap
76
89
  end
77
90
 
78
- function SettingsDataService:_hydrateCacheForPlayer(player: Player)
91
+ function SettingsDataService._hydrateCacheForPlayer(self: SettingsDataService, player: Player): Maid.Maid
79
92
  local playerMaid = Maid.new()
80
93
 
81
- playerMaid:GiveTask(RxInstanceUtils.observeChildrenBrio(player, function(value)
94
+ playerMaid:GiveTask((RxInstanceUtils.observeChildrenBrio(player, function(value): any
82
95
  -- We really only care about this, and we can assume we have the tag immediately
83
96
  return value:HasTag("PlayerSettings")
84
- end)
97
+ end) :: any)
85
98
  :Pipe({
86
- RxBrioUtils.flatMapBrio(function(playerSettingsInstance)
99
+ RxBrioUtils.flatMapBrio(function(playerSettingsInstance): any
87
100
  return PlayerSettingsInterface:ObserveBrio(playerSettingsInstance, self._tieRealmService:GetTieRealm())
88
101
  end),
89
102
  })
90
- :Subscribe(function(brio)
103
+ :Subscribe(function(brio): ()
91
104
  if brio:IsDead() then
92
105
  return
93
106
  end
@@ -104,7 +117,7 @@ end
104
117
 
105
118
  @return { SettingDefinition }
106
119
  ]=]
107
- function SettingsDataService:GetSettingDefinitions()
120
+ function SettingsDataService.GetSettingDefinitions(self: SettingsDataService): { any }
108
121
  return self._settingDefinitions:GetList()
109
122
  end
110
123
 
@@ -114,7 +127,7 @@ end
114
127
  @param definition SettingDefinition
115
128
  @return callback -- Cleanup callback
116
129
  ]=]
117
- function SettingsDataService:RegisterSettingDefinition(definition)
130
+ function SettingsDataService.RegisterSettingDefinition(self: SettingsDataService, definition: any): () -> ()
118
131
  assert(definition, "No definition")
119
132
 
120
133
  return self._settingDefinitions:Add(definition)
@@ -125,7 +138,9 @@ end
125
138
 
126
139
  @return Observable<Brio<SettingDefinition>>
127
140
  ]=]
128
- function SettingsDataService:ObserveRegisteredDefinitionsBrio()
141
+ function SettingsDataService.ObserveRegisteredDefinitionsBrio(
142
+ self: SettingsDataService
143
+ ): Observable.Observable<Brio.Brio<any>>
129
144
  return self._settingDefinitions:ObserveItemsBrio()
130
145
  end
131
146
 
@@ -135,10 +150,16 @@ end
135
150
  @param player Player
136
151
  @return Observable<PlayerSettingsBase>
137
152
  ]=]
138
- function SettingsDataService:ObservePlayerSettings(player: Player)
153
+ function SettingsDataService.ObservePlayerSettings(
154
+ self: SettingsDataService,
155
+ player: Player
156
+ ): Observable.Observable<any>
139
157
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
140
158
 
141
- return self:_getPlayerSettingsMapForPlayer(player):ObserveAtKey(player, self._tieRealmService:GetTieRealm())
159
+ return (self:_getPlayerSettingsMapForPlayer(player) :: any):ObserveAtKey(
160
+ player,
161
+ self._tieRealmService:GetTieRealm()
162
+ )
142
163
  end
143
164
 
144
165
  --[=[
@@ -147,8 +168,14 @@ end
147
168
  @param player Player
148
169
  @return Observable<Brio<PlayerSettingsClient>>
149
170
  ]=]
150
- function SettingsDataService:ObservePlayerSettingsBrio(player: Player)
151
- return self:_getPlayerSettingsMapForPlayer(player):ObserveAtKeyBrio(player, self._tieRealmService:GetTieRealm())
171
+ function SettingsDataService.ObservePlayerSettingsBrio(
172
+ self: SettingsDataService,
173
+ player: Player
174
+ ): Observable.Observable<Brio.Brio<any>>
175
+ return (self:_getPlayerSettingsMapForPlayer(player) :: any):ObserveAtKeyBrio(
176
+ player,
177
+ self._tieRealmService:GetTieRealm()
178
+ )
152
179
  end
153
180
 
154
181
  --[=[
@@ -158,12 +185,16 @@ end
158
185
  @param cancelToken CancelToken
159
186
  @return Promise<PlayerSettingsBase>
160
187
  ]=]
161
- function SettingsDataService:PromisePlayerSettings(player: Player, cancelToken)
188
+ function SettingsDataService.PromisePlayerSettings(
189
+ self: SettingsDataService,
190
+ player: Player,
191
+ cancelToken: any
192
+ ): Promise.Promise<any>
162
193
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
163
194
 
164
195
  return Rx.toPromise(
165
- self:ObservePlayerSettings(player):Pipe({
166
- Rx.where(function(playerSettings)
196
+ (self:ObservePlayerSettings(player) :: any):Pipe({
197
+ Rx.where(function(playerSettings): any
167
198
  return playerSettings ~= nil
168
199
  end),
169
200
  }),
@@ -177,7 +208,7 @@ end
177
208
  @param player Player
178
209
  @return Promise<PlayerSettingsBase>
179
210
  ]=]
180
- function SettingsDataService:GetPlayerSettings(player: Player)
211
+ function SettingsDataService.GetPlayerSettings(self: SettingsDataService, player: Player): any
181
212
  assert(typeof(player) == "Instance" and player:IsA("Player"), "Bad player")
182
213
 
183
214
  return self:_getPlayerSettingsMapForPlayer(player):Get(player)
@@ -186,7 +217,7 @@ end
186
217
  --[=[
187
218
  Cleans up the shared registry service
188
219
  ]=]
189
- function SettingsDataService:Destroy()
220
+ function SettingsDataService.Destroy(self: SettingsDataService): ()
190
221
  self._maid:DoCleaning()
191
222
  end
192
223