@liveblocks/server 1.2.0 → 1.3.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/index.cjs +690 -74
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +421 -43
- package/dist/index.d.ts +421 -43
- package/dist/index.js +677 -61
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -12,16 +12,139 @@ var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "
|
|
|
12
12
|
// src/decoders/ClientMsg.ts
|
|
13
13
|
import { ClientMsgCode } from "@liveblocks/core";
|
|
14
14
|
import {
|
|
15
|
-
array,
|
|
15
|
+
array as array2,
|
|
16
16
|
boolean,
|
|
17
17
|
constant as constant2,
|
|
18
|
+
jsonObject,
|
|
19
|
+
nonEmptyString,
|
|
18
20
|
number,
|
|
19
21
|
object as object2,
|
|
20
|
-
optional as
|
|
21
|
-
string as
|
|
22
|
+
optional as optional3,
|
|
23
|
+
string as string3,
|
|
22
24
|
taggedUnion as taggedUnion2
|
|
23
25
|
} from "decoders";
|
|
24
26
|
|
|
27
|
+
// src/protocol/feedMessages.ts
|
|
28
|
+
var FeedMsgCode = {
|
|
29
|
+
// Server → client (50x)
|
|
30
|
+
FEEDS_LIST: 500,
|
|
31
|
+
FEEDS_ADDED: 501,
|
|
32
|
+
FEEDS_UPDATED: 502,
|
|
33
|
+
FEED_DELETED: 503,
|
|
34
|
+
FEED_MESSAGES_LIST: 504,
|
|
35
|
+
FEED_MESSAGES_ADDED: 505,
|
|
36
|
+
FEED_MESSAGES_UPDATED: 506,
|
|
37
|
+
FEED_MESSAGES_DELETED: 507,
|
|
38
|
+
FEED_REQUEST_FAILED: 508,
|
|
39
|
+
// Client → server (51x)
|
|
40
|
+
FETCH_FEEDS: 510,
|
|
41
|
+
FETCH_FEED_MESSAGES: 511,
|
|
42
|
+
ADD_FEED: 512,
|
|
43
|
+
UPDATE_FEED: 513,
|
|
44
|
+
DELETE_FEED: 514,
|
|
45
|
+
ADD_FEED_MESSAGE: 515,
|
|
46
|
+
UPDATE_FEED_MESSAGE: 516,
|
|
47
|
+
DELETE_FEED_MESSAGE: 517
|
|
48
|
+
};
|
|
49
|
+
var FeedRequestErrorCode = {
|
|
50
|
+
INTERNAL: "INTERNAL",
|
|
51
|
+
FEED_ALREADY_EXISTS: "FEED_ALREADY_EXISTS",
|
|
52
|
+
FEED_NOT_FOUND: "FEED_NOT_FOUND",
|
|
53
|
+
FEED_MESSAGE_NOT_FOUND: "FEED_MESSAGE_NOT_FOUND"
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
// src/protocol/feedErrors.ts
|
|
57
|
+
function feedRequestFailed(requestId, code, reason) {
|
|
58
|
+
return {
|
|
59
|
+
type: FeedMsgCode.FEED_REQUEST_FAILED,
|
|
60
|
+
requestId: requestId ?? "",
|
|
61
|
+
code,
|
|
62
|
+
reason
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function mapFeedError(err) {
|
|
66
|
+
if (!(err instanceof Error)) {
|
|
67
|
+
return { code: FeedRequestErrorCode.INTERNAL };
|
|
68
|
+
}
|
|
69
|
+
const m = err.message;
|
|
70
|
+
if (m.includes("already exists")) {
|
|
71
|
+
return { code: FeedRequestErrorCode.FEED_ALREADY_EXISTS, reason: m };
|
|
72
|
+
}
|
|
73
|
+
if (m.includes("Feed message") && m.includes("not found")) {
|
|
74
|
+
return { code: FeedRequestErrorCode.FEED_MESSAGE_NOT_FOUND, reason: m };
|
|
75
|
+
}
|
|
76
|
+
if (m.includes("not found")) {
|
|
77
|
+
return { code: FeedRequestErrorCode.FEED_NOT_FOUND, reason: m };
|
|
78
|
+
}
|
|
79
|
+
return { code: FeedRequestErrorCode.INTERNAL, reason: m };
|
|
80
|
+
}
|
|
81
|
+
function feedFailureServerMsg(requestId, err) {
|
|
82
|
+
const mapped = mapFeedError(err);
|
|
83
|
+
return feedRequestFailed(requestId, mapped.code, mapped.reason);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
// src/protocol/ProtocolVersion.ts
|
|
87
|
+
import { enum_ } from "decoders";
|
|
88
|
+
var ProtocolVersion = /* @__PURE__ */ ((ProtocolVersion2) => {
|
|
89
|
+
ProtocolVersion2[ProtocolVersion2["V7"] = 7] = "V7";
|
|
90
|
+
ProtocolVersion2[ProtocolVersion2["V8"] = 8] = "V8";
|
|
91
|
+
return ProtocolVersion2;
|
|
92
|
+
})(ProtocolVersion || {});
|
|
93
|
+
var protocolVersionDecoder = enum_(ProtocolVersion).describe(
|
|
94
|
+
"Unsupported protocol version"
|
|
95
|
+
);
|
|
96
|
+
|
|
97
|
+
// src/decoders/feedMetadata.ts
|
|
98
|
+
import {
|
|
99
|
+
array,
|
|
100
|
+
either,
|
|
101
|
+
identifier,
|
|
102
|
+
nullable,
|
|
103
|
+
optional,
|
|
104
|
+
poja,
|
|
105
|
+
record,
|
|
106
|
+
select,
|
|
107
|
+
sized,
|
|
108
|
+
string
|
|
109
|
+
} from "decoders";
|
|
110
|
+
var MAX_METADATA_COUNT = 50;
|
|
111
|
+
var MAX_METADATA_VALUE_LIST_LENGTH = 50;
|
|
112
|
+
var feedMetadataIdDecoder = sized(identifier, { min: 1, max: 40 });
|
|
113
|
+
var metadataStringValue = sized(string, { max: 256 });
|
|
114
|
+
function createRoomMetadataValueDecoder() {
|
|
115
|
+
return select(
|
|
116
|
+
either(string, poja).describe("Must be string or string[]"),
|
|
117
|
+
(x) => typeof x === "string" ? metadataStringValue : array(metadataStringValue).refine(
|
|
118
|
+
(value) => value.length <= MAX_METADATA_VALUE_LIST_LENGTH,
|
|
119
|
+
`Must be at most ${MAX_METADATA_VALUE_LIST_LENGTH} items`
|
|
120
|
+
)
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
var roomMetadataValueDecoder = createRoomMetadataValueDecoder();
|
|
124
|
+
var feedMetadataNullableValueDecoder = nullable(roomMetadataValueDecoder);
|
|
125
|
+
var feedMetadataRecordForCreate = record(
|
|
126
|
+
feedMetadataIdDecoder,
|
|
127
|
+
roomMetadataValueDecoder
|
|
128
|
+
).refine(
|
|
129
|
+
(value) => Object.keys(value).length <= MAX_METADATA_COUNT,
|
|
130
|
+
`Must be at most ${MAX_METADATA_COUNT} items`
|
|
131
|
+
);
|
|
132
|
+
var optionalFeedMetadataDecoder = optional(feedMetadataRecordForCreate);
|
|
133
|
+
var feedMetadataUpdateDecoder = record(
|
|
134
|
+
feedMetadataIdDecoder,
|
|
135
|
+
feedMetadataNullableValueDecoder
|
|
136
|
+
);
|
|
137
|
+
var feedMetadataRecordForFilter = record(
|
|
138
|
+
feedMetadataIdDecoder,
|
|
139
|
+
feedMetadataNullableValueDecoder
|
|
140
|
+
).refine(
|
|
141
|
+
(value) => Object.keys(value).length <= MAX_METADATA_COUNT,
|
|
142
|
+
`Must be at most ${MAX_METADATA_COUNT} items`
|
|
143
|
+
);
|
|
144
|
+
var fetchFeedsMetadataFilterDecoder = optional(
|
|
145
|
+
feedMetadataRecordForFilter
|
|
146
|
+
);
|
|
147
|
+
|
|
25
148
|
// src/decoders/jsonYolo.ts
|
|
26
149
|
import { unknown } from "decoders";
|
|
27
150
|
var jsonYolo = unknown;
|
|
@@ -32,67 +155,67 @@ var jsonObjectYolo = jsonYolo.refine(
|
|
|
32
155
|
|
|
33
156
|
// src/decoders/Op.ts
|
|
34
157
|
import { OpCode } from "@liveblocks/core";
|
|
35
|
-
import { constant, object, optional, string, taggedUnion } from "decoders";
|
|
158
|
+
import { constant, object, optional as optional2, string as string2, taggedUnion } from "decoders";
|
|
36
159
|
var updateObjectOp = object({
|
|
37
160
|
type: constant(OpCode.UPDATE_OBJECT),
|
|
38
|
-
opId:
|
|
39
|
-
id:
|
|
161
|
+
opId: string2,
|
|
162
|
+
id: string2,
|
|
40
163
|
data: jsonObjectYolo
|
|
41
164
|
});
|
|
42
165
|
var createObjectOp = object({
|
|
43
166
|
type: constant(OpCode.CREATE_OBJECT),
|
|
44
|
-
opId:
|
|
45
|
-
id:
|
|
46
|
-
parentId:
|
|
47
|
-
parentKey:
|
|
167
|
+
opId: string2,
|
|
168
|
+
id: string2,
|
|
169
|
+
parentId: string2,
|
|
170
|
+
parentKey: string2,
|
|
48
171
|
data: jsonObjectYolo,
|
|
49
|
-
intent:
|
|
50
|
-
deletedId:
|
|
172
|
+
intent: optional2(constant("set")),
|
|
173
|
+
deletedId: optional2(string2)
|
|
51
174
|
});
|
|
52
175
|
var createListOp = object({
|
|
53
176
|
type: constant(OpCode.CREATE_LIST),
|
|
54
|
-
opId:
|
|
55
|
-
id:
|
|
56
|
-
parentId:
|
|
57
|
-
parentKey:
|
|
58
|
-
intent:
|
|
59
|
-
deletedId:
|
|
177
|
+
opId: string2,
|
|
178
|
+
id: string2,
|
|
179
|
+
parentId: string2,
|
|
180
|
+
parentKey: string2,
|
|
181
|
+
intent: optional2(constant("set")),
|
|
182
|
+
deletedId: optional2(string2)
|
|
60
183
|
});
|
|
61
184
|
var createMapOp = object({
|
|
62
185
|
type: constant(OpCode.CREATE_MAP),
|
|
63
|
-
opId:
|
|
64
|
-
id:
|
|
65
|
-
parentId:
|
|
66
|
-
parentKey:
|
|
67
|
-
intent:
|
|
68
|
-
deletedId:
|
|
186
|
+
opId: string2,
|
|
187
|
+
id: string2,
|
|
188
|
+
parentId: string2,
|
|
189
|
+
parentKey: string2,
|
|
190
|
+
intent: optional2(constant("set")),
|
|
191
|
+
deletedId: optional2(string2)
|
|
69
192
|
});
|
|
70
193
|
var createRegisterOp = object({
|
|
71
194
|
type: constant(OpCode.CREATE_REGISTER),
|
|
72
|
-
opId:
|
|
73
|
-
id:
|
|
74
|
-
parentId:
|
|
75
|
-
parentKey:
|
|
195
|
+
opId: string2,
|
|
196
|
+
id: string2,
|
|
197
|
+
parentId: string2,
|
|
198
|
+
parentKey: string2,
|
|
76
199
|
data: jsonYolo,
|
|
77
|
-
intent:
|
|
78
|
-
deletedId:
|
|
200
|
+
intent: optional2(constant("set")),
|
|
201
|
+
deletedId: optional2(string2)
|
|
79
202
|
});
|
|
80
203
|
var deleteCrdtOp = object({
|
|
81
204
|
type: constant(OpCode.DELETE_CRDT),
|
|
82
|
-
opId:
|
|
83
|
-
id:
|
|
205
|
+
opId: string2,
|
|
206
|
+
id: string2
|
|
84
207
|
});
|
|
85
208
|
var setParentKeyOp = object({
|
|
86
209
|
type: constant(OpCode.SET_PARENT_KEY),
|
|
87
|
-
opId:
|
|
88
|
-
id:
|
|
89
|
-
parentKey:
|
|
210
|
+
opId: string2,
|
|
211
|
+
id: string2,
|
|
212
|
+
parentKey: string2
|
|
90
213
|
});
|
|
91
214
|
var deleteObjectKeyOp = object({
|
|
92
215
|
type: constant(OpCode.DELETE_OBJECT_KEY),
|
|
93
|
-
opId:
|
|
94
|
-
id:
|
|
95
|
-
key:
|
|
216
|
+
opId: string2,
|
|
217
|
+
id: string2,
|
|
218
|
+
key: string2
|
|
96
219
|
});
|
|
97
220
|
var op = taggedUnion("type", {
|
|
98
221
|
[OpCode.UPDATE_OBJECT]: updateObjectOp,
|
|
@@ -114,7 +237,7 @@ var ROOT_YDOC_ID = "root";
|
|
|
114
237
|
var updatePresenceClientMsg = object2({
|
|
115
238
|
type: constant2(ClientMsgCode.UPDATE_PRESENCE),
|
|
116
239
|
data: jsonObjectYolo,
|
|
117
|
-
targetActor:
|
|
240
|
+
targetActor: optional3(number)
|
|
118
241
|
});
|
|
119
242
|
var broadcastEventClientMsg = object2({
|
|
120
243
|
type: constant2(ClientMsgCode.BROADCAST_EVENT),
|
|
@@ -125,21 +248,77 @@ var fetchStorageClientMsg = object2({
|
|
|
125
248
|
});
|
|
126
249
|
var updateStorageClientMsg = object2({
|
|
127
250
|
type: constant2(ClientMsgCode.UPDATE_STORAGE),
|
|
128
|
-
ops:
|
|
251
|
+
ops: array2(op)
|
|
129
252
|
});
|
|
130
253
|
var fetchYDocClientMsg = object2({
|
|
131
254
|
type: constant2(ClientMsgCode.FETCH_YDOC),
|
|
132
|
-
vector:
|
|
133
|
-
guid:
|
|
255
|
+
vector: string3.refineType(),
|
|
256
|
+
guid: optional3(guidDecoder),
|
|
134
257
|
// Don't specify to update the root doc
|
|
135
|
-
v2:
|
|
258
|
+
v2: optional3(boolean)
|
|
136
259
|
});
|
|
137
260
|
var updateYDocClientMsg = object2({
|
|
138
261
|
type: constant2(ClientMsgCode.UPDATE_YDOC),
|
|
139
|
-
update:
|
|
140
|
-
guid:
|
|
262
|
+
update: string3.refineType(),
|
|
263
|
+
guid: optional3(guidDecoder),
|
|
141
264
|
// Don't specify to update the root doc
|
|
142
|
-
v2:
|
|
265
|
+
v2: optional3(boolean)
|
|
266
|
+
});
|
|
267
|
+
var fetchFeedsClientMsg = object2({
|
|
268
|
+
type: constant2(FeedMsgCode.FETCH_FEEDS),
|
|
269
|
+
requestId: string3,
|
|
270
|
+
cursor: optional3(string3),
|
|
271
|
+
since: optional3(number),
|
|
272
|
+
limit: optional3(number),
|
|
273
|
+
metadata: fetchFeedsMetadataFilterDecoder
|
|
274
|
+
});
|
|
275
|
+
var fetchFeedMessagesClientMsg = object2({
|
|
276
|
+
type: constant2(FeedMsgCode.FETCH_FEED_MESSAGES),
|
|
277
|
+
requestId: string3,
|
|
278
|
+
feedId: nonEmptyString,
|
|
279
|
+
cursor: optional3(string3),
|
|
280
|
+
since: optional3(number),
|
|
281
|
+
limit: optional3(number)
|
|
282
|
+
});
|
|
283
|
+
var addFeedClientMsg = object2({
|
|
284
|
+
type: constant2(FeedMsgCode.ADD_FEED),
|
|
285
|
+
feedId: string3,
|
|
286
|
+
metadata: optionalFeedMetadataDecoder,
|
|
287
|
+
timestamp: optional3(number),
|
|
288
|
+
requestId: optional3(string3)
|
|
289
|
+
});
|
|
290
|
+
var updateFeedClientMsg = object2({
|
|
291
|
+
type: constant2(FeedMsgCode.UPDATE_FEED),
|
|
292
|
+
feedId: string3,
|
|
293
|
+
metadata: feedMetadataUpdateDecoder,
|
|
294
|
+
requestId: optional3(string3)
|
|
295
|
+
});
|
|
296
|
+
var deleteFeedClientMsg = object2({
|
|
297
|
+
type: constant2(FeedMsgCode.DELETE_FEED),
|
|
298
|
+
feedId: string3,
|
|
299
|
+
requestId: optional3(string3)
|
|
300
|
+
});
|
|
301
|
+
var addFeedMessageClientMsg = object2({
|
|
302
|
+
type: constant2(FeedMsgCode.ADD_FEED_MESSAGE),
|
|
303
|
+
feedId: string3,
|
|
304
|
+
data: jsonObject,
|
|
305
|
+
id: optional3(string3),
|
|
306
|
+
timestamp: optional3(number),
|
|
307
|
+
requestId: optional3(string3)
|
|
308
|
+
});
|
|
309
|
+
var updateFeedMessageClientMsg = object2({
|
|
310
|
+
type: constant2(FeedMsgCode.UPDATE_FEED_MESSAGE),
|
|
311
|
+
feedId: string3,
|
|
312
|
+
messageId: string3,
|
|
313
|
+
data: jsonObject,
|
|
314
|
+
timestamp: optional3(number),
|
|
315
|
+
requestId: optional3(string3)
|
|
316
|
+
});
|
|
317
|
+
var deleteFeedMessageClientMsg = object2({
|
|
318
|
+
type: constant2(FeedMsgCode.DELETE_FEED_MESSAGE),
|
|
319
|
+
feedId: string3,
|
|
320
|
+
messageId: string3,
|
|
321
|
+
requestId: optional3(string3)
|
|
143
322
|
});
|
|
144
323
|
var clientMsgDecoder = taggedUnion2("type", {
|
|
145
324
|
[ClientMsgCode.UPDATE_PRESENCE]: updatePresenceClientMsg,
|
|
@@ -147,7 +326,15 @@ var clientMsgDecoder = taggedUnion2("type", {
|
|
|
147
326
|
[ClientMsgCode.FETCH_STORAGE]: fetchStorageClientMsg,
|
|
148
327
|
[ClientMsgCode.UPDATE_STORAGE]: updateStorageClientMsg,
|
|
149
328
|
[ClientMsgCode.FETCH_YDOC]: fetchYDocClientMsg,
|
|
150
|
-
[ClientMsgCode.UPDATE_YDOC]: updateYDocClientMsg
|
|
329
|
+
[ClientMsgCode.UPDATE_YDOC]: updateYDocClientMsg,
|
|
330
|
+
[FeedMsgCode.FETCH_FEEDS]: fetchFeedsClientMsg,
|
|
331
|
+
[FeedMsgCode.FETCH_FEED_MESSAGES]: fetchFeedMessagesClientMsg,
|
|
332
|
+
[FeedMsgCode.ADD_FEED]: addFeedClientMsg,
|
|
333
|
+
[FeedMsgCode.UPDATE_FEED]: updateFeedClientMsg,
|
|
334
|
+
[FeedMsgCode.DELETE_FEED]: deleteFeedClientMsg,
|
|
335
|
+
[FeedMsgCode.ADD_FEED_MESSAGE]: addFeedMessageClientMsg,
|
|
336
|
+
[FeedMsgCode.UPDATE_FEED_MESSAGE]: updateFeedMessageClientMsg,
|
|
337
|
+
[FeedMsgCode.DELETE_FEED_MESSAGE]: deleteFeedMessageClientMsg
|
|
151
338
|
}).describe("Must be a valid client message");
|
|
152
339
|
var transientClientMsgDecoder = taggedUnion2("type", {
|
|
153
340
|
// [ClientMsgCode.UPDATE_PRESENCE]: updatePresenceClientMsg,
|
|
@@ -628,17 +815,6 @@ function makeMetadataDB(driver) {
|
|
|
628
815
|
};
|
|
629
816
|
}
|
|
630
817
|
|
|
631
|
-
// src/protocol/ProtocolVersion.ts
|
|
632
|
-
import { enum_ } from "decoders";
|
|
633
|
-
var ProtocolVersion = /* @__PURE__ */ ((ProtocolVersion2) => {
|
|
634
|
-
ProtocolVersion2[ProtocolVersion2["V7"] = 7] = "V7";
|
|
635
|
-
ProtocolVersion2[ProtocolVersion2["V8"] = 8] = "V8";
|
|
636
|
-
return ProtocolVersion2;
|
|
637
|
-
})(ProtocolVersion || {});
|
|
638
|
-
var protocolVersionDecoder = enum_(ProtocolVersion).describe(
|
|
639
|
-
"Unsupported protocol version"
|
|
640
|
-
);
|
|
641
|
-
|
|
642
818
|
// src/Room.ts
|
|
643
819
|
import {
|
|
644
820
|
assertNever as assertNever3,
|
|
@@ -646,12 +822,12 @@ import {
|
|
|
646
822
|
nodeStreamToCompactNodes,
|
|
647
823
|
OpCode as OpCode3,
|
|
648
824
|
raise as raise3,
|
|
649
|
-
ServerMsgCode as
|
|
825
|
+
ServerMsgCode as CoreServerMsgCode,
|
|
650
826
|
tryParseJson,
|
|
651
827
|
WebsocketCloseCodes as CloseCode
|
|
652
828
|
} from "@liveblocks/core";
|
|
653
829
|
import { Mutex, tryAcquire } from "async-mutex";
|
|
654
|
-
import { array as
|
|
830
|
+
import { array as array3, formatInline } from "decoders";
|
|
655
831
|
import { chunked } from "itertools";
|
|
656
832
|
import { nanoid as nanoid2 } from "nanoid";
|
|
657
833
|
|
|
@@ -845,16 +1021,21 @@ function hasStaticDataAt(node, key) {
|
|
|
845
1021
|
return node.type === CrdtType4.OBJECT && Object.prototype.hasOwnProperty.call(node.data, key) && node.data[key] !== void 0;
|
|
846
1022
|
}
|
|
847
1023
|
var InMemoryDriver = class {
|
|
1024
|
+
// Key: `${feedId}:${messageId}`
|
|
848
1025
|
constructor(options) {
|
|
849
1026
|
__publicField(this, "_nextActor");
|
|
850
1027
|
__publicField(this, "_nodes");
|
|
851
1028
|
__publicField(this, "_metadb");
|
|
852
1029
|
__publicField(this, "_ydb");
|
|
853
1030
|
__publicField(this, "_leasedSessions");
|
|
1031
|
+
__publicField(this, "_feeds");
|
|
1032
|
+
__publicField(this, "_feedMessages");
|
|
854
1033
|
this._nodes = /* @__PURE__ */ new Map();
|
|
855
1034
|
this._metadb = /* @__PURE__ */ new Map();
|
|
856
1035
|
this._ydb = /* @__PURE__ */ new Map();
|
|
857
1036
|
this._leasedSessions = /* @__PURE__ */ new Map();
|
|
1037
|
+
this._feeds = /* @__PURE__ */ new Map();
|
|
1038
|
+
this._feedMessages = /* @__PURE__ */ new Map();
|
|
858
1039
|
this._nextActor = options?.initialActor ?? -1;
|
|
859
1040
|
for (const [key, value] of options?.initialNodes ?? []) {
|
|
860
1041
|
this._nodes.set(key, value);
|
|
@@ -894,6 +1075,180 @@ var InMemoryDriver = class {
|
|
|
894
1075
|
takeRowsWritten() {
|
|
895
1076
|
return 0;
|
|
896
1077
|
}
|
|
1078
|
+
// ---------------------------------------------------------------------------
|
|
1079
|
+
// Feed APIs
|
|
1080
|
+
// ---------------------------------------------------------------------------
|
|
1081
|
+
async list_feeds(options) {
|
|
1082
|
+
const limit = Math.min(options?.limit ?? 20, 100);
|
|
1083
|
+
const since = options?.since;
|
|
1084
|
+
const cursor = options?.cursor;
|
|
1085
|
+
const metadata = options?.metadata;
|
|
1086
|
+
let feeds = [];
|
|
1087
|
+
for (const [_, feed] of this._feeds.entries()) {
|
|
1088
|
+
if (metadata !== void 0) {
|
|
1089
|
+
const feedMetadata = feed.metadata;
|
|
1090
|
+
let matches = true;
|
|
1091
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
1092
|
+
if (feedMetadata[key] !== value) {
|
|
1093
|
+
matches = false;
|
|
1094
|
+
break;
|
|
1095
|
+
}
|
|
1096
|
+
}
|
|
1097
|
+
if (!matches) continue;
|
|
1098
|
+
}
|
|
1099
|
+
if (since !== void 0 && feed.createdAt < since) {
|
|
1100
|
+
continue;
|
|
1101
|
+
}
|
|
1102
|
+
feeds.push(feed);
|
|
1103
|
+
}
|
|
1104
|
+
feeds.sort((a, b) => {
|
|
1105
|
+
if (b.createdAt !== a.createdAt) {
|
|
1106
|
+
return b.createdAt - a.createdAt;
|
|
1107
|
+
}
|
|
1108
|
+
return b.feedId.localeCompare(a.feedId);
|
|
1109
|
+
});
|
|
1110
|
+
if (cursor !== void 0) {
|
|
1111
|
+
try {
|
|
1112
|
+
const decoded = JSON.parse(
|
|
1113
|
+
decodeURIComponent(
|
|
1114
|
+
escape(atob(cursor.replace(/-/g, "+").replace(/_/g, "/")))
|
|
1115
|
+
)
|
|
1116
|
+
);
|
|
1117
|
+
const [cursorFeedId, cursorCreatedAt] = decoded;
|
|
1118
|
+
feeds = feeds.filter((s) => {
|
|
1119
|
+
return s.createdAt < cursorCreatedAt || s.createdAt === cursorCreatedAt && s.feedId < cursorFeedId;
|
|
1120
|
+
});
|
|
1121
|
+
} catch {
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
let nextCursor;
|
|
1125
|
+
if (feeds.length > limit) {
|
|
1126
|
+
feeds = feeds.slice(0, limit);
|
|
1127
|
+
const last = feeds[feeds.length - 1];
|
|
1128
|
+
if (last) {
|
|
1129
|
+
const cursorData = [last.feedId, last.createdAt];
|
|
1130
|
+
nextCursor = btoa(
|
|
1131
|
+
unescape(encodeURIComponent(JSON.stringify(cursorData)))
|
|
1132
|
+
).replace("/", "_").replace("+", "-").replace(/=+$/, "");
|
|
1133
|
+
}
|
|
1134
|
+
}
|
|
1135
|
+
return { feeds, nextCursor };
|
|
1136
|
+
}
|
|
1137
|
+
async get_feed(feedId) {
|
|
1138
|
+
const feed = this._feeds.get(feedId);
|
|
1139
|
+
if (feed === void 0) {
|
|
1140
|
+
return void 0;
|
|
1141
|
+
}
|
|
1142
|
+
return feed;
|
|
1143
|
+
}
|
|
1144
|
+
async create_feed(feed) {
|
|
1145
|
+
if (this._feeds.has(feed.feedId)) {
|
|
1146
|
+
throw new Error(`Feed ${feed.feedId} already exists`);
|
|
1147
|
+
}
|
|
1148
|
+
this._feeds.set(feed.feedId, {
|
|
1149
|
+
feedId: feed.feedId,
|
|
1150
|
+
metadata: feed.metadata,
|
|
1151
|
+
createdAt: feed.createdAt,
|
|
1152
|
+
updatedAt: feed.updatedAt
|
|
1153
|
+
});
|
|
1154
|
+
}
|
|
1155
|
+
async update_feed_metadata(feedId, metadata) {
|
|
1156
|
+
const existing = this._feeds.get(feedId);
|
|
1157
|
+
if (existing === void 0) {
|
|
1158
|
+
throw new Error(`Feed ${feedId} not found`);
|
|
1159
|
+
}
|
|
1160
|
+
this._feeds.set(feedId, {
|
|
1161
|
+
...existing,
|
|
1162
|
+
metadata
|
|
1163
|
+
});
|
|
1164
|
+
}
|
|
1165
|
+
async delete_feed(feedId) {
|
|
1166
|
+
const messageKeys = [];
|
|
1167
|
+
for (const [key] of this._feedMessages.entries()) {
|
|
1168
|
+
if (key.startsWith(`${feedId}:`)) {
|
|
1169
|
+
messageKeys.push(key);
|
|
1170
|
+
}
|
|
1171
|
+
}
|
|
1172
|
+
for (const key of messageKeys) {
|
|
1173
|
+
this._feedMessages.delete(key);
|
|
1174
|
+
}
|
|
1175
|
+
this._feeds.delete(feedId);
|
|
1176
|
+
}
|
|
1177
|
+
async list_feed_messages(feedId, options) {
|
|
1178
|
+
const limit = Math.min(options?.limit ?? 20, 100);
|
|
1179
|
+
const since = options?.since;
|
|
1180
|
+
const cursor = options?.cursor;
|
|
1181
|
+
let messages = [];
|
|
1182
|
+
const prefix = `${feedId}:`;
|
|
1183
|
+
for (const [key, message] of this._feedMessages.entries()) {
|
|
1184
|
+
if (key.startsWith(prefix)) {
|
|
1185
|
+
if (since !== void 0 && message.createdAt < since) {
|
|
1186
|
+
continue;
|
|
1187
|
+
}
|
|
1188
|
+
messages.push(message);
|
|
1189
|
+
}
|
|
1190
|
+
}
|
|
1191
|
+
messages.sort((a, b) => {
|
|
1192
|
+
if (b.createdAt !== a.createdAt) {
|
|
1193
|
+
return b.createdAt - a.createdAt;
|
|
1194
|
+
}
|
|
1195
|
+
return b.id.localeCompare(a.id);
|
|
1196
|
+
});
|
|
1197
|
+
if (cursor !== void 0) {
|
|
1198
|
+
try {
|
|
1199
|
+
const decoded = JSON.parse(
|
|
1200
|
+
decodeURIComponent(
|
|
1201
|
+
escape(atob(cursor.replace(/-/g, "+").replace(/_/g, "/")))
|
|
1202
|
+
)
|
|
1203
|
+
);
|
|
1204
|
+
const [cursorMessageId, cursorCreatedAt] = decoded;
|
|
1205
|
+
messages = messages.filter((m) => {
|
|
1206
|
+
return m.createdAt < cursorCreatedAt || m.createdAt === cursorCreatedAt && m.id < cursorMessageId;
|
|
1207
|
+
});
|
|
1208
|
+
} catch {
|
|
1209
|
+
}
|
|
1210
|
+
}
|
|
1211
|
+
let nextCursor;
|
|
1212
|
+
if (messages.length > limit) {
|
|
1213
|
+
messages = messages.slice(0, limit);
|
|
1214
|
+
const last = messages[messages.length - 1];
|
|
1215
|
+
if (last) {
|
|
1216
|
+
const cursorData = [last.id, last.createdAt];
|
|
1217
|
+
nextCursor = btoa(
|
|
1218
|
+
unescape(encodeURIComponent(JSON.stringify(cursorData)))
|
|
1219
|
+
).replace("/", "_").replace("+", "-").replace(/=+$/, "");
|
|
1220
|
+
}
|
|
1221
|
+
}
|
|
1222
|
+
return { messages, nextCursor };
|
|
1223
|
+
}
|
|
1224
|
+
async add_feed_message(feedId, message) {
|
|
1225
|
+
const feed = this._feeds.get(feedId);
|
|
1226
|
+
if (feed === void 0) {
|
|
1227
|
+
throw new Error(`Feed ${feedId} not found`);
|
|
1228
|
+
}
|
|
1229
|
+
this._feedMessages.set(`${feedId}:${message.id}`, message);
|
|
1230
|
+
}
|
|
1231
|
+
async update_feed_message(feedId, messageId, data, timestamp) {
|
|
1232
|
+
const key = `${feedId}:${messageId}`;
|
|
1233
|
+
const message = this._feedMessages.get(key);
|
|
1234
|
+
if (message === void 0) {
|
|
1235
|
+
throw new Error(`Feed message ${messageId} not found in feed ${feedId}`);
|
|
1236
|
+
}
|
|
1237
|
+
const effectiveTimestamp = timestamp ?? Date.now();
|
|
1238
|
+
if (effectiveTimestamp < message.updatedAt) {
|
|
1239
|
+
return message;
|
|
1240
|
+
}
|
|
1241
|
+
const updatedMessage = {
|
|
1242
|
+
...message,
|
|
1243
|
+
updatedAt: effectiveTimestamp,
|
|
1244
|
+
data
|
|
1245
|
+
};
|
|
1246
|
+
this._feedMessages.set(key, updatedMessage);
|
|
1247
|
+
return updatedMessage;
|
|
1248
|
+
}
|
|
1249
|
+
async delete_feed_message(feedId, messageId) {
|
|
1250
|
+
this._feedMessages.delete(`${feedId}:${messageId}`);
|
|
1251
|
+
}
|
|
897
1252
|
next_actor() {
|
|
898
1253
|
return ++this._nextActor;
|
|
899
1254
|
}
|
|
@@ -1672,7 +2027,8 @@ function isLeasedSessionExpired(leasedSession) {
|
|
|
1672
2027
|
}
|
|
1673
2028
|
|
|
1674
2029
|
// src/Room.ts
|
|
1675
|
-
var messagesDecoder =
|
|
2030
|
+
var messagesDecoder = array3(clientMsgDecoder);
|
|
2031
|
+
var ServerMsgCode2 = { ...CoreServerMsgCode, ...FeedMsgCode };
|
|
1676
2032
|
var HIGHEST_PROTOCOL_VERSION = Math.max(
|
|
1677
2033
|
...Object.values(ProtocolVersion).filter(
|
|
1678
2034
|
(v) => typeof v === "number"
|
|
@@ -2368,6 +2724,87 @@ var Room = class {
|
|
|
2368
2724
|
await this.deleteLeasedSession(session, ctx, defer);
|
|
2369
2725
|
}
|
|
2370
2726
|
}
|
|
2727
|
+
// ---------------------------------------------------------------------------
|
|
2728
|
+
// Feed APIs
|
|
2729
|
+
// ---------------------------------------------------------------------------
|
|
2730
|
+
/**
|
|
2731
|
+
* List feeds with pagination and filtering.
|
|
2732
|
+
*/
|
|
2733
|
+
async listFeeds(options) {
|
|
2734
|
+
return await this.driver.list_feeds(options);
|
|
2735
|
+
}
|
|
2736
|
+
/**
|
|
2737
|
+
* Get a specific feed by feed ID.
|
|
2738
|
+
*/
|
|
2739
|
+
async getFeed(feedId) {
|
|
2740
|
+
return await this.driver.get_feed(feedId);
|
|
2741
|
+
}
|
|
2742
|
+
/**
|
|
2743
|
+
* Create a new feed.
|
|
2744
|
+
* If timestamp is not provided, current server time is used.
|
|
2745
|
+
*/
|
|
2746
|
+
async createFeed(feed) {
|
|
2747
|
+
const now = feed.timestamp ?? Date.now();
|
|
2748
|
+
const fullFeed = {
|
|
2749
|
+
...feed,
|
|
2750
|
+
createdAt: now,
|
|
2751
|
+
updatedAt: now
|
|
2752
|
+
};
|
|
2753
|
+
await this.driver.create_feed(fullFeed);
|
|
2754
|
+
return fullFeed;
|
|
2755
|
+
}
|
|
2756
|
+
/**
|
|
2757
|
+
* Update a feed's metadata.
|
|
2758
|
+
*/
|
|
2759
|
+
async updateFeedMetadata(feedId, metadata) {
|
|
2760
|
+
await this.driver.update_feed_metadata(feedId, metadata);
|
|
2761
|
+
}
|
|
2762
|
+
/**
|
|
2763
|
+
* Delete a feed.
|
|
2764
|
+
*/
|
|
2765
|
+
async deleteFeed(feedId) {
|
|
2766
|
+
await this.driver.delete_feed(feedId);
|
|
2767
|
+
}
|
|
2768
|
+
/**
|
|
2769
|
+
* List feed messages for a feed with pagination.
|
|
2770
|
+
*/
|
|
2771
|
+
async listFeedMessages(feedId, options) {
|
|
2772
|
+
return await this.driver.list_feed_messages(feedId, options);
|
|
2773
|
+
}
|
|
2774
|
+
/**
|
|
2775
|
+
* Add a message to a feed.
|
|
2776
|
+
* If message id is not provided, a unique ID is automatically generated.
|
|
2777
|
+
* If timestamp is not provided, current server time is used.
|
|
2778
|
+
*/
|
|
2779
|
+
async addFeedMessage(feedId, message) {
|
|
2780
|
+
const now = message.timestamp ?? Date.now();
|
|
2781
|
+
const fullMessage = {
|
|
2782
|
+
id: message.id ?? nanoid2(),
|
|
2783
|
+
createdAt: now,
|
|
2784
|
+
updatedAt: now,
|
|
2785
|
+
data: message.data
|
|
2786
|
+
};
|
|
2787
|
+
await this.driver.add_feed_message(feedId, fullMessage);
|
|
2788
|
+
return fullMessage;
|
|
2789
|
+
}
|
|
2790
|
+
/**
|
|
2791
|
+
* Update a feed message's data.
|
|
2792
|
+
* Returns the updated message.
|
|
2793
|
+
*/
|
|
2794
|
+
async updateFeedMessage(feedId, messageId, data, timestamp) {
|
|
2795
|
+
return await this.driver.update_feed_message(
|
|
2796
|
+
feedId,
|
|
2797
|
+
messageId,
|
|
2798
|
+
data,
|
|
2799
|
+
timestamp ?? Date.now()
|
|
2800
|
+
);
|
|
2801
|
+
}
|
|
2802
|
+
/**
|
|
2803
|
+
* Delete a feed message.
|
|
2804
|
+
*/
|
|
2805
|
+
async deleteFeedMessage(feedId, messageId) {
|
|
2806
|
+
await this.driver.delete_feed_message(feedId, messageId);
|
|
2807
|
+
}
|
|
2371
2808
|
/**
|
|
2372
2809
|
* Will send the given ServerMsg through all Session, except the Session
|
|
2373
2810
|
* where the message originates from.
|
|
@@ -2704,6 +3141,176 @@ var Room = class {
|
|
|
2704
3141
|
}
|
|
2705
3142
|
break;
|
|
2706
3143
|
}
|
|
3144
|
+
case FeedMsgCode.FETCH_FEEDS: {
|
|
3145
|
+
const fetchMsg = msg;
|
|
3146
|
+
const [result, err] = await tryCatch(
|
|
3147
|
+
this.listFeeds({
|
|
3148
|
+
cursor: fetchMsg.cursor,
|
|
3149
|
+
since: fetchMsg.since,
|
|
3150
|
+
limit: fetchMsg.limit,
|
|
3151
|
+
metadata: fetchMsg.metadata
|
|
3152
|
+
})
|
|
3153
|
+
);
|
|
3154
|
+
if (err) {
|
|
3155
|
+
replyImmediately(feedFailureServerMsg(fetchMsg.requestId, err));
|
|
3156
|
+
break;
|
|
3157
|
+
}
|
|
3158
|
+
replyImmediately({
|
|
3159
|
+
type: FeedMsgCode.FEEDS_LIST,
|
|
3160
|
+
requestId: fetchMsg.requestId,
|
|
3161
|
+
feeds: result.feeds,
|
|
3162
|
+
nextCursor: result.nextCursor
|
|
3163
|
+
});
|
|
3164
|
+
break;
|
|
3165
|
+
}
|
|
3166
|
+
case FeedMsgCode.FETCH_FEED_MESSAGES: {
|
|
3167
|
+
const fetchMsg = msg;
|
|
3168
|
+
const [result, err] = await tryCatch(
|
|
3169
|
+
this.listFeedMessages(fetchMsg.feedId, {
|
|
3170
|
+
cursor: fetchMsg.cursor,
|
|
3171
|
+
since: fetchMsg.since,
|
|
3172
|
+
limit: fetchMsg.limit
|
|
3173
|
+
})
|
|
3174
|
+
);
|
|
3175
|
+
if (err) {
|
|
3176
|
+
replyImmediately(feedFailureServerMsg(fetchMsg.requestId, err));
|
|
3177
|
+
break;
|
|
3178
|
+
}
|
|
3179
|
+
replyImmediately({
|
|
3180
|
+
type: FeedMsgCode.FEED_MESSAGES_LIST,
|
|
3181
|
+
requestId: fetchMsg.requestId,
|
|
3182
|
+
feedId: fetchMsg.feedId,
|
|
3183
|
+
messages: result.messages,
|
|
3184
|
+
nextCursor: result.nextCursor
|
|
3185
|
+
});
|
|
3186
|
+
break;
|
|
3187
|
+
}
|
|
3188
|
+
case FeedMsgCode.ADD_FEED: {
|
|
3189
|
+
const addMsg = msg;
|
|
3190
|
+
const [feed, err] = await tryCatch(
|
|
3191
|
+
this.createFeed({
|
|
3192
|
+
feedId: addMsg.feedId,
|
|
3193
|
+
metadata: addMsg.metadata ?? {},
|
|
3194
|
+
timestamp: addMsg.timestamp
|
|
3195
|
+
})
|
|
3196
|
+
);
|
|
3197
|
+
if (err) {
|
|
3198
|
+
replyImmediately(feedFailureServerMsg(addMsg.requestId, err));
|
|
3199
|
+
break;
|
|
3200
|
+
}
|
|
3201
|
+
const feedsMsg = {
|
|
3202
|
+
type: FeedMsgCode.FEEDS_ADDED,
|
|
3203
|
+
feeds: [feed]
|
|
3204
|
+
};
|
|
3205
|
+
replyImmediately(feedsMsg);
|
|
3206
|
+
scheduleFanOut(feedsMsg);
|
|
3207
|
+
break;
|
|
3208
|
+
}
|
|
3209
|
+
case FeedMsgCode.UPDATE_FEED: {
|
|
3210
|
+
const updateMsg = msg;
|
|
3211
|
+
const [, metaErr] = await tryCatch(
|
|
3212
|
+
this.updateFeedMetadata(updateMsg.feedId, updateMsg.metadata)
|
|
3213
|
+
);
|
|
3214
|
+
if (metaErr) {
|
|
3215
|
+
replyImmediately(feedFailureServerMsg(updateMsg.requestId, metaErr));
|
|
3216
|
+
break;
|
|
3217
|
+
}
|
|
3218
|
+
const feed = await this.getFeed(updateMsg.feedId);
|
|
3219
|
+
if (!feed) {
|
|
3220
|
+
replyImmediately(
|
|
3221
|
+
feedRequestFailed(
|
|
3222
|
+
updateMsg.requestId,
|
|
3223
|
+
FeedRequestErrorCode.FEED_NOT_FOUND
|
|
3224
|
+
)
|
|
3225
|
+
);
|
|
3226
|
+
break;
|
|
3227
|
+
}
|
|
3228
|
+
const feedsMsg = {
|
|
3229
|
+
type: FeedMsgCode.FEEDS_UPDATED,
|
|
3230
|
+
feeds: [feed]
|
|
3231
|
+
};
|
|
3232
|
+
replyImmediately(feedsMsg);
|
|
3233
|
+
scheduleFanOut(feedsMsg);
|
|
3234
|
+
break;
|
|
3235
|
+
}
|
|
3236
|
+
case FeedMsgCode.DELETE_FEED: {
|
|
3237
|
+
const deleteMsg = msg;
|
|
3238
|
+
const [, err] = await tryCatch(this.deleteFeed(deleteMsg.feedId));
|
|
3239
|
+
if (err) {
|
|
3240
|
+
replyImmediately(feedFailureServerMsg(deleteMsg.requestId, err));
|
|
3241
|
+
break;
|
|
3242
|
+
}
|
|
3243
|
+
const feedDeletedMsg = {
|
|
3244
|
+
type: FeedMsgCode.FEED_DELETED,
|
|
3245
|
+
feedId: deleteMsg.feedId
|
|
3246
|
+
};
|
|
3247
|
+
replyImmediately(feedDeletedMsg);
|
|
3248
|
+
scheduleFanOut(feedDeletedMsg);
|
|
3249
|
+
break;
|
|
3250
|
+
}
|
|
3251
|
+
case FeedMsgCode.ADD_FEED_MESSAGE: {
|
|
3252
|
+
const addMsg = msg;
|
|
3253
|
+
const [message, err] = await tryCatch(
|
|
3254
|
+
this.addFeedMessage(addMsg.feedId, {
|
|
3255
|
+
data: addMsg.data,
|
|
3256
|
+
id: addMsg.id,
|
|
3257
|
+
timestamp: addMsg.timestamp
|
|
3258
|
+
})
|
|
3259
|
+
);
|
|
3260
|
+
if (err) {
|
|
3261
|
+
replyImmediately(feedFailureServerMsg(addMsg.requestId, err));
|
|
3262
|
+
break;
|
|
3263
|
+
}
|
|
3264
|
+
const feedMessagesMsg = {
|
|
3265
|
+
type: FeedMsgCode.FEED_MESSAGES_ADDED,
|
|
3266
|
+
feedId: addMsg.feedId,
|
|
3267
|
+
messages: [message]
|
|
3268
|
+
};
|
|
3269
|
+
replyImmediately(feedMessagesMsg);
|
|
3270
|
+
scheduleFanOut(feedMessagesMsg);
|
|
3271
|
+
break;
|
|
3272
|
+
}
|
|
3273
|
+
case FeedMsgCode.UPDATE_FEED_MESSAGE: {
|
|
3274
|
+
const updateMsg = msg;
|
|
3275
|
+
const [message, err] = await tryCatch(
|
|
3276
|
+
this.updateFeedMessage(
|
|
3277
|
+
updateMsg.feedId,
|
|
3278
|
+
updateMsg.messageId,
|
|
3279
|
+
updateMsg.data,
|
|
3280
|
+
updateMsg.timestamp
|
|
3281
|
+
)
|
|
3282
|
+
);
|
|
3283
|
+
if (err) {
|
|
3284
|
+
replyImmediately(feedFailureServerMsg(updateMsg.requestId, err));
|
|
3285
|
+
break;
|
|
3286
|
+
}
|
|
3287
|
+
const feedMessagesMsg = {
|
|
3288
|
+
type: FeedMsgCode.FEED_MESSAGES_UPDATED,
|
|
3289
|
+
feedId: updateMsg.feedId,
|
|
3290
|
+
messages: [message]
|
|
3291
|
+
};
|
|
3292
|
+
replyImmediately(feedMessagesMsg);
|
|
3293
|
+
scheduleFanOut(feedMessagesMsg);
|
|
3294
|
+
break;
|
|
3295
|
+
}
|
|
3296
|
+
case FeedMsgCode.DELETE_FEED_MESSAGE: {
|
|
3297
|
+
const deleteMsg = msg;
|
|
3298
|
+
const [, err] = await tryCatch(
|
|
3299
|
+
this.deleteFeedMessage(deleteMsg.feedId, deleteMsg.messageId)
|
|
3300
|
+
);
|
|
3301
|
+
if (err) {
|
|
3302
|
+
replyImmediately(feedFailureServerMsg(deleteMsg.requestId, err));
|
|
3303
|
+
break;
|
|
3304
|
+
}
|
|
3305
|
+
const feedMessagesMsg = {
|
|
3306
|
+
type: FeedMsgCode.FEED_MESSAGES_DELETED,
|
|
3307
|
+
feedId: deleteMsg.feedId,
|
|
3308
|
+
messageIds: [deleteMsg.messageId]
|
|
3309
|
+
};
|
|
3310
|
+
replyImmediately(feedMessagesMsg);
|
|
3311
|
+
scheduleFanOut(feedMessagesMsg);
|
|
3312
|
+
break;
|
|
3313
|
+
}
|
|
2707
3314
|
default: {
|
|
2708
3315
|
try {
|
|
2709
3316
|
return assertNever3(msg, "Unrecognized client msg");
|
|
@@ -2720,6 +3327,8 @@ export {
|
|
|
2720
3327
|
BrowserSession,
|
|
2721
3328
|
ConsoleTarget,
|
|
2722
3329
|
DefaultMap,
|
|
3330
|
+
FeedMsgCode,
|
|
3331
|
+
FeedRequestErrorCode,
|
|
2723
3332
|
InMemoryDriver,
|
|
2724
3333
|
LogLevel,
|
|
2725
3334
|
LogTarget,
|
|
@@ -2732,12 +3341,19 @@ export {
|
|
|
2732
3341
|
ackIgnoredOp,
|
|
2733
3342
|
clientMsgDecoder,
|
|
2734
3343
|
concatUint8Arrays,
|
|
3344
|
+
feedFailureServerMsg,
|
|
3345
|
+
feedMetadataIdDecoder,
|
|
3346
|
+
feedMetadataUpdateDecoder,
|
|
3347
|
+
feedRequestFailed,
|
|
3348
|
+
fetchFeedsMetadataFilterDecoder,
|
|
2735
3349
|
guidDecoder,
|
|
2736
3350
|
isLeasedSessionExpired,
|
|
2737
3351
|
jsonObjectYolo,
|
|
2738
3352
|
jsonYolo,
|
|
2739
3353
|
makeInMemorySnapshot,
|
|
2740
3354
|
makeMetadataDB,
|
|
3355
|
+
mapFeedError,
|
|
3356
|
+
optionalFeedMetadataDecoder,
|
|
2741
3357
|
plainLsonToNodeStream,
|
|
2742
3358
|
protocolVersionDecoder,
|
|
2743
3359
|
quote,
|