Skip to content

Latest commit

 

History

History
731 lines (491 loc) · 18.4 KB

CHANGELOG.md

File metadata and controls

731 lines (491 loc) · 18.4 KB

v1.0.1

Log stack traces of function calls that resulted in rejected storage mutations to the console in non-production builds to ease debugging.

v1.0.0

This major release marks the maturity of Liveblocks. There are no upgrade instructions for 1.0.0.

@liveblocks/node

authorize option userId is now mandatory.

Our new pricing is based on Monthly Active Users instead of connections. We're using userId to track MAU associated to a Liveblocks account.

v0.19.11

@liveblocks/node

  • WebhookHandler now handles RoomCreatedEvent and RoomDeletedEvent

v0.19.10

@liveblocks/client

v0.19.9

@liveblocks/client

  • Adds a WebhookHandler class
    • new WebhookHandler(secret).verifyRequest({ rawBody, headers }) can be used to verify event requests from Liveblock's Webhook functionality. It also provides fully typed WebhookEvents.
    • Check out our Webhooks guide for more details

v0.19.8

  • Fixes a bug where history didn't reliably undo LiveObject key set changes if any pending local changes existed on that key.
  • Fixes a bug where changes performed inside room.batch were incorrectly ordered inside the history resulting in unexpected undo behavior in some cases.
  • Fixes a bug where under some circumstances the Liveblocks client could get stuck in a "synchronizing" state indefinitely
  • Expose JsonArray and JsonScalar types publicly

v0.19.7

Fix nested storage event handling issue.

v0.19.6

Support authentication with cookies.

v0.19.5

Export the StorageStatus type (introduced with 0.19.3).

v0.19.4

Fix CORS issue.

v0.19.3

In @liveblocks/client:

Room.getStorageStatus

Get the storage status.

  • not-loaded: Initial state when entering the room.
  • loading: Once the storage has been requested via room.getStorage().
  • synchronizing: When some local updates have not been acknowledged by Liveblocks servers.
  • synchronized: Storage is in sync with Liveblocks servers.

Room.subscribe("storage-status", status => { })

Subscribe to storage status changes.

Returns an unsubscribe function.

room.subscribe("storage-status", (status) => {
  switch (status) {
    case "not-loaded":
      break;
    case "loading":
      break;
    case "synchronizing":
      break;
    case "synchronized":
      break;
    default:
      break;
  }
});

Room.reconnect

Close the room connection and try to reconnect.

Internal changes

  • Add support for the upcoming Liveblocks browser extension

v0.19.2

Fixes some internal type definitions.

v0.19.1

Fixes an issue where imports from Liveblocks packages could not be resolved correctly in certain build environments.

v0.19.0

This release brings Zustand v4 support. This is a breaking change only if you’re using @liveblocks/zustand.

