@liveblocks/zustand 0.15.0-alpha.2 → 0.15.0-alpha.3

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.
@@ -1,5 +1,25 @@
1
1
  import { patchLiveObjectKey, liveNodeToJson, patchImmutableObject } from '@liveblocks/client';
2
2
 
3
+ const ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
4
+ function missingClient() {
5
+ return new Error(`${ERROR_PREFIX} client is missing`);
6
+ }
7
+ function missingMapping(mappingType) {
8
+ return new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
9
+ }
10
+ function mappingShouldBeAnObject(mappingType) {
11
+ return new Error(`${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`);
12
+ }
13
+ function mappingValueShouldBeABoolean(mappingType, key) {
14
+ return new Error(`${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`);
15
+ }
16
+ function mappingShouldNotHaveTheSameKeys(key) {
17
+ return new Error(`${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`);
18
+ }
19
+ function mappingToFunctionIsNotAllowed(key) {
20
+ return new Error(`${ERROR_PREFIX} mapping.${key} is invalid. Mapping to a function is not allowed.`);
21
+ }
22
+
3
23
  var __defProp = Object.defineProperty;
4
24
  var __defProps = Object.defineProperties;
5
25
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
@@ -19,17 +39,16 @@ var __spreadValues = (a, b) => {
19
39
  return a;
20
40
  };
