@quenty/datastore 13.20.2 → 13.20.3

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,14 @@
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
+ ## [13.20.3](https://github.com/Quenty/NevermoreEngine/compare/@quenty/datastore@13.20.2...@quenty/datastore@13.20.3) (2025-04-10)
7
+
8
+ **Note:** Version bump only for package @quenty/datastore
9
+
10
+
11
+
12
+
13
+
6
14
  ## [13.20.2](https://github.com/Quenty/NevermoreEngine/compare/@quenty/datastore@13.20.0...@quenty/datastore@13.20.2) (2025-04-07)
7
15
 
8
16
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/datastore",
3
- "version": "13.20.2",
3
+ "version": "13.20.3",
4
4
  "description": "Quenty's Datastore implementation for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -26,22 +26,22 @@
26
26
  "Quenty"
27
27
  ],
28
28
  "dependencies": {
29
- "@quenty/baseobject": "^10.8.2",
30
- "@quenty/bindtocloseservice": "^8.17.2",
31
- "@quenty/loader": "^10.8.2",
32
- "@quenty/maid": "^3.4.2",
29
+ "@quenty/baseobject": "^10.8.3",
30
+ "@quenty/bindtocloseservice": "^8.17.3",
31
+ "@quenty/loader": "^10.8.3",
32
+ "@quenty/maid": "^3.4.3",
33
33
  "@quenty/math": "^2.7.3",
34
- "@quenty/pagesutils": "^5.11.3",
35
- "@quenty/promise": "^10.10.3",
36
- "@quenty/rx": "^13.17.2",
37
- "@quenty/servicebag": "^11.11.3",
38
- "@quenty/signal": "^7.10.2",
34
+ "@quenty/pagesutils": "^5.11.4",
35
+ "@quenty/promise": "^10.10.4",
36
+ "@quenty/rx": "^13.17.3",
37
+ "@quenty/servicebag": "^11.11.4",
38
+ "@quenty/signal": "^7.10.3",
39
39
  "@quenty/symbol": "^3.4.2",
40
- "@quenty/table": "^3.7.3",
41
- "@quenty/valueobject": "^13.17.2"
40
+ "@quenty/table": "^3.7.4",
41
+ "@quenty/valueobject": "^13.17.3"
42
42
  },
43
43
  "publishConfig": {
44
44
  "access": "public"
45
45
  },
46
- "gitHead": "64def70499ec067077ee39f279936b620b217847"
46
+ "gitHead": "b06c070ae91d5dab7bd8de6e290ad2caabb15d8f"
47
47
  }
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Wraps the datastore object to provide async cached loading and saving. See [DataStoreStage] for more API.
3
4
 
@@ -78,14 +79,28 @@ local ValueObject = require("ValueObject")
78
79
 
79
80
  local DEFAULT_DEBUG_WRITING = false
80
81
 
81
- local DEFAULT_AUTO_SAVE_TIME_SECONDS = 60*5
82
+ local DEFAULT_AUTO_SAVE_TIME_SECONDS = 60 * 5
82
83
  local DEFAULT_JITTER_PROPORTION = 0.1 -- Randomly assign jitter so if a ton of players join at once we don't hit the datastore at once
83
84
 
84
85
  local DataStore = setmetatable({}, DataStoreStage)
85
86
  DataStore.ClassName = "DataStore"
86
87
  DataStore.__index = DataStore
87
88
 
88
- export type DataStore = typeof(setmetatable({}, { __index = DataStore }))
89
+ export type DataStore = typeof(setmetatable(
90
+ {} :: {
91
+ _key: string,
92
+ _userIdList: { number }?,
93
+ _robloxDataStore: DataStorePromises.RobloxDataStore,
94
+ _debugWriting: boolean,
95
+ _autoSaveTimeSeconds: ValueObject.ValueObject<number?>,
96
+ _jitterProportion: ValueObject.ValueObject<number>,
97
+ _syncOnSave: ValueObject.ValueObject<boolean>,
98
+ _loadedOk: ValueObject.ValueObject<boolean>,
99
+ _firstLoadPromise: Promise.Promise<()>,
100
+ Saving: Signal.Signal<Promise.Promise<()>>,
101
+ },
102
+ {} :: typeof({ __index = DataStore })
103
+ )) & DataStoreStage.DataStoreStage
89
104
 
90
105
  --[=[
91
106
  Constructs a new DataStore. See [DataStoreStage] for more API.
@@ -98,14 +113,14 @@ export type DataStore = typeof(setmetatable({}, { __index = DataStore }))
98
113
  @param key string
99
114
  @return DataStore
100
115
  ]=]
101
- function DataStore.new(robloxDataStore, key: string)
102
- local self = setmetatable(DataStoreStage.new(key), DataStore)
116
+ function DataStore.new(robloxDataStore: DataStorePromises.RobloxDataStore, key: string)
117
+ local self: DataStore = setmetatable(DataStoreStage.new(key) :: any, DataStore)
103
118
 
104
119
  self._key = key or error("No key")
105
120
  self._robloxDataStore = robloxDataStore or error("No robloxDataStore")
106
121
  self._debugWriting = DEFAULT_DEBUG_WRITING
107
122
 
108
- self._autoSaveTimeSeconds = self._maid:Add(ValueObject.new(DEFAULT_AUTO_SAVE_TIME_SECONDS))
123
+ self._autoSaveTimeSeconds = self._maid:Add(ValueObject.new(DEFAULT_AUTO_SAVE_TIME_SECONDS :: number?))
109
124
  self._jitterProportion = self._maid:Add(ValueObject.new(DEFAULT_JITTER_PROPORTION, "number"))
110
125
  self._syncOnSave = self._maid:Add(ValueObject.new(false, "boolean"))
111
126
  self._loadedOk = self._maid:Add(ValueObject.new(false, "boolean"))
@@ -121,7 +136,7 @@ function DataStore.new(robloxDataStore, key: string)
121
136
  @prop Saving Signal<Promise>
122
137
  @within DataStore
123
138
  ]=]
124
- self.Saving = self._maid:Add(Signal.new()) -- :Fire(promise)
139
+ self.Saving = self._maid:Add(Signal.new() :: any) -- :Fire(promise)
125
140
 
126
141
  self:_setupAutoSaving()
127
142
 
@@ -133,7 +148,7 @@ end
133
148
 
134
149
  @param debugWriting boolean
135
150
  ]=]
136
- function DataStore:SetDoDebugWriting(debugWriting: boolean)
151
+ function DataStore.SetDoDebugWriting(self: DataStore, debugWriting: boolean)
137
152
  assert(type(debugWriting) == "boolean", "Bad debugWriting")
138
153
 
139
154
  self._debugWriting = debugWriting
