Skip to content

Commit

Permalink
Merge pull request #43 from FireBird702/main
Browse files Browse the repository at this point in the history
Add a way to customize the verbosity of the logging, fix .GetStore() returning wrong cached value
  • Loading branch information
noahrepublic authored Dec 9, 2024
2 parents 1d59bf3 + e3e6006 commit 4e7f52d
Show file tree
Hide file tree
Showing 29 changed files with 1,141 additions and 796 deletions.
6 changes: 3 additions & 3 deletions .github/workflows/docs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ jobs:
name: Build and deploy docs
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/setup-node@v2
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: "18"
node-version: "22"
- run: npm i -g moonwave@latest
- name: Publish
run: |
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/wally.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Install Rokit
uses: CompeyDev/[email protected].1
uses: CompeyDev/[email protected].2
- name: Publish release to Wally
shell: bash
run: |
Expand Down
41 changes: 27 additions & 14 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
# DataKeep

## [version 5.0.0](https://github.com/noahrepublic/DataKeep/releases/tag/v5.0.0): 12/02/2024

- Add `DataKeep.Enums`
- Default `logLevel` is now `DataKeep.Enums.LogLevel.Warn`
- Add `store:Identify()`
- Add `store:RemoveKeep()`
- Add `:LoadKeep()` retrying
- Fix `.GetStore()` returning wrong cached value
- Functions made only for specific keep type are only visible for that type
- Types are `--!strict`

### Breaking Changes

- Proper promise handling on loading, see basic usage docs
- Removed `DataKeep.LoadMethods` became, `DataKeep.Enums.LoadMethod`
- Added customization of the verbosity of the logging via `DataKeep.Enums.LogLevel`

## [version 4.1.0](https://github.com/noahrepublic/DataKeep/releases/tag/v4.1.0): 10/22/2024

- Add DataKeep.SetConfig()
Expand All @@ -8,7 +25,8 @@