In @liveblocks/zustand:

  • Support Zustand v4 (actually v4.1.3 or higher)
  • Drop support for Zustand v3 (also v4.1.2 or lower are not supported)
  • Fix bug where some usage pattern could cause the Zustand store to stop synching (#491)

To migrate, make the following code changes:

  • npm install zustand@latest
  • npm install @liveblocks/zustand@latest
  • Change these imports, if applicable:
    -import { middleware } from "@liveblocks/zustand";
    +import { liveblocks } from "@liveblocks/zustand";
    and
    -import type { LiveblocksState } from "@liveblocks/zustand";
    +import type { WithLiveblocks } from "@liveblocks/zustand";
    and rename accordingly.
  • Change the pattern:
    create(liveblocks<MyState, ...>(...))
    to the Zustand v4 recommended pattern:
    create<WithLiveblocks<MyState, ...>>()(liveblocks(...))
    To be clear:
    1. First, move the type annotation away from the liveblocks middleware call, and onto the create call.
    2. Next, wrap your MyState type in a WithLiveblocks<...> wrapper. This will make sure the injected liveblocks property on your Zustand state will be correctly typed.
    3. Finally, make sure to add the extra call () wrapper, needed by Zustand v4 now:
      create<WithLiveblocks<MyState, ...>>()(liveblocks(...))
      //                                  ^^ Not a typo
  • Remove the second argument to state.liveblocks.enterRoom(): it no longer takes an explicit initial state. Instead, it's automatically be populated from your Zustand state.

In @liveblocks/redux:

  • The main export has been renamed:
    -import { enhancer } from "@liveblocks/redux";
    +import { liveblocksEnhancer } from "@liveblocks/redux";
  • The second argument to state.liveblocks.enterRoom() to send in an explicit initial state is no longer supported. It will use the state in your Redux store, for consistency and ease of use.

v0.18.5

Bug fix:

  • Fixes a small bug in a type definition, scopes was removed from BaseUserMeta.

Internal updates:

  • Switch the monorepo over to Turborepo.

v0.18.4

All packages now provide an isReadOnly flag on user instances. It is available when getting self or others. isReadOnly is true when storage is read-only, see the room management guide for more information.

const me = room.getSelf();

me.isReadOnly; // boolean

const others = room.getOthers();
for (const other of others) {
  other.isReadOnly; // boolean
}

In @liveblocks/client:

  • Add a new option shouldInitiallyConnect to client.enter that let you control whether or not the room connects to Liveblocks servers. Default is true.

    Usually set to false when the client is used from the server to not call the authentication endpoint or connect via WebSocket.

In @liveblocks/react:

  • Add a new property shouldInitiallyConnect to RoomProvider that let you control whether or not the room connects to Liveblocks servers. Default is true.

    By default equals to typeof window !== "undefined", meaning the RoomProvider tries to connect to Liveblocks servers only on the client side.

  • Internal package restructurings to increase code sharing. You may notice a new dependency show up in your dependency tree: @liveblocks/core. It contains private APIs that aren't intended for direct consumption.

v0.18.3

  • In @liveblocks/react:

    Fixes the "zombie-child" problem that can occur with React 17 or lower. If you’re on React 18: great, you can ignore this! If you’re using React 17 or lower with Liveblocks, we’ll now start to enforce that you pass the unstable_batchedUpdates prop to RoomProvider, so this problem can be circumvented. This small addition may save you hours of debugging time!

    // ⚠️  Only if you’re using React 17 or lower
    import { unstable_batchedUpdates } from "react-dom";  // 👈
    
    <RoomProvider
      id="my-room"
      initialPresence={...}
      initialStorage={...}
      unstable_batchedUpdates={unstable_batchedUpdates}  // 👈
    >
      <App />
    </RoomProvider>

    To read more, see https://liveblocks.io/docs/guides/troubleshooting#stale-props-zombie-child

  • In @liveblocks/zustand:

    • Fix a confusing error message

v0.18.2

  • In @liveblocks/react:

    • Make sure that useOther will not rerender if tracked users already left the room, so that child components won't get rerendered before the parent got the chance to unmount them.
    • Disallow useOther without selector

v0.18.1

  • In @liveblocks/react:

    • Fix a bug that could cause an error when patching presence during local development. Not an issue in production builds. (#505)

v0.18.0

For information, please read our Upgrade Guide for 0.18.

New React hooks ✨

Breaking changes

  • Remove support for directly importing hooks from @liveblocks/client (e.g. import { useMyPresence } from '@liveblocks/react'). If you’re still using these imports, see the Upgrade Guide for 0.17 for instructions.
  • Remove ClientProvider and useClient hook
  • Remove defaultPresence and defaultStorageRoot arguments. (Just use initialPresence and initialStorage arguments now.)
  • Remove second argument to useMap(), useList(), and useObject().
  • Remove new LiveMap(null) support. (Just use new LiveMap() or new LiveMap([]).)

v0.17.11

General:

  • Fix a packaging bug

In @liveblocks/react:

  • Deprecate an undocumented API

v0.17.9

  • Fix bug that could cause duplicate copies of @liveblocks/client to end up in final bundle, for certain bundler configurations.
  • Fix bug where in some conditions the initial presence for a new connection would not come through to all existing clients in the room
  • Various internal changes

v0.17.8

New history APIs ↩️ ↪️

  • In @liveblocks/client:

    • Add canUndo() and canRedo() utilities to room.history
    • Add "history" event type to room.subscribe() to subscribe to the current user's history changes
  • In @liveblocks/react:

    • Add useCanUndo() and useCanRedo() hooks

v0.17.7

  • In @liveblocks/zustand:

    • Simplify zustand middleware integration with Typescript. TPresence, TStorage, TUserMeta, and TRoomEvent are now optional.

Note that @liveblocks/zustand does not work with zustand > v4 because v3 and v4 have completely different type definitions. As soon as zustand v4 is out of the RC phase, we will consider updating our middleware to work with the latest version.

Example

Let's take a look at our To-do list example. Without our middleware, the store would look like this:

import create from "zustand";

type State = {
  draft: string;
  isTyping: boolean;
  todos: Todo[];
  setDraft: (draft: string) => void;
  addTodo: () => void;
  deleteTodo: (index: number) => void;
};

create<State>(/* ... */);

With our middleware, you simply need to move the State param at the middleware level:

import create from "zustand";
import { createClient } from "@liveblocks/client";
import { middleware } from "@liveblocks/zustand";

const client = createClient({ /*...*/ });

type State = {
  draft: string;
  isTyping: boolean;
  todos: Todo[];
  setDraft: (draft: string) => void;
  addTodo: () => void;
  deleteTodo: (index: number) => void;
};

create(
  middleware<State>(/* ... */, {
    client,
    presenceMapping: { isTyping: true },
    storageMapping: { todos: true }
  })
);

If you want to type others presence, you can use the TPresence generic argument on the middleware.

type Presence = {
  isTyping: true;
}

const useStore = create(
  middleware<State, Presence>(/* ... */, {
    client,
    presenceMapping: { isTyping: true },
    storageMapping: { todos: true }
  })
);

// In your component
useStore(state => state.liveblocks.others[0].presence?.isTyping)

v0.17.6

  • In @liveblocks/react:

    • Expose RoomContext in the return value of createRoomContext()

v0.17.5

  • In @liveblocks/react:

    • Fix bug where changing the key argument of useMap(), useList(), useObject() did not resubscribe to updates correctly
    • Ignore changes to the RoomProvider's initial presence/storage props on subsequent renders. This makes it behave closer to useState(initialState)

v0.17.4

Fix missing documentation for hooks created via createRoomContext().


v0.17.1

Fix @liveblocks/nodes packaging.


v0.17.0

For information, please read our Upgrade Guide.

TypeScript improvements ✨

This release contains major TypeScript improvements. The recommended setup now is that you define your own Presence and Storage types at the highest level (i.e. where you set up the room). After that initial one-time setup, you will no longer need to provide any extra type annotations anywhere for your Liveblocks code! 🙌

To learn how to set that up, follow the instructions in our Upgrade Guide.

  • No more any types used (in @liveblocks/client and @liveblocks/react)
  • All APIs that work with Presence data will now require it to be JSON-serializable
  • All APIs that work with Storage data will now require it to be LSON (= JSON + Live structures)
  • All Live structures now take mandatory type params for their payloads, just like the built-in array, object, and map types do:
    • LiveMap<K, V> (like Map<K, V>)
    • LiveObject<{ a: number, b: string }> (like, for example, { a: number, b: string })
    • LiveList<T> (like Array<T>)

React Native support ✨

We now support React Native! To learn how to use Liveblocks in your React Native projects, see our API reference. It's surprisingly simple!

New APIs ✨

Bug fixes 🐛

  • Improved conflict resolution on LiveList
  • Various minor internal bug fixes

Breaking changes

  • In @liveblocks/client:

    • Removed old Room.unsubscribe() API

New deprecations

  • In @liveblocks/client:

    • The defaultPresence option to client.enter() will get renamed to initialPresence
    • The defaultStorageRoot option to client.enter() will get renamed to initialStorage
    • Calling new LiveMap(null) will stop working. Please use new LiveMap(), or new LiveMap([])
  • In @liveblocks/react:

    • Importing the React hooks directly is deprecated, instead use the new createRoomContext() helper. For help, read the Recommended Upgrade Steps section within our Upgrade Guide
    • The second argument to useList(), useObject(), and useMap() is deprecated
    • The RoomProvider's defaultPresence is renamed to initialPresence
    • The RoomProvider's defaultStorageRoot is renamed to initialStorage

v0.16.17

Fix bug in internal code where some legal authentication tokens would be considered invalid.


v0.16.16

Internals only.


v0.16.15

Internals only.


v0.16.14

Fix an issue where the current user's info would not properly display accented characters.


v0.16.13

(Unpublished.)


v0.16.12

Internals only.


v0.16.11

Expose helper type to help users adopt to using Live structures with interfaces they don't own.


v0.16.10

Restructures a few more internals.


v0.16.9

Restructures a few internals.


v0.16.8

Fix bug in private/internal code.


v0.16.7

Fix bug in private/internal code.


v0.16.6

Fix bug in example code suggested in deprecation warning.


v0.16.5

All packages

  • Various internal refactorings

Bug fixes

  • In @liveblocks/client:

    • If you're using @liveblocks/client in a ES2015 context, you no longer have to polyfill Object.fromEntries().

v0.16.4

All packages

  • Improve our generated bundles. They are now even more tree-shakable, and smaller!
  • Some APIs are being deprecation and will show warnings in the dev console when used

v0.16.3

Bug fixes

  • In @liveblocks/client:

    • Fix bug where internal presence state could not get restored correctly after undo/redo in certain circumstances.
  • In @liveblocks/zustand and @liveblocks/redux:

    • Fixes an issue when initializing an array with items would result in having duplicated items in other clients. Example:

      • Client A updates state : { list: [0] }
      • Client B states is updated to : { list: [0, 0] }

v0.16.2

Bug fixes

  • In @liveblocks/client:

    • Fix small bug related to new JsonObject type, which would reject some values that were legal JSON objects.

v0.16.1

Bug fixes

  • In @liveblocks/react:

    • Fix issue with React 18 and StrictMode.

v0.16.0

New APIs

LiveList.set

Set one element at a specified index.

const list = new LiveList(["🦁", "🦊", "🐵"]);
list.set(0, "🐺");
list.toArray(); // equals ["🐺", "🦊", "🐵"]

liveblocks#147 for more information

⚠️ Before using LiveList.set, you need to make sure that all connected clients are using 0.16.0. If a client is connected to a room with version < 0.16, LiveList.set might lead to slightly unexpected behavior.

TypeScript improvements

@nvie improved our typescript definitions! They are more precise and restrictive (for your own good :)). If typescript errors appears after upgrading to 0.16.0 and they are not clear, please create a Github issue and we'll help you.

More information here: liveblocks#150