@@ -143,7 +158,7 @@ end
143
158
  Returns the full path for the datastore
144
159
  @return string
145
160
  ]=]
146
- function DataStore:GetFullPath(): string
161
+ function DataStore.GetFullPath(self: DataStore): string
147
162
  return string.format("RobloxDataStore@%s", self._key)
148
163
  end
149
164
 
@@ -153,7 +168,7 @@ end
153
168
 
154
169
  @param autoSaveTimeSeconds number?
155
170
  ]=]
156
- function DataStore:SetAutoSaveTimeSeconds(autoSaveTimeSeconds: number?)
171
+ function DataStore.SetAutoSaveTimeSeconds(self: DataStore, autoSaveTimeSeconds: number?)
157
172
  assert(type(autoSaveTimeSeconds) == "number" or autoSaveTimeSeconds == nil, "Bad autoSaveTimeSeconds")
158
173
 
159
174
  self._autoSaveTimeSeconds.Value = autoSaveTimeSeconds
@@ -164,7 +179,7 @@ end
164
179
 
165
180
  @param syncEnabled boolean
166
181
  ]=]
167
- function DataStore:SetSyncOnSave(syncEnabled: boolean)
182
+ function DataStore.SetSyncOnSave(self: DataStore, syncEnabled: boolean)
168
183
  assert(type(syncEnabled) == "boolean", "Bad syncEnabled")
169
184
 
170
185
  self._syncOnSave.Value = syncEnabled
@@ -174,7 +189,7 @@ end
174
189
  Returns whether the datastore failed.
175
190
  @return boolean
176
191
  ]=]
177
- function DataStore:DidLoadFail(): boolean
192
+ function DataStore.DidLoadFail(self: DataStore): boolean
178
193
  if not self._firstLoadPromise then
179
194
  return false
180
195
  end
@@ -191,7 +206,7 @@ end
191
206
 
192
207
  @return Promise<boolean>
193
208
  ]=]
194
- function DataStore:PromiseLoadSuccessful(): Promise.Promise<boolean>
209
+ function DataStore.PromiseLoadSuccessful(self: DataStore): Promise.Promise<boolean>
195
210
  return self._maid:GivePromise(self:PromiseViewUpToDate()):Then(function()
196
211
  return true
197
212
  end, function()
@@ -203,7 +218,7 @@ end
203
218
  Saves all stored data.
204
219
  @return Promise
205
220
  ]=]
206
- function DataStore:Save(): Promise.Promise<()>
221
+ function DataStore.Save(self: DataStore): Promise.Promise<()>
207
222
  return self:_syncData(false)
208
223
  end
209
224
 
@@ -213,7 +228,7 @@ end
213
228
 
214
229
  @return Promise
215
230
  ]=]
216
- function DataStore:Sync(): Promise.Promise<()>
231
+ function DataStore.Sync(self: DataStore): Promise.Promise<()>
217
232
  return self:_syncData(true)
218
233
  end
219
234
 
@@ -222,7 +237,7 @@ end
222
237
 
223
238
  @param userIdList { number }?
224
239
  ]=]
225
- function DataStore:SetUserIdList(userIdList: { number }?)
240
+ function DataStore.SetUserIdList(self: DataStore, userIdList: { number }?)
226
241
  assert(type(userIdList) == "table" or userIdList == nil, "Bad userIdList")
227
242
  assert(not Symbol.isSymbol(userIdList), "Should not be symbol")
228
243
 
@@ -234,7 +249,7 @@ end
234
249
 
235
250
  @return { number }?
236
251
  ]=]
237
- function DataStore:GetUserIdList(): { number }?
252
+ function DataStore.GetUserIdList(self: DataStore): { number }?
238
253
  return self._userIdList
239
254
  end
240
255
 
@@ -243,21 +258,22 @@ end
243
258
 
244
259
  @return Promise
245
260
  ]=]
246
- function DataStore:PromiseViewUpToDate(): Promise.Promise<()>
261
+ function DataStore.PromiseViewUpToDate(self: DataStore): Promise.Promise<()>
247
262
  if self._firstLoadPromise then
248
263
  return self._firstLoadPromise
249
264
  end
250
265
 
251
- self._firstLoadPromise = self:_promiseGetAsyncNoCache()
266
+ local promise = self:_promiseGetAsyncNoCache()
267
+ self._firstLoadPromise = promise
252
268
 
