mirror of
https://github.com/littensy/charm.git
synced 2026-10-22 12:41:37 +00:00
chore: bump deps
This commit is contained in:
parent
28872264a2
commit
41d59cdfad
4 changed files with 58 additions and 94 deletions
|
|
@ -1,51 +1,7 @@
|
||||||
local fs = require("@std/fs")
|
local fs = require("@std/fs")
|
||||||
local json = require("@std/json")
|
|
||||||
local net = require("@lute/net")
|
local net = require("@lute/net")
|
||||||
local process = require("@lute/process")
|
local process = require("@lute/process")
|
||||||
|
|
||||||
local CURRENT_FFLAGS = "https://clientsettingscdn.roblox.com/v1/settings/application?applicationName=PCStudioApp"
|
|
||||||
local FFLAG_KINDS = { "FFlag", "FInt" }
|
|
||||||
|
|
||||||
local function analyze()
|
|
||||||
local args = {
|
|
||||||
"luau-lsp",
|
|
||||||
"analyze",
|
|
||||||
"--sourcemap=sourcemap.json",
|
|
||||||
"--ignore=**/node_modules/**",
|
|
||||||
"--base-luaurc=.luaurc",
|
|
||||||
"--definitions=roblox.d.luau",
|
|
||||||
"--no-flags-enabled",
|
|
||||||
}
|
|
||||||
|
|
||||||
local response = net.request(CURRENT_FFLAGS, { method = "GET" })
|
|
||||||
local data: any = json.deserialize(response.body)
|
|
||||||
|
|
||||||
for name, value in data.applicationSettings do
|
|
||||||
if type(name) ~= "string" then
|
|
||||||
continue
|
|
||||||
end
|
|
||||||
|
|
||||||
for _, kind in FFLAG_KINDS do
|
|
||||||
if string.find(name, `^{kind}Luau`) then
|
|
||||||
table.insert(args, `--flag:{string.sub(name, #kind + 1)}={value}`)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
table.insert(args, "packages")
|
|
||||||
table.insert(args, "tests")
|
|
||||||
table.insert(args, "benches")
|
|
||||||
|
|
||||||
local result = process.run(args)
|
|
||||||
local stderr = string.gsub(result.stderr, "Unknown FFlag[^\n]+\n", "")
|
|
||||||
|
|
||||||
print(stderr)
|
|
||||||
|
|
||||||
if result.exitcode == 1 then
|
|
||||||
process.exit(1)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
process.run({ "rojo", "sourcemap", "--output=sourcemap.json" }, { stdio = "inherit" })
|
process.run({ "rojo", "sourcemap", "--output=sourcemap.json" }, { stdio = "inherit" })
|
||||||
|
|
||||||
fs.writestringtofile(
|
fs.writestringtofile(
|
||||||
|
|
@ -53,24 +9,26 @@ fs.writestringtofile(
|
||||||
net.request("https://luau-lsp.pages.dev/globalTypes.None.d.luau", { method = "GET" }).body
|
net.request("https://luau-lsp.pages.dev/globalTypes.None.d.luau", { method = "GET" }).body
|
||||||
)
|
)
|
||||||
|
|
||||||
analyze()
|
local analyze = process.run({
|
||||||
|
"luau-lsp",
|
||||||
-- process.run({
|
"analyze",
|
||||||
-- "luau-lsp",
|
"--sourcemap=sourcemap.json",
|
||||||
-- "analyze",
|
"--ignore=**/node_modules/**",
|
||||||
-- "--sourcemap=sourcemap.json",
|
"--base-luaurc=.luaurc",
|
||||||
-- "--ignore=**/node_modules/**",
|
"--definitions=roblox.d.luau",
|
||||||
-- "--base-luaurc=.luaurc",
|
"packages",
|
||||||
-- "--defs=roblox.d.luau",
|
"tests",
|
||||||
-- "packages",
|
"benches",
|
||||||
-- "tests",
|
}, { stdio = "inherit" })
|
||||||
-- "benches",
|
|
||||||
-- }, { stdio = "inherit" })
|
|
||||||
|
|
||||||
fs.remove("roblox.d.luau")
|
fs.remove("roblox.d.luau")
|
||||||
|
|
||||||
process.run({ "selene", "packages", "tests", "benches" }, { stdio = "inherit" })
|
local selene = process.run({ "selene", "packages", "tests", "benches" }, { stdio = "inherit" })
|
||||||
|
|
||||||
process.run({ "stylua", "--check", "packages", "tests", "benches" }, { stdio = "inherit" })
|
local stylua = process.run({ "stylua", "--check", "packages", "tests", "benches" }, { stdio = "inherit" })
|
||||||
|
|
||||||
process.run({ "pnpm", "eslint", "packages" }, { stdio = "inherit" })
|
local eslint = process.run({ "pnpm", "eslint", "packages" }, { stdio = "inherit" })
|
||||||
|
|
||||||
|
if not (analyze.ok and selene.ok and stylua.ok and eslint.ok) then
|
||||||
|
process.exit(1)
|
||||||
|
end
|
||||||
|
|
|
||||||
52
README.md
52
README.md
|
|
@ -233,10 +233,9 @@ Effects are fundamental to reactivity, allowing you to react to signal updates.
|
||||||
```luau
|
```luau
|
||||||
local getCounter, setCounter = signal(0)
|
local getCounter, setCounter = signal(0)
|
||||||
|
|
||||||
-- Count is 0
|
|
||||||
effect(function()
|
effect(function()
|
||||||
print(`Count is {getCounter()}`)
|
print(`Count is {getCounter()}`)
|
||||||
end)
|
end) -- Count is 0
|
||||||
|
|
||||||
setCounter(1) -- Count is 1
|
setCounter(1) -- Count is 1
|
||||||
```
|
```
|
||||||
|
|
@ -257,22 +256,33 @@ setCounter(1) -- Cleanup 0
|
||||||
dispose() -- Cleanup 1
|
dispose() -- Cleanup 1
|
||||||
```
|
```
|
||||||
|
|
||||||
Effects can be nested and they will clean up automatically when the parent effect re-runs or gets disposed. This means you don't have to manually clean up inner effects, and this applies to functions like `subscribe()` and `observe()`.
|
### Nested Effects
|
||||||
|
|
||||||
|
Effects can be nested inside other effects. When the outer effect re-runs, inner effects from the previous run are automatically cleaned up, and new inner effects are created if needed. The system ensures proper execution order; outer effects always run before their inner effects:
|
||||||
|
|
||||||
```luau
|
```luau
|
||||||
local getCounter, setCounter = signal(0)
|
local getShow, setShow = signal(true)
|
||||||
|
local getCount, setCount = signal(1)
|
||||||
|
|
||||||
effect(function()
|
effect(function()
|
||||||
print(`Outer: {getCounter()}`)
|
if getShow() then
|
||||||
effect(function()
|
-- This inner effect is created when show() is true
|
||||||
print(`Inner: {getcounter()}`)
|
effect(function()
|
||||||
end)
|
print(`Count is: {getCount()}`)
|
||||||
end)
|
end)
|
||||||
|
end
|
||||||
|
end) -- Output: Count is: 1
|
||||||
|
|
||||||
setCounter(1) -- Outer: 1, Inner: 1
|
setCount(2) -- Count is: 2
|
||||||
setCounter(2) -- Outer: 2, Inner: 2
|
|
||||||
|
-- When show becomes false, the inner effect is cleaned up
|
||||||
|
setShow(false) -- No output
|
||||||
|
|
||||||
|
setCount(3) -- No output (inner effect no longer exists)
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Nested effect cleanup also applies to every reaction API (`subscribe()`, `listen()`, `observe()`) because they are built upon effects.
|
||||||
|
|
||||||
> [!NOTE]
|
> [!NOTE]
|
||||||
> To run code that is "detached" from the parent effect or scope, use `untracked()` or a detached effect scope. If you suspect that the new nested effect behavior is causing issues with migration, try disabling the `flags.trackInnerEffects` flag to assist with debugging.
|
> To run code that is "detached" from the parent effect or scope, use `untracked()` or a detached effect scope. If you suspect that the new nested effect behavior is causing issues with migration, try disabling the `flags.trackInnerEffects` flag to assist with debugging.
|
||||||
|
|
||||||
|
|
@ -289,17 +299,15 @@ local users, setUsers = reactive({
|
||||||
{ name = "John", surname = "Doe" },
|
{ name = "John", surname = "Doe" },
|
||||||
})
|
})
|
||||||
|
|
||||||
-- Output: John Doe
|
|
||||||
effect(function()
|
effect(function()
|
||||||
print(`{users[1].name} {users[1].surname}`)
|
print(`{users[1].name} {users[1].surname}`)
|
||||||
end)
|
end) -- Output: John Doe
|
||||||
|
|
||||||
-- Output: Jane Smith
|
|
||||||
setUsers(function(state)
|
setUsers(function(state)
|
||||||
state[1].name = "Jane"
|
state[1].name = "Jane"
|
||||||
state[1].surname = "Smith"
|
state[1].surname = "Smith"
|
||||||
table.insert(state, { name = "Steve", surname = "Doe" })
|
table.insert(state, { name = "Steve", surname = "Doe" })
|
||||||
end)
|
end) -- Output: Jane Smith
|
||||||
|
|
||||||
-- You can also mutate the reactive proxy directly:
|
-- You can also mutate the reactive proxy directly:
|
||||||
users[1].name = "John" -- John Smith
|
users[1].name = "John" -- John Smith
|
||||||
|
|
@ -327,10 +335,9 @@ In case you want to opt-out of dependency tracking in an effect, you can use `un
|
||||||
local getTracked, setTracked = signal(0)
|
local getTracked, setTracked = signal(0)
|
||||||
local getUntracked, setUntracked = signal(0)
|
local getUntracked, setUntracked = signal(0)
|
||||||
|
|
||||||
-- Tracked: 0, Untracked: 0
|
|
||||||
effect(function()
|
effect(function()
|
||||||
print(`Tracked: {getTracked()}, Untracked: {untracked(getUntracked)}`)
|
print(`Tracked: {getTracked()}, Untracked: {untracked(getUntracked)}`)
|
||||||
end)
|
end) -- Output: Tracked: 0, Untracked: 0
|
||||||
|
|
||||||
setTracked(1) -- Tracked: 1, Untracked: 0
|
setTracked(1) -- Tracked: 1, Untracked: 0
|
||||||
setUntracked(1) -- No output
|
setUntracked(1) -- No output
|
||||||
|
|
@ -364,10 +371,9 @@ Similar to `untracked()`, but does not prevent the parent effect from tracking n
|
||||||
```luau
|
```luau
|
||||||
local getCounter, setCounter = signal(0)
|
local getCounter, setCounter = signal(0)
|
||||||
|
|
||||||
-- Count is 0
|
|
||||||
local disposeOuter = effect(function()
|
local disposeOuter = effect(function()
|
||||||
print(`Count is {peek(getCounter)}`)
|
print(`Count is {peek(getCounter)}`)
|
||||||
end)
|
end) -- Output: Count is 0
|
||||||
|
|
||||||
setCounter(1) -- No output; count was accessed in peek()
|
setCounter(1) -- No output; count was accessed in peek()
|
||||||
```
|
```
|
||||||
|
|
@ -430,7 +436,7 @@ The callback also receives the previous value, or `nil` when running for the fir
|
||||||
```luau
|
```luau
|
||||||
local getCounter, setCounter = signal(0)
|
local getCounter, setCounter = signal(0)
|
||||||
|
|
||||||
-- Count is 0 (was nil)
|
-- Output: Count is 0 (was nil)
|
||||||
listen(getCounter, function(count, prevCount)
|
listen(getCounter, function(count, prevCount)
|
||||||
print(`Count is {count} (was {prevCount})`)
|
print(`Count is {count} (was {prevCount})`)
|
||||||
end)
|
end)
|
||||||
|
|
@ -595,9 +601,7 @@ effect(function()
|
||||||
setCounter(function(count)
|
setCounter(function(count)
|
||||||
return math.min(count + 1, 3)
|
return math.min(count + 1, 3)
|
||||||
end)
|
end)
|
||||||
end)
|
end) -- Output: 0, 1, 2, 3
|
||||||
|
|
||||||
-- Output: 0, 1, 2, 3
|
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
@ -931,7 +935,7 @@ This means nilable values may be replaced with `None` in patches, and code worki
|
||||||
Charm v0.11 introduces _a lot_ of breaking changes, so below are some tips that might help you migrate from an older version.
|
Charm v0.11 introduces _a lot_ of breaking changes, so below are some tips that might help you migrate from an older version.
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary><b>Terminology changes</b></summary>
|
<summary><b>Terminology</b></summary>
|
||||||
|
|
||||||
- Signal: A state container with one function to get the state, and another to update it
|
- Signal: A state container with one function to get the state, and another to update it
|
||||||
- Atom: A signal with the getter and setter combined into one function
|
- Atom: A signal with the getter and setter combined into one function
|
||||||
|
|
|
||||||
|
|
@ -191,7 +191,9 @@ local function runCleanups(cleanups: { () -> () })
|
||||||
for key, cleanup in cleanups do
|
for key, cleanup in cleanups do
|
||||||
cleanups[key] = nil
|
cleanups[key] = nil
|
||||||
local prevSub = setActiveSub(nil)
|
local prevSub = setActiveSub(nil)
|
||||||
xpcall(cleanup, warn or print)
|
xpcall(cleanup, function(err)
|
||||||
|
warn("Error occurred during effect cleanup:", debug.traceback(tostring(err), 2))
|
||||||
|
end)
|
||||||
activeSub = prevSub
|
activeSub = prevSub
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
@ -799,14 +801,14 @@ local function batch<Args..., Results...>(fn: (Args...) -> Results..., ...: Args
|
||||||
end
|
end
|
||||||
|
|
||||||
--[[
|
--[[
|
||||||
Converts a non-signal into a computed signal. If the function is already a
|
Wraps a function in a computed signal if it is not already a reactive
|
||||||
signal, it is returned as-is. Useful for memoizing a getter function
|
signal. Useful for memoizing a getter function without creating unnecessary
|
||||||
without creating unnecessary nested signals.
|
nested signals.
|
||||||
|
|
||||||
@param fn A signal or function that accesses signals
|
@param fn A signal or function that accesses signals
|
||||||
@return Computed signal if `fn` is not already a signal
|
@return `fn` wrapped in a computed signal if needed
|
||||||
]]
|
]]
|
||||||
local function toSignal<T>(fn: () -> T): () -> T
|
local function toComputed<T>(fn: () -> T): () -> T
|
||||||
local name = debug.info(fn, "n")
|
local name = debug.info(fn, "n")
|
||||||
return if name == "readSignal" or name == "readComputed" or name == "atomOper" then fn else computed(fn)
|
return if name == "readSignal" or name == "readComputed" or name == "atomOper" then fn else computed(fn)
|
||||||
end
|
end
|
||||||
|
|
@ -825,7 +827,7 @@ end
|
||||||
@see https://github.com/littensy/charm?tab=readme-ov-file#listengetter-callback
|
@see https://github.com/littensy/charm?tab=readme-ov-file#listengetter-callback
|
||||||
]]
|
]]
|
||||||
local function listen<T>(getter: () -> T, fn: (state: T, previous: T?) -> ()): () -> ()
|
local function listen<T>(getter: () -> T, fn: (state: T, previous: T?) -> ()): () -> ()
|
||||||
local tracked = toSignal(getter)
|
local tracked = toComputed(getter)
|
||||||
local current: T
|
local current: T
|
||||||
|
|
||||||
return effect(function()
|
return effect(function()
|
||||||
|
|
@ -849,7 +851,7 @@ end
|
||||||
@see https://github.com/littensy/charm?tab=readme-ov-file#subscribegetter-callback
|
@see https://github.com/littensy/charm?tab=readme-ov-file#subscribegetter-callback
|
||||||
]]
|
]]
|
||||||
local function subscribe<T>(getter: () -> T, fn: (state: T, lastState: T) -> ()): () -> ()
|
local function subscribe<T>(getter: () -> T, fn: (state: T, lastState: T) -> ()): () -> ()
|
||||||
local tracked = toSignal(getter)
|
local tracked = toComputed(getter)
|
||||||
local current: T
|
local current: T
|
||||||
local firstRun = true
|
local firstRun = true
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,5 +3,5 @@ wally = "UpliftGames/wally@0.3.2"
|
||||||
rojo = "rojo-rbx/rojo@7.6.1"
|
rojo = "rojo-rbx/rojo@7.6.1"
|
||||||
stylua = "johnnymorganz/stylua@2.3.1"
|
stylua = "johnnymorganz/stylua@2.3.1"
|
||||||
selene = "Kampfkarren/selene@0.29.0"
|
selene = "Kampfkarren/selene@0.29.0"
|
||||||
luau-lsp = "johnnymorganz/luau-lsp@1.57.1"
|
luau-lsp = "johnnymorganz/luau-lsp@1.60.0"
|
||||||
lute = "luau-lang/lute@0.1.0-nightly.20251213"
|
lute = "luau-lang/lute@0.1.0-nightly.20260112"
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue