@pairlobby/fixtures 0.31.0 → 0.33.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/harness.d.ts CHANGED
@@ -368,6 +368,12 @@ export declare class RoomHarness {
368
368
  latestSeq: number;
369
369
  earliestSeq: number;
370
370
  hasMore: boolean;
371
+ stateRevision?: number | undefined;
372
+ requestRevision?: number | undefined;
373
+ snapshotRevision?: number | undefined;
374
+ turnRevision?: number | undefined;
375
+ lastMessageAt?: number | null | undefined;
376
+ autoCloseAt?: number | null | undefined;
371
377
  receipts?: {
372
378
  at: number;
373
379
  revision: number;
@@ -375,6 +381,126 @@ export declare class RoomHarness {
375
381
  throughSeq: number;
376
382
  }[] | undefined;
377
383
  receiptRevision?: number | undefined;
384
+ snapshot?: {
385
+ name: string;
386
+ roomId: string;
387
+ createdAt: number;
388
+ expiresAt: number | null;
389
+ closedAt: number | null;
390
+ lifecycle: "open" | "closed" | "expired" | "deleted";
391
+ policy: {
392
+ joinPolicy: "invite_only" | "open_to_guests";
393
+ maxParticipants: number;
394
+ maxEventPayloadBytes: number;
395
+ maxRetainedEventBytes: number;
396
+ maxRetainedEvents: number;
397
+ roomLifetimeMs: number | null;
398
+ inviteLifetimeMs: number | null;
399
+ exportWindowMs: number;
400
+ connectTicketLifetimeMs: number;
401
+ type?: "public" | "protected" | "private" | "personal" | undefined;
402
+ maxFileBytes?: number | undefined;
403
+ autoClose?: {
404
+ mode: "off";
405
+ } | {
406
+ mode: "inactivity";
407
+ afterMs: number;
408
+ } | {
409
+ mode: "age";
410
+ afterMs: number;
411
+ } | {
412
+ mode: "agents_and_guests_left";
413
+ } | undefined;
414
+ inviteRole?: "guest" | "member" | undefined;
415
+ localJoin?: boolean | undefined;
416
+ permissions?: {
417
+ invite?: boolean | undefined;
418
+ attach?: boolean | undefined;
419
+ rename?: boolean | undefined;
420
+ lock?: boolean | undefined;
421
+ mute?: boolean | undefined;
422
+ kick?: boolean | undefined;
423
+ pause?: boolean | undefined;
424
+ turns?: boolean | undefined;
425
+ } | undefined;
426
+ maxRetainedFileBytes?: number | undefined;
427
+ };
428
+ controlRevision: number;
429
+ latestSeq: number;
430
+ earliestSeq: number;
431
+ participants: {
432
+ participantId: string;
433
+ displayName: string;
434
+ kind: "agent" | "human";
435
+ role: "controller" | "guest" | "member";
436
+ capabilities: {
437
+ deliverUnsolicited: boolean;
438
+ cancelTurn: boolean;
439
+ cancelTool: boolean;
440
+ runtime?: string | undefined;
441
+ runtimeVersion?: string | undefined;
442
+ } | null;
443
+ controlRevision: number;
444
+ joinedAt: number;
445
+ paused: boolean;
446
+ acknowledgedOutcome: "pause_requested" | "paused_between_turns" | "current_turn_cancelled" | "tool_cancellation_unknown" | "resumed" | "unsupported" | "disconnected" | null;
447
+ revoked: boolean;
448
+ left: boolean;
449
+ member?: string | undefined;
450
+ muted?: boolean | undefined;
451
+ permissions?: {
452
+ invite?: boolean | undefined;
453
+ attach?: boolean | undefined;
454
+ rename?: boolean | undefined;
455
+ lock?: boolean | undefined;
456
+ mute?: boolean | undefined;
457
+ kick?: boolean | undefined;
458
+ pause?: boolean | undefined;
459
+ turns?: boolean | undefined;
460
+ } | undefined;
461
+ nameSource?: "room" | "profile" | undefined;
462
+ origin?: {
463
+ handle: string;
464
+ directory: true;
465
+ listingId: string;
466
+ contact: "questions" | "tasks";
467
+ } | undefined;
468
+ interruptRequested?: boolean | undefined;
469
+ acknowledgedRevision?: number | undefined;
470
+ }[];
471
+ owner?: string | undefined;
472
+ visibility?: {
473
+ handles: string[];
474
+ } | "everyone" | "default" | undefined;
475
+ locked?: boolean | undefined;
476
+ stateRevision?: number | undefined;
477
+ requestRevision?: number | undefined;
478
+ snapshotRevision?: number | undefined;
479
+ turnMode?: "sequential" | "parallel" | undefined;
480
+ turnRevision?: number | undefined;
481
+ lastMessageAt?: number | null | undefined;
482
+ autoCloseArmed?: boolean | undefined;
483
+ autoCloseAt?: number | null | undefined;
484
+ closeReason?: "inactivity" | "age" | "agents_and_guests_left" | "manual" | undefined;
485
+ syncSupported?: boolean | undefined;
486
+ messageReceiptScope?: "recipient" | "members" | undefined;
487
+ receiptMode?: "events" | "both" | "watermark" | undefined;
488
+ messageStagesSupported?: boolean | undefined;
489
+ requestRecoverySupported?: boolean | undefined;
490
+ requestResolutionSupported?: boolean | undefined;
491
+ providerWaitSupported?: boolean | undefined;
492
+ rejoinSupported?: boolean | undefined;
493
+ renameSelfSupported?: boolean | undefined;
494
+ adminRolesSupported?: boolean | undefined;
495
+ permissionsSupported?: boolean | undefined;
496
+ filesSupported?: boolean | undefined;
497
+ inviteRoleSupported?: boolean | undefined;
498
+ autoCloseSupported?: boolean | undefined;
499
+ interruptSupported?: boolean | undefined;
500
+ quotedMessagesSupported?: boolean | undefined;
501
+ groupTurnsSupported?: boolean | undefined;
502
+ workingStatusSupported?: boolean | undefined;
503
+ } | undefined;
378
504
  }>;
379
505
  snapshot(credential: string): Promise<RoomSnapshot>;
380
506
  export(credential: string): Promise<{
@@ -470,11 +596,16 @@ export declare class RoomHarness {
470
596
  handles: string[];
471
597
  } | "everyone" | "default" | undefined;
472
598
  locked?: boolean | undefined;
599
+ stateRevision?: number | undefined;
600
+ requestRevision?: number | undefined;
601
+ snapshotRevision?: number | undefined;
473
602
  turnMode?: "sequential" | "parallel" | undefined;
603
+ turnRevision?: number | undefined;
474
604
  lastMessageAt?: number | null | undefined;
475
605
  autoCloseArmed?: boolean | undefined;
476
606
  autoCloseAt?: number | null | undefined;
477
607
  closeReason?: "inactivity" | "age" | "agents_and_guests_left" | "manual" | undefined;
608
+ syncSupported?: boolean | undefined;
478
609
  messageReceiptScope?: "recipient" | "members" | undefined;
479
610
  receiptMode?: "events" | "both" | "watermark" | undefined;
480
611
  messageStagesSupported?: boolean | undefined;
@@ -842,9 +973,10 @@ export declare class RoomHarness {
842
973
  size: number;
843
974
  mediaType: string;
844
975
  sha256: string;
845
- uploaderId: string;
846
- createdAt: number;
847
976
  eventId: string;
977
+ uploaderId?: string | undefined;
978
+ createdAt?: number | undefined;
979
+ archived?: boolean | undefined;
848
980
  }[] | undefined;
849
981
  }>;
850
982
  dropHistoryBefore(seq: number): void;
@@ -1 +1 @@
1
- {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"harness.d.ts","sourceRoot":"","sources":["../src/harness.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,6 @@
1
1
  import type { HandoverRecord, MessageRequest, RequestPage, InviteRecord, ParticipantRecord, RoomEvent, RoomRecord } from '@pairlobby/protocol';
2
2
  import type { Mutation, RoomView } from '@pairlobby/room-core';
3
- import type { EventPage, FileStore, IdempotencyRecord, RoomStore } from '@pairlobby/server-core';
3
+ import type { EventPage, FileStore, IdempotencyRecord, RoomHead, RoomLoadOptions, RoomStore } from '@pairlobby/server-core';
4
4
  type IdempotencyKey = {
5
5
  key: string;
6
6
  requestDigest: string;
@@ -10,30 +10,41 @@ export declare class MemoryStore implements RoomStore {
10
10
  private requests;
11
11
  private invites;
12
12
  private stored;
13
+ private uploads;
14
+ private receiptRanges;
13
15
  readonly files: FileStore;
16
+ private fileUsage;
17
+ private bumpFileState;
14
18
  private inRoom;
15
19
  createRoom(room: RoomRecord, participant: ParticipantRecord, event: RoomEvent): Promise<void>;
16
- loadRoom(roomId: string): Promise<RoomView | null>;
20
+ roomHead(roomId: string): Promise<RoomHead | null>;
21
+ loadRoom(roomId: string, options?: RoomLoadOptions): Promise<RoomView | null>;
17
22
  apply(mutation: Mutation, idempotency: IdempotencyKey): Promise<void>;
18
- readEvents(roomId: string, after: number, limit: number): Promise<EventPage>;
23
+ readEvents(roomId: string, after: number, limit: number, through?: number): Promise<EventPage>;
19
24
  eventBySeq(roomId: string, seq: number): Promise<RoomEvent | null>;
20
25
  eventById(roomId: string, eventId: string): Promise<RoomEvent | null>;
21
26
  idempotencyRecord(roomId: string, key: string): Promise<IdempotencyRecord | null>;
22
- putInvite(invite: InviteRecord): Promise<void>;
27
+ putInvite(invite: InviteRecord, expectedStateRevision?: number): Promise<void>;
23
28
  inviteByDigest(digest: string): Promise<InviteRecord | null>;
24
- reserveInvite(digest: string, attemptId: string, credentialHash: string, expectedOccupantId: string | null): Promise<InviteRecord | null>;
25
- completeInvite(digest: string, participantId: string): Promise<void>;
29
+ reserveInvite(digest: string, attemptId: string, credentialHash: string, expectedOccupantId: string | null, expectedStateRevision?: number): Promise<InviteRecord | null>;
30
+ completeInvite(digest: string, participantId: string, attemptId?: string): Promise<void>;
26
31
  participantByCredential(roomId: string, credentialHash: string): Promise<ParticipantRecord | null>;
27
32
  handovers(roomId: string): Promise<HandoverRecord[]>;
28
33
  messageRequest(roomId: string, eventId: string): Promise<MessageRequest | null>;
29
34
  groupRequests(roomId: string, conversationId: string): Promise<MessageRequest[]>;
30
35
  updateTurns(room: RoomRecord, requests: MessageRequest[], expectedRevision: number): Promise<void>;
31
36
  messageRequests(roomId: string, after: number, limit: number, recipientId?: string): Promise<RequestPage>;
32
- setLifecycle(roomId: string, lifecycle: RoomRecord['lifecycle']): Promise<void>;
37
+ unreceivedRequests(roomId: string, recipientId: string, after: number, limit: number): Promise<RequestPage>;
38
+ pendingRequestCount(roomId: string): Promise<number>;
39
+ private writeReceipts;
40
+ private receiptsChangeRequests;
41
+ private received;
42
+ setLifecycle(roomId: string, lifecycle: RoomRecord['lifecycle'], expectedStateRevision?: number): Promise<void>;
33
43
  deleteRoom(roomId: string): Promise<void>;
34
44
  dueAutoCloses(now: number, limit: number): Promise<string[]>;
35
- nextAutoCloseAt(): Promise<number | null>;
45
+ nextAutoCloseAt(now?: number): Promise<number | null>;
36
46
  private deadlines;
47
+ private bumpRoom;
37
48
  /** Simulates retention dropping the front of the log without touching room state. */
38
49
  dropHistoryBefore(roomId: string, seq: number): void;
39
50
  private require;
@@ -1 +1 @@
1
- {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../src/memory-store.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"memory-store.d.ts","sourceRoot":"","sources":["../src/memory-store.ts"],"names":[],"mappings":"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"}
@@ -1,33 +1,107 @@
1
1
  //! An in-memory `RoomStore`. It is the reference the SQLite and Durable Object
2
2
  //! stores are measured against, and it is deliberately strict: `apply` either
3
3
  //! lands every part of a mutation or throws before touching anything.
4
- import { ProtocolError, mergeMessageRequest } from '@pairlobby/protocol';
4
+ import { FILE_CHUNK_BYTES, ProtocolError, mergeMessageRequest } from '@pairlobby/protocol';
5
+ import { committedRoom, mutationChanges, eventPage, requestPage } from '@pairlobby/server-core';
5
6
  export class MemoryStore {
6
7
  rooms = new Map();
7
8
  requests = new Map();
8
9
  invites = new Map();
9
10
  stored = new Map();
11
+ uploads = new Map();
12
+ receiptRanges = new Map();
10
13
  files = {
11
- putFile: async (file, bytes, limitBytes) => {
12
- const held = [...this.stored.values()].filter((entry) => entry.file.roomId === file.roomId).reduce((total, entry) => total + entry.file.size, 0);
14
+ putFile: async (file, bytes, limitBytes, expectedStateRevision) => {
15
+ const held = this.fileUsage(file.roomId);
13
16
  if (held + file.size > limitBytes) {
14
17
  return false;
15
18
  }
19
+ this.bumpFileState(file.roomId, expectedStateRevision);
16
20
  this.stored.set(file.fileId, { file, bytes: bytes.slice() });
17
21
  return true;
18
22
  },
23
+ createUpload: async (file, limitBytes, expectedStateRevision) => {
24
+ if (this.fileUsage(file.roomId) + file.size > limitBytes) {
25
+ return false;
26
+ }
27
+ this.bumpFileState(file.roomId, expectedStateRevision);
28
+ this.uploads.set(file.fileId, { file, chunks: [], received: 0 });
29
+ return true;
30
+ },
31
+ writeChunk: async (roomId, fileId, index, bytes) => {
32
+ const entry = this.uploads.get(fileId);
33
+ if (!entry || entry.file.roomId !== roomId || entry.chunks.length !== index || bytes.byteLength > FILE_CHUNK_BYTES || entry.received + bytes.byteLength > entry.file.size) {
34
+ throw new ProtocolError('invalid_request', 'the upload is no longer available or its chunks are out of order');
35
+ }
36
+ entry.chunks.push(bytes.slice());
37
+ entry.received += bytes.byteLength;
38
+ },
39
+ completeUpload: async (file, expectedStateRevision) => {
40
+ const entry = this.uploads.get(file.fileId);
41
+ if (!entry || entry.file.roomId !== file.roomId || entry.received !== file.size || entry.file.size !== file.size) {
42
+ throw new ProtocolError('invalid_request', 'the upload did not finish');
43
+ }
44
+ this.bumpFileState(file.roomId, expectedStateRevision);
45
+ const bytes = new Uint8Array(file.size);
46
+ let offset = 0;
47
+ for (const chunk of entry.chunks) {
48
+ bytes.set(chunk, offset);
49
+ offset += chunk.byteLength;
50
+ }
51
+ this.stored.set(file.fileId, { file, bytes });
52
+ this.uploads.delete(file.fileId);
53
+ },
54
+ cancelUpload: async (roomId, fileId) => {
55
+ if (this.uploads.get(fileId)?.file.roomId === roomId) {
56
+ this.uploads.delete(fileId);
57
+ this.bumpFileState(roomId);
58
+ }
59
+ },
60
+ fileStream: async (roomId, fileId) => {
61
+ const file = this.inRoom(roomId, fileId);
62
+ let offset = 0;
63
+ return file ? new ReadableStream({
64
+ pull(controller) {
65
+ if (offset >= file.bytes.byteLength) {
66
+ controller.close();
67
+ }
68
+ else {
69
+ controller.enqueue(file.bytes.slice(offset, offset + FILE_CHUNK_BYTES));
70
+ offset += FILE_CHUNK_BYTES;
71
+ }
72
+ }
73
+ }, { highWaterMark: 0 }) : null;
74
+ },
19
75
  file: async (roomId, fileId) => this.inRoom(roomId, fileId)?.file ?? null,
20
76
  fileBytes: async (roomId, fileId) => this.inRoom(roomId, fileId)?.bytes.slice() ?? null,
21
77
  attachedFiles: async (roomId) => [...this.stored.values()].map((entry) => entry.file).filter((file) => file.roomId === roomId && file.eventId !== null).sort((a, b) => a.createdAt - b.createdAt || a.fileId.localeCompare(b.fileId)),
22
- usedBytes: async (roomId) => [...this.stored.values()].filter((entry) => entry.file.roomId === roomId).reduce((total, entry) => total + entry.file.size, 0),
78
+ usedBytes: async (roomId) => this.fileUsage(roomId),
23
79
  deleteUnattachedFiles: async (roomId, before) => {
80
+ let changed = false;
24
81
  for (const [fileId, { file }] of this.stored) {
25
82
  if (file.roomId === roomId && file.eventId === null && file.createdAt < before) {
26
83
  this.stored.delete(fileId);
84
+ changed = true;
85
+ }
86
+ }
87
+ for (const [fileId, { file }] of this.uploads) {
88
+ if (file.roomId === roomId && file.createdAt < before) {
89
+ this.uploads.delete(fileId);
90
+ changed = true;
27
91
  }
28
92
  }
93
+ if (changed) {
94
+ this.bumpFileState(roomId);
95
+ }
29
96
  },
30
97
  };
98
+ fileUsage(roomId) {
99
+ return [...this.stored.values(), ...this.uploads.values()].filter((entry) => entry.file.roomId === roomId).reduce((total, entry) => total + entry.file.size, 0);
100
+ }
101
+ bumpFileState(roomId, expectedStateRevision) {
102
+ const table = this.require(roomId);
103
+ table.room = committedRoom(table.room, { ...table.room, stateRevision: expectedStateRevision ?? table.room.stateRevision ?? 0 });
104
+ }
31
105
  inRoom(roomId, fileId) {
32
106
  const entry = this.stored.get(fileId);
33
107
  return entry?.file.roomId === roomId ? entry : undefined;
@@ -35,12 +109,16 @@ export class MemoryStore {
35
109
  async createRoom(room, participant, event) {
36
110
  this.rooms.set(room.roomId, { room, participants: [participant], handovers: [], controls: [], events: [event], idempotency: new Map(), earliestSeq: 1 });
37
111
  }
38
- async loadRoom(roomId) {
112
+ async roomHead(roomId) {
113
+ const table = this.rooms.get(roomId);
114
+ return table ? { room: table.room, earliestSeq: table.earliestSeq } : null;
115
+ }
116
+ async loadRoom(roomId, options = {}) {
39
117
  const table = this.rooms.get(roomId);
40
118
  if (!table) {
41
119
  return null;
42
120
  }
43
- return { room: table.room, participants: table.participants, handovers: table.handovers, controls: table.controls, earliestSeq: table.earliestSeq };
121
+ return { room: table.room, participants: table.participants, handovers: options.handovers === false ? [] : table.handovers, controls: table.controls, earliestSeq: table.earliestSeq };
44
122
  }
45
123
  async apply(mutation, idempotency) {
46
124
  const table = this.require(mutation.room.roomId);
@@ -48,8 +126,10 @@ export class MemoryStore {
48
126
  throw new ProtocolError('turn_conflict', 'the room turn changed; retry');
49
127
  }
50
128
  if (table.room.nextSeq !== mutation.appendEvent.seq) {
51
- throw new ProtocolError(mutation.expectedTurnRevision === undefined ? 'server_unavailable' : 'turn_conflict', 'concurrent room mutation; retry with the same idempotency key');
129
+ throw new ProtocolError('turn_conflict', 'concurrent room mutation; retry with the same idempotency key');
52
130
  }
131
+ const changes = mutationChanges(mutation);
132
+ const room = committedRoom(table.room, mutation.room, { ...changes, requests: changes.requests || this.receiptsChangeRequests(table.room, mutation.room) });
53
133
  const attaching = (mutation.attachFiles ?? []).map((fileId) => this.inRoom(mutation.room.roomId, fileId));
54
134
  if (attaching.some((entry) => !entry || entry.file.eventId !== null)) {
55
135
  throw new ProtocolError('invalid_request', 'an attached file is no longer available; upload it again');
@@ -57,7 +137,8 @@ export class MemoryStore {
57
137
  for (const entry of attaching) {
58
138
  entry.file = { ...entry.file, eventId: mutation.appendEvent.eventId };
59
139
  }
60
- table.room = mutation.room;
140
+ this.writeReceipts(table.room, room);
141
+ table.room = room;
61
142
  for (const participant of mutation.upsertParticipants)
62
143
  table.participants = upsert(table.participants, participant, 'participantId');
63
144
  for (const handover of mutation.upsertHandovers)
@@ -66,18 +147,17 @@ export class MemoryStore {
66
147
  table.controls = upsert(table.controls, control, 'targetParticipantId');
67
148
  for (const request of mutation.upsertRequests ?? []) {
68
149
  const previous = this.requests.get(request.eventId);
69
- this.requests.set(request.eventId, mergeMessageRequest(previous, request));
150
+ this.requests.set(request.eventId, mergeMessageRequest(previous ? this.received(previous) : null, request));
70
151
  }
71
152
  table.events.push(mutation.appendEvent);
72
153
  if (idempotency) {
73
154
  table.idempotency.set(idempotency.key, { requestDigest: idempotency.requestDigest, seq: mutation.appendEvent.seq });
74
155
  }
75
156
  }
76
- async readEvents(roomId, after, limit) {
157
+ async readEvents(roomId, after, limit, through = Number.MAX_SAFE_INTEGER) {
77
158
  const table = this.require(roomId);
78
- const matching = table.events.filter((event) => event.seq > after);
79
- const page = matching.slice(0, limit);
80
- return { events: page, hasMore: matching.length > page.length };
159
+ const matching = table.events.filter((event) => event.seq > after && event.seq <= through);
160
+ return eventPage(matching.map((event) => ({ body: JSON.stringify(event) })), limit);
81
161
  }
82
162
  async eventBySeq(roomId, seq) {
83
163
  return this.require(roomId).events.find((event) => event.seq === seq) ?? null;
@@ -88,13 +168,14 @@ export class MemoryStore {
88
168
  async idempotencyRecord(roomId, key) {
89
169
  return this.require(roomId).idempotency.get(key) ?? null;
90
170
  }
91
- async putInvite(invite) {
171
+ async putInvite(invite, expectedStateRevision) {
172
+ this.bumpRoom(invite.roomId, expectedStateRevision);
92
173
  this.invites.set(invite.digest, invite);
93
174
  }
94
175
  async inviteByDigest(digest) {
95
176
  return this.invites.get(digest) ?? null;
96
177
  }
97
- async reserveInvite(digest, attemptId, credentialHash, expectedOccupantId) {
178
+ async reserveInvite(digest, attemptId, credentialHash, expectedOccupantId, expectedStateRevision) {
98
179
  const invite = this.invites.get(digest);
99
180
  if (!invite) {
100
181
  return null;
@@ -117,14 +198,22 @@ export class MemoryStore {
117
198
  return null;
118
199
  }
119
200
  const reserved = { ...invite, state: 'reserved', boundAttemptId: attemptId, boundCredentialHash: credentialHash };
201
+ this.bumpRoom(invite.roomId, expectedStateRevision);
120
202
  this.invites.set(digest, reserved);
121
203
  return reserved;
122
204
  }
123
- async completeInvite(digest, participantId) {
205
+ async completeInvite(digest, participantId, attemptId) {
124
206
  const invite = this.invites.get(digest);
125
207
  if (!invite) {
126
208
  return;
127
209
  }
210
+ if (attemptId !== undefined && invite.boundAttemptId !== attemptId) {
211
+ throw new ProtocolError('invite_already_redeemed', 'this invite belongs to another redemption attempt');
212
+ }
213
+ if (invite.state === 'redeemed' && invite.redeemedParticipantId === participantId) {
214
+ return;
215
+ }
216
+ this.bumpRoom(invite.roomId);
128
217
  this.invites.set(digest, { ...invite, state: 'redeemed', redeemedParticipantId: participantId });
129
218
  }
130
219
  async participantByCredential(roomId, credentialHash) {
@@ -135,30 +224,61 @@ export class MemoryStore {
135
224
  }
136
225
  async messageRequest(roomId, eventId) {
137
226
  const value = this.requests.get(eventId);
138
- return value?.roomId === roomId ? value : null;
227
+ return value?.roomId === roomId ? this.received(value) : null;
139
228
  }
140
229
  async groupRequests(roomId, conversationId) {
141
- return [...this.requests.values()].filter((request) => request.roomId === roomId && request.conversationId === conversationId).sort((a, b) => a.seq - b.seq);
230
+ return [...this.requests.values()].filter((request) => request.roomId === roomId && request.conversationId === conversationId).sort((a, b) => a.seq - b.seq).map((request) => this.received(request));
142
231
  }
143
232
  async updateTurns(room, requests, expectedRevision) {
144
233
  const table = this.require(room.roomId);
145
234
  if ((table.room.turnRevision ?? 0) !== expectedRevision || table.room.nextSeq !== room.nextSeq) {
146
235
  throw new ProtocolError('turn_conflict', 'the room turn changed; retry');
147
236
  }
148
- table.room = room;
237
+ const committed = committedRoom(table.room, room, { requests: requests.length > 0 || this.receiptsChangeRequests(table.room, room) });
238
+ this.writeReceipts(table.room, committed);
239
+ table.room = committed;
149
240
  for (const request of requests) {
150
- this.requests.set(request.eventId, mergeMessageRequest(this.requests.get(request.eventId), request));
241
+ const previous = this.requests.get(request.eventId);
242
+ this.requests.set(request.eventId, mergeMessageRequest(previous ? this.received(previous) : null, request));
151
243
  }
152
244
  }
153
245
  async messageRequests(roomId, after, limit, recipientId) {
154
246
  const records = [...this.requests.values()]
155
247
  .filter((r) => r.roomId === roomId && r.seq > after && r.requiresReply && !r.responseEventId && (!recipientId || r.to === recipientId))
156
248
  .sort((a, b) => a.seq - b.seq);
157
- return { requests: records.slice(0, limit), hasMore: records.length > limit };
249
+ return requestPage(records.map((request) => ({ body: JSON.stringify(this.received(request)) })), limit);
250
+ }
251
+ async unreceivedRequests(roomId, recipientId, after, limit) {
252
+ const records = [...this.requests.values()].map((request) => this.received(request)).filter((request) => request.roomId === roomId && request.to === recipientId && request.seq > after && request.receivedAt === null).sort((a, b) => a.seq - b.seq);
253
+ return requestPage(records.map((request) => ({ body: JSON.stringify(request) })), limit);
254
+ }
255
+ async pendingRequestCount(roomId) {
256
+ return [...this.requests.values()].filter((request) => request.roomId === roomId && request.requiresReply && request.responseEventId === null).length;
257
+ }
258
+ writeReceipts(previous, room) {
259
+ for (const [participantId, mark] of Object.entries(room.receipts ?? {})) {
260
+ if (mark.throughSeq > (previous.receipts?.[participantId]?.throughSeq ?? 0)) {
261
+ const key = `${room.roomId}:${participantId}`;
262
+ const ranges = this.receiptRanges.get(key) ?? [];
263
+ ranges.push({ throughSeq: mark.throughSeq, at: mark.at });
264
+ this.receiptRanges.set(key, ranges);
265
+ }
266
+ }
267
+ }
268
+ receiptsChangeRequests(previous, room) {
269
+ return [...this.requests.values()].some((request) => request.roomId === room.roomId && request.requiresReply && !request.responseEventId && this.received(request).receivedAt === null && (room.receipts?.[request.to]?.throughSeq ?? 0) > (previous.receipts?.[request.to]?.throughSeq ?? 0) && (request.messageSeq ?? 0) <= (room.receipts?.[request.to]?.throughSeq ?? 0));
270
+ }
271
+ received(request) {
272
+ if (request.receivedAt !== null) {
273
+ return request;
274
+ }
275
+ const seq = request.messageSeq ?? this.require(request.roomId).events.find((event) => event.eventId === (request.conversationId ?? request.eventId))?.seq ?? 0;
276
+ const range = this.receiptRanges.get(`${request.roomId}:${request.to}`)?.find((mark) => mark.throughSeq >= seq);
277
+ return range ? { ...request, receivedAt: range.at } : request;
158
278
  }
159
- async setLifecycle(roomId, lifecycle) {
279
+ async setLifecycle(roomId, lifecycle, expectedStateRevision) {
160
280
  const table = this.require(roomId);
161
- table.room = { ...table.room, lifecycle };
281
+ table.room = committedRoom(table.room, { ...table.room, lifecycle, stateRevision: expectedStateRevision ?? table.room.stateRevision ?? 0 }, { snapshot: true });
162
282
  }
163
283
  async deleteRoom(roomId) {
164
284
  const table = this.rooms.get(roomId);
@@ -174,21 +294,30 @@ export class MemoryStore {
174
294
  this.stored.delete(fileId);
175
295
  }
176
296
  }
297
+ for (const [fileId, { file }] of this.uploads) {
298
+ if (file.roomId === roomId) {
299
+ this.uploads.delete(fileId);
300
+ }
301
+ }
177
302
  table.events = [];
178
303
  table.handovers = [];
179
304
  }
180
305
  async dueAutoCloses(now, limit) {
181
- return this.deadlines().filter(([, at]) => at <= now).slice(0, limit).map(([roomId]) => roomId);
306
+ return this.deadlines(now).filter(([, at]) => at <= now).slice(0, limit).map(([roomId]) => roomId);
182
307
  }
183
- async nextAutoCloseAt() {
184
- return this.deadlines()[0]?.[1] ?? null;
308
+ async nextAutoCloseAt(now = Date.now()) {
309
+ return this.deadlines(now)[0]?.[1] ?? null;
185
310
  }
186
- deadlines() {
311
+ deadlines(now) {
187
312
  return [...this.rooms.values()]
188
- .filter((table) => table.room.lifecycle === 'open' && typeof table.room.autoCloseAt === 'number')
313
+ .filter((table) => table.room.lifecycle === 'open' && typeof table.room.autoCloseAt === 'number' && (table.room.expiresAt === null || table.room.expiresAt > now))
189
314
  .map((table) => [table.room.roomId, table.room.autoCloseAt])
190
315
  .sort((left, right) => left[1] - right[1]);
191
316
  }
317
+ bumpRoom(roomId, expectedStateRevision) {
318
+ const table = this.require(roomId);
319
+ table.room = committedRoom(table.room, { ...table.room, stateRevision: expectedStateRevision ?? table.room.stateRevision ?? 0 });
320
+ }
192
321
  /** Simulates retention dropping the front of the log without touching room state. */
193
322
  dropHistoryBefore(roomId, seq) {
194
323
  const table = this.require(roomId);