253
- self._firstLoadPromise:Tap(function()
269
+ promise:Tap(function()
254
270
  self._loadedOk.Value = true
255
271
  end)
256
272
 
257
- return self._firstLoadPromise
273
+ return promise
258
274
  end
259
275
 
260
- function DataStore:_setupAutoSaving()
276
+ function DataStore._setupAutoSaving(self: DataStore)
261
277
  local startTime = os.clock()
262
278
 
263
279
  self._maid:GiveTask(Rx.combineLatest({
@@ -307,17 +323,18 @@ function DataStore:_setupAutoSaving()
307
323
  end))
308
324
  end
309
325
 
310
- function DataStore:_syncData(doMergeNewData: boolean)
326
+ function DataStore._syncData(self: DataStore, doMergeNewData: boolean)
311
327
  if self:DidLoadFail() then
312
328
  warn("[DataStore] - Not syncing, failed to load")
313
329
  return Promise.rejected("Load not successful, not syncing")
314
330
  end
315
331
 
316
- return self._maid:GivePromise(self:PromiseViewUpToDate())
332
+ return self._maid
333
+ :GivePromise(self:PromiseViewUpToDate())
317
334
  :Then(function()
318
335
  return self._maid:GivePromise(self:PromiseInvokeSavingCallbacks())
319
336
  end)
320
- :Then(function()
337
+ :Then(function(): Promise.Promise<()>?
321
338
  if not self:HasWritableData() then
322
339
  if doMergeNewData then
323
340
  -- Reads are cheaper than update async calls
@@ -336,7 +353,7 @@ function DataStore:_syncData(doMergeNewData: boolean)
336
353
  end)
337
354
  end
338
355
 
339
- function DataStore:_doDataSync(writer, doMergeNewData)
356
+ function DataStore._doDataSync(self: DataStore, writer, doMergeNewData: boolean): Promise.Promise<()>
340
357
  assert(type(doMergeNewData) == "boolean", "Bad doMergeNewData")
341
358
 
342
359
  -- Cache user id list
@@ -352,63 +369,75 @@ function DataStore:_doDataSync(writer, doMergeNewData)
352
369
  end
353
370
 
354
371
  -- This is, of course, dangerous, because we won't merge
355
- promise:Resolve(maid:GivePromise(DataStorePromises.removeAsync(self._robloxDataStore, self._key)):Then(function()
356
- if doMergeNewData then
357
- -- Write our data
358
- self:MarkDataAsSaved(writer)
372
+ promise:Resolve(
373
+ maid:GivePromise(DataStorePromises.removeAsync(self._robloxDataStore, self._key)):Then(function(): any
374
+ if doMergeNewData then
375
+ -- Write our data
376
+ self:MarkDataAsSaved(writer)
359
377
 
360
- -- Do syncing after
361
- return self:_promiseGetAsyncNoCache()
362
- end
378
+ -- Do syncing after
379
+ return self:_promiseGetAsyncNoCache()
380
+ end
363
381
 
364
- return nil
365
- end))
382
+ return nil
383
+ end)
384
+ )
366
385
  else
367
386
  if self._debugWriting then
368
- print(string.format("[DataStore] - DataStorePromises.updateAsync(%q) with doMergeNewData = %s", self._key, tostring(doMergeNewData)))
387
+ print(
388
+ string.format(
389
+ "[DataStore] - DataStorePromises.updateAsync(%q) with doMergeNewData = %s",
390
+ self._key,
391
+ tostring(doMergeNewData)
392
+ )
393
+ )
369
394
  end
370
395
 
371
- promise:Resolve(maid:GivePromise(DataStorePromises.updateAsync(self._robloxDataStore, self._key, function(original, datastoreKeyInfo)
372
- if promise:IsRejected() then
373
- -- Cancel if we have another request
374
- return nil
375
- end
396
+ promise:Resolve(
397
+ maid:GivePromise(
398
+ DataStorePromises.updateAsync(self._robloxDataStore, self._key, function(original, datastoreKeyInfo)
399
+ if promise:IsRejected() then
400
+ -- Cancel if we have another request
401
+ return nil
402
+ end
376
403
 
377
- local diffSnapshot
378
- if doMergeNewData then
379
- diffSnapshot = writer:ComputeDiffSnapshot(original)
380
- end
404
+ local diffSnapshot
405
+ if doMergeNewData then
406
+ diffSnapshot = writer:ComputeDiffSnapshot(original)
407
+ end
381
408
 
382
- local result = writer:WriteMerge(original)
409
+ local result = writer:WriteMerge(original)
383
410
 
384
- if result == DataStoreDeleteToken or result == nil then
385
- result = {}
386
- end
411
+ if result == DataStoreDeleteToken or result == nil then
412
+ result = {}
413
+ end
387
414
 
388
- self:_checkSnapshotIntegrity("writer:WriteMerge(original)", result)
415
+ self:_checkSnapshotIntegrity("writer:WriteMerge(original)", result)
389
416
 
390
- if self._debugWriting then
391
- print("[DataStore] - Writing", result)
392
- end
417
+ if self._debugWriting then
418
+ print("[DataStore] - Writing", result)
419
+ end
393
420
 
394
- if doMergeNewData then
395
- -- This prevents resaving at high frequency
396
- self:MarkDataAsSaved(writer)
397
- self:MergeDiffSnapshot(diffSnapshot)
398
- end
421
+ if doMergeNewData then
422
+ -- This prevents resaving at high frequency
423
+ self:MarkDataAsSaved(writer)
424
+ self:MergeDiffSnapshot(diffSnapshot)
425
+ end
399
426
 
400
- local userIdList = writer:GetUserIdList()
401
- if datastoreKeyInfo then
402
- userIdList = datastoreKeyInfo:GetUserIds()
403
- end
427
+ local userIdList = writer:GetUserIdList()
428
+ if datastoreKeyInfo then
429
+ userIdList = datastoreKeyInfo:GetUserIds()
430
+ end
404
431
 
405
- local metadata = nil
406
- if datastoreKeyInfo then
407
- metadata = datastoreKeyInfo:GetMetadata()
408
- end
432
+ local metadata = nil
433
+ if datastoreKeyInfo then
434
+ metadata = datastoreKeyInfo:GetMetadata()
435
+ end
409
436
 
410
- return result, userIdList, metadata
411
- end)))
437
+ return result, userIdList, metadata
438
+ end)
439
+ )
440
+ )
412
441
  end
413
442
 
414
443
  promise:Tap(nil, function(err)
@@ -425,7 +454,7 @@ function DataStore:_doDataSync(writer, doMergeNewData)
425
454
  return promise
426
455
  end
427
456
 
428
- function DataStore:_promiseGetAsyncNoCache()
457
+ function DataStore._promiseGetAsyncNoCache(self: DataStore): Promise.Promise<()>
429
458
  return self._maid:GivePromise(DataStorePromises.getAsync(self._robloxDataStore, self._key))
430
459
  :Catch(function(err)
431
460
  warn(string.format("DataStorePromises.getAsync(%q) -> warning - %s", tostring(self._key), tostring(err or "empty error")))
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Provides a data storage facility with an ability to get sub-stores. So you can write
3
4
  directly to this store, overwriting all children, or you can have more partial control
@@ -36,13 +37,27 @@ local DataStoreStage = setmetatable({}, BaseObject)
36
37
  DataStoreStage.ClassName = "DataStoreStage"
37
38
  DataStoreStage.__index = DataStoreStage
38
39
 
40
+ export type DataStoreStageKey = string | number
41
+
42
+ export type DataStoreCallback = () -> Promise.Promise<()>?
43
+
39
44
  export type DataStoreStage = typeof(setmetatable(
40
45
  {} :: {
46
+ _loadName: DataStoreStageKey,
47
+ _loadParent: DataStoreStage?,
48
+ _saveDataSnapshot: any,
49
+ _fullPath: string?,
50
+ _baseDataSnapshot: any,
51
+ _viewSnapshot: any,
52
+ _stores: { [DataStoreStageKey]: DataStoreStage },
53
+ _savingCallbacks: { DataStoreCallback },
54
+ _keySubscriptions: ObservableSubscriptionTable.ObservableSubscriptionTable<any>,
55
+
41
56
  Changed: Signal.Signal<any>,
42
57
  DataStored: Signal.Signal<any>,
43
58
  },
44
- DataStoreStage
45
- ))
59
+ {} :: typeof({ __index = DataStoreStage })
60
+ )) & BaseObject.BaseObject
46
61
 
47
62
  --[=[
48
63
  Constructs a new DataStoreStage to load from. Prefer to use DataStore because this doesn't
@@ -59,8 +74,8 @@ export type DataStoreStage = typeof(setmetatable(
59
74
  @param loadParent DataStoreStage?
60
75
  @return DataStoreStage
61
76
  ]=]
62
- function DataStoreStage.new(loadName: string, loadParent: DataStoreStage?)
63
- local self = setmetatable(BaseObject.new(), DataStoreStage)
77
+ function DataStoreStage.new(loadName: DataStoreStageKey, loadParent: DataStoreStage?): DataStoreStage
78
+ local self: DataStoreStage = setmetatable(BaseObject.new() :: any, DataStoreStage)
64
79
 
65
80
  -- LoadParent is optional, used for loading
66
81
  self._loadName = loadName
@@ -94,7 +109,7 @@ end
94
109
  @param key string
95
110
  @param value any
96
111
  ]=]
97
- function DataStoreStage:Store(key: string, value: any)
112
+ function DataStoreStage.Store(self: DataStoreStage, key: string, value: any)
98
113
  assert(type(key) == "string", "Bad key")
99
114
 
100
115
  if value == nil then
@@ -120,7 +135,7 @@ end
120
135
  @param defaultValue T?
121
136
  @return Promise<T>
122
137
  ]=]
123
- function DataStoreStage:Load<T>(key: string | number, defaultValue: T?): Promise.Promise<T>
138
+ function DataStoreStage.Load<T>(self: DataStoreStage, key: DataStoreStageKey, defaultValue: T?): Promise.Promise<T>
124
139
  assert(type(key) == "string" or type(key) == "number", "Bad key")
125
140
 
126
141
  return self:PromiseViewUpToDate():Then(function()
@@ -149,7 +164,7 @@ end
149
164
  @param defaultValue any
150
165
  @return Promise<any>
151
166
  ]=]
