use-everywhere 0.7.0 → 0.8.0
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/{chunk-LNJEF4DI.js → chunk-75TICQ7E.js} +67 -13
- package/dist/devtools/index.cjs +14 -5
- package/dist/devtools/index.js +1 -1
- package/dist/index.cjs +259 -68
- package/dist/index.d.cts +242 -10
- package/dist/index.d.ts +242 -10
- package/dist/index.js +164 -26
- package/package.json +23 -11
|
@@ -5,6 +5,7 @@ import {
|
|
|
5
5
|
createChannel,
|
|
6
6
|
createLeader,
|
|
7
7
|
createPresence,
|
|
8
|
+
createSharedReducer,
|
|
8
9
|
createSharedStore,
|
|
9
10
|
DEFAULT_NAME,
|
|
10
11
|
NoopTransport
|
|
@@ -49,6 +50,12 @@ var unsubscribe = () => noop;
|
|
|
49
50
|
var INERT = Object.freeze({
|
|
50
51
|
clientId: SERVER_CLIENT_ID,
|
|
51
52
|
// store
|
|
53
|
+
//
|
|
54
|
+
// Resolved, unlike the leader's `waitForLeadership` below. A server render
|
|
55
|
+
// has nothing to restore and is documented to render defaults, so `await
|
|
56
|
+
// store.hydrated` must proceed — a never-settling promise would hang the
|
|
57
|
+
// render rather than describe it honestly.
|
|
58
|
+
hydrated: Promise.resolve(),
|
|
52
59
|
state: EMPTY,
|
|
53
60
|
getVersions: () => EMPTY,
|
|
54
61
|
set: noop,
|
|
@@ -57,6 +64,8 @@ var INERT = Object.freeze({
|
|
|
57
64
|
// store + leader share getSnapshot; presence has getPeers
|
|
58
65
|
getSnapshot: () => EMPTY,
|
|
59
66
|
getPeers: () => NO_PEERS,
|
|
67
|
+
// presence
|
|
68
|
+
setMetadata: noop,
|
|
60
69
|
// leader
|
|
61
70
|
resign: noop,
|
|
62
71
|
setEligible: noop,
|
|
@@ -75,6 +84,12 @@ var createServerLeader = () => ({
|
|
|
75
84
|
getSnapshot: () => NO_LEADER,
|
|
76
85
|
waitForLeadership: NEVER
|
|
77
86
|
});
|
|
87
|
+
var createServerReducer = (initial) => ({
|
|
88
|
+
...INERT,
|
|
89
|
+
getSnapshot: () => initial,
|
|
90
|
+
dispatch: noop,
|
|
91
|
+
pendingCount: () => 0
|
|
92
|
+
});
|
|
78
93
|
var createServerChannel = (name) => ({ ...INERT, name, post: noop, on: unsubscribe });
|
|
79
94
|
|
|
80
95
|
// src/registry.ts
|
|
@@ -95,15 +110,17 @@ function getSharedStore(name = DEFAULT_NAME, scope = "everywhere") {
|
|
|
95
110
|
function configSignature(options) {
|
|
96
111
|
const persist = options?.persist;
|
|
97
112
|
if (!persist) return "none";
|
|
98
|
-
return `persist:${persist.keys?.join(",") ?? "*"}:${persist.debounceMs ?? "default"}`;
|
|
113
|
+
return `persist:${persist.keys?.join(",") ?? "*"}:${persist.debounceMs ?? "default"}:v${persist.version ?? 0}`;
|
|
99
114
|
}
|
|
100
115
|
function configureStore(name, scope, options) {
|
|
101
116
|
const key = `${scope} ${name}`;
|
|
102
117
|
if (stores.has(key)) {
|
|
103
118
|
if (configSignature(storeConfig.get(key)) === configSignature(options)) return;
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
119
|
+
if (process.env.NODE_ENV !== "production") {
|
|
120
|
+
devWarn(
|
|
121
|
+
`[use-everywhere] defineStore('${name}') ran after that store was already created, with different options. The live store keeps the configuration it was built with. Move defineStore to module scope, before any component reads the store.`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
107
124
|
return;
|
|
108
125
|
}
|
|
109
126
|
storeConfig.set(key, options);
|
|
@@ -117,11 +134,12 @@ function getStore(name, scope = "everywhere") {
|
|
|
117
134
|
}
|
|
118
135
|
return store;
|
|
119
136
|
}
|
|
120
|
-
function getPresence(name) {
|
|
121
|
-
|
|
137
|
+
function getPresence(name, includeSelf = false) {
|
|
138
|
+
const key = includeSelf ? `self ${name}` : name;
|
|
139
|
+
let presence = presences.get(key);
|
|
122
140
|
if (!presence) {
|
|
123
|
-
presence = isServer() ? createServerPresence() : createPresence(name);
|
|
124
|
-
presences.set(
|
|
141
|
+
presence = isServer() ? createServerPresence() : createPresence(name, { includeSelf });
|
|
142
|
+
presences.set(key, presence);
|
|
125
143
|
}
|
|
126
144
|
return presence;
|
|
127
145
|
}
|
|
@@ -142,26 +160,53 @@ function warnOnLeaderOptionConflict(name, options) {
|
|
|
142
160
|
for (const key of ["heartbeatMs", "leaseMs"]) {
|
|
143
161
|
const requested = options[key];
|
|
144
162
|
if (requested !== void 0 && requested !== first?.[key]) {
|
|
163
|
+
if (process.env.NODE_ENV !== "production") {
|
|
164
|
+
devWarn(
|
|
165
|
+
`[use-everywhere] leader "${name}": ${key} ignored \u2014 the first useLeader/getLeader call fixes the election timings for this tab.`
|
|
166
|
+
);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
var channelConfig = /* @__PURE__ */ new Map();
|
|
172
|
+
function configureChannel(name, options) {
|
|
173
|
+
if (channels.has(name)) {
|
|
174
|
+
const before = Object.keys(channelConfig.get(name)?.schema ?? {}).sort();
|
|
175
|
+
const after = Object.keys(options.schema ?? {}).sort();
|
|
176
|
+
if (before.join() === after.join()) return;
|
|
177
|
+
if (process.env.NODE_ENV !== "production") {
|
|
145
178
|
devWarn(
|
|
146
|
-
`[use-everywhere]
|
|
179
|
+
`[use-everywhere] defineChannel('${name}') ran after that channel was already created, with different options. The live channel keeps the configuration it was built with. Move defineChannel to module scope, before any component sends or receives on it.`
|
|
147
180
|
);
|
|
148
181
|
}
|
|
182
|
+
return;
|
|
149
183
|
}
|
|
184
|
+
channelConfig.set(name, options);
|
|
185
|
+
}
|
|
186
|
+
var reducers = /* @__PURE__ */ new Map();
|
|
187
|
+
function getReducer(name, key, reducer, initial) {
|
|
188
|
+
const id = `${name} ${key}`;
|
|
189
|
+
let existing = reducers.get(id);
|
|
190
|
+
if (!existing) {
|
|
191
|
+
existing = isServer() ? createServerReducer(initial) : createSharedReducer(name, reducer, initial, { key, leader: getLeader(name) });
|
|
192
|
+
reducers.set(id, existing);
|
|
193
|
+
}
|
|
194
|
+
return existing;
|
|
150
195
|
}
|
|
151
196
|
function getChannel(name) {
|
|
152
197
|
let channel = channels.get(name);
|
|
153
198
|
if (!channel) {
|
|
154
|
-
channel = isServer() ? createServerChannel(name) : createChannel(name);
|
|
199
|
+
channel = isServer() ? createServerChannel(name) : createChannel(name, channelConfig.get(name));
|
|
155
200
|
channels.set(name, channel);
|
|
156
201
|
}
|
|
157
202
|
return channel;
|
|
158
203
|
}
|
|
159
204
|
|
|
160
205
|
// src/use-peers.ts
|
|
161
|
-
import { useCallback, useSyncExternalStore } from "react";
|
|
206
|
+
import { useCallback, useEffect, useSyncExternalStore } from "react";
|
|
162
207
|
var NO_PEERS2 = Object.freeze([]);
|
|
163
208
|
function usePeers(options) {
|
|
164
|
-
const presence = getPresence(options?.name ?? DEFAULT_NAME);
|
|
209
|
+
const presence = getPresence(options?.name ?? DEFAULT_NAME, options?.includeSelf ?? false);
|
|
165
210
|
return useSyncExternalStore(
|
|
166
211
|
useCallback((onChange) => presence.subscribe(onChange), [presence]),
|
|
167
212
|
() => presence.getPeers(),
|
|
@@ -180,6 +225,12 @@ function useClientId(options) {
|
|
|
180
225
|
() => SERVER_CLIENT_ID
|
|
181
226
|
);
|
|
182
227
|
}
|
|
228
|
+
function usePresenceMetadata(metadata, options) {
|
|
229
|
+
const presence = getPresence(options?.name ?? DEFAULT_NAME, options?.includeSelf ?? false);
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
presence.setMetadata(metadata);
|
|
232
|
+
}, [presence, metadata]);
|
|
233
|
+
}
|
|
183
234
|
|
|
184
235
|
export {
|
|
185
236
|
warnOnInitialMismatch,
|
|
@@ -188,7 +239,10 @@ export {
|
|
|
188
239
|
configureStore,
|
|
189
240
|
getStore,
|
|
190
241
|
getLeader,
|
|
242
|
+
configureChannel,
|
|
243
|
+
getReducer,
|
|
191
244
|
getChannel,
|
|
192
245
|
usePeers,
|
|
193
|
-
useClientId
|
|
246
|
+
useClientId,
|
|
247
|
+
usePresenceMetadata
|
|
194
248
|
};
|
package/dist/devtools/index.cjs
CHANGED
|
@@ -42,6 +42,12 @@ var unsubscribe = () => noop;
|
|
|
42
42
|
var INERT = Object.freeze({
|
|
43
43
|
clientId: SERVER_CLIENT_ID,
|
|
44
44
|
// store
|
|
45
|
+
//
|
|
46
|
+
// Resolved, unlike the leader's `waitForLeadership` below. A server render
|
|
47
|
+
// has nothing to restore and is documented to render defaults, so `await
|
|
48
|
+
// store.hydrated` must proceed — a never-settling promise would hang the
|
|
49
|
+
// render rather than describe it honestly.
|
|
50
|
+
hydrated: Promise.resolve(),
|
|
45
51
|
state: EMPTY,
|
|
46
52
|
getVersions: () => EMPTY,
|
|
47
53
|
set: noop,
|
|
@@ -50,6 +56,8 @@ var INERT = Object.freeze({
|
|
|
50
56
|
// store + leader share getSnapshot; presence has getPeers
|
|
51
57
|
getSnapshot: () => EMPTY,
|
|
52
58
|
getPeers: () => NO_PEERS,
|
|
59
|
+
// presence
|
|
60
|
+
setMetadata: noop,
|
|
53
61
|
// leader
|
|
54
62
|
resign: noop,
|
|
55
63
|
setEligible: noop,
|
|
@@ -83,11 +91,12 @@ function getStore(name, scope = "everywhere") {
|
|
|
83
91
|
}
|
|
84
92
|
return store;
|
|
85
93
|
}
|
|
86
|
-
function getPresence(name) {
|
|
87
|
-
|
|
94
|
+
function getPresence(name, includeSelf = false) {
|
|
95
|
+
const key = includeSelf ? `self ${name}` : name;
|
|
96
|
+
let presence = presences.get(key);
|
|
88
97
|
if (!presence) {
|
|
89
|
-
presence = isServer() ? createServerPresence() : (0, import_core.createPresence)(name);
|
|
90
|
-
presences.set(
|
|
98
|
+
presence = isServer() ? createServerPresence() : (0, import_core.createPresence)(name, { includeSelf });
|
|
99
|
+
presences.set(key, presence);
|
|
91
100
|
}
|
|
92
101
|
return presence;
|
|
93
102
|
}
|
|
@@ -96,7 +105,7 @@ function getPresence(name) {
|
|
|
96
105
|
var import_react = require("react");
|
|
97
106
|
var NO_PEERS2 = Object.freeze([]);
|
|
98
107
|
function usePeers(options) {
|
|
99
|
-
const presence = getPresence(options?.name ?? import_core.DEFAULT_NAME);
|
|
108
|
+
const presence = getPresence(options?.name ?? import_core.DEFAULT_NAME, options?.includeSelf ?? false);
|
|
100
109
|
return (0, import_react.useSyncExternalStore)(
|
|
101
110
|
(0, import_react.useCallback)((onChange) => presence.subscribe(onChange), [presence]),
|
|
102
111
|
() => presence.getPeers(),
|
package/dist/devtools/index.js
CHANGED