@replicast/react 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/connection-store.d.ts +16 -0
- package/dist/connection-store.d.ts.map +1 -0
- package/dist/connection-store.js +12 -0
- package/dist/connection-store.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -0
- package/dist/init-rpc.d.ts +26 -0
- package/dist/init-rpc.d.ts.map +1 -0
- package/dist/init-rpc.js +50 -0
- package/dist/init-rpc.js.map +1 -0
- package/dist/use-connection.d.ts +3 -0
- package/dist/use-connection.d.ts.map +1 -0
- package/dist/use-connection.js +12 -0
- package/dist/use-connection.js.map +1 -0
- package/package.json +29 -0
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export type ConnectionStatus = 'disconnected' | 'connecting' | 'connected' | 'reconnecting';
|
|
2
|
+
export type ConnectionQuality = 'good' | 'fair' | 'poor';
|
|
3
|
+
export interface ConnectionState {
|
|
4
|
+
status: ConnectionStatus;
|
|
5
|
+
playerId: string | null;
|
|
6
|
+
latency: number | null;
|
|
7
|
+
quality: ConnectionQuality | null;
|
|
8
|
+
}
|
|
9
|
+
interface ConnectionStore extends ConnectionState {
|
|
10
|
+
setStatus: (status: ConnectionStatus, playerId: string | null) => void;
|
|
11
|
+
setLatency: (latency: number, quality: ConnectionQuality) => void;
|
|
12
|
+
}
|
|
13
|
+
export declare function createConnectionStore(): import("zustand").UseBoundStore<import("zustand").StoreApi<ConnectionStore>>;
|
|
14
|
+
export type ConnectionStoreInstance = ReturnType<typeof createConnectionStore>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=connection-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-store.d.ts","sourceRoot":"","sources":["../src/connection-store.ts"],"names":[],"mappings":"AAEA,MAAM,MAAM,gBAAgB,GAAG,cAAc,GAAG,YAAY,GAAG,WAAW,GAAG,cAAc,CAAA;AAC3F,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAA;AAExD,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,gBAAgB,CAAA;IACxB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;IACtB,OAAO,EAAE,iBAAiB,GAAG,IAAI,CAAA;CAClC;AAED,UAAU,eAAgB,SAAQ,eAAe;IAC/C,SAAS,EAAE,CAAC,MAAM,EAAE,gBAAgB,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,KAAK,IAAI,CAAA;IACtE,UAAU,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,iBAAiB,KAAK,IAAI,CAAA;CAClE;AAED,wBAAgB,qBAAqB,iFASpC;AAED,MAAM,MAAM,uBAAuB,GAAG,UAAU,CAAC,OAAO,qBAAqB,CAAC,CAAA"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
export function createConnectionStore() {
|
|
3
|
+
return create((set) => ({
|
|
4
|
+
status: 'disconnected',
|
|
5
|
+
playerId: null,
|
|
6
|
+
latency: null,
|
|
7
|
+
quality: null,
|
|
8
|
+
setStatus: (status, playerId) => set({ status, playerId }),
|
|
9
|
+
setLatency: (latency, quality) => set({ latency, quality }),
|
|
10
|
+
}));
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=connection-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"connection-store.js","sourceRoot":"","sources":["../src/connection-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAiBhC,MAAM,UAAU,qBAAqB;IACnC,OAAO,MAAM,CAAkB,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;QACvC,MAAM,EAAE,cAAc;QACtB,QAAQ,EAAE,IAAI;QACd,OAAO,EAAE,IAAI;QACb,OAAO,EAAE,IAAI;QACb,SAAS,EAAE,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,CAAC;QAC1D,UAAU,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,EAAE,OAAO,EAAE,OAAO,EAAE,CAAC;KAC5D,CAAC,CAAC,CAAA;AACL,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA;AACvC,YAAY,EAAE,eAAe,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAA"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAA"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
interface StoreEntry {
|
|
2
|
+
instance: object;
|
|
3
|
+
name: string;
|
|
4
|
+
}
|
|
5
|
+
interface InitRPCOptions {
|
|
6
|
+
client: {
|
|
7
|
+
playerId: string | null;
|
|
8
|
+
latency: number | null;
|
|
9
|
+
quality: any;
|
|
10
|
+
onStatusChange?: (status: any) => void;
|
|
11
|
+
onLatencyChange?: (latency: number, quality: any) => void;
|
|
12
|
+
};
|
|
13
|
+
stores: StoreEntry[];
|
|
14
|
+
}
|
|
15
|
+
type UseStoreHook<T extends object> = () => T;
|
|
16
|
+
type RPCResult<Stores extends StoreEntry[]> = {
|
|
17
|
+
useConnection: () => import('./connection-store.js').ConnectionState;
|
|
18
|
+
} & {
|
|
19
|
+
[K in Stores[number] as `use${K['name']}`]: UseStoreHook<K['instance'] & object>;
|
|
20
|
+
};
|
|
21
|
+
export declare function initRPC<Stores extends StoreEntry[]>(options: {
|
|
22
|
+
client: InitRPCOptions['client'];
|
|
23
|
+
stores: Stores;
|
|
24
|
+
}): RPCResult<Stores>;
|
|
25
|
+
export {};
|
|
26
|
+
//# sourceMappingURL=init-rpc.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-rpc.d.ts","sourceRoot":"","sources":["../src/init-rpc.ts"],"names":[],"mappings":"AAIA,UAAU,UAAU;IAClB,QAAQ,EAAE,MAAM,CAAA;IAChB,IAAI,EAAE,MAAM,CAAA;CACb;AAED,UAAU,cAAc;IACtB,MAAM,EAAE;QACN,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAA;QACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAA;QACtB,OAAO,EAAE,GAAG,CAAA;QACZ,cAAc,CAAC,EAAE,CAAC,MAAM,EAAE,GAAG,KAAK,IAAI,CAAA;QACtC,eAAe,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,GAAG,KAAK,IAAI,CAAA;KAC1D,CAAA;IACD,MAAM,EAAE,UAAU,EAAE,CAAA;CACrB;AAED,KAAK,YAAY,CAAC,CAAC,SAAS,MAAM,IAAI,MAAM,CAAC,CAAA;AAE7C,KAAK,SAAS,CAAC,MAAM,SAAS,UAAU,EAAE,IAAI;IAC5C,aAAa,EAAE,MAAM,OAAO,uBAAuB,EAAE,eAAe,CAAA;CACrE,GAAG;KACD,CAAC,IAAI,MAAM,CAAC,MAAM,CAAC,IAAI,MAAM,CAAC,CAAC,MAAM,CAAC,EAAE,GAAG,YAAY,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,MAAM,CAAC;CACjF,CAAA;AAED,wBAAgB,OAAO,CAAC,MAAM,SAAS,UAAU,EAAE,EACjD,OAAO,EAAE;IAAE,MAAM,EAAE,cAAc,CAAC,QAAQ,CAAC,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GAC5D,SAAS,CAAC,MAAM,CAAC,CAyDnB"}
|
package/dist/init-rpc.js
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { create } from 'zustand';
|
|
2
|
+
import { createConnectionStore } from './connection-store.js';
|
|
3
|
+
import { createUseConnection } from './use-connection.js';
|
|
4
|
+
export function initRPC(options) {
|
|
5
|
+
const { client, stores } = options;
|
|
6
|
+
// Set up connection Zustand store
|
|
7
|
+
const connectionStore = createConnectionStore();
|
|
8
|
+
client.onStatusChange = (status) => {
|
|
9
|
+
connectionStore.getState().setStatus(status, client.playerId);
|
|
10
|
+
};
|
|
11
|
+
client.onLatencyChange = (latency, quality) => {
|
|
12
|
+
connectionStore.getState().setLatency(latency, quality);
|
|
13
|
+
};
|
|
14
|
+
// Build per-store Zustand stores
|
|
15
|
+
const storeHooks = {};
|
|
16
|
+
for (const { instance, name } of stores) {
|
|
17
|
+
// Create a snapshot of the instance's public state as initial state.
|
|
18
|
+
// Use getSnapshot() if available (BaseStore) to avoid capturing private runtime fields.
|
|
19
|
+
const maybeStore = instance;
|
|
20
|
+
const initialState = typeof maybeStore.getSnapshot === 'function'
|
|
21
|
+
? maybeStore.getSnapshot()
|
|
22
|
+
: Object.fromEntries(Object.entries(instance)
|
|
23
|
+
.filter(([k, v]) => !k.startsWith('_') && v !== undefined));
|
|
24
|
+
const zustandStore = create(() => ({ ...initialState }));
|
|
25
|
+
// Wire up _onReplication to update the Zustand store if instance is a BaseStore.
|
|
26
|
+
// Always overwrite to ensure re-wiring on a second initRPC call is consistent.
|
|
27
|
+
maybeStore._onReplication = (batch) => {
|
|
28
|
+
const update = {};
|
|
29
|
+
if (batch.global && Object.keys(batch.global).length > 0) {
|
|
30
|
+
Object.assign(update, batch.global);
|
|
31
|
+
}
|
|
32
|
+
if (batch.ownerByPlayer instanceof Map) {
|
|
33
|
+
const ownPatch = batch.ownerByPlayer.get(client.playerId);
|
|
34
|
+
if (ownPatch?.patch && Object.keys(ownPatch.patch).length > 0) {
|
|
35
|
+
Object.assign(update, ownPatch.patch);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
if (Object.keys(update).length > 0) {
|
|
39
|
+
zustandStore.setState(update);
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
storeHooks[`use${name}`] = () => zustandStore();
|
|
43
|
+
}
|
|
44
|
+
const result = {
|
|
45
|
+
useConnection: createUseConnection(connectionStore),
|
|
46
|
+
...storeHooks,
|
|
47
|
+
};
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=init-rpc.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init-rpc.js","sourceRoot":"","sources":["../src/init-rpc.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAA;AAChC,OAAO,EAAE,qBAAqB,EAAE,MAAM,uBAAuB,CAAA;AAC7D,OAAO,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAA;AA0BzD,MAAM,UAAU,OAAO,CACrB,OAA6D;IAE7D,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,GAAG,OAAO,CAAA;IAElC,kCAAkC;IAClC,MAAM,eAAe,GAAG,qBAAqB,EAAE,CAAA;IAE/C,MAAM,CAAC,cAAc,GAAG,CAAC,MAAM,EAAE,EAAE;QACjC,eAAe,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,QAAQ,CAAC,CAAA;IAC/D,CAAC,CAAA;IAED,MAAM,CAAC,eAAe,GAAG,CAAC,OAAO,EAAE,OAAO,EAAE,EAAE;QAC5C,eAAe,CAAC,QAAQ,EAAE,CAAC,UAAU,CAAC,OAAO,EAAE,OAAO,CAAC,CAAA;IACzD,CAAC,CAAA;IAED,iCAAiC;IACjC,MAAM,UAAU,GAAiC,EAAE,CAAA;IAEnD,KAAK,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,IAAI,MAAM,EAAE,CAAC;QACxC,qEAAqE;QACrE,wFAAwF;QACxF,MAAM,UAAU,GAAG,QAAe,CAAA;QAClC,MAAM,YAAY,GAAG,OAAO,UAAU,CAAC,WAAW,KAAK,UAAU;YAC/D,CAAC,CAAC,UAAU,CAAC,WAAW,EAAE;YAC1B,CAAC,CAAC,MAAM,CAAC,WAAW,CAChB,MAAM,CAAC,OAAO,CAAC,QAAmC,CAAC;iBAChD,MAAM,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC,CAC7D,CAAA;QAEL,MAAM,YAAY,GAAG,MAAM,CAA0B,GAAG,EAAE,CAAC,CAAC,EAAE,GAAG,YAAY,EAAE,CAAC,CAAC,CAAA;QAEjF,iFAAiF;QACjF,+EAA+E;QAC/E,UAAU,CAAC,cAAc,GAAG,CAAC,KAAU,EAAE,EAAE;YACzC,MAAM,MAAM,GAA4B,EAAE,CAAA;YAC1C,IAAI,KAAK,CAAC,MAAM,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACzD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,MAAM,CAAC,CAAA;YACrC,CAAC;YACD,IAAI,KAAK,CAAC,aAAa,YAAY,GAAG,EAAE,CAAC;gBACvC,MAAM,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAA;gBACzD,IAAI,QAAQ,EAAE,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC9D,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAA;gBACvC,CAAC;YACH,CAAC;YACD,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACnC,YAAY,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAA;YAC/B,CAAC;QACH,CAAC,CAAA;QAED,UAAU,CAAC,MAAM,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC,YAAY,EAAE,CAAA;IACjD,CAAC;IAED,MAAM,MAAM,GAAQ;QAClB,aAAa,EAAE,mBAAmB,CAAC,eAAe,CAAC;QACnD,GAAG,UAAU;KACd,CAAA;IAED,OAAO,MAAM,CAAA;AACf,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-connection.d.ts","sourceRoot":"","sources":["../src/use-connection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,eAAe,EAAE,uBAAuB,EAAE,MAAM,uBAAuB,CAAA;AAErF,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,uBAAuB,SAC/B,eAAe,CAQjD"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { useShallow } from 'zustand/react/shallow';
|
|
2
|
+
export function createUseConnection(store) {
|
|
3
|
+
return function useConnection() {
|
|
4
|
+
return store(useShallow((s) => ({
|
|
5
|
+
status: s.status,
|
|
6
|
+
playerId: s.playerId,
|
|
7
|
+
latency: s.latency,
|
|
8
|
+
quality: s.quality,
|
|
9
|
+
})));
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=use-connection.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"use-connection.js","sourceRoot":"","sources":["../src/use-connection.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,uBAAuB,CAAA;AAGlD,MAAM,UAAU,mBAAmB,CAAC,KAA8B;IAChE,OAAO,SAAS,aAAa;QAC3B,OAAO,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC9B,MAAM,EAAE,CAAC,CAAC,MAAM;YAChB,QAAQ,EAAE,CAAC,CAAC,QAAQ;YACpB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,OAAO,EAAE,CAAC,CAAC,OAAO;SACnB,CAAC,CAAC,CAAC,CAAA;IACN,CAAC,CAAA;AACH,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@replicast/react",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "React hooks for replicast — initRPC, useConnection, and reactive per-store hooks",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"main": "./dist/index.js",
|
|
8
|
+
"types": "./dist/index.d.ts",
|
|
9
|
+
"files": ["dist"],
|
|
10
|
+
"scripts": {
|
|
11
|
+
"build": "tsc -p tsconfig.build.json",
|
|
12
|
+
"test": "vitest run"
|
|
13
|
+
},
|
|
14
|
+
"dependencies": {
|
|
15
|
+
"@replicast/core": "*",
|
|
16
|
+
"zustand": "^4.5.0"
|
|
17
|
+
},
|
|
18
|
+
"peerDependencies": {
|
|
19
|
+
"react": "^18.0.0"
|
|
20
|
+
},
|
|
21
|
+
"devDependencies": {
|
|
22
|
+
"@testing-library/react": "^16.3.2",
|
|
23
|
+
"@types/react": "^18.0.0",
|
|
24
|
+
"jsdom": "^29.1.1",
|
|
25
|
+
"react": "^19.2.7",
|
|
26
|
+
"react-dom": "^19.2.7",
|
|
27
|
+
"vitest": "^1.6.0"
|
|
28
|
+
}
|
|
29
|
+
}
|