refactor: remove pnpm, fix tests

This commit is contained in:
littensy 2025-05-03 20:30:10 -07:00
parent 861ee5acd7
commit e34b0c9aca
65 changed files with 353 additions and 2458 deletions

View file

@ -1,26 +0,0 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"jsx": true,
"useJSXTextNode": true,
"ecmaVersion": 2018,
"sourceType": "module",
"project": "./tsconfig.json"
},
"plugins": [
"@typescript-eslint",
"roblox-ts",
"prettier"
],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"plugin:roblox-ts/recommended",
"plugin:prettier/recommended"
],
"rules": {
"prettier/prettier": "warn",
"@typescript-eslint/no-explicit-any": "off",
"@typescript-eslint/no-unsafe-declaration-merging": "off"
}
}

1
.gitattributes vendored
View file

@ -1 +0,0 @@
* text=auto eol=lf

View file

@ -7,16 +7,16 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
with:
run_install: true
- uses: CompeyDev/setup-rokit@v0.1.2
- name: Install Wally dependencies
run: pnpm wally
- name: Install dependencies
run: sh bin/install.sh
- name: Check code quality
run: pnpm check
run: sh bin/check.sh
- name: Run tests
run: sh bin/test.sh
- name: Build models
run: pnpm build
run: sh bin/build.sh

View file

@ -9,11 +9,10 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v4
- uses: CompeyDev/setup-rokit@v0.1.2
- name: Build models
run: pnpm build
run: sh bin/build.sh
- name: Upload release assets
uses: AButler/upload-release-assets@v3.0

7
.gitignore vendored
View file

@ -1,14 +1,9 @@
/.vscode
/node_modules
/build
/modules/DevPackages
/packages/**/node_modules
/roblox_packages
/packages/**/wally.lock
/packages/**/README.md
/packages/**/LICENSE.md
/sourcemap.json
*.tsbuildinfo
*.tgz
*.rbxm
.DS_Store
roblox.d.luau

View file

@ -1,6 +0,0 @@
{
"printWidth": 120,
"tabWidth": 4,
"trailingComma": "all",
"useTabs": true
}

View file

@ -1,5 +1,5 @@
mkdir build
rojo build packages/charm -o build/charm.rbxm
rojo build packages/charm-sync -o build/charm-sync.rbxm
rojo build packages/react -o build/react-charm.rbxm
rojo build packages/vide -o build/vide-charm.rbxm
rojo build packages/react-charm -o build/react-charm.rbxm
rojo build packages/vide-charm -o build/vide-charm.rbxm

View file

@ -6,13 +6,11 @@ luau-lsp analyze \
--defs=bin/roblox.d.luau \
--flag:LuauFixIndexerSubtypingOrdering=true \
--sourcemap=sourcemap.json \
--ignore="**/_Index/**" \
--ignore="roblox_packages/**" \
packages tests
selene packages tests
stylua --check packages tests
eslint packages
rm bin/roblox.d.luau

View file

@ -1,4 +1,2 @@
cd modules
wally install
cd ..
pesde install
rojo sourcemap --output sourcemap.json

View file

@ -4,27 +4,17 @@
"$className": "DataModel",
"ReplicatedStorage": {
"$className": "ReplicatedStorage",
"DevPackages": {
"$path": "modules/DevPackages",
"Charm": {
"$path": "packages/charm"
},
"CharmSync": {
"$path": "packages/charm-sync"
},
"ReactCharm": {
"$path": "packages/react"
},
"VideCharm": {
"$path": "packages/vide"
}
"Packages": {
"$path": "roblox_packages",
"Charm": { "$path": "packages/charm" },
"CharmSync": { "$path": "packages/charm-sync" },
"ReactCharm": { "$path": "packages/react-charm" },
"VideCharm": { "$path": "packages/vide-charm" }
}
},
"ServerScriptService": {
"$className": "ServerScriptService",
"Tests": {
"$path": "tests"
}
"Tests": { "$path": "tests" }
}
}
}

View file

@ -1,103 +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 = "littensy/charm"
version = "0.1.0"
dependencies = [["React", "jsdotlua/react@17.2.1"], ["ReactRoblox", "jsdotlua/react-roblox@17.2.1"], ["TestEZ", "roblox/testez@0.4.1"], ["Vide", "centau/vide@0.3.1"]]
[[package]]
name = "roblox/testez"
version = "0.4.1"
dependencies = []

View file

@ -1,10 +0,0 @@
[package]
name = "littensy/charm"
version = "0.1.0"
registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"
[dev-dependencies]
React = "jsdotlua/react@17.2.0"
ReactRoblox = "jsdotlua/react-roblox@17.2.0"
Vide = "centau/vide@0.3.1"

View file