152
- function DataStoreStage:LoadAll(defaultValue)
167
+ function DataStoreStage.LoadAll(self: DataStoreStage, defaultValue)
153
168
  return self:PromiseViewUpToDate():Then(function()
154
169
  if self._viewSnapshot == nil then
155
170
  return defaultValue
@@ -173,7 +188,7 @@ end
173
188
  @param key string | number
174
189
  @return DataStoreStage
175
190
  ]=]
176
- function DataStoreStage:GetSubStore(key: string | number)
191
+ function DataStoreStage.GetSubStore(self: DataStoreStage, key: DataStoreStageKey)
177
192
  assert(type(key) == "string" or type(key) == "number", "Bad key")
178
193
 
179
194
  if self._stores[key] then
@@ -228,7 +243,7 @@ end
228
243
 
229
244
  @param key string | number
230
245
  ]=]
231
- function DataStoreStage:Delete(key: string)
246
+ function DataStoreStage.Delete(self: DataStoreStage, key: string)
232
247
  assert(type(key) == "string", "Bad key")
233
248
 
234
249
  self:_storeAtKey(key, DataStoreDeleteToken)
@@ -237,7 +252,7 @@ end
237
252
  --[=[
238
253
  Queues up a wipe of all values. This will completely set the data to nil.
239
254
  ]=]
240
- function DataStoreStage:Wipe()
255
+ function DataStoreStage.Wipe(self: DataStoreStage)
241
256
  self:Overwrite(DataStoreDeleteToken)
242
257
  end
243
258
 
@@ -250,7 +265,7 @@ end
250
265
  @param defaultValue T?
251
266
  @return Observable<T>
252
267
  ]=]
253
- function DataStoreStage:Observe(key, defaultValue)
268
+ function DataStoreStage.Observe(self: DataStoreStage, key, defaultValue)
254
269
  assert(type(key) == "string" or type(key) == "number" or key == nil, "Bad key")
255
270
 
256
271
  if key == nil then
@@ -282,16 +297,13 @@ function DataStoreStage:Observe(key, defaultValue)
282
297
  return Observable.new(function(sub)
283
298
  local maid = Maid.new()
284
299
 
285
- maid:GiveTask(
286
- self._keySubscriptions:Observe(key):Subscribe(function(value)
287
- if value == nil then
288
- sub:Fire(defaultValue)
289
- else
290
- sub:Fire(value)
291
- end
292
- end),
293
- sub:GetFailComplete()
294
- )
300
+ maid:GiveTask(self._keySubscriptions:Observe(key):Subscribe(function(value)
301
+ if value == nil then
302
+ sub:Fire(defaultValue)
303
+ else
304
+ sub:Fire(value)
305
+ end
306
+ end, sub:GetFailComplete()))
295
307
 
296
308
  -- Load initially
297
309
  maid:GivePromise(self:Load(key, defaultValue)):Then(function(value)
@@ -310,7 +322,7 @@ end
310
322
  @param callback function -- May return a promise
311
323
  @return function -- Call to remove
312
324
  ]=]
313
- function DataStoreStage:AddSavingCallback(callback: () -> ())
325
+ function DataStoreStage.AddSavingCallback(self: DataStoreStage, callback: DataStoreCallback?)
314
326
  assert(type(callback) == "function", "Bad callback")
315
327
 
316
328
  table.insert(self._savingCallbacks, callback)
@@ -326,7 +338,7 @@ end
326
338
  Removes a saving callback from the data store stage
327
339
  @param callback function
328
340
  ]=]
329
- function DataStoreStage:RemoveSavingCallback(callback: () -> ())
341
+ function DataStoreStage.RemoveSavingCallback(self: DataStoreStage, callback: DataStoreCallback?)
330
342
  assert(type(callback) == "function", "Bad callback")
331
343
 
332
344
  local index = table.find(self._savingCallbacks, callback)
@@ -340,7 +352,7 @@ end
340
352
 
341
353
  @return Signal
342
354
  ]=]
343
- function DataStoreStage:GetTopLevelDataStoredSignal()
355
+ function DataStoreStage.GetTopLevelDataStoredSignal(self: DataStoreStage)
344
356
  return self.DataStored
345
357
  end
346
358
 
@@ -349,15 +361,17 @@ end
349
361
 
350
362
  @return string
351
363
  ]=]
352
- function DataStoreStage:GetFullPath()
364
+ function DataStoreStage.GetFullPath(self: DataStoreStage): string
353
365
  if self._fullPath then
354
366
  return self._fullPath
355
367
  elseif self._loadParent then
356
- self._fullPath = self._loadParent:GetFullPath() .. "." .. tostring(self._loadName)
357
- return self._fullPath
368
+ local fullPath = self._loadParent:GetFullPath() .. "." .. tostring(self._loadName)
369
+ self._fullPath = fullPath
370
+ return fullPath
358
371
  else
359
- self._fullPath = tostring(self._loadName)
360
- return self._fullPath
372
+ local fullPath = tostring(self._loadName)
373
+ self._fullPath = fullPath
374
+ return fullPath
361
375
  end
362
376
  end
363
377
 
@@ -366,15 +380,14 @@ end
366
380
 
367
381
  @return Promise<{ string }>
368
382
  ]=]
