@liveblocks/zustand 0.18.4 → 0.19.0-beta0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.d.ts CHANGED
@@ -1,14 +1,12 @@
1
1
  import { JsonObject, LsonObject, BaseUserMeta, Json, Room, User, Client } from '@liveblocks/client';
2
- import { StateCreator, SetState, GetState, StoreApi } from 'zustand';
2
+ import { StoreMutatorIdentifier, StateCreator } from 'zustand';
3
3
 
4
- declare type ZustandState = Record<string, unknown>;
5
- declare type LiveblocksContext<TState extends ZustandState, TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
4
+ declare type LiveblocksContext<TPresence extends JsonObject, TStorage extends LsonObject, TUserMeta extends BaseUserMeta, TRoomEvent extends Json> = {
6
5
  /**
7
6
  * Enters a room and starts sync it with zustand state
8
7
  * @param roomId The id of the room
9
- * @param initialState The initial state of the room storage. If a key does not exist if your room storage root, initialState[key] will be used.
10
8
  */
11
- readonly enterRoom: (roomId: string, initialState: Partial<TState>) => void;
9
+ readonly enterRoom: (roomId: string) => void;
12
10
  /**
13
11
  * Leaves a room and stops sync it with zustand state.
14
12
  * @param roomId The id of the room
@@ -31,11 +29,15 @@ declare type LiveblocksContext<TState extends ZustandState, TPresence extends Js
31
29
  */
32
30
  readonly connection: "closed" | "authenticating" | "unavailable" | "failed" | "open" | "connecting";
33
31
  };