@ -1,24 +0,0 @@
{
"private": true,
"scripts": {
"build": "sh bin/build.sh",
"check": "sh bin/check.sh",
"wally": "sh bin/install.sh",
"publish:npm": "pnpm publish -r --access public",
"publish:wally": "pnpm -r --workspace-concurrency 1 publish:wally"
},
"devDependencies": {
"@rbxts/compiler-types": "3.0.0-types.0",
"@rbxts/types": "^1.0.811",
"@typescript-eslint/eslint-plugin": "^7.18.0",
"@typescript-eslint/parser": "^7.18.0",
"eslint": "^8.57.1",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-prettier": "^5.2.1",
"eslint-plugin-roblox-ts": "^0.0.36",
"prettier": "^3.3.3",
"roblox-ts": "^3.0.0",
"typescript": "~5.5.4"
},
"packageManager": "pnpm@10.10.0"
}

View file

@ -1,16 +0,0 @@
{
"name": "@rbxts/charm-sync",
"version": "0.3.0",
"description": "Sync server state with clients using Charm",
"repository": "littensy/charm",
"license": "MIT",
"main": "src/init.luau",
"types": "src/index.d.ts",
"scripts": {
"prepare": "cp ../../LICENSE.md . && cp ../../README.md .",
"publish:wally": "wally publish"
},
"peerDependencies": {
"@rbxts/charm": "workspace:*"
}
}

View file

@ -1,6 +1,7 @@
local Charm = require(script.Parent.Parent.Charm)
local patch = require(script.Parent.patch)
local types = require(script.Parent.types)
type AtomMap = types.AtomMap
type SyncPayload = types.SyncPayload

View file