21
41
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
- const middleware = (config, {
23
- client,
24
- storageMapping: unvalidatedMapping,
25
- presenceMapping: unvalidatedPresenceMapping = {}
26
- }) => {
27
- if (client == null) {
28
- throw new Error(`${ERROR_PREFIX} client is missing`);
42
+ function middleware(config, options) {
43
+ if (process.env.NODE_ENV !== "production" && options.client == null) {
44
+ throw missingClient();
45
+ }
46
+ const client = options.client;
47
+ const mapping = validateMapping(options.storageMapping, "storageMapping");
48
+ const presenceMapping = validateMapping(options.presenceMapping || {}, "presenceMapping");
49
+ if (process.env.NODE_ENV !== "production") {
50
+ validateNoDuplicateKeys(mapping, presenceMapping);
29
51
  }
30
- const mapping = validateMapping(unvalidatedMapping, "storageMapping");
31
- const presenceMapping = validateMapping(unvalidatedPresenceMapping, "presenceMapping");
32
- validateNoDuplicateKeys(mapping, presenceMapping);
33
52
  return (set, get, api) => {
34
53
  const typedSet = set;
35
54
  let room = null;
@@ -117,7 +136,7 @@ const middleware = (config, {
117
136
  }
118
137
  });
119
138
  };
120
- };
139
+ }
121
140
  function patchState(state, updates, mapping) {
122
141
  const partialState = {};
123
142
  for (const key in mapping) {
@@ -140,6 +159,9 @@ function broadcastInitialPresence(room, state, mapping) {
140
159
  }
141
160
  function updatePresence(room, oldState, newState, presenceMapping) {
142
161
  for (const key in presenceMapping) {
162
+ if (typeof newState[key] === "function") {
163
+ throw mappingToFunctionIsNotAllowed("value");
164
+ }
143
165
  if (oldState[key] !== newState[key]) {
144
166
  room.updatePresence({ [key]: newState[key] });
145
167
  }
@@ -147,6 +169,9 @@ function updatePresence(room, oldState, newState, presenceMapping) {
147
169
  }
148
170
  function patchLiveblocksStorage(root, oldState, newState, mapping) {
149
171
  for (const key in mapping) {
172
+ if (process.env.NODE_ENV !== "production" && typeof newState[key] === "function") {
173
+ throw mappingToFunctionIsNotAllowed("value");
174
+ }
150
175
  if (oldState[key] !== newState[key]) {
151
176
  patchLiveObjectKey(root, key, oldState[key], newState[key]);
152
177
  }
@@ -158,21 +183,23 @@ function isObject(value) {
158
183
  function validateNoDuplicateKeys(storageMapping, presenceMapping) {
159
184
  for (const key in storageMapping) {
160
185
  if (presenceMapping[key] !== void 0) {
161
- throw new Error(`${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`);
186
+ throw mappingShouldNotHaveTheSameKeys(key);
162
187
  }
163
188
  }
164
189
  }
165
190
  function validateMapping(mapping, mappingType) {
166
- if (mapping == null) {
167
- throw new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
168
- }
169
- if (!isObject(mapping)) {
170
- throw new Error(`${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`);
191
+ if (process.env.NODE_ENV !== "production") {
192
+ if (mapping == null) {
193
+ throw missingMapping(mappingType);
194
+ }
195
+ if (!isObject(mapping)) {
196
+ throw mappingShouldBeAnObject(mappingType);
197
+ }
171
198
  }
172
199
  const result = {};
173
200
  for (const key in mapping) {
174
- if (typeof mapping[key] !== "boolean") {
175
- throw new Error(`${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`);
201
+ if (process.env.NODE_ENV !== "production" && typeof mapping[key] !== "boolean") {
202
+ throw mappingValueShouldBeABoolean(mappingType, key);
176
203
  }
177
204
  if (mapping[key] === true) {
178
205
  result[key] = true;
@@ -180,6 +207,5 @@ function validateMapping(mapping, mappingType) {
180
207
  }
181
208
  return result;
182
209
  }
183
- const ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
184
210
 
185
211
  export { middleware };
@@ -1,5 +1,25 @@
1
1
  import { patchLiveObjectKey, liveNodeToJson, patchImmutableObject } from '@liveblocks/client';
2
2
 
3
+ const ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
4
+ function missingClient() {
5
+ return new Error(`${ERROR_PREFIX} client is missing`);
6
+ }
7
+ function missingMapping(mappingType) {
8
+ return new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
9
+ }
10
+ function mappingShouldBeAnObject(mappingType) {
11
+ return new Error(`${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`);
12
+ }
13
+ function mappingValueShouldBeABoolean(mappingType, key) {
14
+ return new Error(`${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`);
15
+ }
16
+ function mappingShouldNotHaveTheSameKeys(key) {
17
+ return new Error(`${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`);
18
+ }
19
+ function mappingToFunctionIsNotAllowed(key) {
20
+ return new Error(`${ERROR_PREFIX} mapping.${key} is invalid. Mapping to a function is not allowed.`);
21
+ }
22
+
3
23
  var __defProp = Object.defineProperty;
4
24
  var __defProps = Object.defineProperties;
5
25
  var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
@@ -19,17 +39,16 @@ var __spreadValues = (a, b) => {
19
39
  return a;
20
40
  };
21
41
  var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
22
- const middleware = (config, {
23
- client,
24
- storageMapping: unvalidatedMapping,
25
- presenceMapping: unvalidatedPresenceMapping = {}
26
- }) => {
27
- if (client == null) {
28
- throw new Error(`${ERROR_PREFIX} client is missing`);
42
+ function middleware(config, options) {
43
+ if (process.env.NODE_ENV !== "production" && options.client == null) {
44
+ throw missingClient();
45
+ }
46
+ const client = options.client;
47
+ const mapping = validateMapping(options.storageMapping, "storageMapping");
48
+ const presenceMapping = validateMapping(options.presenceMapping || {}, "presenceMapping");
49
+ if (process.env.NODE_ENV !== "production") {
50
+ validateNoDuplicateKeys(mapping, presenceMapping);
29
51
  }
30
- const mapping = validateMapping(unvalidatedMapping, "storageMapping");
31
- const presenceMapping = validateMapping(unvalidatedPresenceMapping, "presenceMapping");
32
- validateNoDuplicateKeys(mapping, presenceMapping);
33
52
  return (set, get, api) => {
34
53
  const typedSet = set;
35
54
  let room = null;
@@ -117,7 +136,7 @@ const middleware = (config, {
117
136
  }
118
137
  });
119
138
  };
120
- };
139
+ }
121
140
  function patchState(state, updates, mapping) {
122
141
  const partialState = {};
123
142
  for (const key in mapping) {
@@ -140,6 +159,9 @@ function broadcastInitialPresence(room, state, mapping) {
140
159
  }
141
160
  function updatePresence(room, oldState, newState, presenceMapping) {
142
161
  for (const key in presenceMapping) {
162
+ if (typeof newState[key] === "function") {
163
+ throw mappingToFunctionIsNotAllowed("value");
164
+ }
143
165
  if (oldState[key] !== newState[key]) {
144
166
  room.updatePresence({ [key]: newState[key] });
145
167
  }
@@ -147,6 +169,9 @@ function updatePresence(room, oldState, newState, presenceMapping) {
147
169
  }
148
170
  function patchLiveblocksStorage(root, oldState, newState, mapping) {
149
171
  for (const key in mapping) {
172
+ if (process.env.NODE_ENV !== "production" && typeof newState[key] === "function") {
173
+ throw mappingToFunctionIsNotAllowed("value");
174
+ }
150
175
  if (oldState[key] !== newState[key]) {
151
176
  patchLiveObjectKey(root, key, oldState[key], newState[key]);
152
177
  }
@@ -158,21 +183,23 @@ function isObject(value) {
158
183
  function validateNoDuplicateKeys(storageMapping, presenceMapping) {
159
184
  for (const key in storageMapping) {
160
185
  if (presenceMapping[key] !== void 0) {
161
- throw new Error(`${ERROR_PREFIX} "${key}" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.`);
186
+ throw mappingShouldNotHaveTheSameKeys(key);
162
187
  }
163
188
  }
164
189
  }
165
190
  function validateMapping(mapping, mappingType) {
166
- if (mapping == null) {
167
- throw new Error(`${ERROR_PREFIX} ${mappingType} is missing.`);
168
- }
169
- if (!isObject(mapping)) {
170
- throw new Error(`${ERROR_PREFIX} ${mappingType} should be an object where the values are boolean.`);
191
+ if (process.env.NODE_ENV !== "production") {
192
+ if (mapping == null) {
193
+ throw missingMapping(mappingType);
194
+ }
195
+ if (!isObject(mapping)) {
196
+ throw mappingShouldBeAnObject(mappingType);
197
+ }
171
198
  }
172
199
  const result = {};
173
200
  for (const key in mapping) {
174
- if (typeof mapping[key] !== "boolean") {
175
- throw new Error(`${ERROR_PREFIX} ${mappingType}.${key} value should be a boolean`);
201
+ if (process.env.NODE_ENV !== "production" && typeof mapping[key] !== "boolean") {
202
+ throw mappingValueShouldBeABoolean(mappingType, key);
176
203
  }
177
204
  if (mapping[key] === true) {
178
205
  result[key] = true;
@@ -180,6 +207,5 @@ function validateMapping(mapping, mappingType) {
180
207
  }
181
208
  return result;
182
209
  }
183
- const ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
184
210
 
185
211
  export { middleware };
package/lib/index.d.ts CHANGED
@@ -1,20 +1,55 @@
1
1
  import { StateCreator, SetState, GetState, StoreApi } from "zustand";
2
2
  import { Client, User, Room } from "@liveblocks/client";
3
3
  export declare type LiveblocksState<TState, TPresence = any> = TState & {
4
+ /**
5
+ * Liveblocks extra state attached by the middleware
6
+ */
4
7
  readonly liveblocks: {
5
- readonly enterRoom: (room: string, initialState: Partial<TState>) => void;
6
- readonly leaveRoom: (room: string) => void;
8
+ /**
9
+ * Enters a room and starts sync it with zustand state
10
+ * @param roomId The id of the room
11
+ * @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.
12
+ */
13
+ readonly enterRoom: (roomId: string, initialState: Partial<TState>) => void;
14
+ /**
15
+ * Leaves a room and stops sync it with zustand state.
16
+ * @param roomId The id of the room
17
+ */
18
+ readonly leaveRoom: (roomId: string) => void;
19
+ /**
20
+ * The room currently synced to your zustand state.
21
+ */
7
22
  readonly room: Room | null;
23
+ /**
24
+ * Other users in the room. Empty no room is currently synced
25
+ */
8
26
  readonly others: Array<User<TPresence>>;
27
+ /**
28
+ * Whether or not the room storage is currently loading
29
+ */
9
30
  readonly isStorageLoading: boolean;
31
+ /**
32
+ * Connection state of the room
33
+ */
10
34
  readonly connection: "closed" | "authenticating" | "unavailable" | "failed" | "open" | "connecting";
11
35
  };
12
36
  };
13
37
  export declare type Mapping<T> = Partial<{
14
38
  [Property in keyof T]: boolean;
15
39
  }>;
16
- export declare const middleware: <T extends Object, TPresence extends Object = any>(config: StateCreator<T, SetState<T>, GetState<LiveblocksState<T>>, StoreApi<T>>, options: {
40
+ declare type Options<T> = {
41
+ /**
42
+ * Liveblocks client created by @liveblocks/client createClient
43
+ */
17
44
  client: Client;
45
+ /**
46
+ * Mapping used to synchronize a part of your zustand state with one Liveblocks Room storage.
47
+ */
18
48
  storageMapping: Mapping<T>;
49
+ /**
50
+ * Mapping used to synchronize a part of your zustand state with one Liveblocks Room presence.
51
+ */
19
52
  presenceMapping?: Mapping<T>;
20
- }) => StateCreator<LiveblocksState<T, TPresence>, SetState<LiveblocksState<T, TPresence>>, GetState<LiveblocksState<T, TPresence>>, StoreApi<LiveblocksState<T, TPresence>>>;
53
+ };
54
+ export declare function middleware<T extends Object, TPresence extends Object = any>(config: StateCreator<T, SetState<T>, GetState<LiveblocksState<T>>, StoreApi<T>>, options: Options<T>): StateCreator<LiveblocksState<T, TPresence>, SetState<LiveblocksState<T, TPresence>>, GetState<LiveblocksState<T, TPresence>>, StoreApi<LiveblocksState<T, TPresence>>>;
55
+ export {};
package/lib/index.js CHANGED
@@ -60,19 +60,39 @@ function _createForOfIteratorHelperLoose(o, allowArrayLike) {
60
60
  throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
61
61
  }
62
62
 
63
- var middleware = function middleware(config, _ref) {
64
- var client$1 = _ref.client,
65
- unvalidatedMapping = _ref.storageMapping,
66
- _ref$presenceMapping = _ref.presenceMapping,
67
- unvalidatedPresenceMapping = _ref$presenceMapping === void 0 ? {} : _ref$presenceMapping;
68
-
69
- if (client$1 == null) {
70
- throw new Error(ERROR_PREFIX + " client is missing");
63
+ var ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
64
+ function missingClient() {
65
+ return new Error(ERROR_PREFIX + " client is missing");
66
+ }
67
+ function missingMapping(mappingType) {
68
+ return new Error(ERROR_PREFIX + " " + mappingType + " is missing.");
69
+ }
70
+ function mappingShouldBeAnObject(mappingType) {
71
+ return new Error(ERROR_PREFIX + " " + mappingType + " should be an object where the values are boolean.");
72
+ }
73
+ function mappingValueShouldBeABoolean(mappingType, key) {
74
+ return new Error(ERROR_PREFIX + " " + mappingType + "." + key + " value should be a boolean");
75
+ }
76
+ function mappingShouldNotHaveTheSameKeys(key) {
77
+ return new Error(ERROR_PREFIX + " \"" + key + "\" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.");
78
+ }
79
+ function mappingToFunctionIsNotAllowed(key) {
80
+ return new Error(ERROR_PREFIX + " mapping." + key + " is invalid. Mapping to a function is not allowed.");
81
+ }
82
+
83
+ function middleware(config, options) {
84
+ if (process.env.NODE_ENV !== "production" && options.client == null) {
85
+ throw missingClient();
86
+ }
87
+
88
+ var client$1 = options.client;
89
+ var mapping = validateMapping(options.storageMapping, "storageMapping");
90
+ var presenceMapping = validateMapping(options.presenceMapping || {}, "presenceMapping");
91
+
92
+ if (process.env.NODE_ENV !== "production") {
93
+ validateNoDuplicateKeys(mapping, presenceMapping);
71
94
  }
72
95
 
73
- var mapping = validateMapping(unvalidatedMapping, "storageMapping");
74
- var presenceMapping = validateMapping(unvalidatedPresenceMapping, "presenceMapping");
75
- validateNoDuplicateKeys(mapping, presenceMapping);
76
96
  return function (set, get, api) {
77
97
  var typedSet = set;
78
98
  var room = null;
@@ -118,8 +138,8 @@ var middleware = function middleware(config, _ref) {
118
138
  connection: room.getConnectionState()
119
139
  });
120
140
  }));
121
- room.getStorage().then(function (_ref2) {
122
- var root = _ref2.root;
141
+ room.getStorage().then(function (_ref) {
142
+ var root = _ref.root;
123
143
  var updates = {};
124
144
  room.batch(function () {
125
145
  for (var key in mapping) {
@@ -178,7 +198,7 @@ var middleware = function middleware(config, _ref) {
178
198
  }
179
199
  });
180
200
  };
181
- };
201
+ }
182
202
 
183
203
  function patchState(state, updates, mapping) {
184
204
  var partialState = {};
@@ -215,6 +235,10 @@ function broadcastInitialPresence(room, state, mapping) {
215
235
 
216
236
  function updatePresence(room, oldState, newState, presenceMapping) {
217
237
  for (var key in presenceMapping) {
238
+ if (typeof newState[key] === "function") {
239
+ throw mappingToFunctionIsNotAllowed("value");
240
+ }
241
+
218
242
  if (oldState[key] !== newState[key]) {
219
243
  var _room$updatePresence2;
220
244
 
@@ -225,6 +249,10 @@ function updatePresence(room, oldState, newState, presenceMapping) {
225
249
 
226
250
  function patchLiveblocksStorage(root, oldState, newState, mapping) {
227
251
  for (var key in mapping) {
252
+ if (process.env.NODE_ENV !== "production" && typeof newState[key] === "function") {
253
+ throw mappingToFunctionIsNotAllowed("value");
254
+ }
255
+
228
256
  if (oldState[key] !== newState[key]) {
229
257
  client.patchLiveObjectKey(root, key, oldState[key], newState[key]);
230
258
  }
@@ -238,25 +266,27 @@ function isObject(value) {
238
266
  function validateNoDuplicateKeys(storageMapping, presenceMapping) {
239
267
  for (var key in storageMapping) {
240
268
  if (presenceMapping[key] !== undefined) {
241
- throw new Error(ERROR_PREFIX + " \"" + key + "\" is mapped on presenceMapping and storageMapping. A key shouldn't exist on both mapping.");
269
+ throw mappingShouldNotHaveTheSameKeys(key);
242
270
  }
243
271
  }
244
272
  }
245
273
 
246
274
  function validateMapping(mapping, mappingType) {
247
- if (mapping == null) {
248
- throw new Error(ERROR_PREFIX + " " + mappingType + " is missing.");
249
- }
275
+ if (process.env.NODE_ENV !== "production") {
276
+ if (mapping == null) {
277
+ throw missingMapping(mappingType);
278
+ }
250
279
 
251
- if (!isObject(mapping)) {
252
- throw new Error(ERROR_PREFIX + " " + mappingType + " should be an object where the values are boolean.");
280
+ if (!isObject(mapping)) {
281
+ throw mappingShouldBeAnObject(mappingType);
282
+ }
253
283
  }
254
284
 
255
285
  var result = {};
256
286
 
257
287
  for (var key in mapping) {
258
- if (typeof mapping[key] !== "boolean") {
259
- throw new Error(ERROR_PREFIX + " " + mappingType + "." + key + " value should be a boolean");
288
+ if (process.env.NODE_ENV !== "production" && typeof mapping[key] !== "boolean") {
289
+ throw mappingValueShouldBeABoolean(mappingType, key);
260
290
  }
261
291
 
262
292
  if (mapping[key] === true) {
@@ -267,6 +297,4 @@ function validateMapping(mapping, mappingType) {
267
297
  return result;
268
298
  }
269
299
 
270
- var ERROR_PREFIX = "Invalid @liveblocks/zustand middleware config.";
271
-
272
300
  exports.middleware = middleware;
package/package.json CHANGED
@@ -1,6 +1,7 @@
1
1
  {
2
2
  "name": "@liveblocks/zustand",
3
- "version": "0.15.0-alpha.2",
3
+ "version": "0.15.0-alpha.3",
4
+ "sideEffects": false,
4
5
  "description": "",
5
6
  "main": "./lib/index.js",
6
7
  "types": "./lib/index.d.ts",
@@ -35,7 +36,7 @@
35
36
  "directory": "packages/liveblocks-zustand"
36
37
  },
37
38
  "peerDependencies": {
38
- "@liveblocks/client": "0.15.0-alpha.2",
39
+ "@liveblocks/client": "0.15.0-alpha.3",
39
40
  "zustand": "^3"
40
41
  },
41
42
  "devDependencies": {
@@ -58,4 +59,4 @@
58
59
  "whatwg-fetch": "^3.6.2",
59
60
  "zustand": "^3.6.9"
60
61
  }
61
- }
62
+ }