mirror of
https://github.com/littensy/charm.git
synced 2026-10-20 17:51:37 +00:00
refactor: remove pnpm, fix tests
This commit is contained in:
parent
861ee5acd7
commit
e34b0c9aca
65 changed files with 353 additions and 2458 deletions
26
.eslintrc
26
.eslintrc
|
|
@ -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
1
.gitattributes
vendored
|
|
@ -1 +0,0 @@
|
|||
* text=auto eol=lf
|
||||
14
.github/workflows/ci.yml
vendored
14
.github/workflows/ci.yml
vendored
|
|
@ -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
|
||||
|
|
|
|||
3
.github/workflows/release.yml
vendored
3
.github/workflows/release.yml
vendored
|
|
@ -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
7
.gitignore
vendored
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,6 +0,0 @@
|
|||
{
|
||||
"printWidth": 120,
|
||||
"tabWidth": 4,
|
||||
"trailingComma": "all",
|
||||
"useTabs": true
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,2 @@
|
|||
cd modules
|
||||
wally install
|
||||
cd ..
|
||||
pesde install
|
||||
rojo sourcemap --output sourcemap.json
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 = []
|
||||
|
|
@ -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"
|
||||
24
package.json
24
package.json
|
|
@ -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"
|
||||
}
|
||||
|
|
@ -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:*"
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
local types = require(script.Parent.types)
|
||||
|
||||
type AtomMap = types.AtomMap
|
||||
|
||||
type NestedAtomMap = {
|
||||
|
|
|
|||
214
packages/charm-sync/src/index.d.ts
vendored
214
packages/charm-sync/src/index.d.ts
vendored
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
local Charm = require(script.Parent.Parent.Charm)
|
||||
|
||||
type Atom<T> = Charm.Atom<T>
|
||||
|
||||
--[=[
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@ registry = "https://github.com/UpliftGames/wally-index"
|
|||
realm = "shared"
|
||||
|
||||
[dependencies]
|
||||
charm = "littensy/charm@^0.10"
|
||||
Charm = "littensy/charm@^0.10"
|
||||
|
|
|
|||
|
|
@ -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"
|
||||
}
|
||||
}
|
||||
165
packages/charm/src/index.d.ts
vendored
165
packages/charm/src/index.d.ts
vendored
|
|
@ -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>;
|
||||
}
|
||||
|
|
@ -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,
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
@ -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"
|
||||
|
|
@ -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": "*"
|
||||
}
|
||||
}
|
||||
13
packages/react/src/index.d.ts
vendored
13
packages/react/src/index.d.ts
vendored
|
|
@ -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;
|
||||
|
|
@ -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"
|
||||
|
|
@ -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": "*"
|
||||
}
|
||||
}
|
||||
7
packages/vide/src/index.d.ts
vendored
7
packages/vide/src/index.d.ts
vendored
|
|
@ -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
195
pesde.lock
Normal 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
17
pesde.toml
Normal 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
1656
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,2 +0,0 @@
|
|||
packages:
|
||||
- packages/*
|
||||
|
|
@ -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"
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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
3
tests/charm.luau
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
return if game
|
||||
then require(game:GetService("ReplicatedStorage").Packages.Charm)
|
||||
else require("../packages/charm/src/lib")
|
||||
|
|
@ -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 {}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
local signals = require("../../packages/charm/src/signals")
|
||||
local signals = require("../charm").signals
|
||||
local suite = require("../suite")
|
||||
|
||||
local test = suite.test
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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`)
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue