diff --git a/docs/pages/get-started/yjs-superdoc-javascript.mdx b/docs/pages/get-started/yjs-superdoc-javascript.mdx
index e005c9b8cce..a981c2b7525 100644
--- a/docs/pages/get-started/yjs-superdoc-javascript.mdx
+++ b/docs/pages/get-started/yjs-superdoc-javascript.mdx
@@ -84,13 +84,17 @@ collaboration to your JavaScript application using the APIs from the
const yDoc = yProvider.getYDoc();
function initSuperDoc() {
+ // Get the current user's info from Liveblocks
+ const { id, info } = room.getSelf();
+
new SuperDoc({
selector: "#superdoc",
toolbar: "#superdoc-toolbar",
documentMode: "editing",
user: {
- name: "User " + Math.floor(Math.random() * 1000),
- email: "user@example.com",
+ email: id,
+ name: info?.name ?? "Anonymous",
+ image: info?.avatar ?? undefined,
},
modules: {
// The collaboration contract is the same for every Yjs provider:
diff --git a/docs/pages/get-started/yjs-superdoc-nextjs.mdx b/docs/pages/get-started/yjs-superdoc-nextjs.mdx
index 42e462d6cf4..31d9dc0b5d3 100644
--- a/docs/pages/get-started/yjs-superdoc-nextjs.mdx
+++ b/docs/pages/get-started/yjs-superdoc-nextjs.mdx
@@ -151,7 +151,11 @@ collaboration to your Next.js application using the APIs from the
diff --git a/docs/pages/get-started/yjs-superdoc-react.mdx b/docs/pages/get-started/yjs-superdoc-react.mdx
index a906cc8660c..3f12d292123 100644
--- a/docs/pages/get-started/yjs-superdoc-react.mdx
+++ b/docs/pages/get-started/yjs-superdoc-react.mdx
@@ -151,7 +151,11 @@ collaboration to your React application using the APIs from the
diff --git a/docs/pages/get-started/yjs-superdoc-svelte.mdx b/docs/pages/get-started/yjs-superdoc-svelte.mdx
index bc5e208d202..be01ca343b3 100644
--- a/docs/pages/get-started/yjs-superdoc-svelte.mdx
+++ b/docs/pages/get-started/yjs-superdoc-svelte.mdx
@@ -76,13 +76,17 @@ collaboration to your Svelte application using the APIs from the
let superdoc;
function initSuperDoc() {
+ // Get the current user's info from Liveblocks
+ const { id, info } = room.getSelf();
+
superdoc = new SuperDoc({
selector: "#superdoc",
toolbar: "#superdoc-toolbar",
documentMode: "editing",
user: {
- name: "User " + Math.floor(Math.random() * 1000),
- email: "user@example.com",
+ email: id,
+ name: info?.name ?? "Anonymous",
+ image: info?.avatar ?? undefined,
},
modules: {
// The collaboration contract is the same for every Yjs provider:
diff --git a/docs/pages/get-started/yjs-superdoc-vuejs.mdx b/docs/pages/get-started/yjs-superdoc-vuejs.mdx
index 9aee1517832..39722887c78 100644
--- a/docs/pages/get-started/yjs-superdoc-vuejs.mdx
+++ b/docs/pages/get-started/yjs-superdoc-vuejs.mdx
@@ -75,13 +75,17 @@ collaboration to your Vue.js application using the APIs from the
let superdoc = null;
function initSuperDoc() {
+ // Get the current user's info from Liveblocks
+ const { id, info } = room.getSelf();
+
superdoc = new SuperDoc({
selector: "#superdoc",
toolbar: "#superdoc-toolbar",
documentMode: "editing",
user: {
- name: "User " + Math.floor(Math.random() * 1000),
- email: "user@example.com",
+ email: id,
+ name: info?.name ?? "Anonymous",
+ image: info?.avatar ?? undefined,
},
modules: {
// The collaboration contract is the same for every Yjs provider:
diff --git a/examples/nextjs-yjs-superdoc/src/components/CollaborativeEditor.tsx b/examples/nextjs-yjs-superdoc/src/components/CollaborativeEditor.tsx
index ff4d4416aca..ef49f7d1e28 100644
--- a/examples/nextjs-yjs-superdoc/src/components/CollaborativeEditor.tsx
+++ b/examples/nextjs-yjs-superdoc/src/components/CollaborativeEditor.tsx
@@ -36,7 +36,11 @@ export function CollaborativeEditor() {
diff --git a/examples/nextjs-yjs-superdoc/src/globals.css b/examples/nextjs-yjs-superdoc/src/globals.css
index a3faa0acf8c..902712f0f8e 100644
--- a/examples/nextjs-yjs-superdoc/src/globals.css
+++ b/examples/nextjs-yjs-superdoc/src/globals.css
@@ -34,3 +34,8 @@ main {
padding: 16px;
background: #e8eaee;
}
+
+.presentation-editor__remote-label {
+ margin: -5px 0 0 -1px;
+ border-bottom-left-radius: 0 !important;
+}
diff --git a/packages/liveblocks-server/src/MetadataDB.ts b/packages/liveblocks-server/src/MetadataDB.ts
index 8b60202c7e0..42162cf9efa 100644
--- a/packages/liveblocks-server/src/MetadataDB.ts
+++ b/packages/liveblocks-server/src/MetadataDB.ts
@@ -15,18 +15,18 @@
* along with this program. If not, see .
*/
-import type { Awaitable, Json } from "@liveblocks/core";
+import type { Json } from "@liveblocks/core";
import type { Decoder } from "decoders";
import type { IStorageDriver } from "~/interfaces";
export interface MetadataDB {
// Getter supports optional decoder
- get(key: string): Promise;
- get(decoder: Decoder, key: string): Promise;
+ get(key: string): Json | undefined;
+ get(decoder: Decoder, key: string): T | undefined;
- put(key: string, value: Json): Awaitable;
- delete(key: string): Awaitable;
+ put(key: string, value: Json): void;
+ delete(key: string): void;
}
/**
@@ -34,19 +34,13 @@ export interface MetadataDB {
* functionality, including type-safe reads.
*/
export function makeMetadataDB(driver: IStorageDriver): MetadataDB {
- async function get(key: string): Promise;
- async function get(
- decoder: Decoder,
- key: string
- ): Promise;
- async function get(
- a1: string | Decoder,
- a2?: string
- ): Promise {
+ function get(key: string): Json | undefined;
+ function get(decoder: Decoder, key: string): T | undefined;
+ function get(a1: string | Decoder, a2?: string): T | Json | undefined {
if (a2 === undefined) {
- return await driver.get_meta(a1 as string);
+ return driver.get_meta(a1 as string);
} else {
- return (a1 as Decoder).value(await driver.get_meta(a2));
+ return (a1 as Decoder).value(driver.get_meta(a2));
}
}
diff --git a/packages/liveblocks-server/src/Room.ts b/packages/liveblocks-server/src/Room.ts
index 15e8dc8e476..4cdf335aa8d 100644
--- a/packages/liveblocks-server/src/Room.ts
+++ b/packages/liveblocks-server/src/Room.ts
@@ -617,6 +617,7 @@ export class Room {
* to call multiple times. After awaiting `room.load()` the Room is ready to
* be used.
*/
+ // XXXX We should now be able to remove this asyncness here too
public async load(ctx?: C): Promise {
if (this._loadData$ === null) {
this._data = null;
@@ -657,15 +658,13 @@ export class Room {
* connection is established. If the socket is never established, this
* unused Ticket will simply get garbage collected.
*/
- public async createTicket(
- options?: CreateTicketOptions
- ): Promise> {
- const actor$ = options?.actor ?? this.getNextActor();
+ public createTicket(options?: CreateTicketOptions): Ticket {
+ const actor = options?.actor ?? this.getNextActor();
const sessionKey = nanoid() as SessionKey;
const info = options?.info;
const ticket: Ticket = {
version: options?.version ?? HIGHEST_PROTOCOL_VERSION,
- actor: await actor$,
+ actor,
sessionKey,
meta: options?.meta,
publicMeta: options?.publicMeta,
@@ -680,10 +679,11 @@ export class Room {
return ticket;
}
- public async createBackendSession_experimental(): Promise<
- [session: BackendSession, outgoingMessages: jstring[]]
- > {
- const ticket = (await this.createTicket()) as Ticket;
+ public createBackendSession_experimental(): [
+ session: BackendSession,
+ outgoingMessages: jstring[],
+ ] {
+ const ticket = this.createTicket() as Ticket;
const capturedServerMsgs: jstring[] = [];
const stub = {
send: (data) => {
@@ -1069,7 +1069,7 @@ export class Room {
* Upsert a leased session. Creates a new session if it doesn't exist (or is expired),
* or updates an existing session with merged presence.
*/
- public async upsertLeasedSession(
+ public upsertLeasedSession(
sessionId: string,
presence: JsonObject,
ttl: number,
@@ -1081,18 +1081,18 @@ export class Room {
"Pass a `defer` callback to upsertLeasedSession() to collect async side effects."
);
}
- ): Promise {
- const existingSession = await this.driver.get_leased_session(sessionId);
+ ): void {
+ const existingSession = this.driver.get_leased_session(sessionId);
const isExpired =
existingSession !== undefined && isLeasedSessionExpired(existingSession);
if (isExpired) {
- await this.deleteLeasedSession(existingSession, ctx, defer);
+ this.deleteLeasedSession(existingSession, ctx, defer);
}
if (existingSession === undefined || isExpired) {
// Creating new session (or was expired)
- const actorId = await this.getNextActor();
+ const actorId = this.getNextActor();
const now = Date.now();
const session: LeasedSession = {
sessionId,
@@ -1103,7 +1103,7 @@ export class Room {
actorId,
};
- await this.driver.put_leased_session(session);
+ this.driver.put_leased_session(session);
// Broadcast USER_JOINED to all existing sessions
this.sendToAll(
@@ -1143,7 +1143,7 @@ export class Room {
ttl,
};
- await this.driver.put_leased_session(updatedSession);
+ this.driver.put_leased_session(updatedSession);
// Broadcast UPDATE_PRESENCE WITHOUT targetActor to all sessions (patch)
this.sendToAll(
@@ -1172,7 +1172,7 @@ export class Room {
}
): Promise {
await this.load(ctx);
- const sessions = await this.driver.list_leased_sessions();
+ const sessions = this.driver.list_leased_sessions();
const validSessions: LeasedSession[] = [];
const toDelete: LeasedSession[] = [];
for (const [_, session] of sessions) {
@@ -1184,7 +1184,7 @@ export class Room {
}
for (const session of toDelete) {
- await this.deleteLeasedSession(session, ctx, defer);
+ this.deleteLeasedSession(session, ctx, defer);
}
return validSessions;
@@ -1193,7 +1193,7 @@ export class Room {
/**
* Delete a server session and broadcast USER_LEFT to all sessions.
*/
- public async deleteLeasedSession(
+ public deleteLeasedSession(
session: LeasedSession,
ctx?: C,
defer: (promise: Promise) => void = () => {
@@ -1202,7 +1202,7 @@ export class Room {
"Pass a `defer` callback to deleteLeasedSession() to collect async side effects."
);
}
- ): Promise {
+ ): void {
// Broadcast USER_LEFT to all sessions
this.sendToAll(
{
@@ -1212,7 +1212,7 @@ export class Room {
ctx,
defer
);
- await this.driver.delete_leased_session(session.sessionId);
+ this.driver.delete_leased_session(session.sessionId);
}
/**
@@ -1228,9 +1228,9 @@ export class Room {
}
): Promise {
await this.load(ctx);
- const sessions = await this.driver.list_leased_sessions();
+ const sessions = this.driver.list_leased_sessions();
for (const [_, session] of sessions) {
- await this.deleteLeasedSession(session, ctx, defer);
+ this.deleteLeasedSession(session, ctx, defer);
}
}
@@ -1241,59 +1241,56 @@ export class Room {
/**
* List feeds with pagination and filtering.
*/
- public async listFeeds(options?: ListFeedsOptions): Promise {
- return await this.driver.list_feeds(options);
+ public listFeeds(options?: ListFeedsOptions): ListFeedsResult {
+ return this.driver.list_feeds(options);
}
/**
* Get a specific feed by feed ID.
*/
- public async getFeed(feedId: string): Promise {
- return await this.driver.get_feed(feedId);
+ public getFeed(feedId: string): Feed | undefined {
+ return this.driver.get_feed(feedId);
}
/**
* Create a new feed.
* If timestamp is not provided, current server time is used.
*/
- public async createFeed(
+ public createFeed(
feed: Omit & { timestamp?: number }
- ): Promise {
+ ): Feed {
const now = feed.timestamp ?? Date.now();
const fullFeed: Feed = {
...feed,
createdAt: now,
updatedAt: now,
};
- await this.driver.create_feed(fullFeed);
+ this.driver.create_feed(fullFeed);
return fullFeed;
}
/**
* Update a feed's metadata.
*/
- public async updateFeedMetadata(
- feedId: string,
- metadata: Json
- ): Promise {
- await this.driver.update_feed_metadata(feedId, metadata);
+ public updateFeedMetadata(feedId: string, metadata: Json): void {
+ this.driver.update_feed_metadata(feedId, metadata);
}
/**
* Delete a feed.
*/
- public async deleteFeed(feedId: string): Promise {
- await this.driver.delete_feed(feedId);
+ public deleteFeed(feedId: string): void {
+ this.driver.delete_feed(feedId);
}
/**
* List feed messages for a feed with pagination.
*/
- public async listFeedMessages(
+ public listFeedMessages(
feedId: string,
options?: ListFeedMessagesOptions
- ): Promise {
- return await this.driver.list_feed_messages(feedId, options);
+ ): ListFeedMessagesResult {
+ return this.driver.list_feed_messages(feedId, options);
}
/**
@@ -1301,11 +1298,11 @@ export class Room {
* If message id is not provided, a unique ID is automatically generated.
* If timestamp is not provided, current server time is used.
*/
- public async addFeedMessage(
+ public addFeedMessage(
feedId: string,
message: Omit &
Partial> & { timestamp?: number }
- ): Promise {
+ ): FeedMessage {
const now = message.timestamp ?? Date.now();
const fullMessage: FeedMessage = {
id: message.id ?? nanoid(),
@@ -1313,7 +1310,7 @@ export class Room {
updatedAt: now,
data: message.data,
};
- await this.driver.add_feed_message(feedId, fullMessage);
+ this.driver.add_feed_message(feedId, fullMessage);
return fullMessage;
}
@@ -1321,13 +1318,13 @@ export class Room {
* Update a feed message's data.
* Returns the updated message.
*/
- public async updateFeedMessage(
+ public updateFeedMessage(
feedId: string,
messageId: string,
data: Json,
timestamp?: number
- ): Promise {
- return await this.driver.update_feed_message(
+ ): FeedMessage {
+ return this.driver.update_feed_message(
feedId,
messageId,
data,
@@ -1338,11 +1335,8 @@ export class Room {
/**
* Delete a feed message.
*/
- public async deleteFeedMessage(
- feedId: string,
- messageId: string
- ): Promise {
- await this.driver.delete_feed_message(feedId, messageId);
+ public deleteFeedMessage(feedId: string, messageId: string): void {
+ this.driver.delete_feed_message(feedId, messageId);
}
/**
@@ -1409,6 +1403,13 @@ export class Room {
}
}
+ /**
+ * Returns a new, unique, actor ID.
+ */
+ public getNextActor(): ActorID {
+ return this.driver.next_actor() as ActorID;
+ }
+
// ------------------------------------------------------------------------------------
// Private APIs
// ------------------------------------------------------------------------------------
@@ -1442,13 +1443,6 @@ export class Room {
await this.hooks.onRoomDidLoad?.(ctx);
}
- /**
- * Returns a new, unique, actor ID.
- */
- private async getNextActor(): Promise {
- return (await this.driver.next_actor()) as ActorID;
- }
-
/**
* Iterates over all *other* Sessions and their session keys.
*/
@@ -1694,7 +1688,7 @@ export class Room {
// semantics to provide snapshot isolation.
this.driver.bump_storage_version?.();
- const result = await this.storage.applyOps(msg.ops);
+ const result = this.storage.applyOps(msg.ops);
const opsToForward: ServerWireOp[] = result.flatMap((r) =>
r.action === "accepted" ? [r.op] : []
@@ -1807,7 +1801,7 @@ export class Room {
// Feed messages
case FeedMsgCode.FETCH_FEEDS: {
const fetchMsg = msg;
- const [result, err] = await tryCatch(
+ const [result, err] = await tryCatch(() =>
this.listFeeds({
cursor: fetchMsg.cursor,
since: fetchMsg.since,
@@ -1830,7 +1824,7 @@ export class Room {
case FeedMsgCode.FETCH_FEED_MESSAGES: {
const fetchMsg = msg;
- const [result, err] = await tryCatch(
+ const [result, err] = await tryCatch(() =>
this.listFeedMessages(fetchMsg.feedId, {
cursor: fetchMsg.cursor,
since: fetchMsg.since,
@@ -1853,7 +1847,7 @@ export class Room {
case FeedMsgCode.ADD_FEED: {
const addMsg = msg;
- const [feed, err] = await tryCatch(
+ const [feed, err] = await tryCatch(() =>
this.createFeed({
feedId: addMsg.feedId,
metadata: (addMsg.metadata as Json) ?? {},
@@ -1874,14 +1868,14 @@ export class Room {
case FeedMsgCode.UPDATE_FEED: {
const updateMsg = msg;
- const [, metaErr] = await tryCatch(
+ const [, metaErr] = await tryCatch(() =>
this.updateFeedMetadata(updateMsg.feedId, updateMsg.metadata as Json)
);
if (metaErr) {
replyImmediately(feedFailureServerMsg(updateMsg.requestId, metaErr));
break;
}
- const feed = await this.getFeed(updateMsg.feedId);
+ const feed = this.getFeed(updateMsg.feedId);
if (!feed) {
replyImmediately(
feedRequestFailed(
@@ -1902,7 +1896,7 @@ export class Room {
case FeedMsgCode.DELETE_FEED: {
const deleteMsg = msg;
- const [, err] = await tryCatch(this.deleteFeed(deleteMsg.feedId));
+ const [, err] = await tryCatch(() => this.deleteFeed(deleteMsg.feedId));
if (err) {
replyImmediately(feedFailureServerMsg(deleteMsg.requestId, err));
break;
@@ -1918,7 +1912,7 @@ export class Room {
case FeedMsgCode.ADD_FEED_MESSAGE: {
const addMsg = msg;
- const [message, err] = await tryCatch(
+ const [message, err] = await tryCatch(() =>
this.addFeedMessage(addMsg.feedId, {
data: addMsg.data as Json,
id: addMsg.id,
@@ -1940,7 +1934,7 @@ export class Room {
case FeedMsgCode.UPDATE_FEED_MESSAGE: {
const updateMsg = msg;
- const [message, err] = await tryCatch(
+ const [message, err] = await tryCatch(() =>
this.updateFeedMessage(
updateMsg.feedId,
updateMsg.messageId,
@@ -1963,7 +1957,7 @@ export class Room {
case FeedMsgCode.DELETE_FEED_MESSAGE: {
const deleteMsg = msg;
- const [, err] = await tryCatch(
+ const [, err] = await tryCatch(() =>
this.deleteFeedMessage(deleteMsg.feedId, deleteMsg.messageId)
);
if (err) {
diff --git a/packages/liveblocks-server/src/Storage.ts b/packages/liveblocks-server/src/Storage.ts
index 19990c26f03..bd98e17f0b9 100644
--- a/packages/liveblocks-server/src/Storage.ts
+++ b/packages/liveblocks-server/src/Storage.ts
@@ -15,11 +15,7 @@
* along with this program. If not, see .
*/
-import type {
- Awaitable,
- SerializedChild,
- SerializedCrdt,
-} from "@liveblocks/core";
+import type { SerializedChild, SerializedCrdt } from "@liveblocks/core";
import {
asPos,
assertNever,
@@ -123,7 +119,7 @@ export class Storage {
}
// REFACTOR NOTE: Eventually raw_iter_nodes has to be removed here
- raw_iter_nodes(): Awaitable> {
+ raw_iter_nodes(): Iterable<[string, SerializedCrdt]> {
return this.coreDriver.raw_iter_nodes();
}
@@ -133,8 +129,11 @@ export class Storage {
* Storage tree, and special keys where we store usage metrics, or room
* metadata.
*/
+ // XXXX Now that the driver has become fully sync, we no longer need this
+ // .load() construct. We should be able to refactor it away.
+ // eslint-disable-next-line @typescript-eslint/require-await
async load(logger: Logger): Promise {
- this._loadedDriver = await this.coreDriver.load_nodes_api(logger);
+ this._loadedDriver = this.coreDriver.load_nodes_api(logger);
}
unload(): void {
@@ -144,10 +143,10 @@ export class Storage {
/**
* Applies a batch of Ops.
*/
- async applyOps(ops: ClientWireOp[]): Promise {
+ applyOps(ops: ClientWireOp[]): ApplyOpResult[] {
const results: ApplyOpResult[] = [];
for (const op of ops) {
- results.push(await this.applyOp(op));
+ results.push(this.applyOp(op));
}
return results;
}
@@ -159,25 +158,25 @@ export class Storage {
/**
* Applies a single Op.
*/
- private async applyOp(op: ClientWireOp): Promise {
+ private applyOp(op: ClientWireOp): ApplyOpResult {
switch (op.type) {
case OpCode.CREATE_LIST:
case OpCode.CREATE_MAP:
case OpCode.CREATE_REGISTER:
case OpCode.CREATE_OBJECT:
- return await this.applyCreateOp(op);
+ return this.applyCreateOp(op);
case OpCode.UPDATE_OBJECT:
- return await this.applyUpdateObjectOp(op);
+ return this.applyUpdateObjectOp(op);
case OpCode.SET_PARENT_KEY:
- return await this.applySetParentKeyOp(op);
+ return this.applySetParentKeyOp(op);
case OpCode.DELETE_OBJECT_KEY:
- return await this.applyDeleteObjectKeyOp(op);
+ return this.applyDeleteObjectKeyOp(op);
case OpCode.DELETE_CRDT:
- return await this.applyDeleteCrdtOp(op);
+ return this.applyDeleteCrdtOp(op);
// istanbul ignore next
default:
@@ -189,7 +188,7 @@ export class Storage {
}
}
- private async applyCreateOp(op: CreateOp & HasOpId): Promise {
+ private applyCreateOp(op: CreateOp & HasOpId): ApplyOpResult {
if (this.loadedDriver.has_node(op.id)) {
// Node already exists, the operation is ignored
return ignore(op);
@@ -217,7 +216,7 @@ export class Storage {
case CrdtType.MAP:
// Children of maps and objects require no special needs
- await this.loadedDriver.set_child(op.id, node, true);
+ this.loadedDriver.set_child(op.id, node, true);
return accept(op);
case CrdtType.LIST:
@@ -235,10 +234,10 @@ export class Storage {
}
}
- private async createChildAsListItem(
+ private createChildAsListItem(
op: CreateOp & HasOpId,
node: SerializedChild
- ): Promise {
+ ): ApplyOpResult {
// The default intent, when not explicitly provided, is to insert, not set,
// into the list.
const intent: "insert" | "set" | "push" = op.intent ?? "insert";
@@ -247,15 +246,11 @@ export class Storage {
if (intent === "insert") {
// Insert at the client's preferred position, resolving any collision to a
// nearby free slot.
- return this.acceptAndFix(
- op,
- node,
- await this.insertIntoList(op.id, node)
- );
+ return this.acceptAndFix(op, node, this.insertIntoList(op.id, node));
} else if (intent === "push") {
// Server-authoritative append: place the node after the authoritative
// end of the list (see `appendToList`), regardless of the client's preference.
- return this.acceptAndFix(op, node, await this.appendToList(op.id, node));
+ return this.acceptAndFix(op, node, this.appendToList(op.id, node));
} else if (intent === "set") {
let fix: FixOp | undefined;
@@ -277,7 +272,7 @@ export class Storage {
: undefined;
if (deletedId !== undefined) {
- await this.loadedDriver.delete_node(deletedId);
+ this.loadedDriver.delete_node(deletedId);
}
const prevItemId = this.loadedDriver.get_child_at(
@@ -294,7 +289,7 @@ export class Storage {
};
}
- await this.loadedDriver.set_child(op.id, node, true);
+ this.loadedDriver.set_child(op.id, node, true);
return accept(op, fix);
} else {
@@ -321,31 +316,25 @@ export class Storage {
return accept(op);
}
- private async applyDeleteObjectKeyOp(
+ private applyDeleteObjectKeyOp(
op: DeleteObjectKeyOp & HasOpId
- ): Promise {
- await this.loadedDriver.delete_child_key(op.id, op.key);
+ ): ApplyOpResult {
+ this.loadedDriver.delete_child_key(op.id, op.key);
return accept(op);
}
- private async applyUpdateObjectOp(
- op: UpdateObjectOp & HasOpId
- ): Promise {
- await this.loadedDriver.set_object_data(op.id, op.data, true);
+ private applyUpdateObjectOp(op: UpdateObjectOp & HasOpId): ApplyOpResult {
+ this.loadedDriver.set_object_data(op.id, op.data, true);
return accept(op);
}
- private async applyDeleteCrdtOp(
- op: DeleteCrdtOp & HasOpId
- ): Promise {
- await this.loadedDriver.delete_node(op.id);
+ private applyDeleteCrdtOp(op: DeleteCrdtOp & HasOpId): ApplyOpResult {
+ this.loadedDriver.delete_node(op.id);
return accept(op);
}
- private async applySetParentKeyOp(
- op: SetParentKeyOp & HasOpId
- ): Promise {
- const newPosition = await this.moveToPosInList(op.id, op.parentKey);
+ private applySetParentKeyOp(op: SetParentKeyOp & HasOpId): ApplyOpResult {
+ const newPosition = this.moveToPosInList(op.id, op.parentKey);
if (newPosition === undefined) {
// The operation got rejected because it didn't make sense, ignore it
return ignore(op);
@@ -376,16 +365,13 @@ export class Storage {
*
* Returns the key that was used for the insertion.
*/
- private async insertIntoList(
- id: string,
- node: SerializedChild
- ): Promise {
+ private insertIntoList(id: string, node: SerializedChild): string {
// First, compute the key to use to insert this node
const key = this.findFreeListPosition(node.parentId, asPos(node.parentKey));
if (key !== node.parentKey) {
node = { ...node, parentKey: key };
}
- await this.loadedDriver.set_child(id, node);
+ this.loadedDriver.set_child(id, node);
return node.parentKey;
}
@@ -399,17 +385,14 @@ export class Storage {
*
* Returns the final key that was used for the insertion.
*/
- private async appendToList(
- id: string,
- node: SerializedChild
- ): Promise {
+ private appendToList(id: string, node: SerializedChild): string {
const lastPos = this.loadedDriver.get_last_sibling(node.parentId);
const preferredPos = asPos(node.parentKey);
const finalKey =
lastPos === undefined || preferredPos > lastPos
? preferredPos
: makePosition(lastPos);
- await this.loadedDriver.set_child(
+ this.loadedDriver.set_child(
id,
finalKey !== node.parentKey ? { ...node, parentKey: finalKey } : node
);
@@ -428,10 +411,7 @@ export class Storage {
* Will return `undefined` if this action could not be interpreted. Will be
* a no-op for non-list items.
*/
- private async moveToPosInList(
- id: string,
- targetKey: string
- ): Promise {
+ private moveToPosInList(id: string, targetKey: string): string | undefined {
const node = this.loadedDriver.get_node(id);
if (node?.parentId === undefined) {
return; /* reject */
@@ -450,7 +430,7 @@ export class Storage {
// First, compute the key to use to insert this node
const key = this.findFreeListPosition(node.parentId, asPos(targetKey));
if (key !== node.parentKey) {
- await this.loadedDriver.move_sibling(id, key);
+ this.loadedDriver.move_sibling(id, key);
}
return key;
}
diff --git a/packages/liveblocks-server/src/YjsStorage.ts b/packages/liveblocks-server/src/YjsStorage.ts
index 57067d6d377..b8a48b9cf91 100644
--- a/packages/liveblocks-server/src/YjsStorage.ts
+++ b/packages/liveblocks-server/src/YjsStorage.ts
@@ -36,7 +36,7 @@ export class YjsStorage {
private readonly doc: Y.Doc = new Y.Doc(); // the root document
private readonly lastSnapshotById = new Map();
- private readonly initPromisesById: Map> = new Map();
+ private readonly initPromisesById: Map = new Map();
private readonly storedKeysById: Map = new Map();
constructor(
@@ -56,9 +56,9 @@ export class YjsStorage {
// Public API
// ------------------------------------------------------------------------------------
+ // eslint-disable-next-line @typescript-eslint/require-await
public async getYDoc(logger: Logger, docId: YDocId): Promise {
- const doc = await this.loadDocByIdIfNotAlreadyLoaded(logger, docId);
- return doc;
+ return this.loadDocByIdIfNotAlreadyLoaded(logger, docId);
}
/**
@@ -170,7 +170,7 @@ export class YjsStorage {
// Check the snapshot before/after to see if the update had an effect
const updated = !Y.equalSnapshots(beforeSnapshot, afterSnapshot);
if (updated) {
- await this.handleYDocUpdate(doc, updateAsU8, isV2);
+ this.handleYDocUpdate(doc, updateAsU8, isV2);
}
return {
@@ -186,25 +186,24 @@ export class YjsStorage {
}
}
- public loadDocByIdIfNotAlreadyLoaded(
- logger: Logger,
- docId: YDocId
- ): Promise {
- let loaded$ = this.initPromisesById.get(docId);
+ public loadDocByIdIfNotAlreadyLoaded(logger: Logger, docId: YDocId): Y.Doc {
+ let loaded = this.initPromisesById.get(docId);
let doc = docId === ROOT_YDOC_ID ? this.doc : this.findYSubdocByGuid(docId);
if (!doc) {
// An API call can load a subdoc without the root doc (this._doc) being loaded, we account for that by just instantiating a doc here.
doc = new Y.Doc();
}
- if (loaded$ === undefined) {
- loaded$ = this._loadYDocFromDurableStorage(logger, doc, docId);
- this.initPromisesById.set(docId, loaded$);
+ if (loaded === undefined) {
+ loaded = this._loadYDocFromDurableStorage(logger, doc, docId);
+ this.initPromisesById.set(docId, loaded);
}
- return loaded$;
+ return loaded;
}
+ // XXXX We should now be able to remove this asyncness here too
+ // eslint-disable-next-line @typescript-eslint/require-await
public async load(logger: Logger): Promise {
- await this.loadDocByIdIfNotAlreadyLoaded(logger, ROOT_YDOC_ID);
+ this.loadDocByIdIfNotAlreadyLoaded(logger, ROOT_YDOC_ID);
}
/**
@@ -246,27 +245,25 @@ export class YjsStorage {
}
// compact the updates into a single update and write it to the durable storage
- private _compactYJSUpdates = async (
+ private _compactYJSUpdates = (
doc: Y.Doc,
docId: YDocId,
storedKeys: string[]
- ): Promise => {
+ ): void => {
const compactedUpdate = Y.encodeStateAsUpdate(doc);
const newKey = nanoid();
- await this.driver.write_y_updates(docId, newKey, compactedUpdate);
+ this.driver.write_y_updates(docId, newKey, compactedUpdate);
// Todo: after we kill the kv driver, we should have an overwrite method in the driverso we don't need to delete and write
- await this.driver.delete_y_updates(docId, storedKeys);
+ this.driver.delete_y_updates(docId, storedKeys);
this.storedKeysById.set(docId, [newKey]);
};
- private _loadYDocFromDurableStorage = async (
+ private _loadYDocFromDurableStorage = (
_logger: Logger,
doc: Y.Doc,
docId: YDocId
- ): Promise => {
- const docUpdates = Object.fromEntries(
- await this.driver.iter_y_updates(docId)
- );
+ ): Y.Doc => {
+ const docUpdates = Object.fromEntries(this.driver.iter_y_updates(docId));
const updates = Object.values(docUpdates);
const beforeSize = updates.reduce((acc, update) => acc + update.length, 0);
const newupdate = Y.mergeUpdates(updates);
@@ -277,7 +274,7 @@ export class YjsStorage {
this.shouldCompactByKeyCount(storedKeys) ||
this.shouldCompactBySize(beforeSize, newupdate.length)
) {
- await this._compactYJSUpdates(doc, docId, storedKeys);
+ this._compactYJSUpdates(doc, docId, storedKeys);
} else {
this.storedKeysById.set(docId, storedKeys);
}
@@ -310,21 +307,22 @@ export class YjsStorage {
}
// gets a subdoc, it will be loaded if not already loaded
+ // eslint-disable-next-line @typescript-eslint/require-await
private async getYSubdoc(logger: Logger, guid: Guid): Promise {
const subdoc = this.findYSubdocByGuid(guid);
if (!subdoc) {
return null;
}
- await this.loadDocByIdIfNotAlreadyLoaded(logger, guid);
+ this.loadDocByIdIfNotAlreadyLoaded(logger, guid);
return subdoc;
}
// When the YJS doc changes, update it in durable storage
- private async handleYDocUpdate(
+ private handleYDocUpdate(
doc: Y.Doc,
update: Uint8Array,
isV2: boolean | undefined
- ): Promise {
+ ): void {
// Todo: in the future, we should pass this detail to the driver so it can store the version as metadata
// this will be easy for sqlite drivers, but not for the KV driver
const v1update = isV2 ? Y.convertUpdateFormatV2ToV1(update) : update;
@@ -335,13 +333,13 @@ export class YjsStorage {
// Every UPDATE_COUNT_THRESHOLD updates, we compact the updates
if (this.shouldCompactByKeyCount(storedKeys)) {
- await this._compactYJSUpdates(doc, docId, storedKeys || []);
+ this._compactYJSUpdates(doc, docId, storedKeys || []);
return;
}
// the whole concept of storing keys is not needed when we kill the kv driver, all of this stuff is trivial in sqlite
const newKey = nanoid();
- await this.driver.write_y_updates(docId, newKey, v1update);
+ this.driver.write_y_updates(docId, newKey, v1update);
// update the stored keys, which we'll need for compaction.
if (!storedKeys) {
diff --git a/packages/liveblocks-server/src/interfaces/IStorageDriver.ts b/packages/liveblocks-server/src/interfaces/IStorageDriver.ts
index e5a195881ba..6031f10c2f2 100644
--- a/packages/liveblocks-server/src/interfaces/IStorageDriver.ts
+++ b/packages/liveblocks-server/src/interfaces/IStorageDriver.ts
@@ -16,7 +16,6 @@
*/
import type {
- Awaitable,
CompactNode,
Json,
JsonObject,
@@ -189,20 +188,20 @@ export interface IStorageDriverNodeAPI {
* If allowOverwrite=true: replace any existing node at this id, deleting its
* entire subtree if it has children.
*/
- set_child(id: string, node: SerializedChild, allowOverwrite?: boolean): Awaitable; // prettier-ignore
+ set_child(id: string, node: SerializedChild, allowOverwrite?: boolean): void;
/**
* Change a node's parentKey, effectively repositioning the node within its
* parent. The new position must be free.
* Throw if another node already occupies (parentId, newPos).
*/
- move_sibling(id: string, newPos: Pos): Awaitable;
+ move_sibling(id: string, newPos: Pos): void;
/**
* Delete a node and its entire subtree recursively.
* Ignore if id="root" (root is immortal).
*/
- delete_node(id: string): Awaitable;
+ delete_node(id: string): void;
/**
* Delete a key from node `id`. Handle two cases:
@@ -213,7 +212,7 @@ export interface IStorageDriverNodeAPI {
*
* No-op if neither applies or if the node doesn't exist.
*/
- delete_child_key(id: string, key: string): Awaitable;
+ delete_child_key(id: string, key: string): void;
/**
* Replace the data object of an OBJECT node.
@@ -223,7 +222,7 @@ export interface IStorageDriverNodeAPI {
* If allowOverwrite=true: first delete any conflicting children (and their
* entire subtrees), then set the data.
*/
- set_object_data(id: string, data: JsonObject, allowOverwrite?: boolean): Awaitable; // prettier-ignore
+ set_object_data(id: string, data: JsonObject, allowOverwrite?: boolean): void;
/**
* Return a readable snapshot of the storage tree.
@@ -251,7 +250,12 @@ export interface IStorageDriver {
* After DANGEROUSLY_reset_nodes(), any previously-loaded instance is
* invalid—must call this again to get a fresh one.
*/
- load_nodes_api(logger: Logger): Awaitable;
+ // XXXX Now that this method has become sync, we could rip it out entirely and
+ // just move the methods from the IStorageDriverNodeAPI interface up to
+ // IStorageDriver. The main reason this interface existed was to support the
+ // KV case which was asynchronous. None of our remaining implementations are
+ // async any longer, so... YAGNI!
+ load_nodes_api(logger: Logger): IStorageDriverNodeAPI;
/**
* Delete all CRDT nodes and replace them with the given document.
@@ -260,14 +264,14 @@ export interface IStorageDriver {
*
* Pass `{ liveblocksType: "LiveObject", data: {} }` to reset to an empty root.
*/
- DANGEROUSLY_reset_nodes(doc: PlainLsonObject): Awaitable;
+ DANGEROUSLY_reset_nodes(doc: PlainLsonObject): void;
/**
* Read raw node data directly from storage.
*
* @internal Test-only API
*/
- raw_iter_nodes(): Awaitable>;
+ raw_iter_nodes(): Iterable<[string, SerializedCrdt]>;
// ---------------------------------------------------------------------------
// Metadata APIs (key-value store, isolated from nodes)
@@ -276,17 +280,17 @@ export interface IStorageDriver {
/**
* Return the value for `key`, or undefined if not set.
*/
- get_meta(key: string): Awaitable;
+ get_meta(key: string): Json | undefined;
/**
* Store `value` under `key`. Overwrite any existing value.
*/
- put_meta(key: string, value: Json): Awaitable;
+ put_meta(key: string, value: Json): void;
/**
* Delete the value under `key`. No-op if not set.
*/
- delete_meta(key: string): Awaitable;
+ delete_meta(key: string): void;
// ---------------------------------------------------------------------------
// System APIs
@@ -296,7 +300,7 @@ export interface IStorageDriver {
* Return a unique actor ID. Each call must return a distinct integer ≥ 0.
* Concurrent calls must never return duplicates.
*/
- next_actor(): Awaitable;
+ next_actor(): number;
/**
* If defined, called once before each storage mutation batch. Can be used by
@@ -311,23 +315,23 @@ export interface IStorageDriver {
/**
* Return all Yjs updates for docId as [key, data] pairs. Return empty if none.
*/
- iter_y_updates(docId: YDocId): Awaitable>; // prettier-ignore
+ iter_y_updates(docId: YDocId): Iterable<[string, Uint8Array]>;
/**
* Store a Yjs update under (docId, key). Overwrite if key exists.
*/
- write_y_updates(docId: YDocId, key: string, data: Uint8Array): Awaitable; // prettier-ignore
+ write_y_updates(docId: YDocId, key: string, data: Uint8Array): void;
/**
* Delete the specified keys for docId.
*/
- delete_y_updates(docId: YDocId, keys: string[]): Awaitable; // prettier-ignore
+ delete_y_updates(docId: YDocId, keys: string[]): void;
/**
* Delete ALL Yjs updates across ALL documents.
* @private Test-only: never use in production.
*/
- DANGEROUSLY_wipe_all_y_updates(): Awaitable;
+ DANGEROUSLY_wipe_all_y_updates(): void;
// ---------------------------------------------------------------------------
// Leased Session APIs (key-value store for leased sessions)
@@ -338,28 +342,26 @@ export interface IStorageDriver {
* Note: Does NOT filter by expiration - returns all stored sessions.
* Expiration logic is handled at the Room.ts level.
*/
- list_leased_sessions(): Awaitable<
- Iterable<[sessionId: string, session: LeasedSession]>
- >;
+ list_leased_sessions(): Iterable<[sessionId: string, session: LeasedSession]>;
/**
* Get a specific leased session by session ID.
* Note: Does NOT check expiration - returns the stored session if it exists.
* Expiration logic is handled at the Room.ts level.
*/
- get_leased_session(sessionId: string): Awaitable;
+ get_leased_session(sessionId: string): LeasedSession | undefined;
/**
* Create or update a leased session.
* Note: This is a full replace operation - the caller is responsible for
* merging/patching presence if needed.
*/
- put_leased_session(session: LeasedSession): Awaitable;
+ put_leased_session(session: LeasedSession): void;
/**
* Delete a leased session by session ID.
*/
- delete_leased_session(sessionId: string): Awaitable;
+ delete_leased_session(sessionId: string): void;
/**
* Return the number of storage rows written since last call to this method,
@@ -375,7 +377,7 @@ export interface IStorageDriver {
* List feeds with pagination, filtering, and metadata querying.
* Feeds are sorted by createdAt descending (newest first).
*/
- list_feeds(options?: ListFeedsOptions): Awaitable;
+ list_feeds(options?: ListFeedsOptions): ListFeedsResult;
/**
* Get a specific feed by feed ID.
@@ -383,26 +385,26 @@ export interface IStorageDriver {
* Use list_feed_messages to retrieve messages for this feed.
* Returns undefined if the feed doesn't exist.
*/
- get_feed(feedId: string): Awaitable;
+ get_feed(feedId: string): Feed | undefined;
/**
* Create a new feed.
* If feedId already exists, throws an error.
*/
- create_feed(feed: Feed): Awaitable;
+ create_feed(feed: Feed): void;
/**
* Update a feed's metadata.
* The feed must exist, otherwise throws an error.
*/
- update_feed_metadata(feedId: string, metadata: Json): Awaitable;
+ update_feed_metadata(feedId: string, metadata: Json): void;
/**
* Delete a feed by feed ID.
* Also deletes all messages associated with the feed (via CASCADE).
* No-op if feed doesn't exist.
*/
- delete_feed(feedId: string): Awaitable;
+ delete_feed(feedId: string): void;
/**
* List feed messages for a feed with pagination.
@@ -411,14 +413,14 @@ export interface IStorageDriver {
list_feed_messages(
feedId: string,
options?: ListFeedMessagesOptions
- ): Awaitable;
+ ): ListFeedMessagesResult;
/**
* Add a message to a feed.
* The message must have id, createdAt, and updatedAt already set (handled by Room layer).
* The feed must exist, otherwise throws an error.
*/
- add_feed_message(feedId: string, message: FeedMessage): Awaitable;
+ add_feed_message(feedId: string, message: FeedMessage): void;
/**
* Update a feed message's data.
@@ -432,11 +434,11 @@ export interface IStorageDriver {
messageId: string,
data: Json,
timestamp?: number
- ): Awaitable;
+ ): FeedMessage;
/**
* Delete a feed message.
* The feed and message must exist, otherwise throws an error.
*/
- delete_feed_message(feedId: string, messageId: string): Awaitable;
+ delete_feed_message(feedId: string, messageId: string): void;
}
diff --git a/packages/liveblocks-server/src/plugins/InMemoryDriver.ts b/packages/liveblocks-server/src/plugins/InMemoryDriver.ts
index a3da51221e5..de6ea7cac01 100644
--- a/packages/liveblocks-server/src/plugins/InMemoryDriver.ts
+++ b/packages/liveblocks-server/src/plugins/InMemoryDriver.ts
@@ -16,7 +16,6 @@
*/
/* eslint-disable @typescript-eslint/explicit-module-boundary-types */
-/* eslint-disable @typescript-eslint/require-await */
import type {
CompactNode,
Json,
@@ -170,29 +169,29 @@ export class InMemoryDriver implements IStorageDriver {
}
}
- async get_meta(key: string) {
+ get_meta(key: string) {
return this._metadb.get(key);
}
- async put_meta(key: string, value: Json) {
+ put_meta(key: string, value: Json) {
this._metadb.set(key, value);
}
- async delete_meta(key: string) {
+ delete_meta(key: string) {
this._metadb.delete(key);
}
- async list_leased_sessions() {
+ list_leased_sessions() {
return this._leasedSessions.entries();
}
- async get_leased_session(sessionId: string) {
+ get_leased_session(sessionId: string) {
return this._leasedSessions.get(sessionId);
}
- async put_leased_session(session: LeasedSession) {
+ put_leased_session(session: LeasedSession) {
this._leasedSessions.set(session.sessionId, session);
}
- async delete_leased_session(sessionId: string) {
+ delete_leased_session(sessionId: string) {
this._leasedSessions.delete(sessionId);
}
@@ -204,7 +203,7 @@ export class InMemoryDriver implements IStorageDriver {
// Feed APIs
// ---------------------------------------------------------------------------
- async list_feeds(options?: ListFeedsOptions): Promise {
+ list_feeds(options?: ListFeedsOptions): ListFeedsResult {
const limit = Math.min(options?.limit ?? 20, 100);
const since = options?.since;
const cursor = options?.cursor;
@@ -285,7 +284,7 @@ export class InMemoryDriver implements IStorageDriver {
return { feeds, nextCursor };
}
- async get_feed(feedId: string): Promise {
+ get_feed(feedId: string): Feed | undefined {
const feed = this._feeds.get(feedId);
if (feed === undefined) {
return undefined;
@@ -294,7 +293,7 @@ export class InMemoryDriver implements IStorageDriver {
return feed;
}
- async create_feed(feed: Feed): Promise {
+ create_feed(feed: Feed): void {
// Check if feed already exists
if (this._feeds.has(feed.feedId)) {
throw new Error(`Feed ${feed.feedId} already exists`);
@@ -309,7 +308,7 @@ export class InMemoryDriver implements IStorageDriver {
});
}
- async update_feed_metadata(feedId: string, metadata: Json): Promise {
+ update_feed_metadata(feedId: string, metadata: Json): void {
const existing = this._feeds.get(feedId);
if (existing === undefined) {
throw new Error(`Feed ${feedId} not found`);
@@ -321,7 +320,7 @@ export class InMemoryDriver implements IStorageDriver {
});
}
- async delete_feed(feedId: string): Promise {
+ delete_feed(feedId: string): void {
// Delete all messages for this feed
const messageKeys: string[] = [];
for (const [key] of this._feedMessages.entries()) {
@@ -337,10 +336,10 @@ export class InMemoryDriver implements IStorageDriver {
this._feeds.delete(feedId);
}
- async list_feed_messages(
+ list_feed_messages(
feedId: string,
options?: ListFeedMessagesOptions
- ): Promise {
+ ): ListFeedMessagesResult {
const limit = Math.min(options?.limit ?? 20, 100);
const since = options?.since;
const cursor = options?.cursor;
@@ -408,7 +407,7 @@ export class InMemoryDriver implements IStorageDriver {
return { messages, nextCursor };
}
- async add_feed_message(feedId: string, message: FeedMessage): Promise {
+ add_feed_message(feedId: string, message: FeedMessage): void {
// Verify feed exists
const feed = this._feeds.get(feedId);
if (feed === undefined) {
@@ -418,12 +417,12 @@ export class InMemoryDriver implements IStorageDriver {
this._feedMessages.set(`${feedId}:${message.id}`, message);
}
- async update_feed_message(
+ update_feed_message(
feedId: string,
messageId: string,
data: Json,
timestamp?: number
- ): Promise {
+ ): FeedMessage {
const key = `${feedId}:${messageId}`;
const message = this._feedMessages.get(key);
@@ -447,7 +446,7 @@ export class InMemoryDriver implements IStorageDriver {
return updatedMessage;
}
- async delete_feed_message(feedId: string, messageId: string): Promise {
+ delete_feed_message(feedId: string, messageId: string): void {
this._feedMessages.delete(`${feedId}:${messageId}`);
}
@@ -455,24 +454,24 @@ export class InMemoryDriver implements IStorageDriver {
return ++this._nextActor;
}
- async iter_y_updates(docId: YDocId) {
+ iter_y_updates(docId: YDocId) {
const prefix = `${docId}@|@`;
return imap(
ifilter(this._ydb.entries(), ([k]) => k.startsWith(prefix)),
([k, v]) => [k.slice(prefix.length), v] as [string, Uint8Array]
);
}
- async write_y_updates(docId: YDocId, key: string, data: Uint8Array) {
+ write_y_updates(docId: YDocId, key: string, data: Uint8Array) {
this._ydb.set(`${docId}@|@${key}`, data);
}
- async delete_y_updates(docId: YDocId, keys: string[]) {
+ delete_y_updates(docId: YDocId, keys: string[]) {
for (const key of keys) {
this._ydb.delete(`${docId}@|@${key}`);
}
}
/** @private Only use this in unit tests, never in production. */
- async DANGEROUSLY_wipe_all_y_updates() {
+ DANGEROUSLY_wipe_all_y_updates() {
this._ydb.clear();
}
@@ -518,11 +517,11 @@ export class InMemoryDriver implements IStorageDriver {
* Inserts a node in the storage tree, deleting any nodes that already exist
* under this key (including all of its children), if any.
*/
- async function set_child(
+ function set_child(
id: string,
node: SerializedChild,
allowOverwrite = false
- ): Promise {
+ ): void {
const parentNode = nodes.get(node.parentId);
// Reject orphans - parent must exist
if (parentNode === undefined) {
@@ -566,7 +565,7 @@ export class InMemoryDriver implements IStorageDriver {
* delete-then-insert would would immediately destroy all (grand)children
* when it's deleted.
*/
- async function move_sibling(id: string, newPos: Pos): Promise {
+ function move_sibling(id: string, newPos: Pos): void {
const node = nodes.get(id);
if (node?.parentId === undefined) {
return;
@@ -591,11 +590,11 @@ export class InMemoryDriver implements IStorageDriver {
* But if `allowOverwrite` is set to true, the conflicting child node (and
* its entire subtree) will be deleted to make room for the new static data.
*/
- async function set_object_data(
+ function set_object_data(
id: string,
data: JsonObject,
allowOverwrite = false
- ): Promise {
+ ): void {
const node = nodes.get(id);
if (node?.type !== CrdtType.OBJECT) {
// Nothing to do
diff --git a/packages/liveblocks-server/test-d/server.test-d.ts b/packages/liveblocks-server/test-d/server.test-d.ts
index 75f012f44fb..6603ac286b1 100644
--- a/packages/liveblocks-server/test-d/server.test-d.ts
+++ b/packages/liveblocks-server/test-d/server.test-d.ts
@@ -37,12 +37,12 @@ async () => {
// Room.createTicket() API
expectType>(
- await room.createTicket({ version: ProtocolVersion.V8 })
+ room.createTicket({ version: ProtocolVersion.V8 })
);
- expectType>(await room.createTicket());
- expectType>(await room.createTicket());
+ expectType>(room.createTicket());
+ expectType>(room.createTicket());
- const ticket = await room.createTicket({ meta: { my: "session-meta" } });
+ const ticket = room.createTicket({ meta: { my: "session-meta" } });
// Room.startBrowserSession() API
expectType(await room.startBrowserSession(ticket, socket));
diff --git a/packages/liveblocks-server/test/MetadataDB.test.ts b/packages/liveblocks-server/test/MetadataDB.test.ts
index 3f25f09a7fb..a131626fbb4 100644
--- a/packages/liveblocks-server/test/MetadataDB.test.ts
+++ b/packages/liveblocks-server/test/MetadataDB.test.ts
@@ -40,68 +40,68 @@ class VoidTarget extends LogTarget {
const blackHole = new LoggerImpl(new VoidTarget());
describe("test in-memory driver", () => {
- test("basic", async () => {
+ test("basic", () => {
const driver = makeNewInMemoryDriver();
const metadataDB = makeMetadataDB(driver);
- expect(await metadataDB.get("foo")).toEqual(undefined);
+ expect(metadataDB.get("foo")).toEqual(undefined);
// Before loading, root node should not exist
- expect(new Map(await driver.raw_iter_nodes())).toEqual(new Map());
+ expect(new Map(driver.raw_iter_nodes())).toEqual(new Map());
// After loading, root node should exist
- const nodesApi = await driver.load_nodes_api(blackHole);
+ const nodesApi = driver.load_nodes_api(blackHole);
expect(new Map(nodesApi.iter_nodes())).toEqual(
new Map([["root", { type: CrdtType.OBJECT, data: {} }]])
);
});
- test("put and get are async", async () => {
+ test("put and get are async", () => {
const driver = makeNewInMemoryDriver();
const metadataDB = makeMetadataDB(driver);
- expect(await metadataDB.get("foo")).toEqual(undefined);
- await metadataDB.put("foo", "bar");
- expect(await metadataDB.get("foo")).toEqual("bar");
+ expect(metadataDB.get("foo")).toEqual(undefined);
+ metadataDB.put("foo", "bar");
+ expect(metadataDB.get("foo")).toEqual("bar");
});
- test("getters with decoders", async () => {
+ test("getters with decoders", () => {
const driver = makeNewInMemoryDriver();
const metadataDB = makeMetadataDB(driver);
- await metadataDB.put("foo", "hi");
- expect(await metadataDB.get("foo")).toEqual("hi");
- expect(await metadataDB.get(number, "foo")).toEqual(undefined);
- expect(await metadataDB.get(rounded, "foo")).toEqual(undefined);
- expect(await metadataDB.get(string, "foo")).toEqual("hi");
+ metadataDB.put("foo", "hi");
+ expect(metadataDB.get("foo")).toEqual("hi");
+ expect(metadataDB.get(number, "foo")).toEqual(undefined);
+ expect(metadataDB.get(rounded, "foo")).toEqual(undefined);
+ expect(metadataDB.get(string, "foo")).toEqual("hi");
// Override
- await metadataDB.put("foo", 123);
- expect(await metadataDB.get("foo")).toEqual(123);
- expect(await metadataDB.get(number, "foo")).toEqual(123);
- expect(await metadataDB.get(integer, "foo")).toEqual(123);
- expect(await metadataDB.get(rounded, "foo")).toEqual(123);
- expect(await metadataDB.get(string, "foo")).toEqual(undefined);
-
- await metadataDB.put("foo", 3.999);
- expect(await metadataDB.get("foo")).toEqual(3.999);
- expect(await metadataDB.get(number, "foo")).toEqual(3.999);
- expect(await metadataDB.get(integer, "foo")).toEqual(undefined);
- expect(await metadataDB.get(rounded, "foo")).toEqual(4);
- expect(await metadataDB.get(string, "foo")).toEqual(undefined);
-
- await metadataDB.put("foo", -3.999);
- expect(await metadataDB.get("foo")).toEqual(-3.999);
- expect(await metadataDB.get(number, "foo")).toEqual(-3.999);
- expect(await metadataDB.get(integer, "foo")).toEqual(undefined);
- expect(await metadataDB.get(rounded, "foo")).toEqual(-4);
- expect(await metadataDB.get(string, "foo")).toEqual(undefined);
+ metadataDB.put("foo", 123);
+ expect(metadataDB.get("foo")).toEqual(123);
+ expect(metadataDB.get(number, "foo")).toEqual(123);
+ expect(metadataDB.get(integer, "foo")).toEqual(123);
+ expect(metadataDB.get(rounded, "foo")).toEqual(123);
+ expect(metadataDB.get(string, "foo")).toEqual(undefined);
+
+ metadataDB.put("foo", 3.999);
+ expect(metadataDB.get("foo")).toEqual(3.999);
+ expect(metadataDB.get(number, "foo")).toEqual(3.999);
+ expect(metadataDB.get(integer, "foo")).toEqual(undefined);
+ expect(metadataDB.get(rounded, "foo")).toEqual(4);
+ expect(metadataDB.get(string, "foo")).toEqual(undefined);
+
+ metadataDB.put("foo", -3.999);
+ expect(metadataDB.get("foo")).toEqual(-3.999);
+ expect(metadataDB.get(number, "foo")).toEqual(-3.999);
+ expect(metadataDB.get(integer, "foo")).toEqual(undefined);
+ expect(metadataDB.get(rounded, "foo")).toEqual(-4);
+ expect(metadataDB.get(string, "foo")).toEqual(undefined);
});
- test("two namespaces of the same type don't conflict", async () => {
+ test("two namespaces of the same type don't conflict", () => {
const driver = makeNewInMemoryDriver();
const metadataDB = makeMetadataDB(driver);
- const nodeDriver = await driver.load_nodes_api(blackHole);
+ const nodeDriver = driver.load_nodes_api(blackHole);
- await metadataDB.put("foo", null);
- await metadataDB.put("foo", 123);
- await metadataDB.put("foo", "bar");
- await metadataDB.put("bar", [42, 1337]);
+ metadataDB.put("foo", null);
+ metadataDB.put("foo", 123);
+ metadataDB.put("foo", "bar");
+ metadataDB.put("bar", [42, 1337]);
const node1 = {
type: CrdtType.OBJECT,
@@ -115,14 +115,14 @@ describe("test in-memory driver", () => {
parentId: "root",
parentKey: "b",
};
- await nodeDriver.set_child("foo", node1);
- await nodeDriver.set_child("bar", node2);
+ nodeDriver.set_child("foo", node1);
+ nodeDriver.set_child("bar", node2);
// Namespaces don't conflict
- expect(await metadataDB.get("foo")).toEqual("bar");
- expect(await metadataDB.get("bar")).toEqual([42, 1337]);
+ expect(metadataDB.get("foo")).toEqual("bar");
+ expect(metadataDB.get("bar")).toEqual([42, 1337]);
// Both raw_iter_nodes and iter_nodes include root
- expect(new Map(await driver.raw_iter_nodes())).toEqual(
+ expect(new Map(driver.raw_iter_nodes())).toEqual(
new Map([
["root", { type: CrdtType.OBJECT, data: {} }],
["foo", node1],
@@ -138,12 +138,12 @@ describe("test in-memory driver", () => {
);
// Deleting foo from metadata namespace has no effect on other namespaces
- await metadataDB.delete("foo");
- expect(await metadataDB.get("foo")).toEqual(undefined);
- expect(new Map(await driver.raw_iter_nodes()).get("foo")).toEqual(node1);
+ metadataDB.delete("foo");
+ expect(metadataDB.get("foo")).toEqual(undefined);
+ expect(new Map(driver.raw_iter_nodes()).get("foo")).toEqual(node1);
expect(
new Map(
- (await driver.load_nodes_api(blackHole)).iter_nodes()
+ driver.load_nodes_api(blackHole).iter_nodes()
).get("foo")
).toEqual(node1);
});
diff --git a/packages/liveblocks-server/test/plugins/_generateFullTestSuite.ts b/packages/liveblocks-server/test/plugins/_generateFullTestSuite.ts
index 0b501457aba..cd09f99278c 100644
--- a/packages/liveblocks-server/test/plugins/_generateFullTestSuite.ts
+++ b/packages/liveblocks-server/test/plugins/_generateFullTestSuite.ts
@@ -156,8 +156,8 @@ function wouldNotOverwriteDefaultDoc(n: {
* exist, in order to express tests more succinctly.
*/
async function withDefaultDocument(driver: IStorageDriver) {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, [
list("0:dl", "root", "l"),
@@ -193,7 +193,7 @@ function assert(
* (in-memory and on-disk), and will throw if _anything_ is in an inconsistent
* state.
*/
-export async function selfCheck(storage: Storage): Promise {
+export function selfCheck(storage: Storage): void {
const driver: IStorageDriverNodeAPI = storage.loadedDriver;
{
@@ -255,7 +255,7 @@ export async function selfCheck(storage: Storage): Promise {
// Loading the persisted data back in from storage now, it should match
// whatever we still have in memory (ignoring the metadata and usage
// metrics keys)
- const onDiskNodes = new Map(await storage.raw_iter_nodes());
+ const onDiskNodes = new Map(storage.raw_iter_nodes());
for (const [id, inMemoryNode] of driver.iter_nodes()) {
if (inMemoryNode.parentId === undefined) {
// This is the root node, which needs special treatment. Root nodes are
@@ -1023,7 +1023,7 @@ async function delete_nodes(db: IStorageDriverNodeAPI, ids: Iterable) {
/** A black hole, where logs disappear beyond the event horizon */
const blackHole = new LoggerImpl(new VoidTarget());
-type TestFn = (driver: TDriver) => Promise;
+type TestFn = (driver: TDriver) => Awaitable;
type RunTestOptions = { initialNodes?: NodeMap };
export function generateFullTestSuite(config: {
@@ -1072,8 +1072,8 @@ export function generateFullTestSuite(config: {
describe("nodes API impl", () => {
test("get_node and iter_nodes with empty store contains root", () =>
- runTest(async (driver) => {
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ const db = driver.load_nodes_api(blackHole);
expect(db.get_node("non-existing")).toEqual(undefined);
// Root node always exists, even in an empty store
@@ -1084,15 +1084,15 @@ export function generateFullTestSuite(config: {
}));
test("get_node and iter_nodes with empty store contains root", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.key(),
- async (key) => {
+ (key) => {
fc.pre(key !== "root");
- const db = await driver.load_nodes_api(blackHole);
+ const db = driver.load_nodes_api(blackHole);
expect(db.get_node(key)).toEqual(undefined);
expect(Array.from(db.iter_nodes())).toEqual([
["root", { type: CrdtType.OBJECT, data: {} }],
@@ -1135,16 +1135,16 @@ export function generateFullTestSuite(config: {
));
test("has_node: root always exists", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.has_node("root")).toBe(true);
}));
test("has_node: non-existing node returns false", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.has_node("non-existing")).toBe(false);
}));
@@ -1174,8 +1174,8 @@ export function generateFullTestSuite(config: {
arb.nodeStream(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries);
// has_node should be true iff get_node returns a value
@@ -1188,23 +1188,23 @@ export function generateFullTestSuite(config: {
));
test("get_child_at: returns undefined for empty store", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.get_child_at("root", "someKey")).toBe(undefined);
expect(db.get_child_at("non-existing", "someKey")).toBe(undefined);
}));
test("get_child_at: returns undefined for empty store (property)", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.key(),
arb.key(),
- async (parentId, parentKey) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ (parentId, parentKey) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.get_child_at(parentId, parentKey)).toBe(undefined);
}
)
@@ -1213,8 +1213,8 @@ export function generateFullTestSuite(config: {
test("set_child: throws if parent does not exist (orphan)", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Trying to add a node with a non-existent parentId should throw
await expectToThrow(
@@ -1230,8 +1230,8 @@ export function generateFullTestSuite(config: {
test("set_child: throws if parent does not exist (ref cycle)", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Trying to add a node with a non-existent parentId should throw
await expectToThrow(
@@ -1247,8 +1247,8 @@ export function generateFullTestSuite(config: {
test("set_child: orphan node is not added after throw", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Try to add orphan, catch the error
try {
@@ -1312,8 +1312,8 @@ export function generateFullTestSuite(config: {
test("get_child_at: returns child id after set", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1327,8 +1327,8 @@ export function generateFullTestSuite(config: {
test("get_child_at: returns undefined after delete", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1343,8 +1343,8 @@ export function generateFullTestSuite(config: {
test("get_child_at: returns undefined after set_object_data would overwrite it", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1359,8 +1359,8 @@ export function generateFullTestSuite(config: {
test("get_child_at: tracks nested children", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// root -> list -> register
await db.set_child("0:0", {
@@ -1387,8 +1387,8 @@ export function generateFullTestSuite(config: {
arb.nodeStream(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries);
// For each node with a parent, get_child_at(parentId, parentKey) should return the node's id
@@ -1406,23 +1406,23 @@ export function generateFullTestSuite(config: {
));
test("has_child_at: returns false for empty store", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.has_child_at("root", "someKey")).toBe(false);
expect(db.has_child_at("non-existing", "someKey")).toBe(false);
}));
test("has_child_at: returns false for empty store (property)", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.key(),
arb.key(),
- async (parentId, parentKey) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ (parentId, parentKey) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.has_child_at(parentId, parentKey)).toBe(false);
}
)
@@ -1431,8 +1431,8 @@ export function generateFullTestSuite(config: {
test("has_child_at: returns true after set, false after delete", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.has_child_at("root", "myList")).toBe(false);
@@ -1458,8 +1458,8 @@ export function generateFullTestSuite(config: {
arb.key(),
async (entries, parentId, parentKey) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries);
// has_child_at should be true iff get_child_at returns a value
@@ -1472,9 +1472,9 @@ export function generateFullTestSuite(config: {
));
test("get_next_sibling: returns undefined for empty parent", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// No children under root, so no next position
expect(db.get_next_sibling("root", FIRST_POSITION)).toBe(undefined);
@@ -1485,8 +1485,8 @@ export function generateFullTestSuite(config: {
test("get_next_sibling: returns undefined when no positions after", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Add a list with one item at FIRST_POSITION
await db.set_child("0:0", {
@@ -1511,8 +1511,8 @@ export function generateFullTestSuite(config: {
test("get_next_sibling: finds next position in ordered list", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Create list with items at FIRST, SECOND, THIRD positions
await db.set_child("0:0", {
@@ -1551,8 +1551,8 @@ export function generateFullTestSuite(config: {
test("get_next_sibling: updates after delete", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1590,9 +1590,9 @@ export function generateFullTestSuite(config: {
}));
test("get_last_sibling: returns undefined for empty parent", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(db.get_last_sibling("root")).toBe(undefined);
expect(db.get_last_sibling("non-existing")).toBe(undefined);
@@ -1600,8 +1600,8 @@ export function generateFullTestSuite(config: {
test("get_last_sibling: returns the rightmost position", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1634,8 +1634,8 @@ export function generateFullTestSuite(config: {
test("get_last_sibling: updates after delete", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1666,8 +1666,8 @@ export function generateFullTestSuite(config: {
test("move: changes parentKey of node", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1701,8 +1701,8 @@ export function generateFullTestSuite(config: {
test("move: updates get_next_sibling correctly", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1739,8 +1739,8 @@ export function generateFullTestSuite(config: {
test("move: multiple moves on same node", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1768,8 +1768,8 @@ export function generateFullTestSuite(config: {
test("move: preserves other siblings", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1811,8 +1811,8 @@ export function generateFullTestSuite(config: {
test("move: throws when target position is occupied", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1847,8 +1847,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: removes static data key from object", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { a: 1, b: 2, c: 3 });
@@ -1867,8 +1867,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: removes child node", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_child("0:0", {
type: CrdtType.LIST,
@@ -1887,8 +1887,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: removes child node and its descendants recursively", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// root -> list -> register
await db.set_child("0:0", {
@@ -1922,8 +1922,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: no-op for non-existing key", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { a: 1 });
@@ -1939,8 +1939,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: preserves sibling data and nodes", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { a: 1, b: 2 });
await db.set_child("0:0", {
@@ -1975,8 +1975,8 @@ export function generateFullTestSuite(config: {
arb.nodeMap(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries as NodeStream);
@@ -2069,8 +2069,8 @@ export function generateFullTestSuite(config: {
test("deleting the root is a no-op", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { foo: 42 });
// Try to delete the root node
@@ -2090,8 +2090,8 @@ export function generateFullTestSuite(config: {
arb.nodeMap(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(Array.from(db.iter_nodes())).toEqual([
["root", { type: CrdtType.OBJECT, data: {} }],
]);
@@ -2116,8 +2116,8 @@ export function generateFullTestSuite(config: {
arb.nodeMap(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
expect(Array.from(db.iter_nodes())).toEqual([
["root", { type: CrdtType.OBJECT, data: {} }],
]);
@@ -2150,8 +2150,8 @@ export function generateFullTestSuite(config: {
arb.nodeMap(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries as NodeStream);
// Parse the wire tuples back into CompactNodes and compare
@@ -2181,8 +2181,8 @@ export function generateFullTestSuite(config: {
arb.nodeStream(),
async (entries) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, entries);
await delete_nodes(
@@ -2355,8 +2355,8 @@ export function generateFullTestSuite(config: {
test("get_snapshot: delete_child_key on static data does not affect snapshot", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { a: 1, b: 2, c: 3 });
// Take snapshot before deleting a key
@@ -2380,8 +2380,8 @@ export function generateFullTestSuite(config: {
test("get_snapshot: set_object_data after snapshot does not affect snapshot", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await db.set_object_data("root", { a: 1, b: 2 });
// Take snapshot before mutating
@@ -2463,9 +2463,9 @@ export function generateFullTestSuite(config: {
}));
test("get_snapshot: iter_all on empty room returns only root", () =>
- runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ runTest((driver) => {
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
const snapshot = db.get_snapshot();
const nodes = [...snapshot.iter_all()];
expect(nodes).toEqual([["root", { type: CrdtType.OBJECT, data: {} }]]);
@@ -2479,8 +2479,8 @@ export function generateFullTestSuite(config: {
test("set: read sees new node before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
const node = {
type: CrdtType.LIST,
@@ -2507,8 +2507,8 @@ export function generateFullTestSuite(config: {
test("delete: read sees deletion before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// First create a node
await db.set_child("0:0", {
@@ -2537,8 +2537,8 @@ export function generateFullTestSuite(config: {
test("move: read sees new position before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Create a list with an item
await db.set_child("0:0", {
@@ -2582,8 +2582,8 @@ export function generateFullTestSuite(config: {
test("set_object_data: read sees new data before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Start with empty root
expect(db.get_node("root")).toEqual({
@@ -2635,8 +2635,8 @@ export function generateFullTestSuite(config: {
test("delete_child_key: read sees deletion before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Set up root with static data and a child node
await db.set_object_data("root", { a: 1, b: 2 });
@@ -2680,8 +2680,8 @@ export function generateFullTestSuite(config: {
test("multiple writes: all visible before any await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Perform multiple writes without awaiting any of them
const p1$ = db.set_child("0:0", {
@@ -2726,8 +2726,8 @@ export function generateFullTestSuite(config: {
test("interleaved write and delete: reads see correct state", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Create a node
const p1$ = db.set_child("0:0", {
@@ -2771,8 +2771,8 @@ export function generateFullTestSuite(config: {
test("get_next_sibling: updated before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Create a list with two items
await db.set_child("0:0", {
@@ -2823,8 +2823,8 @@ export function generateFullTestSuite(config: {
test("set with overwrite: read sees update before await", () =>
runTest(async (driver) => {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
// Create a list to hold registers
await db.set_child("0:0", {
@@ -2881,45 +2881,45 @@ export function generateFullTestSuite(config: {
describe("meta API impl", () => {
test("get_meta with empty store is undefined", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.key(),
- async (key) => {
- expect(await driver.get_meta(key)).toEqual(undefined);
+ (key) => {
+ expect(driver.get_meta(key)).toEqual(undefined);
}
)
)
));
test("put_meta + get_meta", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.metaPair(),
- async ([key, value]) => {
- await driver.put_meta(key, value);
- expect(await driver.get_meta(key)).toEqual(value);
+ ([key, value]) => {
+ driver.put_meta(key, value);
+ expect(driver.get_meta(key)).toEqual(value);
}
)
)
));
test("put_meta + get_meta loop", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
fc.array(arb.metaPair()).map((x) => new Map(x)),
- async (entries) => {
+ (entries) => {
for (const [key, value] of entries) {
- await driver.put_meta(key, value);
+ driver.put_meta(key, value);
}
for (const [key, value] of entries) {
- expect(await driver.get_meta(key)).toEqual(value);
+ expect(driver.get_meta(key)).toEqual(value);
}
}
)
@@ -2927,20 +2927,20 @@ export function generateFullTestSuite(config: {
));
test("put_meta + delete_meta + get_meta", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.key(),
arb.json(),
arb.json(),
- async (key, value1, value2) => {
- await driver.put_meta(key, value1);
- await driver.put_meta(key, value2); // override
- expect(await driver.get_meta(key)).toEqual(value2);
+ (key, value1, value2) => {
+ driver.put_meta(key, value1);
+ driver.put_meta(key, value2); // override
+ expect(driver.get_meta(key)).toEqual(value2);
- await driver.delete_meta(key);
- expect(await driver.get_meta(key)).toEqual(undefined);
+ driver.delete_meta(key);
+ expect(driver.get_meta(key)).toEqual(undefined);
}
)
)
@@ -2963,7 +2963,7 @@ export function generateFullTestSuite(config: {
// Check that readone will also have the same results
const map = new Map(entries); // de-dupe
for (const [key, expected] of map) {
- expect(await driver.get_meta(key)).toEqual(expected);
+ expect(driver.get_meta(key)).toEqual(expected);
}
}
)
@@ -2971,21 +2971,21 @@ export function generateFullTestSuite(config: {
));
test("put_meta + get_meta loop", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.metaEntries(),
- async (entries) => {
+ (entries) => {
// Write all the entries (can have dupes)
for (const [key, value] of entries) {
- await driver.put_meta(key, value);
+ driver.put_meta(key, value);
}
// Check that readone will also have the same results
const map = new Map(entries); // de-dupe
for (const [key, expected] of map) {
- expect(await driver.get_meta(key)).toEqual(expected);
+ expect(driver.get_meta(key)).toEqual(expected);
}
}
)
@@ -2993,21 +2993,21 @@ export function generateFullTestSuite(config: {
));
test("delete_meta (all keys)", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.metaEntries(),
- async (entries) => {
+ (entries) => {
for (const [key, value] of entries) {
- await driver.put_meta(key, value);
+ driver.put_meta(key, value);
}
for (const key of new Map(entries).keys()) {
- await driver.delete_meta(key);
+ driver.delete_meta(key);
}
for (const [key] of entries) {
- expect(await driver.get_meta(key)).toEqual(undefined);
+ expect(driver.get_meta(key)).toEqual(undefined);
}
}
)
@@ -3037,19 +3037,19 @@ export function generateFullTestSuite(config: {
const key2 = entry2[0];
const key3 = entry3[0];
- expect(await driver.get_meta(key1)).not.toEqual(undefined);
- expect(await driver.get_meta(key2)).not.toEqual(undefined);
- expect(await driver.get_meta(key3)).not.toEqual(undefined);
- await driver.delete_meta(key1);
- await driver.delete_meta(key1);
- expect(await driver.get_meta(key1)).toEqual(undefined);
- expect(await driver.get_meta(key2)).not.toEqual(undefined);
- expect(await driver.get_meta(key3)).not.toEqual(undefined);
- await driver.delete_meta(key2);
- await driver.delete_meta(key2);
- expect(await driver.get_meta(key1)).toEqual(undefined);
- expect(await driver.get_meta(key2)).toEqual(undefined);
- expect(await driver.get_meta(key3)).not.toEqual(undefined);
+ expect(driver.get_meta(key1)).not.toEqual(undefined);
+ expect(driver.get_meta(key2)).not.toEqual(undefined);
+ expect(driver.get_meta(key3)).not.toEqual(undefined);
+ driver.delete_meta(key1);
+ driver.delete_meta(key1);
+ expect(driver.get_meta(key1)).toEqual(undefined);
+ expect(driver.get_meta(key2)).not.toEqual(undefined);
+ expect(driver.get_meta(key3)).not.toEqual(undefined);
+ driver.delete_meta(key2);
+ driver.delete_meta(key2);
+ expect(driver.get_meta(key1)).toEqual(undefined);
+ expect(driver.get_meta(key2)).toEqual(undefined);
+ expect(driver.get_meta(key3)).not.toEqual(undefined);
}
)
)
@@ -3058,41 +3058,37 @@ export function generateFullTestSuite(config: {
describe("ydoc API impl", () => {
test("iter_y_updates on an empty store is empty", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.docId(),
- async (docId) => {
- expect(Array.from(await driver.iter_y_updates(docId))).toEqual(
- []
- );
+ (docId) => {
+ expect(Array.from(driver.iter_y_updates(docId))).toEqual([]);
}
)
)
));
test("write_y_updates + iter_y_updates", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
fc.tuple(arb.docId(), arb.docId()).filter(([a, b]) => a !== b),
fc
.array(fc.tuple(arb.key(), fc.uint8Array()))
.map((x) => new Map(x)),
- async ([docId, anotherDocId], entries) => {
- await driver.DANGEROUSLY_wipe_all_y_updates();
+ ([docId, anotherDocId], entries) => {
+ driver.DANGEROUSLY_wipe_all_y_updates();
for (const [key, data] of entries) {
- await driver.write_y_updates(docId, key, data);
+ driver.write_y_updates(docId, key, data);
}
- expect(new Map(await driver.iter_y_updates(docId))).toEqual(
- entries
+ expect(new Map(driver.iter_y_updates(docId))).toEqual(entries);
+ expect(new Map(driver.iter_y_updates(anotherDocId))).toEqual(
+ new Map()
);
- expect(
- new Map(await driver.iter_y_updates(anotherDocId))
- ).toEqual(new Map());
}
)
)
@@ -3101,132 +3097,118 @@ export function generateFullTestSuite(config: {
describe("leased session API impl", () => {
test("list_leased_sessions on empty store is empty", () =>
- runTest(async (driver) => {
- const sessions = Array.from(await driver.list_leased_sessions());
+ runTest((driver) => {
+ const sessions = Array.from(driver.list_leased_sessions());
expect(sessions).toEqual([]);
}));
test("get_leased_session on empty store is undefined", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(arb.sessionId(), async (sessionId) => {
- expect(await driver.get_leased_session(sessionId)).toEqual(
- undefined
- );
+ fc.property(arb.sessionId(), (sessionId) => {
+ expect(driver.get_leased_session(sessionId)).toEqual(undefined);
})
)
));
test("put_leased_session + get_leased_session", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.sessionId(),
arb.leasedSession(),
- async (sessionId, session) => {
+ (sessionId, session) => {
session.sessionId = sessionId;
- await driver.put_leased_session(session);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- session
- );
+ driver.put_leased_session(session);
+ expect(driver.get_leased_session(sessionId)).toEqual(session);
// Cleanup: delete the session added in this iteration
- await driver.delete_leased_session(sessionId);
+ driver.delete_leased_session(sessionId);
}
)
)
));
test("put_leased_session (overwrite) + get_leased_session", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.sessionId(),
arb.leasedSession(),
arb.leasedSession(),
- async (sessionId, session1, session2) => {
+ (sessionId, session1, session2) => {
// Put first session
session1.sessionId = sessionId;
- await driver.put_leased_session(session1);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- session1
- );
+ driver.put_leased_session(session1);
+ expect(driver.get_leased_session(sessionId)).toEqual(session1);
// Overwrite with second session
session2.sessionId = sessionId;
- await driver.put_leased_session(session2);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- session2
- );
+ driver.put_leased_session(session2);
+ expect(driver.get_leased_session(sessionId)).toEqual(session2);
// Cleanup: delete the session added in this iteration
- await driver.delete_leased_session(sessionId);
+ driver.delete_leased_session(sessionId);
}
)
)
));
test("put_leased_session + delete_leased_session + get_leased_session", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.sessionId(),
arb.leasedSession(),
- async (sessionId, session) => {
+ (sessionId, session) => {
session.sessionId = sessionId;
- await driver.put_leased_session(session);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- session
- );
+ driver.put_leased_session(session);
+ expect(driver.get_leased_session(sessionId)).toEqual(session);
- await driver.delete_leased_session(sessionId);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- undefined
- );
+ driver.delete_leased_session(sessionId);
+ expect(driver.get_leased_session(sessionId)).toEqual(undefined);
}
)
)
));
test("delete_leased_session on non-existent session is no-op", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(arb.sessionId(), async (sessionId) => {
+ fc.property(arb.sessionId(), (sessionId) => {
// Deleting a session that doesn't exist should not throw
- await driver.delete_leased_session(sessionId);
- expect(await driver.get_leased_session(sessionId)).toEqual(
- undefined
- );
+ driver.delete_leased_session(sessionId);
+ expect(driver.get_leased_session(sessionId)).toEqual(undefined);
})
)
));
test("put_leased_session + list_leased_sessions", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
fc
.array(arb.leasedSessionPair())
.map((x) => new Map(x))
.filter((m) => m.size > 0), // At least one session
- async (entries) => {
+ (entries) => {
// Put all sessions
for (const [sessionId, session] of entries) {
session.sessionId = sessionId;
- await driver.put_leased_session(session);
+ driver.put_leased_session(session);
}
// List should return all sessions
- const listed = new Map(await driver.list_leased_sessions());
+ const listed = new Map(driver.list_leased_sessions());
expect(listed).toEqual(entries);
// Cleanup: delete all sessions added in this iteration
for (const [sessionId] of entries) {
- await driver.delete_leased_session(sessionId);
+ driver.delete_leased_session(sessionId);
}
}
)
@@ -3234,28 +3216,28 @@ export function generateFullTestSuite(config: {
));
test("put multiple sessions + get each individually", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
fc.array(arb.leasedSessionPair()).map((x) => new Map(x)),
- async (entries) => {
+ (entries) => {
// Put all sessions
for (const [sessionId, session] of entries) {
session.sessionId = sessionId;
- await driver.put_leased_session(session);
+ driver.put_leased_session(session);
}
// Get each session individually and verify
for (const [sessionId, expectedSession] of entries) {
- expect(await driver.get_leased_session(sessionId)).toEqual(
+ expect(driver.get_leased_session(sessionId)).toEqual(
expectedSession
);
}
// Cleanup: delete all sessions added in this iteration
for (const [sessionId] of entries) {
- await driver.delete_leased_session(sessionId);
+ driver.delete_leased_session(sessionId);
}
}
)
@@ -3291,79 +3273,53 @@ export function generateFullTestSuite(config: {
]);
// Verify all exist
- expect(await driver.get_leased_session(sessionId1)).toEqual(
- session1
- );
- expect(await driver.get_leased_session(sessionId2)).toEqual(
- session2
- );
- expect(await driver.get_leased_session(sessionId3)).toEqual(
- session3
- );
+ expect(driver.get_leased_session(sessionId1)).toEqual(session1);
+ expect(driver.get_leased_session(sessionId2)).toEqual(session2);
+ expect(driver.get_leased_session(sessionId3)).toEqual(session3);
// Delete first session
- await driver.delete_leased_session(sessionId1);
- expect(await driver.get_leased_session(sessionId1)).toEqual(
- undefined
- );
- expect(await driver.get_leased_session(sessionId2)).toEqual(
- session2
- );
- expect(await driver.get_leased_session(sessionId3)).toEqual(
- session3
- );
+ driver.delete_leased_session(sessionId1);
+ expect(driver.get_leased_session(sessionId1)).toEqual(undefined);
+ expect(driver.get_leased_session(sessionId2)).toEqual(session2);
+ expect(driver.get_leased_session(sessionId3)).toEqual(session3);
// Delete second session
- await driver.delete_leased_session(sessionId2);
- expect(await driver.get_leased_session(sessionId1)).toEqual(
- undefined
- );
- expect(await driver.get_leased_session(sessionId2)).toEqual(
- undefined
- );
- expect(await driver.get_leased_session(sessionId3)).toEqual(
- session3
- );
+ driver.delete_leased_session(sessionId2);
+ expect(driver.get_leased_session(sessionId1)).toEqual(undefined);
+ expect(driver.get_leased_session(sessionId2)).toEqual(undefined);
+ expect(driver.get_leased_session(sessionId3)).toEqual(session3);
// Delete third session
- await driver.delete_leased_session(sessionId3);
- expect(await driver.get_leased_session(sessionId1)).toEqual(
- undefined
- );
- expect(await driver.get_leased_session(sessionId2)).toEqual(
- undefined
- );
- expect(await driver.get_leased_session(sessionId3)).toEqual(
- undefined
- );
+ driver.delete_leased_session(sessionId3);
+ expect(driver.get_leased_session(sessionId1)).toEqual(undefined);
+ expect(driver.get_leased_session(sessionId2)).toEqual(undefined);
+ expect(driver.get_leased_session(sessionId3)).toEqual(undefined);
// List should be empty
- expect(Array.from(await driver.list_leased_sessions())).toEqual(
- []
- );
+ expect(Array.from(driver.list_leased_sessions())).toEqual([]);
}
)
)
));
test("list_leased_sessions returns all sessions in any order", () =>
- runTest(async (driver) =>
+ runTest((driver) =>
fc.assert(
- fc.asyncProperty(
+ fc.property(
fc
.array(arb.leasedSessionPair())
.map((x) => new Map(x))
.filter((m) => m.size > 0),
- async (entries) => {
+ (entries) => {
// Put all sessions
for (const [sessionId, session] of entries) {
session.sessionId = sessionId;
- await driver.put_leased_session(session);
+ driver.put_leased_session(session);
}
// Get listed sessions and convert to a map
- const listed = new Map(await driver.list_leased_sessions());
+ const listed = new Map(driver.list_leased_sessions());
// Both should have the same size
expect(listed.size).toEqual(entries.size);
@@ -3375,7 +3331,7 @@ export function generateFullTestSuite(config: {
// Cleanup: delete all sessions added in this iteration
for (const [sessionId] of entries) {
- await driver.delete_leased_session(sessionId);
+ driver.delete_leased_session(sessionId);
}
}
)
@@ -3427,107 +3383,103 @@ export function generateFullTestSuite(config: {
describe("feed API impl", () => {
test("list_feeds on empty store is empty", () =>
- runTest(async (driver) => {
- const result = await driver.list_feeds();
+ runTest((driver) => {
+ const result = driver.list_feeds();
expect(result.feeds).toEqual([]);
expect(result.nextCursor).toBeUndefined();
}));
test("get_feed on empty store is undefined", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(arb.feedId(), async (feedId) => {
- expect(await driver.get_feed(feedId)).toEqual(undefined);
+ fc.property(arb.feedId(), (feedId) => {
+ expect(driver.get_feed(feedId)).toEqual(undefined);
})
);
}));
test("create_feed + get_feed", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(arb.feed(), async (feed) => {
- await driver.create_feed(feed);
- expect(await driver.get_feed(feed.feedId)).toEqual(feed);
+ fc.property(arb.feed(), (feed) => {
+ driver.create_feed(feed);
+ expect(driver.get_feed(feed.feedId)).toEqual(feed);
// Cleanup
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
})
);
}));
test("update_feed_metadata", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
- arb.feed(),
- arb.json(),
- async (feed, newMetadata) => {
- // Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ fc.property(arb.feed(), arb.json(), (feed, newMetadata) => {
+ // Ensure feed doesn't already exist
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.create_feed(feed);
- await driver.update_feed_metadata(feed.feedId, newMetadata);
+ driver.update_feed_metadata(feed.feedId, newMetadata);
- const updated = await driver.get_feed(feed.feedId);
- expect(updated?.metadata).toEqual(newMetadata);
- expect(updated?.feedId).toEqual(feed.feedId);
+ const updated = driver.get_feed(feed.feedId);
+ expect(updated?.metadata).toEqual(newMetadata);
+ expect(updated?.feedId).toEqual(feed.feedId);
- // Cleanup
- await driver.delete_feed(feed.feedId);
- }
- )
+ // Cleanup
+ driver.delete_feed(feed.feedId);
+ })
);
}));
test("delete_feed", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(arb.feed(), async (feed) => {
+ fc.property(arb.feed(), (feed) => {
// Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
- expect(await driver.get_feed(feed.feedId)).toEqual(feed);
+ driver.create_feed(feed);
+ expect(driver.get_feed(feed.feedId)).toEqual(feed);
- await driver.delete_feed(feed.feedId);
- expect(await driver.get_feed(feed.feedId)).toBeUndefined();
+ driver.delete_feed(feed.feedId);
+ expect(driver.get_feed(feed.feedId)).toBeUndefined();
})
);
}));
test("delete_feed on non-existent feed is no-op", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(arb.feedId(), async (feedId) => {
- await driver.delete_feed(feedId);
- expect(await driver.get_feed(feedId)).toBeUndefined();
+ fc.property(arb.feedId(), (feedId) => {
+ driver.delete_feed(feedId);
+ expect(driver.get_feed(feedId)).toBeUndefined();
})
);
}));
test("list_feeds returns all feeds", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
+ fc.property(
fc
.array(arb.feedPair())
.map((x) => new Map(x))
.filter((m) => m.size > 0 && m.size <= 5),
- async (entries) => {
+ (entries) => {
// Ensure feeds don't already exist
for (const [feedId] of entries) {
- await driver.delete_feed(feedId);
+ driver.delete_feed(feedId);
}
// Create all feeds
for (const [, feed] of entries) {
- await driver.create_feed(feed);
+ driver.create_feed(feed);
}
// List all feeds
- const result = await driver.list_feeds();
+ const result = driver.list_feeds();
// Should return all feeds
expect(result.feeds.length).toEqual(entries.size);
@@ -3538,7 +3490,7 @@ export function generateFullTestSuite(config: {
// Cleanup
for (const [feedId] of entries) {
- await driver.delete_feed(feedId);
+ driver.delete_feed(feedId);
}
}
)
@@ -3546,7 +3498,7 @@ export function generateFullTestSuite(config: {
}));
test("list_feeds with pagination", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
// Create 3 feeds with different createdAt timestamps
const feeds: Feed[] = [
{
@@ -3570,11 +3522,11 @@ export function generateFullTestSuite(config: {
];
for (const feed of feeds) {
- await driver.create_feed(feed);
+ driver.create_feed(feed);
}
// List with limit
- const page1 = await driver.list_feeds({ limit: 2 });
+ const page1 = driver.list_feeds({ limit: 2 });
expect(page1.feeds.length).toBe(2);
expect(page1.nextCursor).toBeDefined();
@@ -3583,7 +3535,7 @@ export function generateFullTestSuite(config: {
expect(page1.feeds[1]?.feedId).toBe("feed-2");
// Get next page
- const page2 = await driver.list_feeds({
+ const page2 = driver.list_feeds({
cursor: page1.nextCursor,
});
expect(page2.feeds.length).toBe(1);
@@ -3592,12 +3544,12 @@ export function generateFullTestSuite(config: {
// Cleanup
for (const feed of feeds) {
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}
}));
test("list_feeds with since filter", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
const feeds: Feed[] = [
{
feedId: "feed-old",
@@ -3614,68 +3566,64 @@ export function generateFullTestSuite(config: {
];
for (const feed of feeds) {
- await driver.create_feed(feed);
+ driver.create_feed(feed);
}
// List feeds since 2000
- const result = await driver.list_feeds({ since: 2000 });
+ const result = driver.list_feeds({ since: 2000 });
expect(result.feeds.length).toBe(1);
expect(result.feeds[0]?.feedId).toBe("feed-new");
// Cleanup
for (const feed of feeds) {
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}
}));
test("add_feed_message", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
- arb.feed(),
- arb.feedMessage(),
- async (feed, message) => {
- // Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ fc.property(arb.feed(), arb.feedMessage(), (feed, message) => {
+ // Ensure feed doesn't already exist
+ driver.delete_feed(feed.feedId);
- // Create feed
- await driver.create_feed(feed);
+ // Create feed
+ driver.create_feed(feed);
- // Add message
- await driver.add_feed_message(feed.feedId, message);
+ // Add message
+ driver.add_feed_message(feed.feedId, message);
- // List messages and verify message was added
- const result = await driver.list_feed_messages(feed.feedId);
- expect(result.messages).toHaveLength(1);
- expect(result.messages[0]).toEqual(message);
+ // List messages and verify message was added
+ const result = driver.list_feed_messages(feed.feedId);
+ expect(result.messages).toHaveLength(1);
+ expect(result.messages[0]).toEqual(message);
- // Cleanup
- await driver.delete_feed(feed.feedId);
- }
- )
+ // Cleanup
+ driver.delete_feed(feed.feedId);
+ })
);
}));
test("list_feed_messages", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(arb.feed(), async (feed) => {
+ fc.property(arb.feed(), (feed) => {
// Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.create_feed(feed);
- const result = await driver.list_feed_messages(feed.feedId);
+ const result = driver.list_feed_messages(feed.feedId);
expect(result.messages.length).toBe(0);
// Cleanup
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
})
);
}));
test("list_feed_messages with pagination", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
const messages: FeedMessage[] = [
{
id: "msg-1",
@@ -3704,15 +3652,15 @@ export function generateFullTestSuite(config: {
updatedAt: Date.now(),
};
- await driver.create_feed(feed);
+ driver.create_feed(feed);
// Add messages one by one
for (const message of messages) {
- await driver.add_feed_message(feed.feedId, message);
+ driver.add_feed_message(feed.feedId, message);
}
// List with limit
- const page1 = await driver.list_feed_messages(feed.feedId, {
+ const page1 = driver.list_feed_messages(feed.feedId, {
limit: 2,
});
expect(page1.messages.length).toBe(2);
@@ -3723,7 +3671,7 @@ export function generateFullTestSuite(config: {
expect(page1.messages[1]?.id).toBe("msg-2");
// Get next page
- const page2 = await driver.list_feed_messages(feed.feedId, {
+ const page2 = driver.list_feed_messages(feed.feedId, {
cursor: page1.nextCursor,
});
expect(page2.messages.length).toBe(1);
@@ -3731,46 +3679,42 @@ export function generateFullTestSuite(config: {
expect(page2.nextCursor).toBeUndefined();
// Cleanup
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}));
test("update_feed_message", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
+ fc.property(
arb.feed(),
arb.feedMessage(),
arb.json(),
- async (feed, message, newData) => {
+ (feed, message, newData) => {
// Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.create_feed(feed);
// Add message to the feed
- await driver.add_feed_message(feed.feedId, message);
+ driver.add_feed_message(feed.feedId, message);
- await driver.update_feed_message(
- feed.feedId,
- message.id,
- newData
- );
+ driver.update_feed_message(feed.feedId, message.id, newData);
- const result = await driver.list_feed_messages(feed.feedId);
+ const result = driver.list_feed_messages(feed.feedId);
const updatedMessage = result.messages.find(
(m) => m.id === message.id
);
expect(updatedMessage?.data).toEqual(newData);
// Cleanup
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}
)
);
}));
test("update_feed_message ignores stale timestamped updates for same message", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
const feed: Feed = {
feedId: "test-feed",
metadata: {},
@@ -3784,11 +3728,11 @@ export function generateFullTestSuite(config: {
data: { value: "original" },
};
- await driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
- await driver.add_feed_message(feed.feedId, message);
+ driver.delete_feed(feed.feedId);
+ driver.create_feed(feed);
+ driver.add_feed_message(feed.feedId, message);
- const newer = await driver.update_feed_message(
+ const newer = driver.update_feed_message(
feed.feedId,
message.id,
{ value: "newer-update" },
@@ -3797,7 +3741,7 @@ export function generateFullTestSuite(config: {
expect(newer.updatedAt).toBe(2000);
expect(newer.data).toEqual({ value: "newer-update" });
- const stale = await driver.update_feed_message(
+ const stale = driver.update_feed_message(
feed.feedId,
message.id,
{ value: "stale-update" },
@@ -3806,16 +3750,16 @@ export function generateFullTestSuite(config: {
expect(stale.updatedAt).toBe(2000);
expect(stale.data).toEqual({ value: "newer-update" });
- const result = await driver.list_feed_messages(feed.feedId);
+ const result = driver.list_feed_messages(feed.feedId);
const latest = result.messages.find((m) => m.id === message.id);
expect(latest?.updatedAt).toBe(2000);
expect(latest?.data).toEqual({ value: "newer-update" });
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}));
test("list_feed_messages order remains by createdAt after update", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
const feed: Feed = {
feedId: "test-feed",
metadata: {},
@@ -3837,24 +3781,24 @@ export function generateFullTestSuite(config: {
},
];
- await driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.delete_feed(feed.feedId);
+ driver.create_feed(feed);
for (const m of messages) {
- await driver.add_feed_message(feed.feedId, m);
+ driver.add_feed_message(feed.feedId, m);
}
- const beforeUpdate = await driver.list_feed_messages(feed.feedId);
+ const beforeUpdate = driver.list_feed_messages(feed.feedId);
expect(beforeUpdate.messages[0]?.id).toBe("msg-second");
expect(beforeUpdate.messages[1]?.id).toBe("msg-first");
- await driver.update_feed_message(
+ driver.update_feed_message(
feed.feedId,
"msg-first",
{ value: "first-updated" },
9999
);
- const afterUpdate = await driver.list_feed_messages(feed.feedId);
+ const afterUpdate = driver.list_feed_messages(feed.feedId);
expect(afterUpdate.messages[0]?.id).toBe("msg-second");
expect(afterUpdate.messages[1]?.id).toBe("msg-first");
expect(afterUpdate.messages[1]?.data).toEqual({
@@ -3862,92 +3806,77 @@ export function generateFullTestSuite(config: {
});
expect(afterUpdate.messages[1]?.updatedAt).toBe(9999);
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
}));
test("delete_feed_message", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
- arb.feed(),
- arb.feedMessage(),
- async (feed, message) => {
- // Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ fc.property(arb.feed(), arb.feedMessage(), (feed, message) => {
+ // Ensure feed doesn't already exist
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.create_feed(feed);
- // Add message to the feed
- await driver.add_feed_message(feed.feedId, message);
+ // Add message to the feed
+ driver.add_feed_message(feed.feedId, message);
- await driver.delete_feed_message(feed.feedId, message.id);
+ driver.delete_feed_message(feed.feedId, message.id);
- const result = await driver.list_feed_messages(feed.feedId);
- expect(result.messages.length).toBe(0);
- expect(
- result.messages.find((m) => m.id === message.id)
- ).toBeUndefined();
+ const result = driver.list_feed_messages(feed.feedId);
+ expect(result.messages.length).toBe(0);
+ expect(
+ result.messages.find((m) => m.id === message.id)
+ ).toBeUndefined();
- // Cleanup
- await driver.delete_feed(feed.feedId);
- }
- )
+ // Cleanup
+ driver.delete_feed(feed.feedId);
+ })
);
}));
test("delete_feed_message on non-existent message is no-op", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
- arb.feed(),
- arb.feedMessage(),
- async (feed, message) => {
- // Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ fc.property(arb.feed(), arb.feedMessage(), (feed, message) => {
+ // Ensure feed doesn't already exist
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
+ driver.create_feed(feed);
- // Add message to the feed
- await driver.add_feed_message(feed.feedId, message);
+ // Add message to the feed
+ driver.add_feed_message(feed.feedId, message);
- await driver.delete_feed_message(
- feed.feedId,
- "non-existent-message-id"
- );
+ driver.delete_feed_message(feed.feedId, "non-existent-message-id");
- const result = await driver.list_feed_messages(feed.feedId);
- expect(result.messages.length).toBe(1);
+ const result = driver.list_feed_messages(feed.feedId);
+ expect(result.messages.length).toBe(1);
- // Cleanup
- await driver.delete_feed(feed.feedId);
- }
- )
+ // Cleanup
+ driver.delete_feed(feed.feedId);
+ })
);
}));
test("delete_feed deletes all messages", () =>
- runTest(async (driver) => {
+ runTest((driver) => {
return fc.assert(
- fc.asyncProperty(
- arb.feed(),
- arb.feedMessage(),
- async (feed, message) => {
- // Ensure feed doesn't already exist
- await driver.delete_feed(feed.feedId);
+ fc.property(arb.feed(), arb.feedMessage(), (feed, message) => {
+ // Ensure feed doesn't already exist
+ driver.delete_feed(feed.feedId);
- await driver.create_feed(feed);
- await driver.add_feed_message(feed.feedId, message);
+ driver.create_feed(feed);
+ driver.add_feed_message(feed.feedId, message);
- await driver.delete_feed(feed.feedId);
+ driver.delete_feed(feed.feedId);
- // Feed should be gone
- expect(await driver.get_feed(feed.feedId)).toBeUndefined();
+ // Feed should be gone
+ expect(driver.get_feed(feed.feedId)).toBeUndefined();
- // Messages should be gone too
- const result = await driver.list_feed_messages(feed.feedId);
- expect(result.messages).toEqual([]);
- }
- )
+ // Messages should be gone too
+ const result = driver.list_feed_messages(feed.feedId);
+ expect(result.messages).toEqual([]);
+ })
);
}));
});
@@ -5570,7 +5499,7 @@ export function generateFullTestSuite(config: {
// Pre-populate with yjs updates if provided
if (yjsUpdates.length > 0) {
for (const update of yjsUpdates) {
- await driver.write_y_updates(guid, nanoid(), update);
+ driver.write_y_updates(guid, nanoid(), update);
}
}
diff --git a/packages/liveblocks-server/test/room.test.ts b/packages/liveblocks-server/test/room.test.ts
index 2963fe71e12..8de34d2d3ba 100644
--- a/packages/liveblocks-server/test/room.test.ts
+++ b/packages/liveblocks-server/test/room.test.ts
@@ -116,7 +116,7 @@ describe("room", () => {
test.skip('room will throw "no such session" errors when used before the session is started', async () => {
const room = new Room("my-room");
await room.load();
- const ticket = await room.createTicket();
+ const ticket = room.createTicket();
const key = ticket.sessionKey;
// Errors will happen if used before .startBrowserSession() is used
@@ -127,11 +127,11 @@ describe("room", () => {
test("starting multiple sessions", async () => {
const room = new Room("my-room");
await room.load();
- const ticket1 = await room.createTicket();
- const ticket2 = await room.createTicket();
- const ticket3 = await room.createTicket();
- const ticket4 = await room.createTicket();
- const ticket5 = await room.createTicket();
+ const ticket1 = room.createTicket();
+ const ticket2 = room.createTicket();
+ const ticket3 = room.createTicket();
+ const ticket4 = room.createTicket();
+ const ticket5 = room.createTicket();
await room.startBrowserSession(ticket1, new MockServerWebSocket());
await room.startBrowserSession(ticket2, new MockServerWebSocket());
await room.startBrowserSession(ticket3, new MockServerWebSocket());
@@ -143,9 +143,9 @@ describe("room", () => {
test("starting a second session for an actor kicks the first one", async () => {
const room = new Room("my-room");
await room.load();
- const ticket1 = await room.createTicket({ actor: 13 as ActorID });
- const ticket2 = await room.createTicket();
- const ticket3 = await room.createTicket({ actor: 13 as ActorID });
+ const ticket1 = room.createTicket({ actor: 13 as ActorID });
+ const ticket2 = room.createTicket();
+ const ticket3 = room.createTicket({ actor: 13 as ActorID });
expect(room.numSessions).toEqual(0);
await room.startBrowserSession(ticket1, new MockServerWebSocket());
expect(room.numSessions).toEqual(1);
@@ -158,7 +158,7 @@ describe("room", () => {
test("enter + leave", async () => {
const room = new Room("my-room");
await room.load();
- const ticket = await room.createTicket();
+ const ticket = room.createTicket();
await room.startBrowserSession(ticket, new MockServerWebSocket());
room.endBrowserSession(ticket.sessionKey, 1001, "bleh");
});
@@ -264,11 +264,9 @@ describe("room (w/ last actor ID)", () => {
// Create 1000 tickets
const actors = new Set(
- (
- await Promise.all(
- Array.from({ length: 1000 }).map(() => room.createTicket())
- )
- ).map((t) => t.actor)
+ Array.from({ length: 1000 })
+ .map(() => room.createTicket())
+ .map((t) => t.actor)
);
// The set contains 1000 unique elements
diff --git a/packages/liveblocks-server/test/storage/model-based/index.model.test.ts b/packages/liveblocks-server/test/storage/model-based/index.model.test.ts
index a86425bc1d1..7c00a44b990 100644
--- a/packages/liveblocks-server/test/storage/model-based/index.model.test.ts
+++ b/packages/liveblocks-server/test/storage/model-based/index.model.test.ts
@@ -43,21 +43,20 @@ describe("Storage (model-based test)", () => {
}),
}),
- async ({ initialNodes, commands }) => {
+ ({ initialNodes, commands }) =>
// Set up real and reference model
// In this case, there is no reference model, because the real model
// will perform a self-check
- await runWithStorage(initialNodes, async ({ storage: real }) => {
- await selfCheck(real);
+ runWithStorage(initialNodes, ({ storage: real }) => {
+ selfCheck(real);
const model = new Model(real.loadedDriver.iter_nodes());
// Tries running randomized sequences of commands (think calling
// "applyOp()" a million times)
- await fc.asyncModelRun(() => ({ model, real }), commands);
- });
- }
+ fc.modelRun(() => ({ model, real }), commands);
+ })
),
{
numRuns: 200, // Stop after 200 iterations, or...
diff --git a/packages/liveblocks-server/test/storage/model-based/storage-model.ts b/packages/liveblocks-server/test/storage/model-based/storage-model.ts
index d83fd0a6e2f..2f51abcf8fd 100644
--- a/packages/liveblocks-server/test/storage/model-based/storage-model.ts
+++ b/packages/liveblocks-server/test/storage/model-based/storage-model.ts
@@ -52,7 +52,7 @@ export class Model {
}
}
-class ApplyOpCommand implements fc.AsyncCommand {
+class ApplyOpCommand implements fc.Command {
constructor(
readonly op: ClientWireOp,
readonly version: ProtocolVersion
@@ -94,8 +94,8 @@ class ApplyOpCommand implements fc.AsyncCommand {
* deleting nodes that don't exist are much less likely to be produced. (See
* the `check` method above.)
*/
- async run(model: Model, real: RealStorage): Promise {
- await real.applyOps([this.op]);
+ run(model: Model, real: RealStorage): void {
+ real.applyOps([this.op]);
switch (this.op.type) {
case OpCode.CREATE_OBJECT:
@@ -132,7 +132,7 @@ class ApplyOpCommand implements fc.AsyncCommand {
return assertNever(this.op, "Unhandled case");
}
- await selfCheck(real);
+ selfCheck(real);
}
/**
diff --git a/packages/liveblocks-server/test/storage/push.test.ts b/packages/liveblocks-server/test/storage/push.test.ts
index f89783da947..3afcb7eaa46 100644
--- a/packages/liveblocks-server/test/storage/push.test.ts
+++ b/packages/liveblocks-server/test/storage/push.test.ts
@@ -33,11 +33,11 @@ describe("push intent — server-authoritative append", () => {
test("keeps the guessed position when it already sorts after the tail (no fix)", () =>
runWithStorage(
[rootObj(), list("0:1", "root", "list")],
- async ({ storage, loadedDriver }) => {
+ ({ storage, loadedDriver }) => {
// Empty list; the client guessed THIRD. It already sorts after every
// existing sibling (there are none), so the server keeps it as-is
// rather than pointlessly relocating it to the canonical first slot.
- const [res] = await storage.applyOps([
+ const [res] = storage.applyOps([
createRegisterOp("1:0", "0:1", THIRD, "a", "push"),
]);
@@ -56,10 +56,10 @@ describe("push intent — server-authoritative append", () => {
list("0:1", "root", "list"),
register("0:2", "0:1", FIRST, "a"),
],
- async ({ storage, loadedDriver }) => {
+ ({ storage, loadedDriver }) => {
// Client knows about "a" and guesses SECOND, which is also where the
// server appends — no correction needed.
- const [res] = await storage.applyOps([
+ const [res] = storage.applyOps([
createRegisterOp("1:0", "0:1", SECOND, "b", "push"),
]);
@@ -79,9 +79,9 @@ describe("push intent — server-authoritative append", () => {
register("0:2", "0:1", FIRST, "a"),
register("0:3", "0:1", SECOND, "b"),
],
- async ({ storage, loadedDriver }) => {
+ ({ storage, loadedDriver }) => {
// Stale guess of the head position; the server appends after "b".
- const [res] = await storage.applyOps([
+ const [res] = storage.applyOps([
createRegisterOp("1:0", "0:1", FIRST, "c", "push"),
]);
@@ -100,11 +100,11 @@ describe("push intent — server-authoritative append", () => {
test("concurrent pushes all guessing the head settle in arrival order", () =>
runWithStorage(
[rootObj(), list("0:1", "root", "list")],
- async ({ storage, loadedDriver }) => {
+ ({ storage, loadedDriver }) => {
// Three independent clients each guess the head position. Applied
// serially (as the room mutex guarantees), each appends after the
// previous one — strictly increasing keys, no wedge.
- await storage.applyOps([
+ storage.applyOps([
createRegisterOp("1:0", "0:1", FIRST, "a", "push"),
createRegisterOp("2:0", "0:1", FIRST, "b", "push"),
createRegisterOp("3:0", "0:1", FIRST, "c", "push"),
diff --git a/packages/liveblocks-server/test/storage/utils.ts b/packages/liveblocks-server/test/storage/utils.ts
index 0ffd4e20cfb..a5fce341dd1 100644
--- a/packages/liveblocks-server/test/storage/utils.ts
+++ b/packages/liveblocks-server/test/storage/utils.ts
@@ -97,7 +97,7 @@ export async function runWithStorage(
// Also run an integrity check after initializing _corrupted_ storage.
// Because the Storage class ignores any such corruptions, even when loading
// corruptions the in-memory nodemap should be consistent.
- await selfCheck(storage);
+ selfCheck(storage);
return callback({ storage, loadedDriver: storage.loadedDriver });
}
diff --git a/tools/liveblocks-cli/src/dev-server/index.ts b/tools/liveblocks-cli/src/dev-server/index.ts
index da23d1d97a1..0f23b3e8481 100644
--- a/tools/liveblocks-cli/src/dev-server/index.ts
+++ b/tools/liveblocks-cli/src/dev-server/index.ts
@@ -267,7 +267,7 @@ const dev: SubCommand = {
const room = Rooms.getRoomInstance(roomId);
await room.load();
- const ticket = await room.createTicket(ticketData);
+ const ticket = room.createTicket(ticketData);
const sessionKey = ticket.sessionKey;
const success = server.upgrade(req, {
data: { room, ticket, sessionKey },
diff --git a/tools/liveblocks-cli/src/dev-server/routes/rest-api.ts b/tools/liveblocks-cli/src/dev-server/routes/rest-api.ts
index d55286cc951..cee0a1a98bb 100644
--- a/tools/liveblocks-cli/src/dev-server/routes/rest-api.ts
+++ b/tools/liveblocks-cli/src/dev-server/routes/rest-api.ts
@@ -335,7 +335,7 @@ zen.route(
}
// Initialize storage
- await room.driver.DANGEROUSLY_reset_nodes(body);
+ room.driver.DANGEROUSLY_reset_nodes(body);
room.unload();
return new Response(JSON.stringify(body), {
@@ -360,7 +360,7 @@ zen.route("DELETE /v2/rooms//storage", async ({ p }) => {
liveblocksType: "LiveObject",
data: {},
};
- await room.driver.DANGEROUSLY_reset_nodes(emptyStorage);
+ room.driver.DANGEROUSLY_reset_nodes(emptyStorage);
room.unload();
return new Response(null, { status: 204 });
@@ -641,7 +641,7 @@ zen.route(
const room = Rooms.getRoomInstance(p.roomId);
await room.load();
- const actor = await room.driver.next_actor();
+ const actor = room.getNextActor();
const snapshot = room.storage.loadedDriver.get_snapshot(false);
return ndjsonStream(
chain([{ actor }], snapshotToNodeStream(snapshot))
@@ -663,7 +663,7 @@ zen.route(
await room.load();
const [session, capturedServerMsgs] =
- await room.createBackendSession_experimental();
+ room.createBackendSession_experimental();
await room.processClientMsgFromBackendSession(session, body.messages);
diff --git a/tools/liveblocks-cli/test/devserver/rest-api/ydoc.test.ts b/tools/liveblocks-cli/test/devserver/rest-api/ydoc.test.ts
index a312c1faede..59d5f34626c 100644
--- a/tools/liveblocks-cli/test/devserver/rest-api/ydoc.test.ts
+++ b/tools/liveblocks-cli/test/devserver/rest-api/ydoc.test.ts
@@ -76,7 +76,7 @@ describe("PUT /v2/rooms//ydoc", () => {
const room = Rooms.getRoomInstance(roomId);
await room.load();
const { received, socket } = makeFakeSocket();
- const ticket = await room.createTicket({});
+ const ticket = room.createTicket({});
await room.startBrowserSession(ticket, socket);
// Mark how much was sent during session bootstrap so we only inspect
diff --git a/tools/liveblocks-cli/test/plugins/_generateFullTestSuite.ts b/tools/liveblocks-cli/test/plugins/_generateFullTestSuite.ts
index 9802f7eeede..2790f84d45e 100644
--- a/tools/liveblocks-cli/test/plugins/_generateFullTestSuite.ts
+++ b/tools/liveblocks-cli/test/plugins/_generateFullTestSuite.ts
@@ -162,8 +162,8 @@ function wouldNotOverwriteDefaultDoc(n: {
* exist, in order to express tests more succinctly.
*/
async function withDefaultDocument(driver: IStorageDriver) {
- await driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
- const db = await driver.load_nodes_api(blackHole);
+ driver.DANGEROUSLY_reset_nodes(EMPTY_DOC);
+ const db = driver.load_nodes_api(blackHole);
await write_nodes(db, [
list("0:dl", "root", "l"),
@@ -199,7 +199,7 @@ function assert(
* (in-memory and on-disk), and will throw if _anything_ is in an inconsistent
* state.
*/
-export async function selfCheck(storage: Storage): Promise {
+export function selfCheck(storage: Storage): void {
const driver: IStorageDriverNodeAPI = storage.loadedDriver;
{
@@ -261,7 +261,7 @@ export async function selfCheck(storage: Storage): Promise {
// Loading the persisted data back in from storage now, it should match
// whatever we still have in memory (ignoring the metadata and usage
// metrics keys)
- const onDiskNodes = new Map(await storage.raw_iter_nodes());
+ const onDiskNodes = new Map(storage.raw_iter_nodes());
for (const [id, inMemoryNode] of driver.iter_nodes()) {
if (inMemoryNode.parentId === undefined) {
// This is the root node, which needs special treatment. Root nodes are
@@ -1029,7 +1029,7 @@ async function delete_nodes(db: IStorageDriverNodeAPI, ids: Iterable) {
/** A black hole, where logs disappear beyond the event horizon */
const blackHole = new LoggerImpl(new VoidTarget());
-type TestFn = (driver: TDriver) => Promise;
+type TestFn = (driver: TDriver) => Awaitable