@liveblocks/zustand 0.17.7 → 0.17.10-debug

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.
@@ -0,0 +1 @@
1
+ cee9f7e7c838f96a08436ef427e52a81b3c66977
package/index.d.ts CHANGED
@@ -1,97 +1,58 @@
1
- import {
2
- JsonObject,
3
- LsonObject,
4
- BaseUserMeta,
5
- Json,
6
- Room,
7
- User,
8
- Client,
9
- } from "@liveblocks/client";
10
- import { StateCreator, SetState, GetState, StoreApi } from "zustand";
1
+ import { JsonObject, LsonObject, BaseUserMeta, Json, Room, User, Client } from '@liveblocks/client';
2
+ import { StateCreator, SetState, GetState, StoreApi } from 'zustand';
11
3
 
12
4
  declare type ZustandState = Record<string, unknown>;
13
- declare type LiveblocksState<
14
- TState extends ZustandState,
15
- TPresence extends JsonObject = JsonObject,
16
- TStorage extends LsonObject = LsonObject,
17
- TUserMeta extends BaseUserMeta = BaseUserMeta,
18
- TRoomEvent extends Json = Json
19
- > = TState & {
20
- /**
21
- * Liveblocks extra state attached by the middleware
22
- */
23
- readonly liveblocks: {
5
+ declare type LiveblocksState<TState extends ZustandState, TPresence extends JsonObject = JsonObject, TStorage extends LsonObject = LsonObject, TUserMeta extends BaseUserMeta = BaseUserMeta, TRoomEvent extends Json = Json> = TState & {
24
6
  /**
25
- * Enters a room and starts sync it with zustand state
26
- * @param roomId The id of the room
27
- * @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.
7
+ * Liveblocks extra state attached by the middleware
28
8
  */
29
- readonly enterRoom: (roomId: string, initialState: Partial<TState>) => void;
30
- /**
31
- * Leaves a room and stops sync it with zustand state.
32
- * @param roomId The id of the room
33
- */
34
- readonly leaveRoom: (roomId: string) => void;
35
- /**
36
- * The room currently synced to your zustand state.
37
- */
38
- readonly room: Room<TPresence, TStorage, TUserMeta, TRoomEvent> | null;
9
+ readonly liveblocks: {
10
+ /**
11
+ * Enters a room and starts sync it with zustand state
12
+ * @param roomId The id of the room
13
+ * @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.
14
+ */
15
+ readonly enterRoom: (roomId: string, initialState: Partial<TState>) => void;
16
+ /**
17
+ * Leaves a room and stops sync it with zustand state.
18
+ * @param roomId The id of the room
19
+ */
20
+ readonly leaveRoom: (roomId: string) => void;
21
+ /**
22
+ * The room currently synced to your zustand state.
23
+ */
24
+ readonly room: Room<TPresence, TStorage, TUserMeta, TRoomEvent> | null;
25
+ /**
26
+ * Other users in the room. Empty no room is currently synced
27
+ */
28
+ readonly others: Array<User<TPresence, TUserMeta>>;
29
+ /**
30
+ * Whether or not the room storage is currently loading
31
+ */
32
+ readonly isStorageLoading: boolean;
33
+ /**
34
+ * Connection state of the room
35
+ */
36
+ readonly connection: "closed" | "authenticating" | "unavailable" | "failed" | "open" | "connecting";
37
+ };
38
+ };
39
+ declare type Mapping<T> = {
40
+ [K in keyof T]?: boolean;
41
+ };
42
+ declare type Options<T> = {
39
43
  /**
40
- * Other users in the room. Empty no room is currently synced
44
+ * Liveblocks client created by @liveblocks/client createClient
41
45
  */
42
- readonly others: Array<User<TPresence, TUserMeta>>;
46
+ client: Client;
43
47
  /**
44
- * Whether or not the room storage is currently loading
48
+ * Mapping used to synchronize a part of your zustand state with one Liveblocks Room storage.
45
49
  */
46
- readonly isStorageLoading: boolean;
50
+ storageMapping?: Mapping<T>;
47
51
  /**
48
- * Connection state of the room
52
+ * Mapping used to synchronize a part of your zustand state with one Liveblocks Room presence.
49
53
  */
50
- readonly connection:
51
- | "closed"
52
- | "authenticating"
53
- | "unavailable"
54
- | "failed"
55
- | "open"
56
- | "connecting";
57
- };
58
- };
59
- declare type Mapping<T> = {
60
- [K in keyof T]?: boolean;
61
- };
62
- declare type Options<T> = {
63
- /**
64
- * Liveblocks client created by @liveblocks/client createClient
65
- */
66
- client: Client;
67
- /**
68
- * Mapping used to synchronize a part of your zustand state with one Liveblocks Room storage.
69
- */
70
- storageMapping?: Mapping<T>;
71
- /**
72
- * Mapping used to synchronize a part of your zustand state with one Liveblocks Room presence.
73
- */
74
- presenceMapping?: Mapping<T>;
54
+ presenceMapping?: Mapping<T>;
75
55
  };
76
- declare function middleware<
77
- T extends ZustandState,
78
- TPresence extends JsonObject = JsonObject,
79
- TStorage extends LsonObject = LsonObject,
80
- TUserMeta extends BaseUserMeta = BaseUserMeta,
81
- TRoomEvent extends Json = Json
82
- >(
83
- config: StateCreator<
84
- T,
85
- SetState<T>,
86
- GetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>,
87
- StoreApi<T>
88
- >,
89
- options: Options<T>
90
- ): StateCreator<
91
- LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>,
92
- SetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>,
93
- GetState<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>,
94
- StoreApi<LiveblocksState<T, TPresence, TStorage, TUserMeta, TRoomEvent>>
95
- >;
56
+ 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>>>;
96
57
 
97
58
  export { LiveblocksState, Mapping, ZustandState, middleware };
package/index.js CHANGED
@@ -1,326 +1,285 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: !0 });
3
- var internal = require("@liveblocks/client/internal");
4
- function _extends() {
5
- return (
6
- (_extends =
7
- Object.assign ||
8
- function (target) {
9
- for (var i = 1; i < arguments.length; i++) {
10
- var source = arguments[i];
11
- for (var key in source)
12
- Object.prototype.hasOwnProperty.call(source, key) &&
13
- (target[key] = source[key]);
14
- }
15
- return target;
16
- }),
17
- _extends.apply(this, arguments)
18
- );
1
+ "use strict";Object.defineProperty(exports, "__esModule", {value: true});var __defProp = Object.defineProperty;
2
+ var __defProps = Object.defineProperties;
3
+ var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
4
+ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __propIsEnum = Object.prototype.propertyIsEnumerable;
7
+ var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
8
+ var __spreadValues = (a, b) => {
9
+ for (var prop in b || (b = {}))
10
+ if (__hasOwnProp.call(b, prop))
11
+ __defNormalProp(a, prop, b[prop]);
12
+ if (__getOwnPropSymbols)
13
+ for (var prop of __getOwnPropSymbols(b)) {
14
+ if (__propIsEnum.call(b, prop))
15
+ __defNormalProp(a, prop, b[prop]);
16
+ }
17
+ return a;
18
+ };
19
+ var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
20
+
21
+ // src/index.ts
22
+
23
+
24
+
25
+
26
+ var _internal = require('@liveblocks/client/internal');
27
+
28
+ // src/errors.ts
29
+ var ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
30
+ function missingClient() {
31
+ return new Error(`${ERROR_PREFIX} client is missing`);
19
32
  }
20
- function _arrayLikeToArray(arr, len) {
21
- (null == len || len > arr.length) && (len = arr.length);
22
- for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i];
23
- return arr2;
33
+ function missingMapping(mappingType) {
34
+ return new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
24
35
  }
25
- function _createForOfIteratorHelperLoose(o, allowArrayLike) {
26
- var it =
27
- ("undefined" != typeof Symbol && o[Symbol.iterator]) || o["@@iterator"];
28
- if (it) return (it = it.call(o)).next.bind(it);
29
- if (
30
- Array.isArray(o) ||
31
- (it = (function (o, minLen) {
32
- if (o) {
33
- if ("string" == typeof o) return _arrayLikeToArray(o, minLen);
34
- var n = Object.prototype.toString.call(o).slice(8, -1);
35
- return (
36
- "Object" === n && o.constructor && (n = o.constructor.name),
37
- "Map" === n || "Set" === n
38
- ? Array.from(o)
39
- : "Arguments" === n ||
40
- /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)
41
- ? _arrayLikeToArray(o, minLen)
42
- : void 0
43
- );
44
- }
45
- })(o)) ||
46
- (allowArrayLike && o && "number" == typeof o.length)
47
- ) {
48
- it && (o = it);
49
- var i = 0;
50
- return function () {
51
- return i >= o.length ? { done: !0 } : { done: !1, value: o[i++] };
52
- };
53
- }
54
- throw new TypeError(
55
- "Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."
36
+ function mappingShouldBeAnObject(mappingType) {
37
+ return new Error(
38
+ `${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`
56
39
  );
57
40
  }
58
- var ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
59
41
  function mappingValueShouldBeABoolean(mappingType, key) {
60
42
  return new Error(
61
- ERROR_PREFIX + " " + mappingType + "." + key + " value should be a boolean"
43
+ `${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`
62
44
  );
63
45
  }
64
46
  function mappingShouldNotHaveTheSameKeys(key) {
65
47
  return new Error(
66
- ERROR_PREFIX +
67
- ' "' +
68
- key +
69
- "\" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping."
48
+ `${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`
70
49
  );
71
50
  }
72
51
  function mappingToFunctionIsNotAllowed(key) {
73
52
  return new Error(
74
- ERROR_PREFIX +
75
- " mapping." +
76
- key +
77
- " is invalid. Mapping to a function is not allowed."
53
+ `${ERROR_PREFIX} mapping.${key} is invalid. Mapping to a function is not allowed.`
78
54
  );
79
55
  }
56
+
57
+ // src/index.ts
80
58
  function isJson(value) {
81
- return (
82
- null === value ||
83
- "string" == typeof value ||
84
- "number" == typeof value ||
85
- "boolean" == typeof value ||
86
- (Array.isArray(value) && value.every(isJson)) ||
87
- ("object" == typeof value && Object.values(value).every(isJson))
59
+ 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);
60
+ }
61
+ function middleware(config, options) {
62
+ if (process.env.NODE_ENV !== "production" && options.client == null) {
63
+ throw missingClient();
64
+ }
65
+ const client = options.client;
66
+ const storageMapping = validateMapping(
67
+ options.storageMapping || {},
68
+ "storageMapping"
69
+ );
70
+ const presenceMapping = validateMapping(
71
+ options.presenceMapping || {},
72
+ "presenceMapping"
88
73
  );
74
+ if (process.env.NODE_ENV !== "production") {
75
+ validateNoDuplicateKeys(storageMapping, presenceMapping);
76
+ }
77
+ return (set, get, api) => {
78
+ const typedSet = set;
79
+ let room = null;
80
+ let isPatching = false;
81
+ let storageRoot = null;
82
+ let unsubscribeCallbacks = [];
83
+ const store = config(
84
+ (args) => {
85
+ const oldState = get();
86
+ set(args);
87
+ const newState = get();
88
+ if (room) {
89
+ isPatching = true;
90
+ updatePresence(
91
+ room,
92
+ oldState,
93
+ newState,
94
+ presenceMapping
95
+ );
96
+ room.batch(() => {
97
+ if (storageRoot) {
98
+ patchLiveblocksStorage(
99
+ storageRoot,
100
+ oldState,
101
+ newState,
102
+ storageMapping
103
+ );
104
+ }
105
+ });
106
+ isPatching = false;
107
+ }
108
+ },
109
+ get,
110
+ api
111
+ );
112
+ function enterRoom(roomId, initialState) {
113
+ if (storageRoot) {
114
+ return;
115
+ }
116
+ room = client.enter(roomId);
117
+ updateZustandLiveblocksState(set, {
118
+ isStorageLoading: true,
119
+ room
120
+ });
121
+ const state = get();
122
+ broadcastInitialPresence(room, state, presenceMapping);
123
+ unsubscribeCallbacks.push(
124
+ room.subscribe("others", (others) => {
125
+ updateZustandLiveblocksState(set, { others: others.toArray() });
126
+ })
127
+ );
128
+ unsubscribeCallbacks.push(
129
+ room.subscribe("connection", () => {
130
+ updateZustandLiveblocksState(set, {
131
+ connection: room.getConnectionState()
132
+ });
133
+ })
134
+ );
135
+ unsubscribeCallbacks.push(
136
+ room.subscribe("my-presence", () => {
137
+ if (isPatching === false) {
138
+ set(
139
+ patchPresenceState(room.getPresence(), presenceMapping)
140
+ );
141
+ }
142
+ })
143
+ );
144
+ room.getStorage().then(({ root }) => {
145
+ const updates = {};
146
+ room.batch(() => {
147
+ for (const key in storageMapping) {
148
+ const liveblocksStatePart = root.get(key);
149
+ if (liveblocksStatePart == null) {
150
+ updates[key] = initialState[key];
151
+ _internal.patchLiveObjectKey.call(void 0, root, key, void 0, initialState[key]);
152
+ } else {
153
+ updates[key] = _internal.lsonToJson.call(void 0, liveblocksStatePart);
154
+ }
155
+ }
156
+ });
157
+ typedSet(updates);
158
+ storageRoot = root;
159
+ unsubscribeCallbacks.push(
160
+ room.subscribe(
161
+ root,
162
+ (updates2) => {
163
+ if (isPatching === false) {
164
+ set(patchState(get(), updates2, storageMapping));
165
+ }
166
+ },
167
+ { isDeep: true }
168
+ )
169
+ );
170
+ updateZustandLiveblocksState(set, { isStorageLoading: false });
171
+ });
172
+ }
173
+ function leaveRoom(roomId) {
174
+ for (const unsubscribe of unsubscribeCallbacks) {
175
+ unsubscribe();
176
+ }
177
+ storageRoot = null;
178
+ room = null;
179
+ isPatching = false;
180
+ unsubscribeCallbacks = [];
181
+ client.leave(roomId);
182
+ updateZustandLiveblocksState(set, {
183
+ others: [],
184
+ connection: "closed",
185
+ isStorageLoading: false,
186
+ room: null
187
+ });
188
+ }
189
+ return __spreadProps(__spreadValues({}, store), {
190
+ liveblocks: {
191
+ enterRoom,
192
+ leaveRoom,
193
+ room: null,
194
+ others: [],
195
+ connection: "closed",
196
+ isStorageLoading: false
197
+ }
198
+ });
199
+ };
200
+ }
201
+ function patchState(state, updates, mapping) {
202
+ const partialState = {};
203
+ for (const key in mapping) {
204
+ partialState[key] = state[key];
205
+ }
206
+ const patched = _internal.patchImmutableObject.call(void 0, partialState, updates);
207
+ const result = {};
208
+ for (const key in mapping) {
209
+ result[key] = patched[key];
210
+ }
211
+ return result;
212
+ }
213
+ function patchPresenceState(presence, mapping) {
214
+ const partialState = {};
215
+ for (const key in mapping) {
216
+ partialState[key] = presence[key];
217
+ }
218
+ return partialState;
89
219
  }
90
220
  function updateZustandLiveblocksState(set, partial) {
91
- set(function (state) {
92
- return { liveblocks: _extends({}, state.liveblocks, partial) };
93
- });
221
+ set((state) => ({ liveblocks: __spreadValues(__spreadValues({}, state.liveblocks), partial) }));
222
+ }
223
+ function broadcastInitialPresence(room, state, mapping) {
224
+ for (const key in mapping) {
225
+ room == null ? void 0 : room.updatePresence({ [key]: state[key] });
226
+ }
227
+ }
228
+ function updatePresence(room, oldState, newState, presenceMapping) {
229
+ for (const key in presenceMapping) {
230
+ if (typeof newState[key] === "function") {
231
+ throw mappingToFunctionIsNotAllowed("value");
232
+ }
233
+ if (oldState[key] !== newState[key]) {
234
+ const val = newState[key];
235
+ room.updatePresence({ [key]: val });
236
+ }
237
+ }
238
+ }
239
+ function patchLiveblocksStorage(root, oldState, newState, mapping) {
240
+ for (const key in mapping) {
241
+ if (process.env.NODE_ENV !== "production" && typeof newState[key] === "function") {
242
+ throw mappingToFunctionIsNotAllowed("value");
243
+ }
244
+ if (oldState[key] !== newState[key]) {
245
+ const oldVal = oldState[key];
246
+ const newVal = newState[key];
247
+ if ((oldVal === void 0 || isJson(oldVal)) && (newVal === void 0 || isJson(newVal))) {
248
+ _internal.patchLiveObjectKey.call(void 0, root, key, oldVal, newVal);
249
+ }
250
+ }
251
+ }
252
+ }
253
+ function isObject(value) {
254
+ return Object.prototype.toString.call(value) === "[object Object]";
255
+ }
256
+ function validateNoDuplicateKeys(storageMapping, presenceMapping) {
257
+ for (const key in storageMapping) {
258
+ if (presenceMapping[key] !== void 0) {
259
+ throw mappingShouldNotHaveTheSameKeys(key);
260
+ }
261
+ }
94
262
  }
95
263
  function validateMapping(mapping, mappingType) {
96
- if ("production" !== process.env.NODE_ENV) {
97
- if (null == mapping)
98
- throw (function (mappingType) {
99
- return new Error(ERROR_PREFIX + " " + mappingType + " is missing.");
100
- })(mappingType);
101
- if (
102
- ((value = mapping),
103
- "[object Object]" !== Object.prototype.toString.call(value))
104
- )
105
- throw (function (mappingType) {
106
- return new Error(
107
- ERROR_PREFIX +
108
- " " +
109
- mappingType +
110
- " should be an object where the values are boolean."
111
- );
112
- })(mappingType);
264
+ if (process.env.NODE_ENV !== "production") {
265
+ if (mapping == null) {
266
+ throw missingMapping(mappingType);
267
+ }
268
+ if (!isObject(mapping)) {
269
+ throw mappingShouldBeAnObject(mappingType);
270
+ }
113
271
  }
114
- var value,
115
- result = {};
116
- for (var key in mapping) {
117
- if (
118
- "production" !== process.env.NODE_ENV &&
119
- "boolean" != typeof mapping[key]
120
- )
272
+ const result = {};
273
+ for (const key in mapping) {
274
+ if (process.env.NODE_ENV !== "production" && typeof mapping[key] !== "boolean") {
121
275
  throw mappingValueShouldBeABoolean(mappingType, key);
122
- !0 === mapping[key] && (result[key] = !0);
276
+ }
277
+ if (mapping[key] === true) {
278
+ result[key] = true;
279
+ }
123
280
  }
124
281
  return result;
125
282
  }
126
- exports.middleware = function (config, options) {
127
- if ("production" !== process.env.NODE_ENV && null == options.client)
128
- throw new Error(ERROR_PREFIX + " client is missing");
129
- var client = options.client,
130
- storageMapping = validateMapping(
131
- options.storageMapping || {},
132
- "storageMapping"
133
- ),
134
- presenceMapping = validateMapping(
135
- options.presenceMapping || {},
136
- "presenceMapping"
137
- );
138
- return (
139
- "production" !== process.env.NODE_ENV &&
140
- (function (storageMapping, presenceMapping) {
141
- for (var key in storageMapping)
142
- if (void 0 !== presenceMapping[key])
143
- throw mappingShouldNotHaveTheSameKeys(key);
144
- })(storageMapping, presenceMapping),
145
- function (set, get, api) {
146
- var typedSet = set,
147
- room = null,
148
- isPatching = !1,
149
- storageRoot = null,
150
- unsubscribeCallbacks = [],
151
- store = config(
152
- function (args) {
153
- var oldState = get();
154
- set(args);
155
- var newState = get();
156
- room &&
157
- ((isPatching = !0),
158
- (function (room, oldState, newState, presenceMapping) {
159
- for (var key in presenceMapping) {
160
- if ("function" == typeof newState[key])
161
- throw mappingToFunctionIsNotAllowed("value");
162
- if (oldState[key] !== newState[key]) {
163
- var _room$updatePresence2,
164
- val = newState[key];
165
- room.updatePresence(
166
- (((_room$updatePresence2 = {})[key] = val),
167
- _room$updatePresence2)
168
- );
169
- }
170
- }
171
- })(room, oldState, newState, presenceMapping),
172
- room.batch(function () {
173
- storageRoot &&
174
- (function (root, oldState, newState, mapping) {
175
- for (var key in mapping) {
176
- if (
177
- "production" !== process.env.NODE_ENV &&
178
- "function" == typeof newState[key]
179
- )
180
- throw mappingToFunctionIsNotAllowed("value");
181
- if (oldState[key] !== newState[key]) {
182
- var oldVal = oldState[key],
183
- newVal = newState[key];
184
- (void 0 !== oldVal && !isJson(oldVal)) ||
185
- (void 0 !== newVal && !isJson(newVal)) ||
186
- internal.patchLiveObjectKey(
187
- root,
188
- key,
189
- oldVal,
190
- newVal
191
- );
192
- }
193
- }
194
- })(storageRoot, oldState, newState, storageMapping);
195
- }),
196
- (isPatching = !1));
197
- },
198
- get,
199
- api
200
- );
201
- return _extends({}, store, {
202
- liveblocks: {
203
- enterRoom: function (roomId, initialState) {
204
- if (!storageRoot) {
205
- (room = client.enter(roomId)),
206
- updateZustandLiveblocksState(set, {
207
- isStorageLoading: !0,
208
- room: room,
209
- });
210
- var state = get();
211
- !(function (room, state, mapping) {
212
- for (var key in mapping) {
213
- var _room$updatePresence;
214
- null == room ||
215
- room.updatePresence(
216
- (((_room$updatePresence = {})[key] = state[key]),
217
- _room$updatePresence)
218
- );
219
- }
220
- })(room, state, presenceMapping),
221
- unsubscribeCallbacks.push(
222
- room.subscribe("others", function (others) {
223
- updateZustandLiveblocksState(set, {
224
- others: others.toArray(),
225
- });
226
- })
227
- ),
228
- unsubscribeCallbacks.push(
229
- room.subscribe("connection", function () {
230
- updateZustandLiveblocksState(set, {
231
- connection: room.getConnectionState(),
232
- });
233
- })
234
- ),
235
- unsubscribeCallbacks.push(
236
- room.subscribe("my-presence", function () {
237
- !1 === isPatching &&
238
- set(
239
- (function (presence, mapping) {
240
- var partialState = {};
241
- for (var key in mapping)
242
- partialState[key] = presence[key];
243
- return partialState;
244
- })(room.getPresence(), presenceMapping)
245
- );
246
- })
247
- ),
248
- room.getStorage().then(function (_ref) {
249
- var root = _ref.root,
250
- updates = {};
251
- room.batch(function () {
252
- for (var key in storageMapping) {
253
- var liveblocksStatePart = root.get(key);
254
- null == liveblocksStatePart
255
- ? ((updates[key] = initialState[key]),
256
- internal.patchLiveObjectKey(
257
- root,
258
- key,
259
- void 0,
260
- initialState[key]
261
- ))
262
- : (updates[key] =
263
- internal.lsonToJson(liveblocksStatePart));
264
- }
265
- }),
266
- typedSet(updates),
267
- (storageRoot = root),
268
- unsubscribeCallbacks.push(
269
- room.subscribe(
270
- root,
271
- function (updates) {
272
- !1 === isPatching &&
273
- set(
274
- (function (state, updates, mapping) {
275
- var partialState = {};
276
- for (var key in mapping)
277
- partialState[key] = state[key];
278
- var patched = internal.patchImmutableObject(
279
- partialState,
280
- updates
281
- ),
282
- result = {};
283
- for (var _key in mapping)
284
- result[_key] = patched[_key];
285
- return result;
286
- })(get(), updates, storageMapping)
287
- );
288
- },
289
- { isDeep: !0 }
290
- )
291
- ),
292
- updateZustandLiveblocksState(set, { isStorageLoading: !1 });
293
- });
294
- }
295
- },
296
- leaveRoom: function (roomId) {
297
- for (
298
- var _step,
299
- _iterator =
300
- _createForOfIteratorHelperLoose(unsubscribeCallbacks);
301
- !(_step = _iterator()).done;
302
283
 
303
- ) {
304
- (0, _step.value)();
305
- }
306
- (storageRoot = null),
307
- (room = null),
308
- (isPatching = !1),
309
- (unsubscribeCallbacks = []),
310
- client.leave(roomId),
311
- updateZustandLiveblocksState(set, {
312
- others: [],
313
- connection: "closed",
314
- isStorageLoading: !1,
315
- room: null,
316
- });
317
- },
318
- room: null,
319
- others: [],
320
- connection: "closed",
321
- isStorageLoading: !1,
322
- },
323
- });
324
- }
325
- );
326
- };
284
+
285
+ exports.middleware = middleware;
package/index.mjs CHANGED
@@ -1,240 +1 @@
1
- import {
2
- patchLiveObjectKey,
3
- lsonToJson,
4
- patchImmutableObject,
5
- } from "@liveblocks/client/internal";
6
- const ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
7
- function mappingValueShouldBeABoolean(mappingType, key) {
8
- return new Error(
9
- `${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`
10
- );
11
- }
12
- function mappingShouldNotHaveTheSameKeys(key) {
13
- return new Error(
14
- `${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`
15
- );
16
- }
17
- function mappingToFunctionIsNotAllowed(key) {
18
- return new Error(
19
- `${ERROR_PREFIX} mapping.${key} is invalid. Mapping to a function is not allowed.`
20
- );
21
- }
22
- function isJson(value) {
23
- return (
24
- null === value ||
25
- "string" == typeof value ||
26
- "number" == typeof value ||
27
- "boolean" == typeof value ||
28
- (Array.isArray(value) && value.every(isJson)) ||
29
- ("object" == typeof value && Object.values(value).every(isJson))
30
- );
31
- }
32
- function middleware(config, options) {
33
- if ("production" !== process.env.NODE_ENV && null == options.client)
34
- throw new Error(`${ERROR_PREFIX} client is missing`);
35
- const client = options.client,
36
- storageMapping = validateMapping(
37
- options.storageMapping || {},
38
- "storageMapping"
39
- ),
40
- presenceMapping = validateMapping(
41
- options.presenceMapping || {},
42
- "presenceMapping"
43
- );
44
- return (
45
- "production" !== process.env.NODE_ENV &&
46
- (function (storageMapping, presenceMapping) {
47
- for (const key in storageMapping)
48
- if (void 0 !== presenceMapping[key])
49
- throw mappingShouldNotHaveTheSameKeys(key);
50
- })(storageMapping, presenceMapping),
51
- (set, get, api) => {
52
- const typedSet = set;
53
- let room = null,
54
- isPatching = !1,
55
- storageRoot = null,
56
- unsubscribeCallbacks = [];
57
- const store = config(
58
- (args) => {
59
- const oldState = get();
60
- set(args);
61
- const newState = get();
62
- room &&
63
- ((isPatching = !0),
64
- (function (room, oldState, newState, presenceMapping) {
65
- for (const key in presenceMapping) {
66
- if ("function" == typeof newState[key])
67
- throw mappingToFunctionIsNotAllowed("value");
68
- if (oldState[key] !== newState[key]) {
69
- const val = newState[key];
70
- room.updatePresence({ [key]: val });
71
- }
72
- }
73
- })(room, oldState, newState, presenceMapping),
74
- room.batch(() => {
75
- storageRoot &&
76
- (function (root, oldState, newState, mapping) {
77
- for (const key in mapping) {
78
- if (
79
- "production" !== process.env.NODE_ENV &&
80
- "function" == typeof newState[key]
81
- )
82
- throw mappingToFunctionIsNotAllowed("value");
83
- if (oldState[key] !== newState[key]) {
84
- const oldVal = oldState[key],
85
- newVal = newState[key];
86
- (void 0 !== oldVal && !isJson(oldVal)) ||
87
- (void 0 !== newVal && !isJson(newVal)) ||
88
- patchLiveObjectKey(root, key, oldVal, newVal);
89
- }
90
- }
91
- })(storageRoot, oldState, newState, storageMapping);
92
- }),
93
- (isPatching = !1));
94
- },
95
- get,
96
- api
97
- );
98
- return Object.assign(Object.assign({}, store), {
99
- liveblocks: {
100
- enterRoom: function (roomId, initialState) {
101
- if (storageRoot) return;
102
- (room = client.enter(roomId)),
103
- updateZustandLiveblocksState(set, {
104
- isStorageLoading: !0,
105
- room: room,
106
- });
107
- const state = get();
108
- !(function (room, state, mapping) {
109
- for (const key in mapping)
110
- null == room || room.updatePresence({ [key]: state[key] });
111
- })(room, state, presenceMapping),
112
- unsubscribeCallbacks.push(
113
- room.subscribe("others", (others) => {
114
- updateZustandLiveblocksState(set, {
115
- others: others.toArray(),
116
- });
117
- })
118
- ),
119
- unsubscribeCallbacks.push(
120
- room.subscribe("connection", () => {
121
- updateZustandLiveblocksState(set, {
122
- connection: room.getConnectionState(),
123
- });
124
- })
125
- ),
126
- unsubscribeCallbacks.push(
127
- room.subscribe("my-presence", () => {
128
- !1 === isPatching &&
129
- set(
130
- (function (presence, mapping) {
131
- const partialState = {};
132
- for (const key in mapping)
133
- partialState[key] = presence[key];
134
- return partialState;
135
- })(room.getPresence(), presenceMapping)
136
- );
137
- })
138
- ),
139
- room.getStorage().then(({ root: root }) => {
140
- const updates = {};
141
- room.batch(() => {
142
- for (const key in storageMapping) {
143
- const liveblocksStatePart = root.get(key);
144
- null == liveblocksStatePart
145
- ? ((updates[key] = initialState[key]),
146
- patchLiveObjectKey(
147
- root,
148
- key,
149
- void 0,
150
- initialState[key]
151
- ))
152
- : (updates[key] = lsonToJson(liveblocksStatePart));
153
- }
154
- }),
155
- typedSet(updates),
156
- (storageRoot = root),
157
- unsubscribeCallbacks.push(
158
- room.subscribe(
159
- root,
160
- (updates) => {
161
- !1 === isPatching &&
162
- set(
163
- (function (state, updates, mapping) {
164
- const partialState = {};
165
- for (const key in mapping)
166
- partialState[key] = state[key];
167
- const patched = patchImmutableObject(
168
- partialState,
169
- updates
170
- ),
171
- result = {};
172
- for (const key in mapping)
173
- result[key] = patched[key];
174
- return result;
175
- })(get(), updates, storageMapping)
176
- );
177
- },
178
- { isDeep: !0 }
179
- )
180
- ),
181
- updateZustandLiveblocksState(set, { isStorageLoading: !1 });
182
- });
183
- },
184
- leaveRoom: function (roomId) {
185
- for (const unsubscribe of unsubscribeCallbacks) unsubscribe();
186
- (storageRoot = null),
187
- (room = null),
188
- (isPatching = !1),
189
- (unsubscribeCallbacks = []),
190
- client.leave(roomId),
191
- updateZustandLiveblocksState(set, {
192
- others: [],
193
- connection: "closed",
194
- isStorageLoading: !1,
195
- room: null,
196
- });
197
- },
198
- room: null,
199
- others: [],
200
- connection: "closed",
201
- isStorageLoading: !1,
202
- },
203
- });
204
- }
205
- );
206
- }
207
- function updateZustandLiveblocksState(set, partial) {
208
- set((state) => ({
209
- liveblocks: Object.assign(Object.assign({}, state.liveblocks), partial),
210
- }));
211
- }
212
- function validateMapping(mapping, mappingType) {
213
- if ("production" !== process.env.NODE_ENV) {
214
- if (null == mapping)
215
- throw (function (mappingType) {
216
- return new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
217
- })(mappingType);
218
- if (
219
- ((value = mapping),
220
- "[object Object]" !== Object.prototype.toString.call(value))
221
- )
222
- throw (function (mappingType) {
223
- return new Error(
224
- `${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`
225
- );
226
- })(mappingType);
227
- }
228
- var value;
229
- const result = {};
230
- for (const key in mapping) {
231
- if (
232
- "production" !== process.env.NODE_ENV &&
233
- "boolean" != typeof mapping[key]
234
- )
235
- throw mappingValueShouldBeABoolean(mappingType, key);
236
- !0 === mapping[key] && (result[key] = !0);
237
- }
238
- return result;
239
- }
240
- export { middleware };
1
+ export { middleware } from "./index.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@liveblocks/zustand",
3
- "version": "0.17.7",
3
+ "version": "0.17.10-debug",
4
4
  "description": "A middleware to integrate Liveblocks into Zustand stores.",
5
5
  "main": "./index.js",
6
6
  "module": "./index.mjs",
@@ -20,7 +20,7 @@
20
20
  "directory": "packages/liveblocks-zustand"
21
21
  },
22
22
  "peerDependencies": {
23
- "@liveblocks/client": "0.17.7",
23
+ "@liveblocks/client": "0.17.10-debug",
24
24
  "zustand": "^3"
25
25
  },
26
26
  "sideEffects": false