369
- function DataStoreStage:PromiseKeyList()
370
- return self:PromiseKeySet()
371
- :Then(function(keys)
372
- local list = {}
383
+ function DataStoreStage.PromiseKeyList(self: DataStoreStage): Promise.Promise<{ string }>
384
+ return self:PromiseKeySet():Then(function(keys)
385
+ local list = {}
373
386
  for key, _ in keys do
374
387
  table.insert(list, key)
375
388
  end
376
389
  return list
377
- end)
390
+ end)
378
391
  end
379
392
 
380
393
  --[=[
@@ -382,7 +395,7 @@ end
382
395
 
383
396
  @return Promise<{ [string]: true }>
384
397
  ]=]
385
- function DataStoreStage:PromiseKeySet()
398
+ function DataStoreStage.PromiseKeySet(self: DataStoreStage): Promise.Promise<{ [string]: true }>
386
399
  return self:PromiseViewUpToDate():Then(function()
387
400
  if type(self._viewSnapshot) == "table" then
388
401
  return Set.fromKeys(self._viewSnapshot)
@@ -402,7 +415,7 @@ end
402
415
 
403
416
  @param diffSnapshot any
404
417
  ]=]
405
- function DataStoreStage:MergeDiffSnapshot(diffSnapshot)
418
+ function DataStoreStage.MergeDiffSnapshot(self: DataStoreStage, diffSnapshot)
406
419
  self:_checkIntegrity()
407
420
 
408
421
  self._baseDataSnapshot = self:_updateStoresAndComputeBaseDataSnapshotFromDiffSnapshot(diffSnapshot)
@@ -419,7 +432,7 @@ end
419
432
 
420
433
  @param parentWriter DataStoreWriter
421
434
  ]=]
422
- function DataStoreStage:MarkDataAsSaved(parentWriter)
435
+ function DataStoreStage.MarkDataAsSaved(self: DataStoreStage, parentWriter: DataStoreWriter.DataStoreWriter)
423
436
  -- Update all children first
424
437
  for key, subwriter in pairs(parentWriter:GetSubWritersMap()) do
425
438
  local store = self._stores[key]
@@ -489,7 +502,7 @@ end
489
502
 
490
503
  @return Promise
491
504
  ]=]
492
- function DataStoreStage:PromiseViewUpToDate()
505
+ function DataStoreStage.PromiseViewUpToDate(self: DataStoreStage)
493
506
  if not self._loadParent then
494
507
  error("[DataStoreStage.Load] - Failed to load, no loadParent!")
495
508
  end
@@ -510,7 +523,7 @@ end
510
523
 
511
524
  @param data any
512
525
  ]=]
513
- function DataStoreStage:Overwrite(data)
526
+ function DataStoreStage.Overwrite(self: DataStoreStage, data)
514
527
  -- Ensure that we at least start loading (and thus the autosave loop) for write
515
528
  self:PromiseViewUpToDate()
516
529
 
@@ -522,7 +535,7 @@ function DataStoreStage:Overwrite(data)
522
535
  local newSaveSnapshot = {}
523
536
 
524
537
  local remaining = Set.fromKeys(self._stores)
525
- for key, store in self._stores do
538
+ for key, store: any in self._stores do
526
539
  -- Update each store
527
540
  store:Overwrite(data[key])
528
541
  end
@@ -542,7 +555,7 @@ function DataStoreStage:Overwrite(data)
542
555
 
543
556
  self._saveDataSnapshot = table.freeze(newSaveSnapshot)
544
557
  else
545
- for _, store in self._stores do
558
+ for _, store: any in self._stores do
546
559
  store:Overwrite(DataStoreDeleteToken)
547
560
  end
548
561
 
@@ -563,7 +576,7 @@ end
563
576
 
564
577
  @param data any
565
578
  ]=]
566
- function DataStoreStage:OverwriteMerge(data)
579
+ function DataStoreStage.OverwriteMerge(self: DataStoreStage, data)
567
580
  -- Ensure that we at least start loading (and thus the autosave loop) for write
568
581
  self:PromiseViewUpToDate()
569
582
 
@@ -585,7 +598,7 @@ end
585
598
  @param valueObj Instance -- ValueBase object to store on
586
599
  @return MaidTask -- Cleanup to remove this writer and free the key.
587
600
  ]=]
588
- function DataStoreStage:StoreOnValueChange(name, valueObj)
601
+ function DataStoreStage.StoreOnValueChange(self: DataStoreStage, name: DataStoreStageKey, valueObj)
589
602
  assert(type(name) == "string" or type(name) == "number", "Bad name")
590
603
  assert(typeof(valueObj) == "Instance" or (type(valueObj) == "table" and valueObj.Changed), "Bad valueObj")
591
604
 
@@ -610,14 +623,14 @@ end
610
623
 
611
624
  @return boolean
612
625
  ]=]
613
- function DataStoreStage:HasWritableData()
626
+ function DataStoreStage.HasWritableData(self: DataStoreStage): boolean
614
627
  if self._saveDataSnapshot ~= nil then
615
628
  return true
616
629
  end
617
630
 
618
- for name, store in self._stores do
631
+ for name, store: any in self._stores do
619
632
  if not store.Destroy then
620
- warn(string.format("[DataStoreStage] - Substore %q destroyed", name))
633
+ warn(string.format("[DataStoreStage] - Substore %q destroyed", tostring(name)))
621
634
  continue
622
635
  end
623
636
 
@@ -638,7 +651,7 @@ end
638
651
 
639
652
  @return DataStoreWriter
640
653
  ]=]
641
- function DataStoreStage:GetNewWriter()
654
+ function DataStoreStage.GetNewWriter(self: DataStoreStage): DataStoreWriter.DataStoreWriter
642
655
  self:_checkIntegrity()
643
656
 
644
657
  local writer = DataStoreWriter.new(self:GetFullPath())
@@ -649,9 +662,9 @@ function DataStoreStage:GetNewWriter()
649
662
  writer:SetSaveDataSnapshot(self._saveDataSnapshot)
650
663
  end
651
664
 
652
- for key, store in self._stores do
665
+ for key, store: any in self._stores do
653
666
  if not store.Destroy then
654
- warn(string.format("[DataStoreStage] - Substore %q destroyed", key))
667
+ warn(string.format("[DataStoreStage] - Substore %q destroyed", tostring(key)))
655
668
  continue
656
669
  end
657
670
 
@@ -674,17 +687,17 @@ end
674
687
 
675
688
  @return Promise
676
689
  ]=]
677
- function DataStoreStage:PromiseInvokeSavingCallbacks()
678
- local removingPromises = {}
690
+ function DataStoreStage.PromiseInvokeSavingCallbacks(self: DataStoreStage)
691
+ local removingPromises: { Promise.Promise<()> } = {}
679
692
 