@ -1,4 +1,5 @@
local types = require(script.Parent.types)
type AtomMap = types.AtomMap
type NestedAtomMap = {

View file

@ -1,214 +0,0 @@
import { Atom, Selector } from "@rbxts/charm";
export = CharmSync;
export as namespace CharmSync;
type Cleanup = () => void;
type Key = string | number | symbol;
declare namespace CharmSync {
type AtomMap = Record<string, Atom<any>>;
type SelectorMap = Record<string, Selector<any>>;
/**
* @deprecated Use `SelectorMap` instead.
*/
type MoleculeMap = SelectorMap;
/**
* Infers the type of the return values produced by a map of functions.
*/
type StateOfMap<T> = {
readonly [P in keyof T]: T[P] extends Selector<infer State> ? State : never;
};
/**
* Represents the removal of a value from the state.
*/
interface None {
readonly __none: "__none";
}
type MaybeNone<T> = undefined extends T ? None : never;
/**
* Creates a `ClientSyncer` object that receives patches from the server and
* applies them to the local state.
*
* @client
* @param options The atoms to synchronize with the server.
* @returns A `ClientSyncer` object.
*/
function client<Atoms extends AtomMap>(options: ClientOptions<Atoms>): ClientSyncer<Atoms>;
/**
* Creates a `ServerSyncer` object that sends patches to the client and
* hydrates the client's state.
*
* @server
* @param options The atoms to synchronize with the client.
* @returns A `ServerSyncer` object.
*/
function server<Selectors extends SelectorMap, Serialize extends boolean = true>(
options: ServerOptions<Selectors, Serialize>,
): ServerSyncer<Selectors, Serialize>;
/**
* Checks whether a value is `None`. If `true`, the value is scheduled to be
* removed from the state when the patch is applied.
*
* @param value The value to check.
* @returns `true` if the value is `None`, otherwise `false`.
*/
function isNone(value: unknown): value is None;
interface NestedAtomMap {
readonly [key: string]: NestedAtomMap | Atom<any>;
}
type AppendPath<Path extends Key | undefined, Name extends Key> = undefined extends Path
? Name
: Name extends string
? Path extends string
? `${Path}/${Name}`
: never
: never;
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (k: infer I) => void ? I : never;
type IntersectValues<T> = UnionToIntersection<{ readonly [K in keyof T]: T[K] }[keyof T]>;
type FlattenNestedAtoms<Atoms extends NestedAtomMap, Path extends Key | undefined = undefined> = IntersectValues<{
readonly [Name in keyof Atoms as AppendPath<Path, Name>]: Atoms[Name] extends Atom<any>
? { readonly [K in AppendPath<Path, Name>]: Atoms[Name] }
: Atoms[Name] extends NestedAtomMap
? FlattenNestedAtoms<Atoms[Name], AppendPath<Path, Name>>
: never;
}>;
/**
* Flattens a nested atom map into a single object with slash-separated
* keys. Useful for recursively collecting atoms returned by modules.
*
* @param atoms The nested atom map to flatten.
* @return A flattened atom map.
*/
function flatten<Atoms extends NestedAtomMap>(atoms: Atoms): FlattenNestedAtoms<Atoms>;
type DataTypes = {
[P in keyof CheckableTypes as P extends keyof CheckablePrimitives ? never : P]: CheckableTypes[P];
};
/**
* A type that should not be made partial in patches.
*/
type DataType = DataTypes[keyof DataTypes];
/**
* A partial patch that can be applied to the state to update it. Represents
* the difference between the current state and the next state.
*
* If a value was removed, it is replaced with `None`. This can be checked
* using the `sync.isNone` function.
*/
type SyncPatch<State, Serialize extends boolean = true> = MaybeNone<State> | State extends
| ReadonlyMap<infer K, infer V>
| Map<infer K, infer V>
? ReadonlyMap<K, SyncPatch<V, Serialize> | None>
: State extends Set<infer T> | ReadonlySet<infer T>
? ReadonlyMap<T, true | None>
: State extends readonly (infer T)[]
? Serialize extends true
? ReadonlyMap<string | number, SyncPatch<T, Serialize> | None>
: readonly (SyncPatch<T, Serialize> | None | undefined)[]
: State extends DataType
? State
: State extends object
? { readonly [P in keyof State]?: SyncPatch<State[P], Serialize> }
: State;
/**
* A payload that can be sent from the server to the client to synchronize
* state between the two.
*/
type SyncPayload<Selectors extends SelectorMap, Serialize extends boolean = true> =
| { readonly type: "init"; readonly data: StateOfMap<Selectors> }
| { readonly type: "patch"; readonly data: SyncPatch<StateOfMap<Selectors>, Serialize> };
interface ClientOptions<Atoms extends AtomMap> {
/**
* The atoms to synchronize with the server.
*/
atoms: Atoms;
/**
* Whether to ignore patches sent before the client has been hydrated.
* Defaults to `true`.
*/
ignoreUnhydrated?: boolean;
}
interface ServerOptions<Selectors extends SelectorMap, Serialize extends boolean = true> {
/**
* The atoms to synchronize with the client.
*/
atoms: Selectors;
/**
* The interval at which to send patches to the client, in seconds.
* Defaults to `0` (patches are sent up to once per frame). Set to a
* negative value to disable automatic syncing.
*/
interval?: number;
/**
* Whether the history of state changes since the client's last update
* should be preserved. This is useful for values that change multiple times
* per frame, where each individual change is important. Defaults to `false`.
*
* If `true`, the broadcaster will send a list of payloads to the client
* instead of a single payload. The client will apply each payload in order
* to reconstruct the state's changes over time.
*/
preserveHistory?: boolean;
/**
* When `true`, Charm will apply validation and serialize unsafe arrays
* to address remote event argument limitations. Defaults to `true`.
*
* This option should be disabled if your network library uses a custom
* serialization method (i.e. Zap, ByteNet) to prevent interference.
*/
autoSerialize?: Serialize;
}
interface ClientSyncer<Atoms extends AtomMap> {
/**
* Applies a patch or initializes the state of the atoms with the given
* payload from the server.
*
* @param payloads The patches or hydration payloads to apply.
*/
sync(...payloads: SyncPayload<Atoms, boolean>[]): void;
}
interface ServerSyncer<Selectors extends SelectorMap, Serialize extends boolean> {
/**
* Sets up a subscription to each atom that schedules a patch to be sent to
* the client whenever the state changes. When a change occurs, the `callback`
* is called with the player and the payloads to send.
*
* Note that a `payload` object should not be mutated. If you need to modify
* a payload, apply the changes to a copy of the object.
*
* @param callback The function to call when the state changes.
* @returns A cleanup function that unsubscribes all listeners.
*/
connect(callback: (player: Player, ...payloads: SyncPayload<Selectors, Serialize>[]) => void): Cleanup;
/**
* Hydrates the client's state with the server's state. This should be
* called when a player joins the game and requires the server's state.
*
* @param player The player to hydrate.
*/
hydrate(player: Player): void;
}
}

View file

@ -3,6 +3,7 @@ local flatten = require(script.flatten)
local patch = require(script.patch)
local server = require(script.server)
local types = require(script.types)
local validate = require(script.validate)
export type SyncPayload = types.SyncPayload
@ -14,5 +15,7 @@ return {
client = client,
server = server,
flatten = flatten,
validate = validate,
patch = patch,
isNone = patch.isNone,
}

View file

@ -4,6 +4,7 @@ local Charm = require(script.Parent.Parent.Charm)
local interval = require(script.Parent.interval)
local patch = require(script.Parent.patch)
local types = require(script.Parent.types)
type AtomMap = types.AtomMap
type SyncPayload = types.SyncPayload

View file

@ -1,4 +1,5 @@
local Charm = require(script.Parent.Parent.Charm)
type Atom<T> = Charm.Atom<T>
--[=[

View file

@ -5,4 +5,4 @@ registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"
[dependencies]
charm = "littensy/charm@^0.10"
Charm = "littensy/charm@^0.10"

View file

@ -1,13 +0,0 @@
{
"name": "@rbxts/charm",
"version": "0.10.0",
"description": "An atomic state management library for Roblox",
"repository": "littensy/charm",
"license": "MIT",
"main": "src/init.luau",
"types": "src/index.d.ts",
"scripts": {
"prepare": "cp ../../LICENSE.md . && cp ../../README.md .",
"publish:wally": "wally publish"
}
}

View file

@ -1,165 +0,0 @@
export = Charm;
export as namespace Charm;
type Dispose = () => void;
declare namespace Charm {
/**
* A primitive state container that can be read from or written to. When
* the state changes, all subscribers are notified.
*
* @param state The next state or a function that produces the next state.
* @returns The current state.
*/
interface Atom<State> {
(): State;
(nextState: State | ((prevState: State) => State)): State;
}
/**
* A function that depends on one or more atoms and produces a value. Can be
* used to derive state from atoms.
*
* @returns The current state.
*/
type Selector<State> = () => State;
/**
* Infers the type of the state produced by the given function.
*/
type StateOf<T> = T extends () => infer State ? State : never;
interface AtomOptions<State> {
/**
* A function that determines whether the state has changed. By default,
* a strict equality check (`===`) is used.
*/
equals?: (prev: State, next: State) => boolean;
}
/**
* Creates a new atom with the given state.
*
* @param state The initial state.
* @param options Optional configuration.
* @returns A new atom.
*/
function atom<State>(state: State, options?: AtomOptions<State>): Atom<State>;
// Overload for no arguments
function atom<State>(state?: State, options?: AtomOptions<State>): Atom<State | undefined>;
/**
* Creates a read-only atom that derives its state from one or more atoms.
* Used to avoid unnecessary recomputations if multiple listeners depend on
* the same atoms.
*
* @param callback The function that produces the state.
* @returns A new read-only atom.
*/
function computed<State>(callback: (prevResult?: State) => State): () => State;
/**
* Subscribes to changes in the given atom or selector. The callback is
* called with the current state and the previous state only after a change
* occurs.
*
* @param callback The atom or selector to subscribe to.
* @param listener The function to call when the state changes.
* @returns A function that unsubscribes the callback.
*/
function subscribe<State>(callback: () => State, listener: (state: State, prevState: State) => void): Dispose;
/**
* Subscribes to changes in the given atom or selector. The callback is
* called with the current state and the previous state immediately after
* subscribing, and again when a change occurs.
*
* @param callback The atom or selector to subscribe to.
* @param listener The function to call when the state changes.
* @returns A function that unsubscribes the callback.
*/
function listen<State>(
callback: () => State,
listener: (state: State, prevState: State, dispose: Dispose) => void,
): Dispose;
/**
* Runs the given callback immediately and whenever any atom it depends on
* changes. Returns a cleanup function that unsubscribes the callback.
*
* @param callback The function to run.
* @returns A function that unsubscribes the callback.
*/
function effect(callback: (dispose: Dispose) => Dispose | void): Dispose;
/**
* Runs the given function and schedules listeners to be notified only once
* after the function has completed. Useful for batching multiple changes.
*
* @param callback The function to run.
*/
function batched(callback: () => void): void;
/**
* Returns the result of the function without subscribing to changes.
*
* @param callback The atom or selector to get the state of.
* @param args Arguments to pass to the function.
* @returns The current state.
*/
function untracked<State, Args extends unknown[]>(callback: (...args: Args) => State, ...args: Args): State;
/**
* Creates an instance of `factory` for each item in the atom's state, and
* cleans up the instance when the item is removed. Returns a cleanup function
* that unsubscribes all instances.
*
* @param callback The atom or selector to observe.
* @param factory The function that tracks the lifecycle of each item.
* @returns A function that unsubscribes all instances.
*/
function observe<Item>(
callback: () => readonly Item[],
factory: (item: Item, index: number) => Dispose | void,
): Dispose;
function observe<Key, Item>(
callback: () => Map<Key, Item> | ReadonlyMap<Key, Item>,
factory: (item: Item, key: Key) => Dispose | void,
): Dispose;
function observe<Key extends string | number | symbol, Item>(
callback: () => { readonly [P in Key]: Item },
factory: (item: Item, key: Key) => Dispose | void,
): Dispose;
/**
* Maps each entry in the atom's state to a new key-value pair. If the `mapper`
* function returns `undefined`, the entry is omitted from the resulting map.
* When the atom changes, the `mapper` only runs for the changed entries.
*
* @param callback The atom or selector to map.
* @param mapper The function that maps each entry.
* @returns A new atom with the mapped state.
*/
function mapped<V0, K1, V1>(
callback: () => readonly V0[],
mapper: (value: V0, index: number) => LuaTuple<[value: V1 | undefined, key: K1]>,
): () => ReadonlyMap<K1, V1>;
function mapped<V0, V1>(
callback: () => readonly V0[],
mapper: (value: V0, index: number) => V1,
): () => readonly V1[];
function mapped<K0, V0, K1 = K0, V1 = V0>(
callback: () => Map<K0, V0> | ReadonlyMap<K0, V0>,
mapper: (value: V0, key: K0) => LuaTuple<[value: V1 | undefined, key: K1]> | V1,
): () => ReadonlyMap<K1, V1>;
function mapped<K0 extends string | number | symbol, V0, K1 = K0, V1 = V0>(
callback: () => { readonly [P in K0]: V0 },
mapper: (value: V0, key: K0) => LuaTuple<[value: V1 | undefined, key: K1]> | V1,
): () => ReadonlyMap<K1, V1>;
}

View file

@ -6,6 +6,7 @@ local effectScope = require("./effectScope")
local listen = require("./listen")
local mapped = require("./mapped")
local observe = require("./observe")
local signals = require("./signals")
local subscribe = require("./subscribe")
local types = require("./types")
local untracked = require("./untracked")
@ -25,4 +26,5 @@ return {
observe = observe,
subscribe = subscribe,
untracked = untracked,
signals = signals,
}

View file

@ -19,7 +19,7 @@ local useState = React.useState
@param dependencies An array of values that the subscription depends on.
@return The current state.
]=]
local function useAtom<State>(callback: Charm.Selector<State>, dependencies: { any }?): State
local function useAtom<State>(callback: () -> State, dependencies: { any }?): State
local state, setState = useState(callback)
useEffect(function()

View file

@ -5,5 +5,5 @@ registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"
[dependencies]
charm = "littensy/charm@^0.10"
Charm = "littensy/charm@^0.10"
React = "jsdotlua/react@^17"

View file

@ -1,17 +0,0 @@
{
"name": "@rbxts/react-charm",
"version": "0.3.0",
"description": "React bindings for Charm",
"repository": "littensy/charm",
"license": "MIT",
"main": "src/init.luau",
"types": "src/index.d.ts",
"scripts": {
"prepare": "cp ../../LICENSE.md . && cp ../../README.md .",
"publish:wally": "wally publish"
},
"peerDependencies": {
"@rbxts/charm": "workspace:*",
"@rbxts/react": "*"
}
}

View file

@ -1,13 +0,0 @@
/**
* A hook that subscribes to changes in the given atom or selector. The
* component is re-rendered whenever the state changes.
*
* If the `dependencies` array is provided, the subscription to the atom or
* selector is re-created whenever the dependencies change. Otherwise, the
* subscription is created once when the component is mounted.
*
* @param callback The atom or selector to subscribe to.
* @param dependencies An array of values that the subscription depends on.
* @returns The current state.
*/
export function useAtom<State>(callback: () => State, dependencies?: unknown[]): State;

View file

@ -5,5 +5,5 @@ registry = "https://github.com/UpliftGames/wally-index"
realm = "shared"
[dependencies]
charm = "littensy/charm@^0.10"
Charm = "littensy/charm@^0.10"
Vide = "centau/vide@^0.3"

View file

@ -1,17 +0,0 @@
{
"name": "@rbxts/vide-charm",
"version": "0.3.0",
"description": "Vide bindings for Charm",
"repository": "littensy/charm",
"license": "MIT",
"main": "src/init.luau",
"types": "src/index.d.ts",
"scripts": {
"prepare": "cp ../../LICENSE.md . && cp ../../README.md .",
"publish:wally": "wally publish"
},
"peerDependencies": {
"@rbxts/charm": "workspace:*",
"@rbxts/vide": "*"
}
}

View file

@ -1,7 +0,0 @@
/**
* Subscribes to the state of an atom and returns a Vide source.
*
* @param callback The atom or selector to subscribe to.
* @returns The reactive source.
*/
export function useAtom<T>(callback: () => T): () => T;

195
pesde.lock Normal file
View file

@ -0,0 +1,195 @@
# This file is automatically @generated by pesde.
# It is not intended for manual editing.
format = 2
name = "littensy/charm"
version = "0.1.0"
target = "roblox"
[graph."wally#centau/vide@0.3.1 roblox"]
direct = ["Vide", { wally = "wally#centau/vide", version = "^0.3.1", index = "default" }, "standard"]
[graph."wally#centau/vide@0.3.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/boolean@1.2.7 roblox".dependencies]
number = ["wally#jsdotlua/number@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/boolean@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/boolean@1.2.7 roblox".pkg_ref.dependencies]
number = [{ wally = "wally#jsdotlua/number", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/collections@1.2.7 roblox".dependencies]
es7-types = ["wally#jsdotlua/es7-types@1.2.7 roblox", "standard"]
instance-of = ["wally#jsdotlua/instance-of@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/collections@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/collections@1.2.7 roblox".pkg_ref.dependencies]
es7-types = [{ wally = "wally#jsdotlua/es7-types", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
instance-of = [{ wally = "wally#jsdotlua/instance-of", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/console@1.2.7 roblox".dependencies]
collections = ["wally#jsdotlua/collections@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/console@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/console@1.2.7 roblox".pkg_ref.dependencies]
collections = [{ wally = "wally#jsdotlua/collections", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/es7-types@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/instance-of@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/luau-polyfill@1.2.7 roblox".dependencies]
boolean = ["wally#jsdotlua/boolean@1.2.7 roblox", "standard"]
collections = ["wally#jsdotlua/collections@1.2.7 roblox", "standard"]
console = ["wally#jsdotlua/console@1.2.7 roblox", "standard"]
es7-types = ["wally#jsdotlua/es7-types@1.2.7 roblox", "standard"]
instance-of = ["wally#jsdotlua/instance-of@1.2.7 roblox", "standard"]
math = ["wally#jsdotlua/math@1.2.7 roblox", "standard"]
number = ["wally#jsdotlua/number@1.2.7 roblox", "standard"]
string = ["wally#jsdotlua/string@1.2.7 roblox", "standard"]
symbol-luau = ["wally#jsdotlua/symbol-luau@1.0.1 roblox", "standard"]
timers = ["wally#jsdotlua/timers@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/luau-polyfill@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/luau-polyfill@1.2.7 roblox".pkg_ref.dependencies]
boolean = [{ wally = "wally#jsdotlua/boolean", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
collections = [{ wally = "wally#jsdotlua/collections", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
console = [{ wally = "wally#jsdotlua/console", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
es7-types = [{ wally = "wally#jsdotlua/es7-types", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
instance-of = [{ wally = "wally#jsdotlua/instance-of", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
math = [{ wally = "wally#jsdotlua/math", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
number = [{ wally = "wally#jsdotlua/number", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
string = [{ wally = "wally#jsdotlua/string", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
symbol-luau = [{ wally = "wally#jsdotlua/symbol-luau", version = ">=1.0.0, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
timers = [{ wally = "wally#jsdotlua/timers", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/math@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/number@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/promise@3.5.2 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/react@17.2.1 roblox"]
direct = ["React", { wally = "wally#jsdotlua/react", version = "^17.2.1", index = "default" }, "standard"]
[graph."wally#jsdotlua/react@17.2.1 roblox".dependencies]
luau-polyfill = ["wally#jsdotlua/luau-polyfill@1.2.7 roblox", "standard"]
shared = ["wally#jsdotlua/shared@17.2.1 roblox", "standard"]
[graph."wally#jsdotlua/react@17.2.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/react@17.2.1 roblox".pkg_ref.dependencies]
luau-polyfill = [{ wally = "wally#jsdotlua/luau-polyfill", version = ">=1.2.6, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
shared = [{ wally = "wally#jsdotlua/shared", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/react-reconciler@17.2.1 roblox".dependencies]
luau-polyfill = ["wally#jsdotlua/luau-polyfill@1.2.7 roblox", "standard"]
promise = ["wally#jsdotlua/promise@3.5.2 roblox", "standard"]
react = ["wally#jsdotlua/react@17.2.1 roblox", "standard"]
scheduler = ["wally#jsdotlua/scheduler@17.2.1 roblox", "standard"]
shared = ["wally#jsdotlua/shared@17.2.1 roblox", "standard"]
[graph."wally#jsdotlua/react-reconciler@17.2.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/react-reconciler@17.2.1 roblox".pkg_ref.dependencies]
luau-polyfill = [{ wally = "wally#jsdotlua/luau-polyfill", version = ">=1.2.6, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
promise = [{ wally = "wally#jsdotlua/promise", version = ">=3.5.0, <4.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
react = [{ wally = "wally#jsdotlua/react", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
scheduler = [{ wally = "wally#jsdotlua/scheduler", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
shared = [{ wally = "wally#jsdotlua/shared", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/react-roblox@17.2.1 roblox"]
direct = ["ReactRoblox", { wally = "wally#jsdotlua/react-roblox", version = "^17.2.1", index = "default" }, "standard"]
[graph."wally#jsdotlua/react-roblox@17.2.1 roblox".dependencies]
luau-polyfill = ["wally#jsdotlua/luau-polyfill@1.2.7 roblox", "standard"]
react = ["wally#jsdotlua/react@17.2.1 roblox", "standard"]
react-reconciler = ["wally#jsdotlua/react-reconciler@17.2.1 roblox", "standard"]
scheduler = ["wally#jsdotlua/scheduler@17.2.1 roblox", "standard"]
shared = ["wally#jsdotlua/shared@17.2.1 roblox", "standard"]
[graph."wally#jsdotlua/react-roblox@17.2.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/react-roblox@17.2.1 roblox".pkg_ref.dependencies]
luau-polyfill = [{ wally = "wally#jsdotlua/luau-polyfill", version = ">=1.2.6, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
react = [{ wally = "wally#jsdotlua/react", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
react-reconciler = [{ wally = "wally#jsdotlua/react-reconciler", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
scheduler = [{ wally = "wally#jsdotlua/scheduler", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
shared = [{ wally = "wally#jsdotlua/shared", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/scheduler@17.2.1 roblox".dependencies]
luau-polyfill = ["wally#jsdotlua/luau-polyfill@1.2.7 roblox", "standard"]
shared = ["wally#jsdotlua/shared@17.2.1 roblox", "standard"]
[graph."wally#jsdotlua/scheduler@17.2.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/scheduler@17.2.1 roblox".pkg_ref.dependencies]
luau-polyfill = [{ wally = "wally#jsdotlua/luau-polyfill", version = ">=1.2.6, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
shared = [{ wally = "wally#jsdotlua/shared", version = ">=17.2.1, <18.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/shared@17.2.1 roblox".dependencies]
luau-polyfill = ["wally#jsdotlua/luau-polyfill@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/shared@17.2.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/shared@17.2.1 roblox".pkg_ref.dependencies]
luau-polyfill = [{ wally = "wally#jsdotlua/luau-polyfill", version = ">=1.2.6, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/string@1.2.7 roblox".dependencies]
es7-types = ["wally#jsdotlua/es7-types@1.2.7 roblox", "standard"]
number = ["wally#jsdotlua/number@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/string@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/string@1.2.7 roblox".pkg_ref.dependencies]
es7-types = [{ wally = "wally#jsdotlua/es7-types", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
number = [{ wally = "wally#jsdotlua/number", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]
[graph."wally#jsdotlua/symbol-luau@1.0.1 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/timers@1.2.7 roblox".dependencies]
collections = ["wally#jsdotlua/collections@1.2.7 roblox", "standard"]
[graph."wally#jsdotlua/timers@1.2.7 roblox".pkg_ref]
ref_ty = "wally"
index_url = "https://github.com/UpliftGames/wally-index"
[graph."wally#jsdotlua/timers@1.2.7 roblox".pkg_ref.dependencies]
collections = [{ wally = "wally#jsdotlua/collections", version = ">=1.2.7, <2.0.0", index = "https://github.com/UpliftGames/wally-index" }, "standard"]

17
pesde.toml Normal file
View file

@ -0,0 +1,17 @@
name = "littensy/charm"
version = "0.1.0"
license = "MIT"
[target]
environment = "roblox"
[indices]
default = "https://github.com/pesde-pkg/index"
[wally_indices]
default = "https://github.com/UpliftGames/wally-index"
[dependencies]
React = { wally = "jsdotlua/react", version = "^17.2.1" }
ReactRoblox = { wally = "jsdotlua/react-roblox", version = "^17.2.1" }
Vide = { wally = "centau/vide", version = "^0.3.1" }

1656
pnpm-lock.yaml generated

File diff suppressed because it is too large Load diff

View file

@ -1,2 +0,0 @@
packages:
- packages/*

View file

@ -6,8 +6,8 @@
[tools]
wally = "UpliftGames/wally@0.3.2"
rojo = "rojo-rbx/rojo@7.5.1"
wally-package-types = "JohnnyMorganz/wally-package-types@1.4.2"
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.20250503"
pesde = "daimond113/pesde@0.7.0-rc.1+registry.0.2.3-rc.1"

View file

@ -1,6 +1,6 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local Charm = require(ReplicatedStorage.Packages.Charm)
local computed = Charm.computed
local effect = Charm.effect

View file

@ -1,6 +1,8 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local patch = require(ReplicatedStorage.DevPackages.CharmSync.patch)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local patch = CharmSync.patch
local USERS = 1000

View file

@ -1,7 +1,8 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local signals = require(ReplicatedStorage.DevPackages.Charm.signals)
local Charm = require(ReplicatedStorage.Packages.Charm)
local signals = Charm.signals
local function propagate(
signal: <T>(T) -> (T?) -> T,

View file

@ -1,14 +1,12 @@
local Charm = require("../../packages/charm/src/lib")
local Charm = require("../charm")
local atom = Charm.atom
local computed = Charm.computed
local effect = Charm.effect
local signals = require("../../packages/charm/src/signals")
local signal = signals.signal
local computedSignal = signals.computed
local effectSignal = signals.effect
local signal = Charm.signals.signal
local computedSignal = Charm.signals.computed
local effectSignal = Charm.signals.effect
local w = 10
local h = 10

View file

@ -1,8 +1,8 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local CharmSync = require(ReplicatedStorage.DevPackages.CharmSync)
local Charm = require(ReplicatedStorage.Packages.Charm)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local suite = require(ServerScriptService.Tests.suite)
local atom = Charm.atom

View file

@ -1,8 +1,8 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local CharmSync = require(ReplicatedStorage.DevPackages.CharmSync)
local Charm = require(ReplicatedStorage.Packages.Charm)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local suite = require(ServerScriptService.Tests.suite)
local atom = Charm.atom

View file

@ -1,10 +1,10 @@
local HttpService = game:GetService("HttpService")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local patch = require(ReplicatedStorage.DevPackages.CharmSync.patch)
local suite = require(ServerScriptService.Tests.suite)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local suite = require("../suite")
local patch = CharmSync.patch
local test = suite.test
local function serdes(value: { [any]: any })
@ -124,7 +124,6 @@ test("optionally validates state", function()
end)
assert(success)
assert(success)
end)
return {}

View file

@ -1,15 +1,15 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local CharmSync = require(ReplicatedStorage.DevPackages.CharmSync)
local patch = require(ReplicatedStorage.DevPackages.CharmSync.patch)
local Charm = require(ReplicatedStorage.Packages.Charm)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local suite = require(ServerScriptService.Tests.suite)
type SyncPayload = CharmSync.SyncPayload
local atom = Charm.atom
local server = CharmSync.server
local patch = CharmSync.patch
local test = suite.test
local target: Player = {} :: any
@ -98,3 +98,5 @@ test("preserves history", function()
disconnect()
end)
return {}

View file

@ -1,11 +1,12 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local Charm = require(ReplicatedStorage.Packages.Charm)
local CharmSync = require(ReplicatedStorage.Packages.CharmSync)
local suite = require(ServerScriptService.Tests.suite)
local validate = require(ReplicatedStorage.DevPackages.CharmSync.validate)
local atom = Charm.atom
local validate = CharmSync.validate
local test = suite.test
test("validates inputs", function()
@ -33,3 +34,5 @@ test("validates inputs", function()
end
end
end)
return {}

3
tests/charm.luau Normal file
View file

@ -0,0 +1,3 @@
return if game
then require(game:GetService("ReplicatedStorage").Packages.Charm)
else require("../packages/charm/src/lib")

View file

@ -1,9 +1,9 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local ReactCharm = require(ReplicatedStorage.DevPackages.ReactCharm)
local renderHook = require(script.Parent.Parent.utils.renderHook)
local Charm = require(ReplicatedStorage.Packages.Charm)
local ReactCharm = require(ReplicatedStorage.Packages.ReactCharm)
local renderHook = require(ServerScriptService.Tests.utils.renderHook)
local suite = require(ServerScriptService.Tests.suite)
local atom = Charm.atom
@ -46,3 +46,5 @@ test("tracks dependencies", function()
state(1)
assert(hook.result == 1)
end)
return {}

View file

@ -1,5 +1,5 @@
local test = require("../suite").test
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local computed = signals.computed
local signal = signals.signal

View file

@ -1,5 +1,5 @@
local test = require("../suite").test
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local computed = signals.computed
local effect = signals.effect

View file

@ -1,5 +1,5 @@
local test = require("../suite").test
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local effect = signals.effect
local effectScope = signals.effectScope

View file

@ -1,5 +1,5 @@
local test = require("../suite").test
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local computed = signals.computed
local effect = signals.effect

View file

@ -1,4 +1,4 @@
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local suite = require("../suite")
local test = suite.test

View file

@ -1,5 +1,5 @@
local test = require("../suite").test
local signals = require("../../packages/charm/src/signals")
local signals = require("../charm").signals
local computed = signals.computed
local pauseTracking = signals.pauseTracking

View file

@ -12,9 +12,10 @@ end
test("signals")
if game then
test("sync")
test("react")
test("vide")
_G.__DEV__ = true
test("charm-sync")
test("react-charm")
test("vide-charm")
end
finish()

View file

@ -44,13 +44,13 @@ local function describe(name: string, callback: () -> ())
end
local function finish()
print(`\n🔵 {tests - #errors} / {tests} tests passed\n`)
local output = { `\n🔵 {tests - #errors} / {tests} tests passed\n` }
for _, result in results do
print(result)
table.insert(output, result)
end
print()
print(table.concat(output, "\n") .. "\n")
if #errors > 0 then
error(`{#errors} test(s) failed:\n{table.concat(errors, "\n")}\n`)

View file

@ -2,8 +2,8 @@ local ReplicatedStorage = game:GetService("ReplicatedStorage")
_G.__ROACT_17_MOCK_SCHEDULER__ = true
local React = require(ReplicatedStorage.DevPackages.React)
local ReactRoblox = require(ReplicatedStorage.DevPackages.ReactRoblox)
local React = require(ReplicatedStorage.Packages.React)
local ReactRoblox = require(ReplicatedStorage.Packages.ReactRoblox)
type RenderedHook<Props, Result> = {
result: Result,

View file

@ -1,9 +1,9 @@
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerScriptService = game:GetService("ServerScriptService")
local Charm = require(ReplicatedStorage.DevPackages.Charm)
local Vide = require(ReplicatedStorage.DevPackages.Vide)
local VideCharm = require(ReplicatedStorage.DevPackages.VideCharm)
local Charm = require(ReplicatedStorage.Packages.Charm)
local Vide = require(ReplicatedStorage.Packages.Vide)
local VideCharm = require(ReplicatedStorage.Packages.VideCharm)
local suite = require(ServerScriptService.Tests.suite)
local atom = Charm.atom

View file

@ -1,27 +0,0 @@
{
"compilerOptions": {
// required
"allowSyntheticDefaultImports": true,
"downlevelIteration": true,
"jsx": "react",
"jsxFactory": "React.createElement",
"jsxFragmentFactory": "React.Fragment",
"module": "commonjs",
"moduleResolution": "Node",
"noLib": true,
"resolveJsonModule": true,
"experimentalDecorators": true,
"forceConsistentCasingInFileNames": true,
"moduleDetection": "force",
"strict": true,
"target": "ESNext",
"typeRoots": ["node_modules/@rbxts"],
// configurable
"rootDir": "src",
"outDir": "out",
"incremental": true,
"tsBuildInfoFile": "out/tsconfig.tsbuildinfo",
"declaration": true
}
}