@quenty/datastore 3.2.1-canary.8533eea.0 → 3.3.1

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,15 @@
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
- ## [3.2.1-canary.8533eea.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/datastore@3.2.0...@quenty/datastore@3.2.1-canary.8533eea.0) (2021-12-18)
6
+ ## [3.3.1](https://github.com/Quenty/NevermoreEngine/compare/@quenty/datastore@3.3.0...@quenty/datastore@3.3.1) (2021-12-30)
7
+
8
+ **Note:** Version bump only for package @quenty/datastore
9
+
10
+
11
+
12
+
13
+
14
+ # [3.3.0](https://github.com/Quenty/NevermoreEngine/compare/@quenty/datastore@3.2.0...@quenty/datastore@3.3.0) (2021-12-18)
7
15
 
8
16
  **Note:** Version bump only for package @quenty/datastore
9
17
 
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
1
  # Quenty's DataStore System
2
2
  <div align="center">
3
- <a href="http://quenty.github.io/api/">
4
- <img src="https://img.shields.io/badge/docs-website-green.svg" alt="Documentation" />
3
+ <a href="http://quenty.github.io/NevermoreEngine/">
4
+ <img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/docs.yml/badge.svg" alt="Documentation status" />
5
5
  </a>
6
6
  <a href="https://discord.gg/mhtGUS8">
7
- <img src="https://img.shields.io/badge/discord-nevermore-blue.svg" alt="Discord" />
7
+ <img src="https://img.shields.io/discord/385151591524597761?color=5865F2&label=discord&logo=discord&logoColor=white" alt="Discord" />
8
8
  </a>
9
9
  <a href="https://github.com/Quenty/NevermoreEngine/actions">
10
10
  <img src="https://github.com/Quenty/NevermoreEngine/actions/workflows/build.yml/badge.svg" alt="Build and release status" />
@@ -13,6 +13,8 @@
13
13
 
14
14
  This system is a reliable datastore system designed with promises and asyncronious code in mind, and has been tested on several games. Underlying this system are several key design points.
15
15
 
16
+ <div align="center"><a href="https://quenty.github.io/NevermoreEngine/api/DataStore">View docs →</a></div>
17
+
16
18
  ## Installation