680
693
  for _, func in self._savingCallbacks do
681
694
  local result = func()
682
695
  if Promise.isPromise(result) then
683
- table.insert(removingPromises, result)
696
+ table.insert(removingPromises, result :: any)
684
697
  end
685
698
  end
686
699
 
687
- for _, substore in self._stores do
700
+ for _, substore: any in self._stores do
688
701
  local promise = substore:PromiseInvokeSavingCallbacks()
689
702
  if promise then
690
703
  table.insert(removingPromises, promise)
@@ -694,7 +707,7 @@ function DataStoreStage:PromiseInvokeSavingCallbacks()
694
707
  return PromiseUtils.all(removingPromises)
695
708
  end
696
709
 
697
- function DataStoreStage:_createFullBaseDataSnapshot()
710
+ function DataStoreStage._createFullBaseDataSnapshot(self: DataStoreStage)
698
711
  if self._baseDataSnapshot == DataStoreDeleteToken then
699
712
  error("BadDataSnapshot cannot be a delete token")
700
713
  elseif type(self._baseDataSnapshot) == "table" or self._baseDataSnapshot == nil then
@@ -705,9 +718,9 @@ function DataStoreStage:_createFullBaseDataSnapshot()
705
718
  newSnapshot = {}
706
719
  end
707
720
 
708
- for key, store in self._stores do
721
+ for key, store: any in self._stores do
709
722
  if not store.Destroy then
710
- warn(string.format("[DataStoreStage] - Substore %q destroyed", key))
723
+ warn(string.format("[DataStoreStage] - Substore %q destroyed", tostring(key)))
711
724
  continue
712
725
  end
713
726
 
@@ -726,7 +739,7 @@ function DataStoreStage:_createFullBaseDataSnapshot()
726
739
  end
727
740
  end
728
741
 
729
- function DataStoreStage:_updateStoresAndComputeBaseDataSnapshotFromDiffSnapshot(diffSnapshot)
742
+ function DataStoreStage._updateStoresAndComputeBaseDataSnapshotFromDiffSnapshot(self: DataStoreStage, diffSnapshot)
730
743
  if diffSnapshot == DataStoreDeleteToken then
731
744
  return nil
732
745
  elseif type(diffSnapshot) == "table" then