- [Types Rewrite](https://github.com/noahrepublic/DataKeep/pull/32)

#### Breaking Changes ! !
### Breaking Changes

- Changed `globalUpdate.ID` -> `globalUpdate.Id`
- DataKeep:LoadStore() requires wrapper as third parameter (for strict types)
- Default Wrapper now moved to `DataKeep.Wrapper`
Expand All @@ -34,9 +52,9 @@

## [version 3.1.2](https://github.com/noahrepublic/DataKeep/releases/tag/v3.1.2): 05/28/2024

- Fix a few things by @FireBird702 in <https://github.com/noahrepublic/DataKeep/pull/20>
- Fix for #22 by @FireBird702 in <https://github.com/noahrepublic/DataKeep/pull/23>
- `:SetAsync()` in mock store should deep copy value by @FireBird702 in <https://github.com/noahrepublic/DataKeep/pull/26>
- [Fix a few things](https://github.com/noahrepublic/DataKeep/pull/20) by @FireBird702
- Fix for [#22](https://github.com/noahrepublic/DataKeep/pull/23) by @FireBird702
- [`:SetAsync()` in mock store should deep copy value](https://github.com/noahrepublic/DataKeep/pull/26) by @FireBird702

## [version 3.1.1](https://github.com/noahrepublic/DataKeep/releases/tag/v3.1.1): 03/17/2024

Expand All @@ -54,7 +72,7 @@

- Mock detection fix

### SLIGHT BREAKING CHANGE
### Slight Breaking Change

- GetStore now waits for mockstore detection to finish. Players.PlayerAdded events may fire before getstore is ready. Use a loop of current players first. (See Example)

Expand Down Expand Up @@ -93,15 +111,13 @@

## [version 3.0.0](https://github.com/noahrepublic/DataKeep/releases/tag/v3.0.0): 12/22/2023

**API Breaking Change**

### Added

- Documented IssueSignal, CriticalState, & CriticalStateSignal
- Added 'Saving' signal to Keep
- Mockstore didyield detection for more accurate development testing

### Changes
### Breaking Changes

- DataKeep.Wrapper is now: DataStore.Wrapper (independant wrappers supported)
- OnRelease -> Releasing (signal) to address [#13](https://github.com/noahrepublic/DataKeep/issues/13)
Expand All @@ -113,8 +129,6 @@

## [version 2.1.1](https://github.com/noahrepublic/DataKeep/releases/tag/v2.1.1): 12/17/2023

## **API Breaking Change**

### Fixed

- ViewKeep :Save not working, replaced with :Overwrite()
Expand All @@ -137,9 +151,9 @@

## [version 2.0.0](https://github.com/noahrepublic/DataKeep/releases/tag/v2.0.0): 11/28/2023

API Breaking Change
### API Breaking Change

:AttachSave -> :PreSave & :PreLoad
:AttachSave() -> :PreSave() & :PreLoad()

Allows for more control and not limited to just compression/decompression but transforming the data however.

Expand All @@ -149,8 +163,7 @@ Allows for more control and not limited to just compression/decompression but tr

### Added

- Finally added compression 'plugins' see <https://github.com/noahrepublic/DataKeep/issues/2>
:AttachToSave()
- [Finally added compression 'plugins'](https://github.com/noahrepublic/DataKeep/issues/2)

## [version 1.2.2](https://github.com/noahrepublic/DataKeep/releases/tag/v1.2.2): 11/21/2023

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,4 +33,4 @@ Flaws in ProfileService:
- Profile does not automatically clean up internal connections, making the developer have to perform inconvenient clean ups
- ProfileService async calls make it difficult to wait for Profiles to be loaded. Causing weird patterns when waiting for Profiles, DataKeep is promise based
- Shorter, cleaner, scripts for faster future development, and contributors
- Type checking, caveat due to Luau limitations, can not type check what Promises return
- Type checking, caveat due to Luau limitations, cannot type check what Promises return
28 changes: 9 additions & 19 deletions docs/DevProducts.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,7 @@ sidebar_position: 5

The following example shows how you would handle developer product purchases:

```lua
-- DataTemplate.luau

```lua title="DataTemplate.luau"
local dataTemplate = {
PurchaseHistory = {},

Expand All @@ -20,9 +18,7 @@ export type template = typeof(dataTemplate)
return table.freeze(dataTemplate)
```

```lua
-- DevProducts.luau

```lua title="DevProducts.luau"
local DataKeep = require(path_to_datakeep)
local DataTemplate = require(path_to_datatemplate)

Expand All @@ -37,9 +33,7 @@ local devProducts = {
return devProducts
```

```lua
-- SetProcessReceipt.luau

```lua title="SetProcessReceipt.luau"
local MarketplaceService = game:GetService("MarketplaceService")
local Players = game:GetService("Players")

Expand Down Expand Up @@ -114,9 +108,7 @@ end
return setProcessReceipt
```

```lua
-- Main.luau

```lua title="Main.luau"
local Players = game:GetService("Players")

local DataKeep = require(path_to_datakeep)
Expand All @@ -127,14 +119,10 @@ local keyPrefix = "Player_"

local loadedKeeps = {}

local keepStore = DataKeep.GetStore("PlayerData", DataTemplate, {}):expect()
local store = DataKeep.GetStore("PlayerData", DataTemplate, {}):expect()

local function onPlayerAdded(player: Player)
keepStore:LoadKeep(keyPrefix .. player.UserId):andThen(function(keep)
if keep == nil then
player:Kick("Session lock interrupted!")
end

store:LoadKeep(keyPrefix .. player.UserId):andThen(function(keep)
keep:Reconcile()
keep:AddUserId(player.UserId) -- help with GDPR requests

Expand All @@ -157,12 +145,14 @@ local function onPlayerAdded(player: Player)
loadedKeeps[player] = keep

print(`Loaded {player.Name}'s Keep!`)
end):catch(function()
player:Kick("Data failed to load")
end)
end

-- SetProcessReceipt() must be called before the onPlayerAdded(),
-- otherwise the player's existing receipts won't be processed.
SetProcessReceipt(keepStore, keyPrefix)
SetProcessReceipt(store, keyPrefix)

-- loop through already connected players in case they joined before DataKeep loaded
for _, player in Players:GetPlayers() do
Expand Down
117 changes: 54 additions & 63 deletions docs/Usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,74 +16,69 @@ local Players = game:GetService("Players")
local DataKeep = require(path_to_datakeep)

local dataTemplate = {
Coins = 0,
Coins = 0,
}

local loadedKeeps = {}

local keepStore = DataKeep.GetStore("PlayerData", dataTemplate, {}) -- generally you can just :expect() I just want to showcase Promises to those unfamiliar
local store = DataKeep.GetStore("PlayerData", dataTemplate, {}):expect()

local function onPlayerAdded(player: Player)
keepStore:LoadKeep(`Player_{player.UserId}`):andThen(function(keep)
if keep == nil then
player:Kick("Session lock interrupted!")
end
store:LoadKeep(`Player_{player.UserId}`):andThen(function(keep)
keep:Reconcile()
keep:AddUserId(player.UserId) -- help with GDPR requests

keep:Reconcile()
keep:AddUserId(player.UserId) -- help with GDPR requests
keep.Releasing:Connect(function(state) -- don't have to clean up, it cleans up internally
print(`{player.Name}'s Keep is releasing!`)

keep.Releasing:Connect(function(state) -- don't have to clean up, it cleans up internally
print(`{player.Name}'s Keep is releasing!`)
state:andThen(function()
print(`{player.Name}'s Keep has been released!`)

state:andThen(function()
print(`{player.Name}'s Keep has been released!`)

player:Kick("Session released!")
player:Kick("Session released!")
loadedKeeps[player] = nil
end):catch(function(err)
warn(`{player.Name}'s Keep failed to release!`, err)
end)
end)
end):catch(function(err)
warn(`{player.Name}'s Keep failed to release!`, err)
end)
end)

if not player:IsDescendantOf(Players) then
keep:Release()
return
end
if not player:IsDescendantOf(Players) then
keep:Release()
return
end

loadedKeeps[player] = keep
loadedKeeps[player] = keep

local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"

local coins = Instance.new("NumberValue")
coins.Name = "Coins"
coins.Value = keep.Data.Coins
local coins = Instance.new("NumberValue")
coins.Name = "Coins"
coins.Value = keep.Data.Coins
coins.Parent = leaderstats

leaderstats.Parent = player
leaderstats.Parent = player

print(`Loaded {player.Name}'s Keep!`)
end)
print(`Loaded {player.Name}'s Keep!`)
end):catch(function()
player:Kick("Data failed to load")
end)
end

keepStore:andThen(function(store)
keepStore = store
-- loop through already connected players in case they joined before DataKeep loaded
for _, player in Players:GetPlayers() do
task.spawn(onPlayerAdded, player)
end

-- loop through already connected players in case they joined before DataKeep loaded
for _, player in Players:GetPlayers() do
task.spawn(onPlayerAdded, player)
end

Players.PlayerAdded:Connect(onPlayerAdded)
end)
Players.PlayerAdded:Connect(onPlayerAdded)

Players.PlayerRemoving:Connect(function(player)
local keep = loadedKeeps[player]
local keep = loadedKeeps[player]

if not keep then
if not keep then
return
end

keep:Release()
keep:Release()
end)
```

Expand All @@ -110,7 +105,7 @@ Player.__index = Player

--> Variables

local keepStore = DataKeep.GetStore("PlayerData", DataTemplate, {}):expect()
local store = DataKeep.GetStore("PlayerData", DataTemplate, {}):expect()

--> Private Functions

Expand Down Expand Up @@ -164,36 +159,32 @@ end
local function loadKeep(playerClass)
local player = playerClass.Player

local keep = keepStore:LoadKeep(`Player_{player.UserId}`)
local keepPromise = store:LoadKeep(`Player_{player.UserId}`)

keep:andThen(function(dataKeep)
if dataKeep == nil then
player:Kick("Session lock interrupted!")
end
keepPromise:andThen(function(keep)
keep:Reconcile()
keep:AddUserId(player.UserId) -- help with GDPR requests

dataKeep:Reconcile()
dataKeep:AddUserId(player.UserId) -- help with GDPR requests

dataKeep.Releasing:Connect(function(releaseState) -- don't have to clean up, it cleans up internally
releaseState
:andThen(function()
player:Kick("Session released!")
playerClass:Destroy()
end)
:catch(function(err)
warn(err)
end)
keep.Releasing:Connect(function(state) -- don't have to clean up, it cleans up internally
state:andThen(function()
player:Kick("Session released!")
playerClass:Destroy()
end):catch(function(err)
warn(err)
end)
end)

if not player:IsDescendantOf(Players) then
playerClass:Destroy()
return
end

initKeep(playerClass, dataKeep)
initKeep(playerClass, keep)
end):catch(function()
player:Kick("Data failed to load")
end)

return keep -- so they can attach to the promise
return keepPromise -- so they can attach to the promise
end

--> Constructor
Expand Down
Loading

0 comments on commit 4e7f52d

Please sign in to comment.