17
19
  ```
18
20
  npm install @quenty/datastore --save
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@quenty/datastore",
3
- "version": "3.2.1-canary.8533eea.0",
3
+ "version": "3.3.1",
4
4
  "description": "Quenty's Datastore implementation for Roblox",
5
5
  "keywords": [
6
6
  "Roblox",
@@ -26,16 +26,16 @@
26
26
  "Quenty"
27
27
  ],
28
28
  "dependencies": {
29
- "@quenty/baseobject": "3.2.0",
30
- "@quenty/loader": "3.1.1",
31
- "@quenty/maid": "2.0.1",
32
- "@quenty/promise": "3.2.1-canary.8533eea.0",
33
- "@quenty/signal": "2.0.0",
34
- "@quenty/symbol": "2.0.0",
35
- "@quenty/table": "2.1.0"
29
+ "@quenty/baseobject": "^3.2.1",
30
+ "@quenty/loader": "^3.1.2",
31
+ "@quenty/maid": "^2.0.2",
32
+ "@quenty/promise": "^3.3.1",
33
+ "@quenty/signal": "^2.0.1",
34
+ "@quenty/symbol": "^2.0.1",
35
+ "@quenty/table": "^2.1.1"
36
36
  },
37
37
  "publishConfig": {
38
38
  "access": "public"
39
39
  },
40
- "gitHead": "8533eeade3bf6835c0295785c1c326b9abee3222"
40
+ "gitHead": "d146c77d0a8e452824de0ab0b4b03ba0370bcc1b"
41
41
  }
@@ -1,5 +1,28 @@
1
- --- Wraps the datastore object to provide async cached loading and saving
2
- -- @classmod DataStore
1
+ --[=[
2
+ Wraps the datastore object to provide async cached loading and saving. See [DataStoreStage] for more API.
3
+
4
+ Has the following features
5
+ * Automatic save
6
+ * Jitter
7
+ * De-duplication (only updates data it needs)
8
+
9
+ ```lua
10
+ local playerMoneyValue = Instance.new("IntValue")
11
+ playerMoneyValue.Value = 0
12
+
13
+ local dataStore = DataStore.new(DataStoreService:GetDataStore("test"), test-store")
14
+ dataStore:Load("money", 0):Then(function(money)
15
+ playerMoneyValue.Value = money
16
+ dataStore:StoreOnValueChange("money", playerMoneyValue)
17
+ end):Catch(function()
18
+ -- TODO: Notify player
19
+ end)
20
+
21
+ ```
22
+
23
+ @server
24
+ @class DataStore
25
+ ]=]
3
26
 
4
27
  local require = require(script.Parent.loader).load(script)
5
28
 
@@ -20,12 +43,22 @@ local DataStore = setmetatable({}, DataStoreStage)
20
43
  DataStore.ClassName = "DataStore"
21
44
  DataStore.__index = DataStore
22
45
 
46
+ --[=[
47
+ Constructs a new DataStore. See [DataStoreStage] for more API.
48
+ @param robloxDataStore DataStore
49
+ @param key string
50
+ ]=]
23
51
  function DataStore.new(robloxDataStore, key)
24
52
  local self = setmetatable(DataStoreStage.new(), DataStore)
25
53
 
26
54
  self._key = key or error("No key")
27
55
  self._robloxDataStore = robloxDataStore or error("No robloxDataStore")
28
56
 
57
+ --[=[
58
+ Prop that fires when saving. Promise will resolve once saving is complete.
59
+ @prop Saving Signal<Promise>
60
+ @within DataStore
61
+ ]=]
29
62
  self.Saving = Signal.new() -- :Fire(promise)
30
63
  self._maid:GiveTask(self.Saving)
31
64
 
@@ -56,10 +89,18 @@ function DataStore.new(robloxDataStore, key)
56
89
  return self
57
90
  end
58
91
 
92
+ --[=[
93
+ Returns the full path for the datastore
94
+ @return string
95
+ ]=]
59
96
  function DataStore:GetFullPath()
60
97
  return ("RobloxDataStore@%s"):format(self._key)
61
98
  end
62
99
 
100
+ --[=[
101
+ Returns whether the datastore failed.
102
+ @return boolean
103
+ ]=]
63
104
  function DataStore:DidLoadFail()
64
105
  if not self._loadPromise then
65
106
  return false
@@ -80,7 +121,10 @@ function DataStore:PromiseLoadSuccessful()
80
121
  end)
81
122
  end
82
123
 
83
- -- Saves all stored data
124
+ --[=[
125
+ Saves all stored data.
126
+ @return Promise
127
+ ]=]
84
128
  function DataStore:Save()
85
129
  if self:DidLoadFail() then
86
130
  warn("[DataStore] - Not saving, failed to load")
@@ -98,7 +142,12 @@ function DataStore:Save()
98
142
  return self:_saveData(self:GetNewWriter())
99
143
  end
100
144
 
101
- -- Loads data. This returns the originally loaded data.
145
+ --[=[
146
+ Loads data. This returns the originally loaded data.
147
+ @param keyName string
148
+ @param defaultValue any?
149
+ @return any?
150
+ ]=]
102
151
  function DataStore:Load(keyName, defaultValue)
103
152
  return self:_promiseLoad()
104
153
  :Then(function(data)
@@ -1,5 +1,8 @@
1
- --- Token to use for deleting
2
- -- @classmod DataStoreDeleteToken
1
+ --[=[
2
+ Token to use for deleting.
3
+ @server
4
+ @class DataStoreDeleteToken
5
+ ]=]
3
6
 
4
7
  local require = require(script.Parent.loader).load(script)
5
8
 
@@ -1,8 +1,12 @@
1
- --- Provides a data storage facility with an ability to get sub-stores. So you can write
2
- -- directly to this store, overwriting all children, or you can have more partial control
3
- -- at children level. This minimizes accidently overwriting.
4
- -- The big cost here is that we may leave keys that can't be removed.
5
- -- @classmod DataStoreStage
1
+ --[=[
2
+ Provides a data storage facility with an ability to get sub-stores. So you can write
3
+ directly to this store, overwriting all children, or you can have more partial control
4
+ at children level. This minimizes accidently overwriting.
5
+ The big cost here is that we may leave keys that can't be removed.
6
+
7
+ @server
8
+ @class DataStoreStage
9
+ ]=]
6
10
 
7
11
  local require = require(script.Parent.loader).load(script)
8
12
 
@@ -17,6 +21,13 @@ local DataStoreStage = setmetatable({}, BaseObject)
17
21
  DataStoreStage.ClassName = "DataStoreStage"
18
22
  DataStoreStage.__index = DataStoreStage
19
23
 
24
+ --[=[
25
+ Constructs a new DataStoreStage to load from. Prefer to use DataStore because this doesn't
26
+ have any way to retrieve this.
27
+ @param loadName string
28
+ @param loadParent DataStoreStage?
29
+ @return DataStoreStage
30
+ ]=]
20
31
  function DataStoreStage.new(loadName, loadParent)
21
32
  local self = setmetatable(BaseObject.new(), DataStoreStage)
22
33
 
@@ -30,6 +41,10 @@ function DataStoreStage.new(loadName, loadParent)
30
41
  return self
31
42
  end
32
43
 
44
+ --[=[
45
+ Gets an event that will fire off whenever something is stored at this level
46
+ @return Signal
47
+ ]=]
33
48
  function DataStoreStage:GetTopLevelDataStoredSignal()
34
49
  if self._topLevelStoreSignal then
35
50
  return self._topLevelStoreSignal
@@ -40,6 +55,10 @@ function DataStoreStage:GetTopLevelDataStoredSignal()
40
55
  return self._topLevelStoreSignal
41
56
  end
42
57
 
58
+ --[=[
59
+ Retrieves the full path of this datastore stage for diagnostic purposes.
60
+ @return string
61
+ ]=]
43
62
  function DataStoreStage:GetFullPath()
44
63
  if self._loadParent then
45
64
  return self._loadParent:GetFullPath() .. "." .. tostring(self._loadName)
@@ -48,6 +67,12 @@ function DataStoreStage:GetFullPath()
48
67
  end
49
68
  end
50
69
 
70
+ --[=[
71
+ Loads the data at the `name`.
72
+ @param name string
73
+ @param defaultValue T?
74
+ @return Promise<T>
75
+ ]=]
51
76
  function DataStoreStage:Load(name, defaultValue)
52
77
  if not self._loadParent then
53
78
  error("[DataStoreStage.Load] - Failed to load, no loadParent!")
@@ -93,6 +118,10 @@ function DataStoreStage:_afterLoadGetAndApplyStagedData(name, data, defaultValue
93
118
  end
94
119
  end
95
120
 
121
+ --[=[
122
+ Explicitely deletes data at the key
123
+ @param name string
124
+ ]=]
96
125
  function DataStoreStage:Delete(name)
97
126
  if self._takenKeys[name] then
98
127
  error(("[DataStoreStage] - Already have a writer for %q"):format(name))
@@ -101,6 +130,9 @@ function DataStoreStage:Delete(name)
101
130
  self:_doStore(name, DataStoreDeleteToken)
102
131
  end
103
132
 
133
+ --[=[
134
+ Queues up a wipe of all values. Data must load before it can be wiped.
135
+ ]=]
104
136
  function DataStoreStage:Wipe()
105
137
  return self._loadParent:Load(self._loadName, {})
106
138
  :Then(function(data)
@@ -126,6 +158,11 @@ function DataStoreStage:Store(name, value)
126
158
  self:_doStore(name, value)
127
159
  end
128
160
 
161
+ --[=[
162
+ Gets a sub-datastore that will write at the given name point
163
+ @param name string
164
+ @return DataStoreStage
165
+ ]=]
129
166
  function DataStoreStage:GetSubStore(name)
130
167
  assert(type(name) == "string", "Bad name")
131
168
 
@@ -146,6 +183,12 @@ function DataStoreStage:GetSubStore(name)
146
183
  return newStore
147
184
  end
148
185
 
186
+ --[=[
187
+ Whenever the ValueObject changes, stores the resulting value in that entry.
188
+ @param name string
189
+ @param valueObj Instance -- ValueBase object to store on
190
+ @return MaidTask
191
+ ]=]
149
192
  function DataStoreStage:StoreOnValueChange(name, valueObj)
150
193
  assert(type(name) == "string", "Bad name")
151
194
  assert(typeof(valueObj) == "Instance", "Bad valueObj")
@@ -162,6 +205,10 @@ function DataStoreStage:StoreOnValueChange(name, valueObj)
162
205
  return conn
163
206
  end
164
207
 
208
+ --[=[
209
+ If these is data not yet written then this will return true
210
+ @return boolean
211
+ ]=]
165
212
  function DataStoreStage:HasWritableData()
166
213
  if self._dataToSave then
167
214
  return true
@@ -176,7 +223,10 @@ function DataStoreStage:HasWritableData()
176
223
  return false
177
224
  end
178
225
 
179
- --- Constructs a writer which provides a snapshot of the current data state to write
226
+ --[=[
227
+ Constructs a writer which provides a snapshot of the current data state to write
228
+ @return DataStoreWriter
229
+ ]=]
180
230
  function DataStoreStage:GetNewWriter()
181
231
  local writer = DataStoreWriter.new()
182
232
  if self._dataToSave then
@@ -1,5 +1,8 @@
1
- --- Captures a snapshot of data to write and then merges it with the original
2
- -- @classmod DataStoreWriter
1
+ --[=[
2
+ Captures a snapshot of data to write and then merges it with the original.
3
+ @server
4
+ @class DataStoreWriter
5
+ ]=]
3
6
 
4
7
  local require = require(script.Parent.loader).load(script)
5
8
 
@@ -10,6 +13,11 @@ local DataStoreWriter = {}
10
13
  DataStoreWriter.ClassName = "DataStoreWriter"
11
14
  DataStoreWriter.__index = DataStoreWriter
12
15
 
16
+ --[=[
17
+ Constructs a new DataStoreWriter. In general, you will not use this API directly.
18
+
19
+ @return DataStoreWriter
20
+ ]=]
13
21
  function DataStoreWriter.new()
14
22
  local self = setmetatable({}, DataStoreWriter)
15
23
 
@@ -19,10 +27,19 @@ function DataStoreWriter.new()
19
27
  return self
20
28
  end
21
29
 
30
+ --[=[
31
+ Sets the ray data to write
32
+ @param data table
33
+ ]=]
22
34
  function DataStoreWriter:SetRawData(data)
23
35
  self._rawSetData = Table.deepCopy(data)
24
36
  end
25
37
 
38
+ --[=[
39
+ Adds a recursive child writer to use at the key `name`
40
+ @param name string
41
+ @param writer DataStoreWriter
42
+ ]=]
26
43
  function DataStoreWriter:AddWriter(name, writer)
27
44
  assert(type(name) == "string", "Bad name")
28
45
  assert(not self._writers[name], "Writer already exists for name")
@@ -31,7 +48,12 @@ function DataStoreWriter:AddWriter(name, writer)
31
48
  self._writers[name] = writer
32
49
  end
33
50
 
34
- -- Do merge here
51
+ --[=[
52
+ Merges the new data into the original value
53
+
54
+ @param original table?
55
+ @return table -- The original table
56
+ ]=]
35
57
  function DataStoreWriter:WriteMerge(original)
36
58
  original = original or {}
37
59
 
@@ -1,5 +1,9 @@
1
- --- DataStore manager for player that automatically saves on player leave and game close
2
- -- @classmod PlayerDataStoreManager
1
+ --[=[
2
+ DataStore manager for player that automatically saves on player leave and game close.
3
+
4
+ @server
5
+ @class PlayerDataStoreManager
6
+ ]=]
3
7
 
4
8
  local require = require(script.Parent.loader).load(script)
5
9
 
@@ -16,7 +20,12 @@ local PlayerDataStoreManager = setmetatable({}, BaseObject)
16
20
  PlayerDataStoreManager.ClassName = "PlayerDataStoreManager"
17
21
  PlayerDataStoreManager.__index = PlayerDataStoreManager
18
22
 
19
- -- @param [keyGenerator] Function that takes in a player, and outputs a key
23
+ --[=[
24
+ Constructs a new PlayerDataStoreManager.
25
+ @param robloxDataStore DataStore
26
+ @param keyGenerator (player) -> string -- Function that takes in a player, and outputs a key
27
+ @return PlayerDataStoreManager
28
+ ]=]
20
29
  function PlayerDataStoreManager.new(robloxDataStore, keyGenerator)
21
30
  local self = setmetatable(BaseObject.new(), PlayerDataStoreManager)
22
31
 
@@ -49,24 +58,37 @@ function PlayerDataStoreManager.new(robloxDataStore, keyGenerator)
49
58
  return self
50
59
  end
51
60
 
52
- --- For if you want to disable saving in studio for faster close time!
61
+ --[=[
62
+ For if you want to disable saving in studio for faster close time!
63
+ ]=]
53
64
  function PlayerDataStoreManager:DisableSaveOnCloseStudio()
54
65
  assert(RunService:IsStudio())
55
66
 
56
67
  self._disableSavingInStudio = true
57
68
  end
58
69
 
59
- --- Adds a callback to be called before save on removal
70
+ --[=[
71
+ Adds a callback to be called before save on removal
72
+ @param callback function
73
+ ]=]
60
74
  function PlayerDataStoreManager:AddRemovingCallback(callback)
61
75
  table.insert(self._removingCallbacks, callback)
62
76
  end
63
77
 
64
- --- Callable to allow manual GC so things can properly clean up.
65
- -- This can be used to pre-emptively cleanup players.
78
+ --[=[
79
+ Callable to allow manual GC so things can properly clean up.
80
+ This can be used to pre-emptively cleanup players.
81
+
82
+ @param player Player
83
+ ]=]
66
84
  function PlayerDataStoreManager:RemovePlayerDataStore(player)
67
85
  self:_removePlayerDataStore(player)
68
86
  end
69
87
 
88
+ --[=[
89
+ @param player Player
90
+ @return DataStore
91
+ ]=]
70
92
  function PlayerDataStoreManager:GetDataStore(player)
71
93
  assert(typeof(player) == "Instance", "Bad player")
72
94
  assert(player:IsA("Player"), "Bad player")
@@ -83,6 +105,11 @@ function PlayerDataStoreManager:GetDataStore(player)
83
105
  return self:_createDataStore(player)
84
106
  end
85
107
 
108
+ --[=[
109
+ Removes all player data stores, and returns a promise that
110
+ resolves when all pending saves are saved.
111
+ @return Promise
112
+ ]=]
86
113
  function PlayerDataStoreManager:PromiseAllSaves()
87
114
  for player, _ in pairs(self._datastores) do
88
115
  self:_removePlayerDataStore(player)
@@ -1,5 +1,8 @@
1
- --- Utility methods to interactive with DataStores
2
- -- @module DataStorePromises
1
+ --[=[
2
+ Utility methods to interactive with Roblox datastores.
3
+ @server
4
+ @class DataStorePromises
5
+ ]=]
3
6
 
4
7
  local require = require(script.Parent.loader).load(script)
5
8
 
@@ -8,6 +11,13 @@ local DataStoreService = game:GetService("DataStoreService")
8
11
 
9
12
  local DataStorePromises = {}
10
13
 
14
+ --[=[
15
+ Promises a Roblox datastore object with the name and scope. Generally only fails
16
+ when you haven't published the place.
17
+ @param name string
18
+ @param scope string
19
+ @return Promise<DataStore>
20
+ ]=]
11
21
  function DataStorePromises.promiseDataStore(name, scope)
12
22
  assert(type(name) == "string", "Bad name")
13
23
  assert(type(scope) == "string", "Bad scope")
@@ -25,6 +35,12 @@ function DataStorePromises.promiseDataStore(name, scope)
25
35
 
26
36
  end
27
37
 
38
+ --[=[
39
+ Wraps :GetAsync() in a promise
40
+ @param robloxDataStore DataStore
41
+ @param key string
42
+ @return Promise<T>
43
+ ]=]
28
44
  function DataStorePromises.getAsync(robloxDataStore, key)
29
45
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
30
46
  assert(type(key) == "string", "Bad key")
@@ -41,6 +57,14 @@ function DataStorePromises.getAsync(robloxDataStore, key)
41
57
  end)
42
58
  end
43
59
 
60
+ --[=[
61
+ Wraps :UpdateAsync() in a promise
62
+ @param robloxDataStore DataStore
63
+ @param key string
64
+ @param updateFunc (T) -> T?
65
+ @return Promise<boolean>
66
+ ]=]
67
+
44
68
  function DataStorePromises.updateAsync(robloxDataStore, key, updateFunc)
45
69
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
46
70
  assert(type(key) == "string", "Bad key")
@@ -61,6 +85,13 @@ function DataStorePromises.updateAsync(robloxDataStore, key, updateFunc)
61
85
  end)
62
86
  end
63
87
 
88
+ --[=[
89
+ Wraps :SetAsync() in a promise
90
+ @param robloxDataStore DataStore
91
+ @param key string
92
+ @param value string
93
+ @return Promise<boolean>
94
+ ]=]
64
95
  function DataStorePromises.setAsync(robloxDataStore, key, value)
65
96
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
66
97
  assert(type(key) == "string", "Bad key")
@@ -76,6 +107,13 @@ function DataStorePromises.setAsync(robloxDataStore, key, value)
76
107
  end)
77
108
  end
78
109
 
110
+ --[=[
111
+ Wraps :IncrementAsync() in a promise
112
+ @param robloxDataStore DataStore
113
+ @param key string
114
+ @param delta number
115
+ @return Promise<boolean>
116
+ ]=]
79
117
  function DataStorePromises.promiseIncrementAsync(robloxDataStore, key, delta)
80
118
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
81
119
  assert(type(key) == "string", "Bad key")
@@ -92,6 +130,12 @@ function DataStorePromises.promiseIncrementAsync(robloxDataStore, key, delta)
92
130
  end)
93
131
  end
94
132
 
133
+ --[=[
134
+ Wraps :RemoveAsync() in a promise
135
+ @param robloxDataStore DataStore
136
+ @param key string
137
+ @return Promise<boolean>
138
+ ]=]
95
139
  function DataStorePromises.removeAsync(robloxDataStore, key)
96
140
  assert(typeof(robloxDataStore) == "Instance", "Bad robloxDataStore")
97
141
  assert(type(key) == "string", "Bad key")