@@ -752,7 +765,11 @@ function DataStoreStage:_updateStoresAndComputeBaseDataSnapshotFromDiffSnapshot(
752
765
  end
753
766
  end
754
767
 
755
- function DataStoreStage:_updateStoresAndComputeBaseDataSnapshotValueFromDiffSnapshot(key, value)
768
+ function DataStoreStage._updateStoresAndComputeBaseDataSnapshotValueFromDiffSnapshot(
769
+ self: DataStoreStage,
770
+ key: DataStoreStageKey,
771
+ value
772
+ )
756
773
  assert(type(key) == "string" or type(key) == "number", "Bad key")
757
774
 
758
775
  if self._stores[key] then
@@ -771,7 +788,7 @@ function DataStoreStage:_updateStoresAndComputeBaseDataSnapshotValueFromDiffSnap
771
788
  end
772
789
  end
773
790
 
774
- function DataStoreStage:_recurseMergeTable(original, incoming)
791
+ function DataStoreStage._recurseMergeTable(self: DataStoreStage, original, incoming)
775
792
  if incoming == DataStoreDeleteToken then
776
793
  return nil
777
794
  elseif type(incoming) == "table" and type(original) == "table" then
@@ -789,7 +806,7 @@ function DataStoreStage:_recurseMergeTable(original, incoming)
789
806
  end
790
807
  end
791
808
 
792
- function DataStoreStage:_updateViewSnapshot()
809
+ function DataStoreStage._updateViewSnapshot(self: DataStoreStage)
793
810
  self:_checkIntegrity()
794
811
 
795
812
  local newViewSnapshot = self:_computeNewViewSnapshot()
@@ -818,7 +835,7 @@ function DataStoreStage:_updateViewSnapshot()
818
835
  self:_checkIntegrity()
819
836
  end
820
837
 
821
- function DataStoreStage:_computeChangedKeys(previousViewSnapshot, newViewSnapshot)
838
+ function DataStoreStage._computeChangedKeys(_self: DataStoreStage, previousViewSnapshot, newViewSnapshot)
822
839
  -- Detect keys that changed
823
840
  if type(previousViewSnapshot) == "table" and type(newViewSnapshot) == "table" then
824
841
  local changedKeys = {}
@@ -842,7 +859,7 @@ function DataStoreStage:_computeChangedKeys(previousViewSnapshot, newViewSnapsho
842
859
  end
843
860
  end
844
861
 
845
- function DataStoreStage:_updateViewSnapshotAtKey(key)
862
+ function DataStoreStage._updateViewSnapshotAtKey(self: DataStoreStage, key)
846
863
  assert(type(key) == "string" or type(key) == "number", "Bad key")
847
864
 
848
865
  if type(self._viewSnapshot) ~= "table" then
@@ -866,7 +883,7 @@ function DataStoreStage:_updateViewSnapshotAtKey(key)
866
883
  self:_checkIntegrity()
867
884
  end
868
885
 
869
- function DataStoreStage:_computeNewViewSnapshot()
886
+ function DataStoreStage._computeNewViewSnapshot(self: DataStoreStage)
870
887
  -- This prioritizes save data first, then stores, then base data
871
888
 
872
889
  if self._saveDataSnapshot == DataStoreDeleteToken then
@@ -916,7 +933,7 @@ function DataStoreStage:_computeNewViewSnapshot()
916
933
  end
917
934
  end
918
935
 
919
- function DataStoreStage:_computeViewValueForKey(key)
936
+ function DataStoreStage._computeViewValueForKey(self: DataStoreStage, key)
920
937
  -- This prioritizes save data first, then stores, then base data
921
938
 
922
939
  if self._saveDataSnapshot == DataStoreDeleteToken then
@@ -956,7 +973,7 @@ function DataStoreStage:_computeViewValueForKey(key)
956
973
  end
957
974
 
958
975
  -- Stores the data for overwrite.
959
- function DataStoreStage:_storeAtKey(key, value)
976
+ function DataStoreStage._storeAtKey(self: DataStoreStage, key, value)
960
977
  assert(type(key) == "string" or type(key) == "number", "Bad key")
961
978
  assert(value ~= nil, "Bad value")
962
979
 
@@ -996,7 +1013,7 @@ function DataStoreStage:_storeAtKey(key, value)
996
1013
  self:_checkIntegrity()
997
1014
  end
998
1015
 
999
- function DataStoreStage:_checkSnapshotIntegrity(label, result)
1016
+ function DataStoreStage._checkSnapshotIntegrity(_self: DataStoreStage, label, result)
1000
1017
  assert(type(label) == "string", "Bad label")
1001
1018
 
1002
1019
  if not SLOW_INTEGRITY_CHECK_ENABLED then
@@ -1007,7 +1024,7 @@ function DataStoreStage:_checkSnapshotIntegrity(label, result)
1007
1024
  error(string.format("%s should not be a DataStoreDeleteToken", label))
1008
1025
  end
1009
1026
 
1010
- local function recurse(innerLabel, value)
1027
+ local function recurse(innerLabel: string, value)
1011
1028
  if type(value) ~= "table" then
1012
1029
  return
1013
1030
  end
@@ -1032,7 +1049,7 @@ function DataStoreStage:_checkSnapshotIntegrity(label, result)
1032
1049
  recurse(label, result)
1033
1050
  end
1034
1051
 
1035
- function DataStoreStage:_checkIntegrity()
1052
+ function DataStoreStage._checkIntegrity(self: DataStoreStage)
1036
1053
  if not SLOW_INTEGRITY_CHECK_ENABLED then
1037
1054
  return
1038
1055
  end
@@ -1056,11 +1073,11 @@ function DataStoreStage:_checkIntegrity()
1056
1073
 
1057
1074
  for key, _ in self._stores do
1058
1075
  if type(self._baseDataSnapshot) == "table" and self._baseDataSnapshot[key] ~= nil then
1059
- error(string.format("[DataStoreStage] - Duplicate baseData at key %q", key))
1076
+ error(string.format("[DataStoreStage] - Duplicate baseData at key %q", tostring(key)))
1060
1077
  end
1061
1078
 
1062
1079
  if type(self._saveDataSnapshot) == "table" and self._saveDataSnapshot[key] ~= nil then
1063
- error(string.format("[DataStoreStage] - Duplicate saveData at key %q", key))
1080
+ error(string.format("[DataStoreStage] - Duplicate saveData at key %q", tostring(key)))
1064
1081
  end
1065
1082
  end
1066
1083
  end
@@ -1,3 +1,4 @@
1
+ --!strict
1
2
  --[=[
2
3
  Captures a snapshot of data to write and then merges it with the original.
3
4
  @server
@@ -18,14 +19,27 @@ local DataStoreWriter = {}
18
19
  DataStoreWriter.ClassName = "DataStoreWriter"
19
20
  DataStoreWriter.__index = DataStoreWriter
20
21
 
22
+ export type DataStoreStageKey = string | number
23
+
24
+ export type DataStoreWriter = typeof(setmetatable(
25
+ {} :: {
26
+ _debugName: string,
27
+ _saveDataSnapshot: any,
28
+ _fullBaseDataSnapshot: any,
29
+ _userIdList: { number } | nil,
30
+ _writers: { [DataStoreStageKey]: DataStoreWriter },
31
+ },
32
+ {} :: typeof({ __index = DataStoreWriter })
33
+ ))
34
+
21
35
  --[=[
22
36
  Constructs a new DataStoreWriter. In general, you will not use this API directly.
23
37
 
24
38
  @param debugName string
25
39
  @return DataStoreWriter
26
40
  ]=]
27
- function DataStoreWriter.new(debugName: string)
28
- local self = setmetatable({}, DataStoreWriter)
41
+ function DataStoreWriter.new(debugName: string): DataStoreWriter
42
+ local self: DataStoreWriter = setmetatable({} :: any, DataStoreWriter)
29
43
 
30
44
  self._debugName = assert(debugName, "No debugName")
31
45
  self._saveDataSnapshot = UNSET_TOKEN
@@ -41,7 +55,7 @@ end
41
55
  Sets the ray data to write
42
56
  @param saveDataSnapshot table | any
43
57
  ]=]
44
- function DataStoreWriter:SetSaveDataSnapshot(saveDataSnapshot)
58
+ function DataStoreWriter.SetSaveDataSnapshot(self: DataStoreWriter, saveDataSnapshot)
45
59
  assert(type(saveDataSnapshot) ~= "table" or table.isfrozen(saveDataSnapshot), "saveDataSnapshot should be frozen")
46
60
 
47
61
  if saveDataSnapshot == DataStoreDeleteToken then
@@ -53,7 +67,7 @@ function DataStoreWriter:SetSaveDataSnapshot(saveDataSnapshot)
53
67
  end
54
68
  end
55
69
 
56
- function DataStoreWriter:GetDataToSave()
70
+ function DataStoreWriter.GetDataToSave(self: DataStoreWriter): any
57
71
  if self._saveDataSnapshot == UNSET_TOKEN then
58
72
  return nil
59
73
  end
@@ -61,11 +75,11 @@ function DataStoreWriter:GetDataToSave()
61
75
  return self._saveDataSnapshot
62
76
  end
63
77
 
64
- function DataStoreWriter:GetSubWritersMap()
78
+ function DataStoreWriter.GetSubWritersMap(self: DataStoreWriter): { [DataStoreStageKey]: DataStoreWriter }
65
79
  return self._writers
66
80
  end
67
81
 
68
- function DataStoreWriter:SetFullBaseDataSnapshot(fullBaseDataSnapshot)
82
+ function DataStoreWriter.SetFullBaseDataSnapshot(self: DataStoreWriter, fullBaseDataSnapshot)
69
83
  assert(
70
84
  type(fullBaseDataSnapshot) ~= "table" or table.isfrozen(fullBaseDataSnapshot),
71
85
  "fullBaseDataSnapshot should be frozen"
@@ -81,11 +95,11 @@ end
81
95
 
82
96
  --[=[
83
97
  Adds a recursive child writer to use at the key `name`
84
- @param name string
98
+ @param name string | number
85
99
  @param writer DataStoreWriter
86
100
  ]=]
87
- function DataStoreWriter:AddSubWriter(name: string, writer)
88
- assert(type(name) == "string", "Bad name")
101
+ function DataStoreWriter.AddSubWriter(self: DataStoreWriter, name: DataStoreStageKey, writer: DataStoreWriter)
102
+ assert(type(name) == "string" or type(name) == "number", "Bad name")
89
103
  assert(not self._writers[name], "Writer already exists for name")
90
104
  assert(writer, "Bad writer")
91
105
 
@@ -95,10 +109,10 @@ end
95
109
  --[=[
96
110
  Gets a sub writer
97
111
 
98
- @param name string
112
+ @param name string | number
99
113
  @return DataStoreWriter
100
114
  ]=]
101
- function DataStoreWriter:GetWriter(name: string)
115
+ function DataStoreWriter.GetWriter(self: DataStoreWriter, name: DataStoreStageKey): DataStoreWriter?
102
116
  assert(type(name) == "string", "Bad name")
103
117
 
104
118
  return self._writers[name]
@@ -111,7 +125,7 @@ end
111
125
 
112
126
  @param incoming any
113
127
  ]=]
114
- function DataStoreWriter:ComputeDiffSnapshot(incoming)
128
+ function DataStoreWriter.ComputeDiffSnapshot(self: DataStoreWriter, incoming)
115
129
  assert(incoming ~= DataStoreDeleteToken, "Incoming value should not be DataStoreDeleteToken")
116
130
  assert(not Symbol.isSymbol(incoming), "Incoming should not be symbol")
117
131
 
@@ -149,7 +163,7 @@ function DataStoreWriter:ComputeDiffSnapshot(incoming)
149
163
  end
150
164
  end
151
165
 
152
- function DataStoreWriter:_computeValueDiff(original, incoming)
166
+ function DataStoreWriter._computeValueDiff(self: DataStoreWriter, original, incoming)
153
167
  assert(original ~= DataStoreDeleteToken, "original cannot be DataStoreDeleteToken")
154
168
  assert(incoming ~= DataStoreDeleteToken, "incoming cannot be DataStoreDeleteToken")
155
169
  assert(not Symbol.isSymbol(original), "original should not be symbol")
@@ -166,7 +180,7 @@ function DataStoreWriter:_computeValueDiff(original, incoming)
166
180
  end
167
181
  end
168
182
 
169
- function DataStoreWriter:_computeTableDiff(original, incoming)
183
+ function DataStoreWriter._computeTableDiff(self: DataStoreWriter, original, incoming)
170
184
  assert(type(original) == "table", "Bad original")
171
185
  assert(type(incoming) == "table", "Bad incoming")
172
186
  assert(not Symbol.isSymbol(original), "original should not be symbol")
@@ -191,7 +205,7 @@ end
191
205
 
192
206
  @param userIdList { number }
193
207
  ]=]
