diff --git a/.gitignore b/.gitignore index 89b59ab..b3bbbd9 100644 --- a/.gitignore +++ b/.gitignore @@ -1,9 +1,9 @@ /.vscode /.pesde /build -/DevPackages -/pkgs/**/wally.lock +/packages/**/wally.lock /sourcemap.json +node_modules *.tsbuildinfo *.rbxm .DS_Store diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..e1cba9d --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "test/suite"] + path = test/suite + url = https://gist.github.com/littensy/fa9afcc5d66d25e86538634982be4ee4 diff --git a/.luaurc b/.luaurc index a3678db..5930d72 100644 --- a/.luaurc +++ b/.luaurc @@ -5,6 +5,6 @@ }, "aliases": { "test": "test", - "pkgs": "pkgs" + "packages": "packages" } } diff --git a/.npmrc b/.npmrc new file mode 100644 index 0000000..b644580 --- /dev/null +++ b/.npmrc @@ -0,0 +1 @@ +public-hoist-pattern[]=*@rbxts* diff --git a/benches/mapped.luau b/benches/mapped.luau index 8e72c8f..9fe3ae1 100644 --- a/benches/mapped.luau +++ b/benches/mapped.luau @@ -1,4 +1,4 @@ -local Charm = require("@pkgs/charm/src/lib") +local Charm = require("@packages/charm/src") local bench = require("./bench") local atom = Charm.atom diff --git a/benches/propagate.luau b/benches/propagate.luau index 27b1aed..c31cf52 100644 --- a/benches/propagate.luau +++ b/benches/propagate.luau @@ -1,4 +1,4 @@ -local Charm = require("@pkgs/charm/src/lib") +local Charm = require("@packages/charm/src") local bench = require("./bench") local signals = Charm.signals diff --git a/bin/build.sh b/bin/build.sh index c228f96..be6fdf7 100644 --- a/bin/build.sh +++ b/bin/build.sh @@ -1,5 +1,5 @@ mkdir build -rojo build pkgs/charm -o build/charm.rbxm -rojo build pkgs/charm-sync -o build/charm-sync.rbxm -rojo build pkgs/react-charm -o build/react-charm.rbxm -rojo build pkgs/vide-charm -o build/vide-charm.rbxm +rojo build packages/charm -o build/charm.rbxm +rojo build packages/charm-sync -o build/charm-sync.rbxm +rojo build packages/react-charm -o build/react-charm.rbxm +rojo build packages/vide-charm -o build/vide-charm.rbxm diff --git a/bin/check.sh b/bin/check.sh index f3cccd4..25cd88d 100644 --- a/bin/check.sh +++ b/bin/check.sh @@ -6,11 +6,11 @@ luau-lsp analyze \ --defs=bin/roblox.d.luau \ --flag:LuauFixIndexerSubtypingOrdering=true \ --sourcemap=sourcemap.json \ - --ignore="**/_Index/**" \ - pkgs test + --ignore="**/node_modules/**" \ + packages test -selene pkgs test +selene packages test -stylua --check pkgs test +stylua --check packages test rm bin/roblox.d.luau diff --git a/default.project.json b/default.project.json index 1348524..f40f123 100644 --- a/default.project.json +++ b/default.project.json @@ -5,21 +5,22 @@ "ReplicatedStorage": { "$className": "ReplicatedStorage", "Packages": { - "$path": "DevPackages", - "Charm": { "$path": "pkgs/charm" }, - "CharmSync": { "$path": "pkgs/charm-sync" }, - "ReactCharm": { "$path": "pkgs/react-charm" }, - "VideCharm": { "$path": "pkgs/vide-charm" } + "$path": "node_modules/@rbxts-js", + "Vide": { "$path": "node_modules/@rbxts/vide/src" }, + "Charm": { "$path": "packages/charm" }, + "CharmSync": { "$path": "packages/charm-sync" }, + "ReactCharm": { "$path": "packages/react-charm" }, + "VideCharm": { "$path": "packages/vide-charm" } } }, "ServerScriptService": { "$className": "ServerScriptService", "Tests": { "$path": "test", - "Charm": { "$path": "pkgs/charm/tests" }, - "CharmSync": { "$path": "pkgs/charm-sync/tests" }, - "ReactCharm": { "$path": "pkgs/react-charm/tests" }, - "VideCharm": { "$path": "pkgs/vide-charm/tests" } + "Charm": { "$path": "packages/charm/tests" }, + "CharmSync": { "$path": "packages/charm-sync/tests" }, + "ReactCharm": { "$path": "packages/react-charm/tests" }, + "VideCharm": { "$path": "packages/vide-charm/tests" } }, "Benchmarks": { "$path": "benches" diff --git a/package.json b/package.json new file mode 100644 index 0000000..4d14e9f --- /dev/null +++ b/package.json @@ -0,0 +1,14 @@ +{ + "private": true, + "scripts": { + "test": "lute test/init.luau", + "build": "sh bin/build.sh", + "typecheck": "sh bin/check.sh" + }, + "packageManager": "pnpm@10.11.0", + "devDependencies": { + "@rbxts-js/react": "17.1.20-ts.1", + "@rbxts-js/react-roblox": "17.1.20-ts.1", + "@rbxts/vide": "^0.5.7" + } +} diff --git a/pkgs/charm-sync/default.project.json b/packages/charm-sync/default.project.json similarity index 100% rename from pkgs/charm-sync/default.project.json rename to packages/charm-sync/default.project.json diff --git a/pkgs/charm-sync/src/client.luau b/packages/charm-sync/src/client.luau similarity index 100% rename from pkgs/charm-sync/src/client.luau rename to packages/charm-sync/src/client.luau diff --git a/pkgs/charm-sync/src/flatten.luau b/packages/charm-sync/src/flatten.luau similarity index 100% rename from pkgs/charm-sync/src/flatten.luau rename to packages/charm-sync/src/flatten.luau diff --git a/pkgs/charm-sync/src/init.luau b/packages/charm-sync/src/init.luau similarity index 100% rename from pkgs/charm-sync/src/init.luau rename to packages/charm-sync/src/init.luau diff --git a/pkgs/charm-sync/src/interval.luau b/packages/charm-sync/src/interval.luau similarity index 100% rename from pkgs/charm-sync/src/interval.luau rename to packages/charm-sync/src/interval.luau diff --git a/pkgs/charm-sync/src/patch.luau b/packages/charm-sync/src/patch.luau similarity index 100% rename from pkgs/charm-sync/src/patch.luau rename to packages/charm-sync/src/patch.luau diff --git a/pkgs/charm-sync/src/server.luau b/packages/charm-sync/src/server.luau similarity index 100% rename from pkgs/charm-sync/src/server.luau rename to packages/charm-sync/src/server.luau diff --git a/pkgs/charm-sync/src/types.luau b/packages/charm-sync/src/types.luau similarity index 100% rename from pkgs/charm-sync/src/types.luau rename to packages/charm-sync/src/types.luau diff --git a/pkgs/charm-sync/src/validate.luau b/packages/charm-sync/src/validate.luau similarity index 100% rename from pkgs/charm-sync/src/validate.luau rename to packages/charm-sync/src/validate.luau diff --git a/pkgs/charm-sync/tests/client.spec.luau b/packages/charm-sync/tests/client.spec.luau similarity index 100% rename from pkgs/charm-sync/tests/client.spec.luau rename to packages/charm-sync/tests/client.spec.luau diff --git a/pkgs/charm-sync/tests/flatten.spec.luau b/packages/charm-sync/tests/flatten.spec.luau similarity index 100% rename from pkgs/charm-sync/tests/flatten.spec.luau rename to packages/charm-sync/tests/flatten.spec.luau diff --git a/pkgs/charm-sync/tests/patch.spec.luau b/packages/charm-sync/tests/patch.spec.luau similarity index 100% rename from pkgs/charm-sync/tests/patch.spec.luau rename to packages/charm-sync/tests/patch.spec.luau diff --git a/pkgs/charm-sync/tests/server.spec.luau b/packages/charm-sync/tests/server.spec.luau similarity index 100% rename from pkgs/charm-sync/tests/server.spec.luau rename to packages/charm-sync/tests/server.spec.luau diff --git a/pkgs/charm-sync/tests/spec.luau b/packages/charm-sync/tests/spec.luau similarity index 100% rename from pkgs/charm-sync/tests/spec.luau rename to packages/charm-sync/tests/spec.luau diff --git a/pkgs/charm-sync/tests/validate.spec.luau b/packages/charm-sync/tests/validate.spec.luau similarity index 100% rename from pkgs/charm-sync/tests/validate.spec.luau rename to packages/charm-sync/tests/validate.spec.luau diff --git a/pkgs/charm-sync/wally.toml b/packages/charm-sync/wally.toml similarity index 100% rename from pkgs/charm-sync/wally.toml rename to packages/charm-sync/wally.toml diff --git a/pkgs/charm/default.project.json b/packages/charm/default.project.json similarity index 100% rename from pkgs/charm/default.project.json rename to packages/charm/default.project.json diff --git a/pkgs/charm/src/atom.luau b/packages/charm/src/atom.luau similarity index 100% rename from pkgs/charm/src/atom.luau rename to packages/charm/src/atom.luau diff --git a/pkgs/charm/src/batched.luau b/packages/charm/src/batched.luau similarity index 96% rename from pkgs/charm/src/batched.luau rename to packages/charm/src/batched.luau index 4c23803..31be1dc 100644 --- a/pkgs/charm/src/batched.luau +++ b/packages/charm/src/batched.luau @@ -7,7 +7,7 @@ local endBatch = signals.endBatch local function handleBatched(ok: boolean, ...) endBatch() - if not ok then + if ok then return ... else error(...) diff --git a/pkgs/charm/src/effect.luau b/packages/charm/src/effect.luau similarity index 100% rename from pkgs/charm/src/effect.luau rename to packages/charm/src/effect.luau diff --git a/pkgs/charm/src/effectScope.luau b/packages/charm/src/effectScope.luau similarity index 100% rename from pkgs/charm/src/effectScope.luau rename to packages/charm/src/effectScope.luau diff --git a/pkgs/charm/src/lib.luau b/packages/charm/src/init.luau similarity index 55% rename from pkgs/charm/src/lib.luau rename to packages/charm/src/init.luau index 89bb935..0f049ab 100644 --- a/pkgs/charm/src/lib.luau +++ b/packages/charm/src/init.luau @@ -1,14 +1,14 @@ -local atom = require("./atom") -local batched = require("./batched") -local effect = require("./effect") -local listen = require("./listen") -local mapped = require("./mapped") -local observe = require("./observe") -local onCleanup = require("./onCleanup") -local signals = require("./signals") -local subscribe = require("./subscribe") -local types = require("./types") -local untracked = require("./untracked") +local atom = require("@self/atom") +local batched = require("@self/batched") +local effect = require("@self/effect") +local listen = require("@self/listen") +local mapped = require("@self/mapped") +local observe = require("@self/observe") +local onCleanup = require("@self/onCleanup") +local signals = require("@self/signals") +local subscribe = require("@self/subscribe") +local types = require("@self/types") +local untracked = require("@self/untracked") export type Atom = types.Atom export type Getter = types.Getter diff --git a/pkgs/charm/src/listen.luau b/packages/charm/src/listen.luau similarity index 100% rename from pkgs/charm/src/listen.luau rename to packages/charm/src/listen.luau diff --git a/pkgs/charm/src/mapped.luau b/packages/charm/src/mapped.luau similarity index 100% rename from pkgs/charm/src/mapped.luau rename to packages/charm/src/mapped.luau diff --git a/pkgs/charm/src/noYield.luau b/packages/charm/src/noYield.luau similarity index 100% rename from pkgs/charm/src/noYield.luau rename to packages/charm/src/noYield.luau diff --git a/pkgs/charm/src/observe.luau b/packages/charm/src/observe.luau similarity index 100% rename from pkgs/charm/src/observe.luau rename to packages/charm/src/observe.luau diff --git a/pkgs/charm/src/onCleanup.luau b/packages/charm/src/onCleanup.luau similarity index 100% rename from pkgs/charm/src/onCleanup.luau rename to packages/charm/src/onCleanup.luau diff --git a/pkgs/charm/src/signals.luau b/packages/charm/src/signals.luau similarity index 100% rename from pkgs/charm/src/signals.luau rename to packages/charm/src/signals.luau diff --git a/pkgs/charm/src/subscribe.luau b/packages/charm/src/subscribe.luau similarity index 100% rename from pkgs/charm/src/subscribe.luau rename to packages/charm/src/subscribe.luau diff --git a/pkgs/charm/src/system.luau b/packages/charm/src/system.luau similarity index 100% rename from pkgs/charm/src/system.luau rename to packages/charm/src/system.luau diff --git a/pkgs/charm/src/types.luau b/packages/charm/src/types.luau similarity index 100% rename from pkgs/charm/src/types.luau rename to packages/charm/src/types.luau diff --git a/pkgs/charm/src/untracked.luau b/packages/charm/src/untracked.luau similarity index 100% rename from pkgs/charm/src/untracked.luau rename to packages/charm/src/untracked.luau diff --git a/pkgs/charm/tests/listen.spec.luau b/packages/charm/tests/listen.spec.luau similarity index 98% rename from pkgs/charm/tests/listen.spec.luau rename to packages/charm/tests/listen.spec.luau index ad3fbec..1142347 100644 --- a/pkgs/charm/tests/listen.spec.luau +++ b/packages/charm/tests/listen.spec.luau @@ -1,4 +1,4 @@ -local Charm = require("../src/lib") +local Charm = require("../src") local suite = require("@test/suite") local atom = Charm.atom diff --git a/pkgs/charm/tests/mapped.spec.luau b/packages/charm/tests/mapped.spec.luau similarity index 98% rename from pkgs/charm/tests/mapped.spec.luau rename to packages/charm/tests/mapped.spec.luau index 6d623bc..3d0fcf5 100644 --- a/pkgs/charm/tests/mapped.spec.luau +++ b/packages/charm/tests/mapped.spec.luau @@ -1,4 +1,4 @@ -local Charm = require("../src/lib") +local Charm = require("../src") local suite = require("@test/suite") local atom = Charm.atom diff --git a/pkgs/charm/tests/observe.spec.luau b/packages/charm/tests/observe.spec.luau similarity index 97% rename from pkgs/charm/tests/observe.spec.luau rename to packages/charm/tests/observe.spec.luau index ddceca9..84f5e77 100644 --- a/pkgs/charm/tests/observe.spec.luau +++ b/packages/charm/tests/observe.spec.luau @@ -1,4 +1,4 @@ -local Charm = require("../src/lib") +local Charm = require("../src") local suite = require("@test/suite") local atom = Charm.atom diff --git a/pkgs/charm/tests/signals/computed.spec.luau b/packages/charm/tests/signals/computed.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/computed.spec.luau rename to packages/charm/tests/signals/computed.spec.luau diff --git a/pkgs/charm/tests/signals/effect.spec.luau b/packages/charm/tests/signals/effect.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/effect.spec.luau rename to packages/charm/tests/signals/effect.spec.luau diff --git a/pkgs/charm/tests/signals/effectScope.spec.luau b/packages/charm/tests/signals/effectScope.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/effectScope.spec.luau rename to packages/charm/tests/signals/effectScope.spec.luau diff --git a/pkgs/charm/tests/signals/gc.spec.luau b/packages/charm/tests/signals/gc.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/gc.spec.luau rename to packages/charm/tests/signals/gc.spec.luau diff --git a/pkgs/charm/tests/signals/issue_48.spec.luau b/packages/charm/tests/signals/issue_48.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/issue_48.spec.luau rename to packages/charm/tests/signals/issue_48.spec.luau diff --git a/pkgs/charm/tests/signals/spec.luau b/packages/charm/tests/signals/spec.luau similarity index 100% rename from pkgs/charm/tests/signals/spec.luau rename to packages/charm/tests/signals/spec.luau diff --git a/pkgs/charm/tests/signals/topology.spec.luau b/packages/charm/tests/signals/topology.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/topology.spec.luau rename to packages/charm/tests/signals/topology.spec.luau diff --git a/pkgs/charm/tests/signals/untrack.spec.luau b/packages/charm/tests/signals/untrack.spec.luau similarity index 100% rename from pkgs/charm/tests/signals/untrack.spec.luau rename to packages/charm/tests/signals/untrack.spec.luau diff --git a/pkgs/charm/tests/spec.luau b/packages/charm/tests/spec.luau similarity index 100% rename from pkgs/charm/tests/spec.luau rename to packages/charm/tests/spec.luau diff --git a/pkgs/charm/tests/subscribe.spec.luau b/packages/charm/tests/subscribe.spec.luau similarity index 98% rename from pkgs/charm/tests/subscribe.spec.luau rename to packages/charm/tests/subscribe.spec.luau index 7e7ae87..67bebda 100644 --- a/pkgs/charm/tests/subscribe.spec.luau +++ b/packages/charm/tests/subscribe.spec.luau @@ -1,4 +1,4 @@ -local Charm = require("../src/lib") +local Charm = require("../src") local suite = require("@test/suite") type Atom = Charm.Atom diff --git a/pkgs/charm/tests/untracked.spec.luau b/packages/charm/tests/untracked.spec.luau similarity index 97% rename from pkgs/charm/tests/untracked.spec.luau rename to packages/charm/tests/untracked.spec.luau index a4dd1c7..53f7767 100644 --- a/pkgs/charm/tests/untracked.spec.luau +++ b/packages/charm/tests/untracked.spec.luau @@ -1,4 +1,4 @@ -local Charm = require("../src/lib") +local Charm = require("../src") local suite = require("@test/suite") local atom = Charm.atom diff --git a/pkgs/charm/wally.toml b/packages/charm/wally.toml similarity index 100% rename from pkgs/charm/wally.toml rename to packages/charm/wally.toml diff --git a/pkgs/react-charm/default.project.json b/packages/react-charm/default.project.json similarity index 100% rename from pkgs/react-charm/default.project.json rename to packages/react-charm/default.project.json diff --git a/pkgs/react-charm/src/init.luau b/packages/react-charm/src/init.luau similarity index 93% rename from pkgs/react-charm/src/init.luau rename to packages/react-charm/src/init.luau index 9293a5f..8fabbb0 100644 --- a/pkgs/react-charm/src/init.luau +++ b/packages/react-charm/src/init.luau @@ -5,6 +5,7 @@ local effect = Charm.effect local useBinding = React.useBinding local useEffect = React.useEffect local useState = React.useState +local useMemo = React.useMemo --- A hook that subscribes to changes in the given atom or selector. The --- component is re-rendered whenever the state changes. @@ -39,7 +40,8 @@ end --- @param dependencies An array of values that the subscription depends on. --- @return A binding that stores the current state. local function useAtomBinding(selector: () -> State, dependencies: { any }?) - local binding, setBinding = useBinding(selector) + local initialState = useMemo(selector, {}) + local binding, setBinding = useBinding(initialState) useEffect(function() return effect(function() diff --git a/pkgs/react-charm/tests/helpers/renderHook.luau b/packages/react-charm/tests/helpers/renderHook.luau similarity index 100% rename from pkgs/react-charm/tests/helpers/renderHook.luau rename to packages/react-charm/tests/helpers/renderHook.luau diff --git a/pkgs/react-charm/tests/spec.luau b/packages/react-charm/tests/spec.luau similarity index 100% rename from pkgs/react-charm/tests/spec.luau rename to packages/react-charm/tests/spec.luau diff --git a/pkgs/react-charm/tests/useAtom.spec.luau b/packages/react-charm/tests/useAtom.spec.luau similarity index 100% rename from pkgs/react-charm/tests/useAtom.spec.luau rename to packages/react-charm/tests/useAtom.spec.luau diff --git a/pkgs/react-charm/tests/useAtomBinding.spec.luau b/packages/react-charm/tests/useAtomBinding.spec.luau similarity index 100% rename from pkgs/react-charm/tests/useAtomBinding.spec.luau rename to packages/react-charm/tests/useAtomBinding.spec.luau diff --git a/pkgs/react-charm/wally.toml b/packages/react-charm/wally.toml similarity index 100% rename from pkgs/react-charm/wally.toml rename to packages/react-charm/wally.toml diff --git a/pkgs/vide-charm/default.project.json b/packages/vide-charm/default.project.json similarity index 100% rename from pkgs/vide-charm/default.project.json rename to packages/vide-charm/default.project.json diff --git a/pkgs/vide-charm/src/init.luau b/packages/vide-charm/src/init.luau similarity index 100% rename from pkgs/vide-charm/src/init.luau rename to packages/vide-charm/src/init.luau diff --git a/pkgs/vide-charm/tests/spec.luau b/packages/vide-charm/tests/spec.luau similarity index 100% rename from pkgs/vide-charm/tests/spec.luau rename to packages/vide-charm/tests/spec.luau diff --git a/pkgs/vide-charm/tests/useAtom.spec.luau b/packages/vide-charm/tests/useAtom.spec.luau similarity index 100% rename from pkgs/vide-charm/tests/useAtom.spec.luau rename to packages/vide-charm/tests/useAtom.spec.luau diff --git a/pkgs/vide-charm/wally.toml b/packages/vide-charm/wally.toml similarity index 100% rename from pkgs/vide-charm/wally.toml rename to packages/vide-charm/wally.toml diff --git a/pkgs/charm/src/init.luau b/pkgs/charm/src/init.luau deleted file mode 100644 index bc510ce..0000000 --- a/pkgs/charm/src/init.luau +++ /dev/null @@ -1,9 +0,0 @@ -local lib = require(script.lib) - -export type Atom = lib.Atom -export type Getter = lib.Getter -export type Selector = lib.Selector -export type Setter = lib.Setter -export type Update = lib.Update - -return lib diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..b51612c --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,164 @@ +lockfileVersion: '9.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +importers: + + .: + devDependencies: + '@rbxts-js/react': + specifier: 17.1.20-ts.1 + version: 17.1.20-ts.1 + '@rbxts-js/react-roblox': + specifier: 17.1.20-ts.1 + version: 17.1.20-ts.1 + '@rbxts/vide': + specifier: ^0.5.7 + version: 0.5.7 + +packages: + + '@rbxts-js/boolean@1.2.3-ts.1': + resolution: {integrity: sha512-IlYFG9uatXQKXOLR1mdptVeEcxudwBCierO+Vu6VZRRaI+/+JDxUClm+QFZyce/kitwnDTmtNvhqVAUtFvCU0Q==} + + '@rbxts-js/collections@1.2.3-ts.1': + resolution: {integrity: sha512-RYT73QyEdsV+DCQMtyzT2bZ1P12j2b+JSHVdb1x6xrDq/KdVEkk/QAzW+o22vPrLXbHa6/jA5bmVlgVcOOrIjA==} + + '@rbxts-js/console@1.2.3-ts.1': + resolution: {integrity: sha512-qacyJE7bYf4n9448F7mn9e8Y5qljZb7QkSmsmnbQT2HA9Mecvg3gqc9RwCIdVkBV6o1AGVAHbatNQ3a39zPjaw==} + + '@rbxts-js/es7-types@1.2.3-ts.1': + resolution: {integrity: sha512-Z7NitBQp6tyzsr5eKlSX54rmopKXpzGu33lYikjF37llrnGFBpnRcZgCJwHKYciloRmjUtnR/UohUNwbWyG9Zg==} + + '@rbxts-js/instance-of@1.2.3-ts.1': + resolution: {integrity: sha512-3fKvDPvxHuEZALNBP2XdbXfzjEfbgsXAheCm1Jf5kC2r+HgszW+yqg4zY6TjW0pcsJM2JjH+fM52oomSNu3LLQ==} + + '@rbxts-js/luau-polyfill@1.2.3-ts.1': + resolution: {integrity: sha512-2asgvWrOhf311rNgEM/fxMO3+xOVI63Cz1K1PobyZVtDdd87ZJ6RGiZSFl1EAeU77SZc8280toJDVs9YSwxWnA==} + + '@rbxts-js/math@1.2.3-ts.1': + resolution: {integrity: sha512-mF7IMJJyxYE02cRNWJ1wsq4pPaAEXKX+CbGlmI0G3QBgWVHj+Oi02IR6pssyUyE6Y2BKvgvP3dcJuTO51OX25A==} + + '@rbxts-js/number@1.2.3-ts.1': + resolution: {integrity: sha512-tPdt2s7fEBSxImVFBUvuSMtBKIvaZUCtlOjBl58Y0+GKB15VPXFIRW/5biVruXPnv9d4sDE3mh986ZxxN4UQ5w==} + + '@rbxts-js/react-reconciler@17.1.20-ts.1': + resolution: {integrity: sha512-t4vY4nHeM+Scrs+9FbgNsuhK0QR6lg3SNWUhjbzvptNP+IA4+4F8TkHQghR2SSTxQDhegU02BTR7NBpk+AQcUw==} + + '@rbxts-js/react-roblox@17.1.20-ts.1': + resolution: {integrity: sha512-Jv0mq+9txXptgsJ6MDWHgCTwsohaon9HhmllkUe29zkaMwE+di4cHqzF1tgV8VHYGG/LQoitXDddK03CA3L+2g==} + + '@rbxts-js/react@17.1.20-ts.1': + resolution: {integrity: sha512-u/dNRTNj5AaVPuqJLza7FEJ24lyRfJ0CdjflbIS8JiUS1iXiO7yZeHQWwPk6V3oHuAOckv6tA4FN/Eju2rPMrQ==} + + '@rbxts-js/roblox-lua-promise@3.5.0-ts.2': + resolution: {integrity: sha512-H8fxKVJkRnM60yTZ/riO4X43GZD/MViFm+ftCzzAALkAhE4vSaBDNv9E7IUjZZoWi21bG6vZ8mGIiYfavaljvw==} + + '@rbxts-js/safe-flags@17.1.20-ts.1': + resolution: {integrity: sha512-k+16jmCP63LT8sNfhLoytUrp3UB+CGHH7s54BFUAHte+zCANK3wfAKXbpT36NqnUfRqgKDM8grO4lWp6awuacQ==} + + '@rbxts-js/scheduler@17.1.20-ts.1': + resolution: {integrity: sha512-RoXs6bAW3LIB6HL/voMilR2hjcGAtutaVsr0yumu0hUYVFY2FwIkbOVepsdYWDrYhVqsk5zrj8CcVGgUxDldGg==} + + '@rbxts-js/shared@17.1.20-ts.1': + resolution: {integrity: sha512-/3K1BnWV519+any6JMWniIDx1rtq20H6RVgJStSCj4XofrM63kzju0EzRQg1af4lnXCfZNZBusRW8IGQ14xuZQ==} + + '@rbxts-js/string@1.2.3-ts.1': + resolution: {integrity: sha512-Je/WKgZbXF/sAHEsQPuns5n4rWzux327zjr0KRf9Gy62ieUzl2FRZZHjVYce3xdMtHif2JstIf/J3p513TUtRg==} + + '@rbxts-js/symbol-luau@1.0.0-ts.1': + resolution: {integrity: sha512-TQS/ImDCK5KPGvbmyScH5EZS0ELSCDvZEFR3W+ItPlsLl+bDRSI/0uaKtJ7rbwXgdGwBDKM1QXFPjqe+KOphIA==} + + '@rbxts-js/timers@1.2.3-ts.1': + resolution: {integrity: sha512-HKP4ymFX3QLWbR/2Gy4LXwvkhjC9OzbwZ5bNunxu+M8Ocbi1cjRduiZK/y5ogLr9cNIfSoxs6e1DQ3soc8/hwA==} + + '@rbxts/vide@0.5.7': + resolution: {integrity: sha512-Q9R7ybzuHK1phtLicBHgAjQnlJ/dMsXDs2k296PIMLgLqK9aX/f1skOP7F1K/vo7IrSE0jCG3B3XTOtQL1Sb0Q==} + +snapshots: + + '@rbxts-js/boolean@1.2.3-ts.1': + dependencies: + '@rbxts-js/collections': 1.2.3-ts.1 + + '@rbxts-js/collections@1.2.3-ts.1': + dependencies: + '@rbxts-js/es7-types': 1.2.3-ts.1 + '@rbxts-js/instance-of': 1.2.3-ts.1 + + '@rbxts-js/console@1.2.3-ts.1': + dependencies: + '@rbxts-js/collections': 1.2.3-ts.1 + + '@rbxts-js/es7-types@1.2.3-ts.1': {} + + '@rbxts-js/instance-of@1.2.3-ts.1': {} + + '@rbxts-js/luau-polyfill@1.2.3-ts.1': + dependencies: + '@rbxts-js/boolean': 1.2.3-ts.1 + '@rbxts-js/collections': 1.2.3-ts.1 + '@rbxts-js/console': 1.2.3-ts.1 + '@rbxts-js/es7-types': 1.2.3-ts.1 + '@rbxts-js/instance-of': 1.2.3-ts.1 + '@rbxts-js/math': 1.2.3-ts.1 + '@rbxts-js/number': 1.2.3-ts.1 + '@rbxts-js/string': 1.2.3-ts.1 + '@rbxts-js/symbol-luau': 1.0.0-ts.1 + '@rbxts-js/timers': 1.2.3-ts.1 + + '@rbxts-js/math@1.2.3-ts.1': {} + + '@rbxts-js/number@1.2.3-ts.1': {} + + '@rbxts-js/react-reconciler@17.1.20-ts.1': + dependencies: + '@rbxts-js/luau-polyfill': 1.2.3-ts.1 + '@rbxts-js/react': 17.1.20-ts.1 + '@rbxts-js/roblox-lua-promise': 3.5.0-ts.2 + '@rbxts-js/safe-flags': 17.1.20-ts.1 + '@rbxts-js/scheduler': 17.1.20-ts.1 + '@rbxts-js/shared': 17.1.20-ts.1 + + '@rbxts-js/react-roblox@17.1.20-ts.1': + dependencies: + '@rbxts-js/luau-polyfill': 1.2.3-ts.1 + '@rbxts-js/react': 17.1.20-ts.1 + '@rbxts-js/react-reconciler': 17.1.20-ts.1 + '@rbxts-js/scheduler': 17.1.20-ts.1 + '@rbxts-js/shared': 17.1.20-ts.1 + + '@rbxts-js/react@17.1.20-ts.1': + dependencies: + '@rbxts-js/luau-polyfill': 1.2.3-ts.1 + '@rbxts-js/shared': 17.1.20-ts.1 + + '@rbxts-js/roblox-lua-promise@3.5.0-ts.2': {} + + '@rbxts-js/safe-flags@17.1.20-ts.1': {} + + '@rbxts-js/scheduler@17.1.20-ts.1': + dependencies: + '@rbxts-js/luau-polyfill': 1.2.3-ts.1 + '@rbxts-js/safe-flags': 17.1.20-ts.1 + '@rbxts-js/shared': 17.1.20-ts.1 + + '@rbxts-js/shared@17.1.20-ts.1': + dependencies: + '@rbxts-js/luau-polyfill': 1.2.3-ts.1 + '@rbxts-js/safe-flags': 17.1.20-ts.1 + + '@rbxts-js/string@1.2.3-ts.1': + dependencies: + '@rbxts-js/es7-types': 1.2.3-ts.1 + '@rbxts-js/number': 1.2.3-ts.1 + + '@rbxts-js/symbol-luau@1.0.0-ts.1': {} + + '@rbxts-js/timers@1.2.3-ts.1': + dependencies: + '@rbxts-js/collections': 1.2.3-ts.1 + + '@rbxts/vide@0.5.7': {} diff --git a/rokit.toml b/rokit.toml index 7394a8b..93fcd9a 100644 --- a/rokit.toml +++ b/rokit.toml @@ -8,5 +8,5 @@ wally = "UpliftGames/wally@0.3.2" rojo = "rojo-rbx/rojo@7.5.1" stylua = "johnnymorganz/stylua@2.1.0" selene = "Kampfkarren/selene@0.28.0" -luau-lsp = "johnnymorganz/luau-lsp@1.44.1" -lute = "luau-lang/lute@0.1.0-nightly.20250511" +luau-lsp = "johnnymorganz/luau-lsp@1.47.0" +lute = "luau-lang/lute@0.1.0-nightly.20250518" diff --git a/test/init.luau b/test/init.luau index 467958e..07889bd 100644 --- a/test/init.luau +++ b/test/init.luau @@ -4,9 +4,6 @@ if not table.isfrozen(_G) then _G.__DEV__ = true end -require("@pkgs/charm/tests/spec") +require("@packages/charm/tests/spec") -suite.finish({ - colors = true, - verbose = false, -}) +suite.finish() diff --git a/test/suite b/test/suite new file mode 160000 index 0000000..2692eb0 --- /dev/null +++ b/test/suite @@ -0,0 +1 @@ +Subproject commit 2692eb055839cd56d0075ca72482658a5bdaddb9 diff --git a/test/suite.luau b/test/suite.luau deleted file mode 100644 index 516db20..0000000 --- a/test/suite.luau +++ /dev/null @@ -1,438 +0,0 @@ -type Config = { - colors: boolean?, - verbose: boolean?, -} - -type Description = { - status: number, - name: string, - only: boolean, - skip: boolean, - parent: Description?, - children: { Description | Test }, - passes: number, - fails: number, - skips: number, - runtime: number, -} - -type Test = { - status: number, - name: string, - only: boolean, - skip: boolean, - parent: Description?, - children: nil, - run: () -> (), - result: unknown?, - line: number?, - runtime: number, -} - -local options = { - colors = true, - verbose = false, -} - -local color = { - white = function(text: string) - return if options.colors then `\27[37;1m{text}\27[0m` else text - end, - gray = function(text: string) - return if options.colors then `\27[90;1m{text}\27[0m` else text - end, - green = function(text: string) - return if options.colors then `\27[32;1m{text}\27[0m` else `\u{1F7E2} {text}` - end, - red = function(text: string) - return if options.colors then `\27[31;1m{text}\27[0m` else `\u{1F534} {text}` - end, - blue = function(text: string) - return if options.colors then `\27[34;1m{text}\27[0m` else `\u{1F535} {text}` - end, -} - -local PENDING = 0 -local PASS = 1 -local FAIL = 2 -local SKIP = 3 -local ERROR = 4 - -local tests: { Test } = {} -local descriptions: { Description } = {} -local root: Description = { - status = PENDING, - name = "root", - only = false, - skip = false, - children = {}, - passes = 0, - fails = 0, - skips = 0, - runtime = 0, -} -local parent: Description = root - -local function describe(name: string, run: () -> ()): Description - local this: Description = { - status = PENDING, - name = name, - only = false, - skip = false, - parent = parent, - children = {}, - passes = 0, - fails = 0, - skips = 0, - runtime = 0, - } - - local prevDescription = parent - parent = this - run() - parent = prevDescription - - table.insert(parent.children, this) - table.insert(descriptions, this) - - return this -end - -local function test(name: string, run: () -> ()): Test - local this: Test = { - status = PENDING, - name = name, - only = false, - skip = false, - parent = parent, - run = run, - runtime = 0, - } - - table.insert(parent.children, this) - table.insert(tests, this) - - return this -end - -local function skip() - parent.skip = true -end - -local function only() - parent.only = true - root.only = true -end - -local function testSkip(name: string, run: () -> ()): Test - local this = test(name, run) - this.skip = true - return this -end - -local function testOnly(name: string, run: () -> ()): Test - local this = test(name, run) - this.only = true - root.only = true - return this -end - -local function describeSkip(name: string, run: () -> ()): Description - local this = describe(name, run) - this.skip = true - return this -end - -local function describeOnly(name: string, run: () -> ()): Description - local this = describe(name, run) - this.only = true - root.only = true - return this -end - -local function isOnly(test: Test): boolean - if not root.only or test.only then - return true - end - - local description = test.parent - while description and description ~= root do - if description.only then - return true - elseif description.skip then - return false - end - description = description.parent - end - - return false -end - -local function isSkip(test: Test): boolean - if test.only then - return false - elseif test.skip then - return true - end - - local description = test.parent - while description do - if description.only and description ~= root then - return false - elseif description.skip then - return true - end - description = description.parent - end - - return false -end - -local function runTests() - for _, test in tests do - if isSkip(test) or not isOnly(test) then - test.status = SKIP - continue - end - - local start = os.clock() - local success = xpcall(test.run, function(result) - test.status = FAIL - test.result = result - test.line = debug.info(3, "l") - end) - - test.runtime = os.clock() - start - - if success then - test.status = PASS - end - end -end - -local function updateDescription(description: Description) - if not description.children[1] then - description.status = PASS - return - end - - description.status = SKIP - - for _, child in description.children do - if child.children then - updateDescription(child) - description.passes += child.passes - description.fails += child.fails - elseif child.status == PASS then - description.passes += 1 - elseif child.status == FAIL then - description.fails += 1 - end - - -- Only count skips in direct children - if child.status == SKIP then - description.skips += 1 - end - - description.runtime += child.runtime - - if child.status == FAIL then - description.status = FAIL - elseif description.status == SKIP and child.status == PASS then - description.status = PASS - end - end -end - -local function getIndent(node: Description | Test): string - local depth = 0 - local description = node.parent - while description and description ~= root do - depth += 1 - description = description.parent - end - return if depth > 0 then string.rep(" ", depth - 1) .. color.gray("· ") else "" -end - -local function getPath(node: Description | Test): string - local path = { "" } - local description = node.parent - while description and description ~= root do - table.insert(path, 1, description.name) - description = description.parent - end - return table.concat(path, " > ") -end - -local function greenOrRed(text: string, good: boolean): string - return if good then color.green(text) else color.red(text) -end - -local function colorStatus(status: number): string - local wall = color.gray("│") - - if status == PASS then - return color.green("PASS") .. wall - elseif status == FAIL then - return color.red("FAIL") .. wall - elseif status == SKIP then - return color.blue("SKIP") .. wall - else - return color.red("ERROR") .. wall - end -end - -local function report() - local output = {} - - local function reportDescription(description: Description) - local name = color.white(description.name) - local text = `{colorStatus(description.status)} {getIndent(description)}{name}` - - if description.fails > 0 then - text ..= " " .. color.red(`({description.fails})`) - end - - if description.skips > 0 then - text ..= " " .. color.blue(`({description.skips} skipped)`) - elseif description.fails == 0 then - text ..= " " .. color.gray(string.format("%.2fms", description.runtime * 1000)) - end - - table.insert(output, text) - end - - local function reportTest(test: Test, reportError: boolean?) - if test.status ~= FAIL and not options.verbose then - return - end - - local line = color.red(`{test.line}:`) - - if reportError then - local name = color.white(test.name) - local path = color.gray(getPath(test)) - - table.insert(output, `{colorStatus(ERROR)} {path}{line}{name}`) - table.insert(output, `{test.result}`) - else - local name = color.gray(test.name) - local indent = getIndent(test) - - if test.status == FAIL then - table.insert(output, `{colorStatus(FAIL)} {indent}{line}{name}`) - else - table.insert(output, `{colorStatus(test.status)} {indent}{name}`) - end - end - end - - local function reportNode(node: Description | Test) - if not node.children then - return reportTest(node :: Test) - end - - reportDescription(node) - - for _, child in node.children do - reportNode(child) - end - end - - local function reportSummary() - local describePasses = 0 - local describeFails = 0 - - for _, description in descriptions do - if description.status == PASS then - describePasses += 1 - elseif description.status == FAIL then - describeFails += 1 - end - end - - local describes = - `{greenOrRed(`{describePasses} passed`, describeFails == 0)} {color.gray(`({#descriptions})`)}` - local tests = `{greenOrRed(`{root.passes} passed`, root.fails == 0)} {color.gray(`({#tests})`)}` - local duration = `{color.blue(`{string.format("%.2fms", root.runtime * 1000)}`)}` - - table.insert(output, "") - table.insert(output, `Describe {describes}`) - table.insert(output, ` Tests {tests}`) - table.insert(output, `Duration {duration}`) - table.insert(output, "") - end - - local function reportErrors() - if root.fails == 0 then - return - end - - for _, test in tests do - if test.status == FAIL then - reportTest(test, true) - table.insert(output, "") - end - end - end - - table.insert(output, "") - table.insert(output, color.blue("Test Results")) - table.insert(output, "") - - for _, child in root.children do - reportNode(child) - end - - reportSummary() - reportErrors() - - print(table.concat(output, "\n")) - - if root.fails > 0 then - error(color.red(`{root.fails} test(s) failed`)) - end -end - -local function finish(config: Config?) - if config then - options.colors = if config.colors ~= nil then config.colors else options.colors - options.verbose = if config.verbose ~= nil then config.verbose else options.verbose - end - - runTests() - updateDescription(root) - report() -end - -local testCtor = setmetatable({ - skip = testSkip, - only = testOnly, -}, { - __call = function(_, ...) - return test(...) - end, -}) - -local describeCtor = setmetatable({ - skip = describeSkip, - only = describeOnly, -}, { - __call = function(_, ...) - return describe(...) - end, -}) - -return { - test = testCtor :: ((name: string, callback: () -> ()) -> ()) & { - skip: (name: string, callback: () -> ()) -> (), - only: (name: string, callback: () -> ()) -> (), - }, - describe = describeCtor :: ((name: string, callback: () -> ()) -> ()) & { - skip: (name: string, callback: () -> ()) -> (), - only: (name: string, callback: () -> ()) -> (), - }, - skip = skip, - only = only, - finish = finish, -} diff --git a/wally.lock b/wally.lock deleted file mode 100644 index f568be9..0000000 --- a/wally.lock +++ /dev/null @@ -1,98 +0,0 @@ -# This file is automatically @generated by Wally. -# It is not intended for manual editing. -registry = "test" - -[[package]] -name = "centau/vide" -version = "0.3.1" -dependencies = [] - -[[package]] -name = "jsdotlua/boolean" -version = "1.2.7" -dependencies = [["number", "jsdotlua/number@1.2.7"]] - -[[package]] -name = "jsdotlua/collections" -version = "1.2.7" -dependencies = [["es7-types", "jsdotlua/es7-types@1.2.7"], ["instance-of", "jsdotlua/instance-of@1.2.7"]] - -[[package]] -name = "jsdotlua/console" -version = "1.2.7" -dependencies = [["collections", "jsdotlua/collections@1.2.7"]] - -[[package]] -name = "jsdotlua/es7-types" -version = "1.2.7" -dependencies = [] - -[[package]] -name = "jsdotlua/instance-of" -version = "1.2.7" -dependencies = [] - -[[package]] -name = "jsdotlua/luau-polyfill" -version = "1.2.7" -dependencies = [["boolean", "jsdotlua/boolean@1.2.7"], ["collections", "jsdotlua/collections@1.2.7"], ["console", "jsdotlua/console@1.2.7"], ["es7-types", "jsdotlua/es7-types@1.2.7"], ["instance-of", "jsdotlua/instance-of@1.2.7"], ["math", "jsdotlua/math@1.2.7"], ["number", "jsdotlua/number@1.2.7"], ["string", "jsdotlua/string@1.2.7"], ["symbol-luau", "jsdotlua/symbol-luau@1.0.1"], ["timers", "jsdotlua/timers@1.2.7"]] - -[[package]] -name = "jsdotlua/math" -version = "1.2.7" -dependencies = [] - -[[package]] -name = "jsdotlua/number" -version = "1.2.7" -dependencies = [] - -[[package]] -name = "jsdotlua/promise" -version = "3.5.2" -dependencies = [] - -[[package]] -name = "jsdotlua/react" -version = "17.2.1" -dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["shared", "jsdotlua/shared@17.2.1"]] - -[[package]] -name = "jsdotlua/react-reconciler" -version = "17.2.1" -dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["promise", "jsdotlua/promise@3.5.2"], ["react", "jsdotlua/react@17.2.1"], ["scheduler", "jsdotlua/scheduler@17.2.1"], ["shared", "jsdotlua/shared@17.2.1"]] - -[[package]] -name = "jsdotlua/react-roblox" -version = "17.2.1" -dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["react", "jsdotlua/react@17.2.1"], ["react-reconciler", "jsdotlua/react-reconciler@17.2.1"], ["scheduler", "jsdotlua/scheduler@17.2.1"], ["shared", "jsdotlua/shared@17.2.1"]] - -[[package]] -name = "jsdotlua/scheduler" -version = "17.2.1" -dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"], ["shared", "jsdotlua/shared@17.2.1"]] - -[[package]] -name = "jsdotlua/shared" -version = "17.2.1" -dependencies = [["luau-polyfill", "jsdotlua/luau-polyfill@1.2.7"]] - -[[package]] -name = "jsdotlua/string" -version = "1.2.7" -dependencies = [["es7-types", "jsdotlua/es7-types@1.2.7"], ["number", "jsdotlua/number@1.2.7"]] - -[[package]] -name = "jsdotlua/symbol-luau" -version = "1.0.1" -dependencies = [] - -[[package]] -name = "jsdotlua/timers" -version = "1.2.7" -dependencies = [["collections", "jsdotlua/collections@1.2.7"]] - -[[package]] -name = "richerd/charm" -version = "0.1.0" -dependencies = [["React", "jsdotlua/react@17.2.1"], ["ReactRoblox", "jsdotlua/react-roblox@17.2.1"], ["Vide", "centau/vide@0.3.1"]] diff --git a/wally.toml b/wally.toml deleted file mode 100644 index 2c4ec2b..0000000 --- a/wally.toml +++ /dev/null @@ -1,10 +0,0 @@ -[package] -name = "richerd/charm" -version = "0.1.0" -registry = "https://github.com/UpliftGames/wally-index" -realm = "shared" - -[dev-dependencies] -React = "jsdotlua/react@17" -ReactRoblox = "jsdotlua/react-roblox@17" -Vide = "centau/vide@0.3"