refactor: refine types and code

This commit is contained in:
Richard 2024-03-27 23:49:33 -07:00
parent 33ecae2f50
commit 382bc3a904
6 changed files with 30 additions and 26 deletions

View file

@ -7,7 +7,7 @@ return function()
local client = sync.client({ atoms = { a = a } }) local client = sync.client({ atoms = { a = a } })
client:sync({ client:sync({
type = "set", type = "init",
data = { a = 2 }, data = { a = 2 },
}) })

View file

@ -17,7 +17,7 @@ return function()
server:hydrate(target) server:hydrate(target)
expect(player).to.equal(target) expect(player).to.equal(target)
expect(payload.type).to.equal("set") expect(payload.type).to.equal("init")
expect(payload.data.a).to.equal(1) expect(payload.data.a).to.equal(1)
disconnect() disconnect()

36
src/index.d.ts vendored
View file

@ -76,34 +76,36 @@ declare namespace Charm {
// Sync // Sync
const sync: { const sync: {
client(options: ClientOptions): ClientSyncer; client: <T extends Record<string, Atom<any>>>(options: ClientOptions<T>) => ClientSyncer<T>;
server(options: ServerOptions): ServerSyncer; server: <T extends Record<string, Atom<any>>>(options: ServerOptions<T>) => ServerSyncer<T>;
collect: (root: Instance) => Record<string, Atom<any>>;
}; };
interface SyncPatch { interface None {
[key: string | number | symbol]: SyncPatch | { __none: "__none" } | string | number | boolean | undefined; __none: "__none";
} }
interface SyncPayload { type SyncPatch<T> = {
type: "set" | "patch"; readonly [P in keyof T]?: (T[P] extends object ? SyncPatch<T[P]> : T[P]) | (T[P] extends undefined ? None : never);
data: SyncPatch; };
type SyncPayload<T> = { type: "init"; data: T } | { type: "patch"; data: SyncPatch<T> };
interface ClientOptions<T extends Record<string, Atom<any>>> {
atoms: T;
} }
interface ClientOptions { interface ServerOptions<T extends Record<string, Atom<any>>> {
atoms: Record<string, Atom<any>>; atoms: T;
}
interface ServerOptions {
atoms: Record<string, Atom<any>>;
interval?: number; interval?: number;
} }
interface ClientSyncer { interface ClientSyncer<T extends Record<string, Atom<any>>> {
sync(payload: SyncPayload): void; sync(payload: SyncPayload<T>): void;
} }
interface ServerSyncer { interface ServerSyncer<T extends Record<string, Atom<any>>> {
connect(callback: (player: Player, payload: SyncPayload) => void): Cleanup; connect(callback: (player: Player, payload: SyncPayload<T>) => void): Cleanup;
hydrate(player: Player): void; hydrate(player: Player): void;
} }
} }

View file

@ -21,16 +21,16 @@ export type SyncPayload = types.SyncPayload
return { return {
atom = atom, atom = atom,
capture = capture,
derive = derive, derive = derive,
effect = effect, effect = effect,
isAtom = isAtom, isAtom = isAtom,
map = map, map = map,
observe = observe, observe = observe,
subscribe = subscribe,
unwrap = unwrap,
capture = capture,
sync = sync,
useAtom = useAtom, useAtom = useAtom,
useAtomState = useAtomState, useAtomState = useAtomState,
useSetAtom = useSetAtom, useSetAtom = useSetAtom,
subscribe = subscribe,
sync = sync,
unwrap = unwrap,
} }

View file

@ -42,10 +42,12 @@ local function server(options: ServerOptions): ServerSyncer
state = getState() state = getState()
if state ~= previous then if state ~= previous then
local diffs = patch.diff(previous, state)
for _, player in Players:GetPlayers() do for _, player in Players:GetPlayers() do
callback(player, { callback(player, {
type = "patch", type = "patch",
data = patch.diff(previous, state), data = diffs,
}) })
end end
end end
@ -66,7 +68,7 @@ local function server(options: ServerOptions): ServerSyncer
assert(sync, "connect() must be called before hydrate()") assert(sync, "connect() must be called before hydrate()")
sync(player, { sync(player, {
type = "set", type = "init",
data = getState(), data = getState(),
}) })
end end

View file

@ -9,7 +9,7 @@ export type AtomOptions<T> = {
} }
export type SyncPayload = { export type SyncPayload = {
type: "patch" | "set", type: "patch" | "init",
data: { [any]: any }, data: { [any]: any },
} }