34
- declare type LiveblocksState<TState extends ZustandState, TPresence extends JsonObject = JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = Json> = TState & {
35
- /**
36
- * Liveblocks extra state attached by the middleware
37
- */
38
- readonly liveblocks: LiveblocksContext<TState, TPresence, TStorage, TUserMeta, TRoomEvent>;
32
+ /**
33
+ * @deprecated Renamed to WithLiveblocks<...>
34
+ */
35
+ declare type LiveblocksState<TState, TPresence extends JsonObject = JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = Json> = WithLiveblocks<TState, TPresence, TStorage, TUserMeta, TRoomEvent>;
36
+ /**
37
+ * Adds the `liveblocks` property to your custom Zustand state.
38
+ */
39
+ declare type WithLiveblocks<TState, TPresence extends JsonObject = JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = Json> = TState & {
40
+ readonly liveblocks: LiveblocksContext<TPresence, TStorage, TUserMeta, TRoomEvent>;
39
41
  };
40
42
  declare type Mapping<T> = {
41
43
  [K in keyof T]?: boolean;
@@ -54,6 +56,11 @@ declare type Options<T> = {
54
56
  */
55
57
  presenceMapping?: Mapping<T>;
56
58
  };
57
- declare function middleware<T extends ZustandState, TPresence extends JsonObject = JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = Json>(config: StateCreator<T, SetState<T>, GetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>, StoreApi<T>>, options: Options<T>): StateCreator<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>, SetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>, GetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>, StoreApi<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>>;
59
+ declare type OuterLiveblocksMiddleware = <TState, Mps extends [StoreMutatorIdentifier, unknown][] = [], Mcs extends [StoreMutatorIdentifier, unknown][] = []>(config: StateCreator<TState, Mps, Mcs, Omit<TState, "liveblocks">>, options: Options<Omit<TState, "liveblocks">>) => StateCreator<TState, Mps, Mcs, TState>;
60
+ declare const liveblocks: OuterLiveblocksMiddleware;
61
+ /**
62
+ * @deprecated Renamed to `liveblocks`.
63
+ */
64
+ declare const middleware: OuterLiveblocksMiddleware;
58
65
 
59
- export { LiveblocksContext, LiveblocksState, Mapping, ZustandState, middleware };
66
+ export { LiveblocksContext, LiveblocksState, Mapping, WithLiveblocks, liveblocks, middleware };
package/dist/index.js CHANGED
@@ -17,6 +17,18 @@ var __spreadValues = (a, b) => {
17
17
  return a;
18
18
  };
19
19
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+ var __objRest = (source, exclude) => {
21
+ var target = {};
22
+ for (var prop in source)
23
+ if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
24
+ target[prop] = source[prop];
25
+ if (source != null && __getOwnPropSymbols)
26
+ for (var prop of __getOwnPropSymbols(source)) {
27
+ if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
28
+ target[prop] = source[prop];
29
+ }
30
+ return target;
31
+ };
20
32
 
21
33
  // src/index.ts
22
34
 
@@ -31,36 +43,34 @@ function mappingToFunctionIsNotAllowed(key) {
31
43
  `${ERROR_PREFIX} mapping.${key} is invalid. Mapping to a function is not allowed.`
32
44
  );
33
45
  }
34
- function isJson(value) {
35
- return value === null || typeof value === "string" || typeof value === "number" || typeof value === "boolean" || Array.isArray(value) && value.every(isJson) || typeof value === "object" && Object.values(value).every(isJson);
36
- }
37
- function middleware(config, options) {
46
+ var middlewareImpl = (config, options) => {
38
47
  const { client, presenceMapping, storageMapping } = validateOptions(options);
39
48
  return (set, get, api) => {
40
- const typedSet = set;
41
- let room = null;
49
+ let maybeRoom = null;
42
50
  let isPatching = false;
43
51
  let storageRoot = null;
44
52
  let unsubscribeCallbacks = [];
45
- function enterRoom(roomId, initialState) {
53
+ function enterRoom(roomId) {
46
54
  if (storageRoot) {
47
55
  return;
48
56
  }
49
- room = client.enter(roomId, { initialPresence: {} });
50
- updateZustandLiveblocksState(set, {
51
- isStorageLoading: true,
52
- room
57
+ const initialPresence = selectFields(
58
+ get(),
59
+ presenceMapping
60
+ );
61
+ const room = client.enter(roomId, {
62
+ initialPresence
53
63
  });
54
- const state = get();
55
- broadcastInitialPresence(room, state, presenceMapping);
64
+ maybeRoom = room;
65
+ updateLiveblocksContext(set, { isStorageLoading: true, room });
56
66
  unsubscribeCallbacks.push(
57
67
  room.events.others.subscribe(({ others }) => {
58
- updateZustandLiveblocksState(set, { others });
68
+ updateLiveblocksContext(set, { others });
59
69
  })
60
70
  );
61
71
  unsubscribeCallbacks.push(
62
72
  room.events.connection.subscribe(() => {
63
- updateZustandLiveblocksState(set, {
73
+ updateLiveblocksContext(set, {
64
74
  connection: room.getConnectionState()
65
75
  });
66
76
  })
@@ -69,7 +79,10 @@ function middleware(config, options) {
69
79
  room.events.me.subscribe(() => {
70
80
  if (isPatching === false) {
71
81
  set(
72
- patchPresenceState(room.getPresence(), presenceMapping)
82
+ selectFields(
83
+ room.getPresence(),
84
+ presenceMapping
85
+ )
73
86
  );
74
87
  }
75
88
  })
@@ -79,15 +92,17 @@ function middleware(config, options) {
79
92
  room.batch(() => {
80
93
  for (const key in storageMapping) {
81
94
  const liveblocksStatePart = root.get(key);
82
- if (liveblocksStatePart == null) {
83
- updates[key] = initialState[key];
84
- _core.patchLiveObjectKey.call(void 0, root, key, void 0, initialState[key]);
95
+ if (liveblocksStatePart === void 0) {
96
+ updates[key] = get()[key];
97
+ _core.patchLiveObjectKey.call(void 0, root, key, void 0, get()[key]);
85
98
  } else {
86
- updates[key] = _core.lsonToJson.call(void 0, liveblocksStatePart);
99
+ updates[key] = _core.lsonToJson.call(void 0,
100
+ liveblocksStatePart
101
+ );
87
102
  }
88
103
  }
89
104
  });
90
- typedSet(updates);
105
+ set(updates);
91
106
  storageRoot = root;
92
107
  unsubscribeCallbacks.push(
93
108
  room.subscribe(
@@ -100,7 +115,9 @@ function middleware(config, options) {
100
115
  { isDeep: true }
101
116
  )
102
117
  );
103
- updateZustandLiveblocksState(set, { isStorageLoading: false });
118
+ updateLiveblocksContext(set, {
119
+ isStorageLoading: false
120
+ });
104
121
  });
105
122
  }
106
123
  function leaveRoom(roomId) {
@@ -108,11 +125,11 @@ function middleware(config, options) {
108
125
  unsubscribe();
109
126
  }
110
127
  storageRoot = null;
111
- room = null;
128
+ maybeRoom = null;
112
129
  isPatching = false;
113
130
  unsubscribeCallbacks = [];
114
131
  client.leave(roomId);
115
- updateZustandLiveblocksState(set, {
132
+ updateLiveblocksContext(set, {
116
133
  others: [],
117
134
  connection: "closed",
118
135
  isStorageLoading: false,
@@ -121,17 +138,13 @@ function middleware(config, options) {
121
138
  }
122
139
  const store = config(
123
140
  (args) => {
124
- const oldState = get();
141
+ const _a = get(), { liveblocks: _ } = _a, oldState = __objRest(_a, ["liveblocks"]);
125
142
  set(args);
126
- const newState = get();
127
- if (room) {
143
+ const _b = get(), { liveblocks: __ } = _b, newState = __objRest(_b, ["liveblocks"]);
144
+ if (maybeRoom) {
145
+ const room = maybeRoom;
128
146
  isPatching = true;
129
- updatePresence(
130
- room,
131
- oldState,
132
- newState,
133
- presenceMapping
134
- );
147
+ updatePresence(room, oldState, newState, presenceMapping);
135
148
  room.batch(() => {
136
149
  if (storageRoot) {
137
150
  patchLiveblocksStorage(
@@ -159,7 +172,9 @@ function middleware(config, options) {
159
172
  }
160
173
  });
161
174
  };
162
- }
175
+ };
176
+ var liveblocks = middlewareImpl;
177
+ var middleware = liveblocks;
163
178
  function patchState(state, updates, mapping) {
164
179
  const partialState = {};
165
180
  for (const key in mapping) {
@@ -172,29 +187,26 @@ function patchState(state, updates, mapping) {
172
187
  }
173
188
  return result;
174
189
  }
175
- function patchPresenceState(presence, mapping) {
190
+ function selectFields(presence, mapping) {
176
191
  const partialState = {};
177
192
  for (const key in mapping) {
178
193
  partialState[key] = presence[key];
179
194
  }
180
195
  return partialState;
181
196
  }
182
- function updateZustandLiveblocksState(set, partial) {
197
+ function updateLiveblocksContext(set, partial) {
183
198
  set((state) => ({ liveblocks: __spreadValues(__spreadValues({}, state.liveblocks), partial) }));
184
199
  }
185
- function broadcastInitialPresence(room, state, mapping) {
186
- for (const key in mapping) {
187
- room == null ? void 0 : room.updatePresence({ [key]: state[key] });
188
- }
189
- }
190
200
  function updatePresence(room, oldState, newState, presenceMapping) {
191
201
  for (const key in presenceMapping) {
192
202
  if (typeof newState[key] === "function") {
193
203
  throw mappingToFunctionIsNotAllowed(key);
194
204
  }
195
205
  if (oldState[key] !== newState[key]) {
196
- const val = newState[key];
197
- room.updatePresence({ [key]: val });
206
+ const val = newState == null ? void 0 : newState[key];
207
+ const patch = {};
208
+ patch[key] = val;
209
+ room.updatePresence(patch);
198
210
  }
199
211
  }
200
212
  }
@@ -206,9 +218,7 @@ function patchLiveblocksStorage(root, oldState, newState, mapping) {
206
218
  if (oldState[key] !== newState[key]) {
207
219
  const oldVal = oldState[key];
208
220
  const newVal = newState[key];
209
- if ((oldVal === void 0 || isJson(oldVal)) && (newVal === void 0 || isJson(newVal))) {
210
- _core.patchLiveObjectKey.call(void 0, root, key, oldVal, newVal);
211
- }
221
+ _core.patchLiveObjectKey.call(void 0, root, key, oldVal, newVal);
212
222
  }
213
223
  }
214
224
  }
@@ -260,4 +270,5 @@ function validateOptions(options) {
260
270
  }
261
271
 
262
272
 
263
- exports.middleware = middleware;
273
+
274
+ exports.liveblocks = liveblocks; exports.middleware = middleware;
package/dist/index.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  import mod from "./index.js";
2
2
 
3
3
  export default mod;
4
+ export const liveblocks = mod.liveblocks;
4
5
  export const middleware = mod.middleware;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/zustand",
3
- "version": "0.18.4",
3
+ "version": "0.19.0-beta0",
4
4
  "description": "A middleware to integrate Liveblocks into Zustand stores.",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",
@@ -18,12 +18,13 @@
18
18
  "collaborative"
19
19
  ],
20
20
  "scripts": {
21
+ "dev": "tsup --watch --onSuccess ../../scripts/build.sh",
21
22
  "build": "tsup && ../../scripts/build.sh",
22
23
  "format": "eslint --fix src/ && prettier --write src/",
23
24
  "lint": "eslint src/",
24
- "test": "jest --watch --silent --verbose",
25
- "test-ci": "jest --silent --verbose",
26
- "dtslint": "dtslint --localTs node_modules/typescript/lib --expectOnly types"
25
+ "test": "jest --silent --verbose",
26
+ "test:types": "tsd",
27
+ "test:watch": "jest --silent --verbose --watch"
27
28
  },
28
29
  "license": "Apache-2.0",
29
30
  "repository": {
@@ -32,30 +33,18 @@
32
33
  "directory": "packages/liveblocks-zustand"
33
34
  },
34
35
  "dependencies": {
35
- "@liveblocks/core": "0.18.4",
36
- "@liveblocks/client": "0.18.4"
36
+ "@liveblocks/client": "0.19.0-beta0",
37
+ "@liveblocks/core": "0.19.0-beta0"
37
38
  },
38
39
  "peerDependencies": {
39
- "zustand": "^3"
40
+ "zustand": "^4.1.3"
40
41
  },
41
42
  "devDependencies": {
42
- "@definitelytyped/dtslint": "^0.0.103",
43
+ "@liveblocks/eslint-config": "*",
44
+ "@liveblocks/jest-config": "*",
43
45
  "@testing-library/jest-dom": "^5.16.5",
44
- "@types/jest": "^29.1.2",
45
- "@typescript-eslint/eslint-plugin": "^5.26.0",
46
- "@typescript-eslint/parser": "^5.26.0",
47
- "eslint": "^8.12.0",
48
- "eslint-plugin-import": "^2.26.0",
49
- "eslint-plugin-simple-import-sort": "^7.0.0",
50
- "jest": "^29.1.2",
51
- "jest-environment-jsdom": "^29.1.2",
52
46
  "msw": "^0.36.4",
53
- "prettier": "^2.7.1",
54
- "ts-jest": "^29.0.3",
55
- "tsup": "^6.2.2",
56
- "typescript": "^4.7.2",
57
- "whatwg-fetch": "^3.6.2",
58
- "zustand": "^3.6.9"
47
+ "zustand": "^4.1.3"
59
48
  },
60
49
  "sideEffects": false
61
50
  }