@kokimoki/app 1.4.6 → 1.5.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/kokimoki-awareness copy.d.ts +22 -0
- package/dist/kokimoki-awareness copy.js +82 -0
- package/dist/kokimoki-client.d.ts +4 -0
- package/dist/kokimoki-client.js +68 -27
- package/dist/kokimoki-local-store.d.ts +12 -0
- package/dist/kokimoki-local-store.js +40 -0
- package/dist/kokimoki.min.d.ts +14 -0
- package/dist/kokimoki.min.js +2404 -30
- package/dist/kokimoki.min.js.map +1 -1
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +2 -1
- package/dist/kokimoki-client-refactored.d.ts +0 -68
- package/dist/kokimoki-client-refactored.js +0 -394
- package/dist/message-queue.d.ts +0 -8
- package/dist/message-queue.js +0 -19
- package/dist/synced-schema.d.ts +0 -59
- package/dist/synced-schema.js +0 -84
- package/dist/synced-store.d.ts +0 -7
- package/dist/synced-store.js +0 -9
- package/dist/synced-types.d.ts +0 -38
- package/dist/synced-types.js +0 -68
- package/dist/ws-message-type copy.d.ts +0 -6
- package/dist/ws-message-type copy.js +0 -7
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { KokimokiStore } from "./kokimoki-store";
|
|
2
|
+
import { KokimokiSchema as S } from "./kokimoki-schema";
|
|
3
|
+
import { RoomSubscriptionMode } from "./room-subscription-mode";
|
|
4
|
+
import type { KokimokiClient } from "./kokimoki-client";
|
|
5
|
+
export declare class KokimokiAwareness<Data extends S.Generic<unknown>> extends KokimokiStore<S.Dict<S.Struct<{
|
|
6
|
+
clientId: S.String;
|
|
7
|
+
lastPing: S.Number;
|
|
8
|
+
data: Data;
|
|
9
|
+
}>>> {
|
|
10
|
+
readonly dataSchema: Data;
|
|
11
|
+
private _data;
|
|
12
|
+
private _pingInterval;
|
|
13
|
+
private _kmClients;
|
|
14
|
+
constructor(roomName: string, dataSchema: Data, _data: Data["defaultValue"], mode?: RoomSubscriptionMode, pingTimeout?: number);
|
|
15
|
+
onJoin(client: KokimokiClient<any>): Promise<void>;
|
|
16
|
+
onBeforeLeave(client: KokimokiClient<any>): Promise<void>;
|
|
17
|
+
onLeave(client: KokimokiClient<any>): Promise<void>;
|
|
18
|
+
getClients(): {
|
|
19
|
+
[clientId: string]: Data["defaultValue"];
|
|
20
|
+
};
|
|
21
|
+
setData(data: Data["defaultValue"]): Promise<void>;
|
|
22
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { KokimokiStore } from "./kokimoki-store";
|
|
2
|
+
import { KokimokiSchema as S } from "./kokimoki-schema";
|
|
3
|
+
import { RoomSubscriptionMode } from "./room-subscription-mode";
|
|
4
|
+
export class KokimokiAwareness extends KokimokiStore {
|
|
5
|
+
dataSchema;
|
|
6
|
+
_data;
|
|
7
|
+
_pingInterval = null;
|
|
8
|
+
_kmClients = new Set();
|
|
9
|
+
constructor(roomName, dataSchema, _data, mode = RoomSubscriptionMode.ReadWrite, pingTimeout = 3000) {
|
|
10
|
+
super(`/a/${roomName}`, S.dict(S.struct({
|
|
11
|
+
clientId: S.string(),
|
|
12
|
+
lastPing: S.number(),
|
|
13
|
+
data: dataSchema,
|
|
14
|
+
})), mode);
|
|
15
|
+
this.dataSchema = dataSchema;
|
|
16
|
+
this._data = _data;
|
|
17
|
+
this._pingInterval = setInterval(async () => {
|
|
18
|
+
const kmClients = Array.from(this._kmClients);
|
|
19
|
+
await Promise.all(kmClients.map(async (client) => {
|
|
20
|
+
try {
|
|
21
|
+
await client.transact((t) => {
|
|
22
|
+
const timestamp = client.serverTimestamp();
|
|
23
|
+
// Update self
|
|
24
|
+
if (this.proxy[client.connectionId]) {
|
|
25
|
+
t.set(this.root[client.connectionId].lastPing, timestamp);
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
t.set(this.root[client.connectionId], {
|
|
29
|
+
clientId: client.id,
|
|
30
|
+
lastPing: timestamp,
|
|
31
|
+
data: this._data,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
// Delete clients that haven't pinged in a while
|
|
35
|
+
for (const connectionId in this.proxy) {
|
|
36
|
+
const { lastPing } = this.proxy[connectionId];
|
|
37
|
+
if (!lastPing || timestamp - lastPing > pingTimeout * 2) {
|
|
38
|
+
t.delete(this.root[connectionId]);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
catch (e) { }
|
|
44
|
+
}));
|
|
45
|
+
}, pingTimeout);
|
|
46
|
+
}
|
|
47
|
+
async onJoin(client) {
|
|
48
|
+
this._kmClients.add(client);
|
|
49
|
+
await client.transact((t) => {
|
|
50
|
+
t.set(this.root[client.connectionId], {
|
|
51
|
+
clientId: client.id,
|
|
52
|
+
lastPing: client.serverTimestamp(),
|
|
53
|
+
data: this._data,
|
|
54
|
+
});
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
async onBeforeLeave(client) {
|
|
58
|
+
await client.transact((t) => {
|
|
59
|
+
t.delete(this.root[client.connectionId]);
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async onLeave(client) {
|
|
63
|
+
this._kmClients.delete(client);
|
|
64
|
+
}
|
|
65
|
+
getClients() {
|
|
66
|
+
const clients = {};
|
|
67
|
+
for (const connectionId in this.proxy) {
|
|
68
|
+
clients[this.proxy[connectionId].clientId] =
|
|
69
|
+
this.proxy[connectionId].data;
|
|
70
|
+
}
|
|
71
|
+
return clients;
|
|
72
|
+
}
|
|
73
|
+
async setData(data) {
|
|
74
|
+
this._data = data;
|
|
75
|
+
const kmClients = Array.from(this._kmClients);
|
|
76
|
+
await Promise.all(kmClients.map(async (client) => {
|
|
77
|
+
await client.transact((t) => {
|
|
78
|
+
t.set(this.root[client.connectionId].data, this._data);
|
|
79
|
+
});
|
|
80
|
+
}));
|
|
81
|
+
}
|
|
82
|
+
}
|
|
@@ -9,6 +9,7 @@ import type { RoomSubscriptionMode } from "./room-subscription-mode";
|
|
|
9
9
|
import { KokimokiQueue } from "./kokimoki-queue";
|
|
10
10
|
import { KokimokiAwareness } from "./kokimoki-awareness";
|
|
11
11
|
import { KokimokiReqRes } from "./kokimoki-req-res";
|
|
12
|
+
import { KokimokiLocalStore } from "./kokimoki-local-store";
|
|
12
13
|
declare const KokimokiClient_base: new () => TypedEmitter<KokimokiClientEvents>;
|
|
13
14
|
export declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
14
15
|
readonly host: string;
|
|
@@ -35,6 +36,7 @@ export declare class KokimokiClient<ClientContextT = any> extends KokimokiClient
|
|
|
35
36
|
private _reconnectTimeout;
|
|
36
37
|
private _pingInterval;
|
|
37
38
|
private _clientTokenKey;
|
|
39
|
+
private _editorContext;
|
|
38
40
|
constructor(host: string, appId: string, code?: string);
|
|
39
41
|
get id(): string;
|
|
40
42
|
get connectionId(): string;
|
|
@@ -44,6 +46,7 @@ export declare class KokimokiClient<ClientContextT = any> extends KokimokiClient
|
|
|
44
46
|
get clientContext(): ClientContextT & ({} | null);
|
|
45
47
|
get connected(): boolean;
|
|
46
48
|
get ws(): WebSocket;
|
|
49
|
+
get isEditor(): boolean;
|
|
47
50
|
connect(): Promise<void>;
|
|
48
51
|
private handleInitMessage;
|
|
49
52
|
private handleBinaryMessage;
|
|
@@ -79,6 +82,7 @@ export declare class KokimokiClient<ClientContextT = any> extends KokimokiClient
|
|
|
79
82
|
getRoomHash<T extends S.Generic<unknown>>(store: KokimokiStore<T>): number;
|
|
80
83
|
/** Initializers */
|
|
81
84
|
store<T extends S.Generic<unknown>>(name: string, schema: T, autoJoin?: boolean): KokimokiStore<T, T["defaultValue"]>;
|
|
85
|
+
localStore<T extends S.Generic<unknown>>(name: string, schema: T): KokimokiLocalStore<T>;
|
|
82
86
|
queue<T extends S.Generic<unknown>>(name: string, schema: T, mode: RoomSubscriptionMode, autoJoin?: boolean): KokimokiQueue<T>;
|
|
83
87
|
awareness<T extends S.Generic<unknown>>(name: string, dataSchema: T, initialData?: T["defaultValue"], autoJoin?: boolean): KokimokiAwareness<T>;
|
|
84
88
|
reqRes<Req extends S.Generic<unknown>, Res extends S.Generic<unknown>>(serviceName: string, reqSchema: Req, resSchema: Res, handleRequest: (payload: Req["defaultValue"]) => Promise<Res["defaultValue"]>): KokimokiReqRes<Req, Res>;
|
package/dist/kokimoki-client.js
CHANGED
|
@@ -10,6 +10,7 @@ import { RoomSubscription } from "./room-subscription";
|
|
|
10
10
|
import { KokimokiQueue } from "./kokimoki-queue";
|
|
11
11
|
import { KokimokiAwareness } from "./kokimoki-awareness";
|
|
12
12
|
import { KokimokiReqRes } from "./kokimoki-req-res";
|
|
13
|
+
import { KokimokiLocalStore } from "./kokimoki-local-store";
|
|
13
14
|
export class KokimokiClient extends EventEmitter {
|
|
14
15
|
host;
|
|
15
16
|
appId;
|
|
@@ -35,6 +36,7 @@ export class KokimokiClient extends EventEmitter {
|
|
|
35
36
|
_reconnectTimeout = 0;
|
|
36
37
|
_pingInterval;
|
|
37
38
|
_clientTokenKey = "KM_TOKEN";
|
|
39
|
+
_editorContext;
|
|
38
40
|
constructor(host, appId, code = "") {
|
|
39
41
|
super();
|
|
40
42
|
this.host = host;
|
|
@@ -57,6 +59,7 @@ export class KokimokiClient extends EventEmitter {
|
|
|
57
59
|
if (window.parent && window.self !== window.parent) {
|
|
58
60
|
window.addEventListener("message", (e) => {
|
|
59
61
|
console.log(`[KM TOOLS] ${e.data}`);
|
|
62
|
+
this._editorContext = e.data;
|
|
60
63
|
if (e.data === "km:clearStorage") {
|
|
61
64
|
localStorage.removeItem(this._clientTokenKey);
|
|
62
65
|
window.location.reload();
|
|
@@ -112,6 +115,9 @@ export class KokimokiClient extends EventEmitter {
|
|
|
112
115
|
}
|
|
113
116
|
return this._ws;
|
|
114
117
|
}
|
|
118
|
+
get isEditor() {
|
|
119
|
+
return !!this._editorContext;
|
|
120
|
+
}
|
|
115
121
|
async connect() {
|
|
116
122
|
if (this._connectPromise) {
|
|
117
123
|
return await this._connectPromise;
|
|
@@ -445,7 +451,13 @@ export class KokimokiClient extends EventEmitter {
|
|
|
445
451
|
}
|
|
446
452
|
// Send subscription request if connected to server
|
|
447
453
|
if (!subscription.joined) {
|
|
448
|
-
|
|
454
|
+
let res;
|
|
455
|
+
if (store instanceof KokimokiLocalStore) {
|
|
456
|
+
res = store.getInitialUpdate(this.appId, this.id);
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
res = await this.sendSubscribeReq(store.roomName, store.mode);
|
|
460
|
+
}
|
|
449
461
|
this._subscriptionsByHash.set(res.roomHash, subscription);
|
|
450
462
|
await subscription.applyInitialResponse(res.roomHash, res.initialUpdate);
|
|
451
463
|
// Trigger onJoin event
|
|
@@ -465,55 +477,76 @@ export class KokimokiClient extends EventEmitter {
|
|
|
465
477
|
}
|
|
466
478
|
}
|
|
467
479
|
async transact(handler) {
|
|
468
|
-
if (!this._connected) {
|
|
469
|
-
|
|
470
|
-
}
|
|
480
|
+
// if (!this._connected) {
|
|
481
|
+
// throw new Error("Client not connected");
|
|
482
|
+
// }
|
|
471
483
|
const transaction = new KokimokiTransaction(this);
|
|
472
484
|
await handler(transaction);
|
|
473
485
|
const { updates, consumedMessages } = await transaction.getUpdates();
|
|
474
486
|
if (!updates.length) {
|
|
475
487
|
return;
|
|
476
488
|
}
|
|
477
|
-
// Construct
|
|
478
|
-
const
|
|
489
|
+
// Construct buffers
|
|
490
|
+
const remoteUpdateWriter = new WsMessageWriter();
|
|
491
|
+
const localUpdateWriter = new WsMessageWriter();
|
|
479
492
|
// Write message type
|
|
480
|
-
|
|
493
|
+
remoteUpdateWriter.writeInt32(WsMessageType.Transaction);
|
|
481
494
|
// Update and write transaction ID
|
|
482
495
|
const transactionId = ++this._messageId;
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
496
|
+
remoteUpdateWriter.writeInt32(transactionId);
|
|
497
|
+
localUpdateWriter.writeInt32(transactionId);
|
|
498
|
+
// Write room hashes where messages were consumed (remote only)
|
|
499
|
+
remoteUpdateWriter.writeInt32(consumedMessages.size);
|
|
486
500
|
for (const roomName of consumedMessages) {
|
|
487
501
|
const subscription = this._subscriptionsByName.get(roomName);
|
|
488
502
|
if (!subscription) {
|
|
489
503
|
throw new Error(`Cannot consume message in "${roomName}" because it hasn't been joined`);
|
|
490
504
|
}
|
|
491
|
-
|
|
505
|
+
remoteUpdateWriter.writeUint32(subscription.roomHash);
|
|
492
506
|
}
|
|
493
507
|
// Write updates
|
|
508
|
+
let localUpdates = 0, remoteUpdates = 0;
|
|
494
509
|
for (const { roomName, update } of updates) {
|
|
495
510
|
const subscription = this._subscriptionsByName.get(roomName);
|
|
496
511
|
if (!subscription) {
|
|
497
512
|
throw new Error(`Cannot send update to "${roomName}" because it hasn't been joined`);
|
|
498
513
|
}
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
// Wait for server to apply transaction
|
|
504
|
-
await new Promise((resolve, reject) => {
|
|
505
|
-
this._transactionPromises.set(transactionId, { resolve, reject });
|
|
506
|
-
// Send update to server
|
|
507
|
-
try {
|
|
508
|
-
this.ws.send(buffer);
|
|
514
|
+
if (subscription.store instanceof KokimokiLocalStore) {
|
|
515
|
+
localUpdates++;
|
|
516
|
+
localUpdateWriter.writeUint32(subscription.roomHash);
|
|
517
|
+
localUpdateWriter.writeUint8Array(update);
|
|
509
518
|
}
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
throw e;
|
|
519
|
+
else {
|
|
520
|
+
remoteUpdates++;
|
|
521
|
+
remoteUpdateWriter.writeUint32(subscription.roomHash);
|
|
522
|
+
remoteUpdateWriter.writeUint8Array(update);
|
|
515
523
|
}
|
|
516
|
-
}
|
|
524
|
+
}
|
|
525
|
+
// Wait for server to apply transaction
|
|
526
|
+
if (remoteUpdates) {
|
|
527
|
+
const remoteBuffer = remoteUpdateWriter.getBuffer();
|
|
528
|
+
await new Promise((resolve, reject) => {
|
|
529
|
+
this._transactionPromises.set(transactionId, { resolve, reject });
|
|
530
|
+
// Send update to server
|
|
531
|
+
try {
|
|
532
|
+
this.ws.send(remoteBuffer);
|
|
533
|
+
}
|
|
534
|
+
catch (e) {
|
|
535
|
+
// Not connected
|
|
536
|
+
console.log("Failed to send update to server:", e);
|
|
537
|
+
// Delete transaction promise
|
|
538
|
+
this._transactionPromises.delete(transactionId);
|
|
539
|
+
// TODO: merge updates or something
|
|
540
|
+
reject(e);
|
|
541
|
+
}
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
// Apply local updates
|
|
545
|
+
if (localUpdates) {
|
|
546
|
+
const localBuffer = localUpdateWriter.getBuffer();
|
|
547
|
+
const reader = new WsMessageReader(localBuffer);
|
|
548
|
+
this.handleRoomUpdateMessage(reader);
|
|
549
|
+
}
|
|
517
550
|
}
|
|
518
551
|
async close() {
|
|
519
552
|
this._autoReconnect = false;
|
|
@@ -543,6 +576,14 @@ export class KokimokiClient extends EventEmitter {
|
|
|
543
576
|
}
|
|
544
577
|
return store;
|
|
545
578
|
}
|
|
579
|
+
// local store
|
|
580
|
+
localStore(name, schema) {
|
|
581
|
+
const store = new KokimokiLocalStore(name, schema);
|
|
582
|
+
this.join(store)
|
|
583
|
+
.then(() => { })
|
|
584
|
+
.catch(() => { });
|
|
585
|
+
return store;
|
|
586
|
+
}
|
|
546
587
|
// queue
|
|
547
588
|
queue(name, schema, mode, autoJoin = true) {
|
|
548
589
|
const queue = new KokimokiQueue(name, schema, mode);
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { KokimokiStore } from "./kokimoki-store";
|
|
2
|
+
import type { KokimokiSchema as S } from "./kokimoki-schema";
|
|
3
|
+
export declare class KokimokiLocalStore<Data extends S.Generic<unknown>> extends KokimokiStore<Data> {
|
|
4
|
+
private readonly localRoomName;
|
|
5
|
+
private _stateKey?;
|
|
6
|
+
private get stateKey();
|
|
7
|
+
constructor(localRoomName: string, schema: Data);
|
|
8
|
+
getInitialUpdate(appId: string, clientId: string): {
|
|
9
|
+
roomHash: number;
|
|
10
|
+
initialUpdate: Uint8Array | undefined;
|
|
11
|
+
};
|
|
12
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { KokimokiStore } from "./kokimoki-store";
|
|
2
|
+
import { RoomSubscriptionMode } from "./room-subscription-mode";
|
|
3
|
+
import { fingerprint32 } from "farmhash-modern";
|
|
4
|
+
import * as Y from "yjs";
|
|
5
|
+
export class KokimokiLocalStore extends KokimokiStore {
|
|
6
|
+
localRoomName;
|
|
7
|
+
_stateKey;
|
|
8
|
+
get stateKey() {
|
|
9
|
+
if (!this._stateKey) {
|
|
10
|
+
throw new Error("Not initialized");
|
|
11
|
+
}
|
|
12
|
+
return this._stateKey;
|
|
13
|
+
}
|
|
14
|
+
constructor(localRoomName, schema) {
|
|
15
|
+
super(`/l/${localRoomName}`, schema, RoomSubscriptionMode.ReadWrite);
|
|
16
|
+
this.localRoomName = localRoomName;
|
|
17
|
+
// Synchronize doc changes to local storage
|
|
18
|
+
// TODO: maybe do not serialize full state every time
|
|
19
|
+
this.doc.on("update", () => {
|
|
20
|
+
const value = Y.encodeStateAsUpdate(this.doc);
|
|
21
|
+
const valueString = String.fromCharCode(...value);
|
|
22
|
+
const valueBase64 = btoa(valueString);
|
|
23
|
+
localStorage.setItem(this.stateKey, valueBase64);
|
|
24
|
+
});
|
|
25
|
+
}
|
|
26
|
+
getInitialUpdate(appId, clientId) {
|
|
27
|
+
this._stateKey = `${appId}/${clientId}/${this.localRoomName}`;
|
|
28
|
+
// get initial update from local storage
|
|
29
|
+
let initialUpdate = undefined;
|
|
30
|
+
const state = localStorage.getItem(this.stateKey);
|
|
31
|
+
if (state) {
|
|
32
|
+
const valueString = atob(state);
|
|
33
|
+
initialUpdate = Uint8Array.from(valueString, (c) => c.charCodeAt(0));
|
|
34
|
+
}
|
|
35
|
+
return {
|
|
36
|
+
roomHash: fingerprint32(this.roomName),
|
|
37
|
+
initialUpdate,
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
}
|
package/dist/kokimoki.min.d.ts
CHANGED
|
@@ -318,6 +318,17 @@ declare class KokimokiReqRes<Req extends KokimokiSchema.Generic<unknown>, Res ex
|
|
|
318
318
|
send(toClientId: string, payload: Req["defaultValue"], timeout?: number): Promise<Res["defaultValue"]>;
|
|
319
319
|
}
|
|
320
320
|
|
|
321
|
+
declare class KokimokiLocalStore<Data extends KokimokiSchema.Generic<unknown>> extends KokimokiStore<Data> {
|
|
322
|
+
private readonly localRoomName;
|
|
323
|
+
private _stateKey?;
|
|
324
|
+
private get stateKey();
|
|
325
|
+
constructor(localRoomName: string, schema: Data);
|
|
326
|
+
getInitialUpdate(appId: string, clientId: string): {
|
|
327
|
+
roomHash: number;
|
|
328
|
+
initialUpdate: Uint8Array | undefined;
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
|
|
321
332
|
declare const KokimokiClient_base: new () => TypedEventEmitter<KokimokiClientEvents>;
|
|
322
333
|
declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
323
334
|
readonly host: string;
|
|
@@ -344,6 +355,7 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
|
344
355
|
private _reconnectTimeout;
|
|
345
356
|
private _pingInterval;
|
|
346
357
|
private _clientTokenKey;
|
|
358
|
+
private _editorContext;
|
|
347
359
|
constructor(host: string, appId: string, code?: string);
|
|
348
360
|
get id(): string;
|
|
349
361
|
get connectionId(): string;
|
|
@@ -353,6 +365,7 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
|
353
365
|
get clientContext(): ClientContextT & ({} | null);
|
|
354
366
|
get connected(): boolean;
|
|
355
367
|
get ws(): WebSocket;
|
|
368
|
+
get isEditor(): boolean;
|
|
356
369
|
connect(): Promise<void>;
|
|
357
370
|
private handleInitMessage;
|
|
358
371
|
private handleBinaryMessage;
|
|
@@ -388,6 +401,7 @@ declare class KokimokiClient<ClientContextT = any> extends KokimokiClient_base {
|
|
|
388
401
|
getRoomHash<T extends KokimokiSchema.Generic<unknown>>(store: KokimokiStore<T>): number;
|
|
389
402
|
/** Initializers */
|
|
390
403
|
store<T extends KokimokiSchema.Generic<unknown>>(name: string, schema: T, autoJoin?: boolean): KokimokiStore<T, T["defaultValue"]>;
|
|
404
|
+
localStore<T extends KokimokiSchema.Generic<unknown>>(name: string, schema: T): KokimokiLocalStore<T>;
|
|
391
405
|
queue<T extends KokimokiSchema.Generic<unknown>>(name: string, schema: T, mode: RoomSubscriptionMode, autoJoin?: boolean): KokimokiQueue<T>;
|
|
392
406
|
awareness<T extends KokimokiSchema.Generic<unknown>>(name: string, dataSchema: T, initialData?: T["defaultValue"], autoJoin?: boolean): KokimokiAwareness<T>;
|
|
393
407
|
reqRes<Req extends KokimokiSchema.Generic<unknown>, Res extends KokimokiSchema.Generic<unknown>>(serviceName: string, reqSchema: Req, resSchema: Res, handleRequest: (payload: Req["defaultValue"]) => Promise<Res["defaultValue"]>): KokimokiReqRes<Req, Res>;
|