194
- function DataStoreWriter:SetUserIdList(userIdList)
208
+ function DataStoreWriter.SetUserIdList(self: DataStoreWriter, userIdList: { number }?)
195
209
  assert(type(userIdList) == "table" or userIdList == nil, "Bad userIdList")
196
210
 
197
211
  self._userIdList = userIdList
@@ -202,7 +216,7 @@ end
202
216
 
203
217
  @return userIdList { number }
204
218
  ]=]
205
- function DataStoreWriter:GetUserIdList()
219
+ function DataStoreWriter.GetUserIdList(self: DataStoreWriter): { number }?
206
220
  if self._userIdList == UNSET_TOKEN then
207
221
  return nil
208
222
  end
@@ -210,7 +224,7 @@ function DataStoreWriter:GetUserIdList()
210
224
  return self._userIdList
211
225
  end
212
226
 
213
- function DataStoreWriter:_writeMergeWriters(original)
227
+ function DataStoreWriter._writeMergeWriters(self: DataStoreWriter, original)
214
228
  local copy
215
229
  if Symbol.isSymbol(original) then
216
230
  copy = original
@@ -285,7 +299,7 @@ end
285
299
  @param original any
286
300
  @return any -- The original value
287
301
  ]=]
288
- function DataStoreWriter:WriteMerge(original)
302
+ function DataStoreWriter.WriteMerge(self: DataStoreWriter, original)
289
303
  -- Prioritize save value first, followed by writers, followed by original value
290
304
 
291
305
  if self._saveDataSnapshot == DataStoreDeleteToken then
@@ -302,7 +316,7 @@ function DataStoreWriter:WriteMerge(original)
302
316
  end
303
317
  end
304
318
 
305
- function DataStoreWriter:IsCompleteWipe(): boolean
319
+ function DataStoreWriter.IsCompleteWipe(self: DataStoreWriter): boolean
306
320
  if self._saveDataSnapshot == UNSET_TOKEN then
307
321
  return false
308
322
  end
@@ -64,6 +64,19 @@ local PlayerDataStoreManager = setmetatable({}, BaseObject)
64
64
  PlayerDataStoreManager.ClassName = "PlayerDataStoreManager"
65
65
  PlayerDataStoreManager.__index = PlayerDataStoreManager
66
66
 
67
+ export type PlayerDataStoreManager = typeof(setmetatable(
68
+ {} :: {
69
+ _robloxDataStore: any,
70
+ _keyGenerator: (Player) -> string,
71
+ _datastores: { [Player]: DataStore },
72
+ _removing: { [Player]: boolean },
73
+ _pendingSaves: PendingPromiseTracker.PendingPromiseTracker<any>,
74
+ _removingCallbacks: { (Player) -> any },
75
+ _disableSavingInStudio: boolean?,
76
+ },
77
+ {} :: typeof({ __index = PlayerDataStoreManager })
78
+ )) & BaseObject.BaseObject
79
+
67
80
  --[=[
68
81
  Constructs a new PlayerDataStoreManager.
69
82
 
@@ -16,6 +16,17 @@ local _ServiceBag = require("ServiceBag")
16
16
  local PlayerDataStoreService = {}
17
17
  PlayerDataStoreService.ServiceName = "PlayerDataStoreService"
18
18
 
19
+ export type PlayerDataStoreService = typeof(setmetatable(
20
+ {} :: {
21
+ _serviceBag: _ServiceBag.ServiceBag,
22
+ _maid: Maid.Maid,
23
+ _dataStoreName: string,
24
+ _dataStoreScope: string,
25
+ _dataStoreManagerPromise: Promise.Promise<PlayerDataStoreManager.PlayerDataStoreManager>,
26
+ },
27
+ {} :: typeof({ __index = PlayerDataStoreService })
28
+ ))
29
+
19
30
  --[=[
20
31
  Initializes the PlayerDataStoreService. Should be done via [ServiceBag.Init].
21
32
  @param serviceBag ServiceBag
@@ -15,6 +15,8 @@ local Table = require("Table")
15
15
 
16
16
  local DataStorePromises = {}
17
17
 
18
+ export type RobloxDataStore = DataStore
19
+
18
20
  --[=[
19
21
  Promises a Roblox datastore object with the name and scope. Generally only fails
20
22
  when you haven't published the place.
@@ -95,7 +97,7 @@ end
95
97
  function DataStorePromises.updateAsync<T>(
96
98
  robloxDataStore: DataStore,
97
99
  key: string,
98
- updateFunc: (T) -> T?
100
+ updateFunc: (T, DataStoreKeyInfo) -> T?
99
101
  ): Promise.Promise<(T, DataStoreKeyInfo)>
100
102
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
101
103
  assert(type(key) == "string", "Bad key")