mindoodb-app-sdk 0.0.14 → 0.0.17

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.
@@ -10,7 +10,9 @@ function createBridgeErrorPayload(error, fallbackCode = "bridge-error") {
10
10
  return { code: fallbackCode, message: String(error) };
11
11
  }
12
12
  function cloneBytes(chunk) {
13
- return new Uint8Array(chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength));
13
+ return new Uint8Array(
14
+ chunk.buffer.slice(chunk.byteOffset, chunk.byteOffset + chunk.byteLength)
15
+ );
14
16
  }
15
17
  function applyDocumentUpdatePatch(current, patch) {
16
18
  const next = {
@@ -20,8 +22,109 @@ function applyDocumentUpdatePatch(current, patch) {
20
22
  for (const key of patch.unset ?? []) {
21
23
  Reflect.deleteProperty(next, key);
22
24
  }
25
+ applyMockJsonPatch(next, patch.json);
26
+ for (const textPatch of patch.text ?? []) {
27
+ applyMockTextPatch(next, textPatch.path, textPatch.edits);
28
+ }
23
29
  return next;
24
30
  }
31
+ function applyMockJsonPatch(target, patch) {
32
+ if (!patch) {
33
+ return;
34
+ }
35
+ for (const operation of patch.set ?? []) {
36
+ setValueAtPath(target, operation.path, structuredClone(operation.value));
37
+ }
38
+ for (const operation of patch.unset ?? []) {
39
+ unsetValueAtPath(target, operation.path);
40
+ }
41
+ for (const operation of patch.listDelete ?? []) {
42
+ const list = readListAtPath(target, operation.path);
43
+ list.splice(operation.index, operation.deleteCount);
44
+ }
45
+ for (const operation of patch.listInsert ?? []) {
46
+ const list = readListAtPath(target, operation.path);
47
+ list.splice(operation.index, 0, ...structuredClone(operation.values));
48
+ }
49
+ }
50
+ function setValueAtPath(target, path, value) {
51
+ if (path.length === 0) {
52
+ throw new Error("JSON set path must contain at least one segment");
53
+ }
54
+ const parent = ensureParentAtPath(target, path);
55
+ parent[path[path.length - 1]] = value;
56
+ }
57
+ function unsetValueAtPath(target, path) {
58
+ if (path.length === 0) {
59
+ throw new Error("JSON unset path must contain at least one segment");
60
+ }
61
+ const parent = readParentAtPath(target, path);
62
+ Reflect.deleteProperty(parent, path[path.length - 1]);
63
+ }
64
+ function readListAtPath(target, path) {
65
+ let value = target;
66
+ for (const segment of path) {
67
+ value = value?.[segment];
68
+ }
69
+ if (!Array.isArray(value)) {
70
+ throw new Error(
71
+ `Cannot apply list operation to non-array value at ${path.map(String).join(".")}`
72
+ );
73
+ }
74
+ return value;
75
+ }
76
+ function ensureParentAtPath(target, path) {
77
+ let parent = target;
78
+ for (let index = 0; index < path.length - 1; index += 1) {
79
+ const segment = path[index];
80
+ const nextSegment = path[index + 1];
81
+ if (parent[segment] == null) {
82
+ parent[segment] = typeof nextSegment === "number" ? [] : {};
83
+ }
84
+ parent = parent[segment];
85
+ }
86
+ return parent;
87
+ }
88
+ function readParentAtPath(target, path) {
89
+ let parent = target;
90
+ for (let index = 0; index < path.length - 1; index += 1) {
91
+ parent = parent?.[path[index]];
92
+ }
93
+ if (parent == null || typeof parent !== "object") {
94
+ throw new Error(
95
+ `Cannot resolve JSON parent at ${path.map(String).join(".")}`
96
+ );
97
+ }
98
+ return parent;
99
+ }
100
+ function applyMockTextPatch(target, path, edits) {
101
+ if (path.length === 0) {
102
+ throw new Error("Text patch path must contain at least one segment");
103
+ }
104
+ let parent = target;
105
+ for (let index = 0; index < path.length - 1; index += 1) {
106
+ const segment = path[index];
107
+ const nextSegment = path[index + 1];
108
+ if (parent[segment] == null) {
109
+ parent[segment] = typeof nextSegment === "number" ? [] : {};
110
+ }
111
+ parent = parent[segment];
112
+ }
113
+ const leaf = path[path.length - 1];
114
+ let value = parent[leaf];
115
+ if (value == null) {
116
+ value = "";
117
+ }
118
+ if (typeof value !== "string") {
119
+ throw new Error(
120
+ `Cannot apply text patch to non-string value at ${path.map(String).join(".")}`
121
+ );
122
+ }
123
+ for (const edit of edits) {
124
+ value = value.slice(0, edit.index) + (edit.insert ?? "") + value.slice(edit.index + edit.deleteCount);
125
+ }
126
+ parent[leaf] = value;
127
+ }
25
128
  function mergeLaunchContext(current, patch) {
26
129
  if (!patch) {
27
130
  return {
@@ -40,7 +143,10 @@ function mergeLaunchContext(current, patch) {
40
143
  sources: view.sources.map((source) => ({ ...source })),
41
144
  columns: view.columns.map((column) => ({
42
145
  ...column,
43
- expression: column.expression.mode === "field" ? { ...column.expression } : { mode: "formula", expression: structuredClone(column.expression.expression) }
146
+ expression: column.expression.mode === "field" ? { ...column.expression } : {
147
+ mode: "formula",
148
+ expression: structuredClone(column.expression.expression)
149
+ }
44
150
  })),
45
151
  filter: view.filter.mode === "rules" ? {
46
152
  mode: "rules",
@@ -73,7 +179,10 @@ function mergeLaunchContext(current, patch) {
73
179
  sources: view.sources.map((source) => ({ ...source })),
74
180
  columns: view.columns.map((column) => ({
75
181
  ...column,
76
- expression: column.expression.mode === "field" ? { ...column.expression } : { mode: "formula", expression: structuredClone(column.expression.expression) }
182
+ expression: column.expression.mode === "field" ? { ...column.expression } : {
183
+ mode: "formula",
184
+ expression: structuredClone(column.expression.expression)
185
+ }
77
186
  })),
78
187
  filter: view.filter.mode === "rules" ? {
79
188
  mode: "rules",
@@ -88,7 +197,10 @@ function mergeLaunchContext(current, patch) {
88
197
  sources: view.sources.map((source) => ({ ...source })),
89
198
  columns: view.columns.map((column) => ({
90
199
  ...column,
91
- expression: column.expression.mode === "field" ? { ...column.expression } : { mode: "formula", expression: structuredClone(column.expression.expression) }
200
+ expression: column.expression.mode === "field" ? { ...column.expression } : {
201
+ mode: "formula",
202
+ expression: structuredClone(column.expression.expression)
203
+ }
92
204
  })),
93
205
  filter: view.filter.mode === "rules" ? {
94
206
  mode: "rules",
@@ -178,7 +290,9 @@ function matchesDocumentFilter(document, filter) {
178
290
  if (!filter) {
179
291
  return true;
180
292
  }
181
- return Object.entries(filter).every(([field, expected]) => getFieldValue(document.data, field) === expected);
293
+ return Object.entries(filter).every(
294
+ ([field, expected]) => getFieldValue(document.data, field) === expected
295
+ );
182
296
  }
183
297
  function decodeMockListCursor(cursor) {
184
298
  if (!cursor) {
@@ -393,6 +507,7 @@ function createDefaultViewNavigator() {
393
507
  }
394
508
  function createDatabaseHandle(definition) {
395
509
  let createCounter = 0;
510
+ let changeCounter = 0;
396
511
  const defaultViewFactory = async () => createDefaultViewNavigator();
397
512
  const storedDocuments = /* @__PURE__ */ new Map();
398
513
  const defaultDocuments = {
@@ -402,7 +517,11 @@ function createDatabaseHandle(definition) {
402
517
  const limit = Math.max(1, query?.limit ?? 50);
403
518
  const offset = decodeMockListCursor(query?.cursor) + skip;
404
519
  const metadataOnly = query?.metadataOnly ?? false;
405
- const items = Array.from(storedDocuments.values()).filter((document) => status === "all" ? true : status === "deleted" ? document.isDeleted : !document.isDeleted).filter((document) => metadataOnly ? true : matchesDocumentFilter(document, query?.filter)).sort((left, right) => left.id.localeCompare(right.id));
520
+ const items = Array.from(storedDocuments.values()).filter(
521
+ (document) => status === "all" ? true : status === "deleted" ? document.isDeleted : !document.isDeleted
522
+ ).filter(
523
+ (document) => metadataOnly ? true : matchesDocumentFilter(document, query?.filter)
524
+ ).sort((left, right) => left.id.localeCompare(right.id));
406
525
  const page = items.slice(offset, offset + limit).map((document) => {
407
526
  if (metadataOnly) {
408
527
  return {
@@ -410,7 +529,12 @@ function createDatabaseHandle(definition) {
410
529
  isDeleted: document.isDeleted
411
530
  };
412
531
  }
413
- const projectedData = query?.fields ? Object.fromEntries(query.fields.map((field) => [field, getFieldValue(document.data, field)])) : document.data;
532
+ const projectedData = query?.fields ? Object.fromEntries(
533
+ query.fields.map((field) => [
534
+ field,
535
+ getFieldValue(document.data, field)
536
+ ])
537
+ ) : document.data;
414
538
  return {
415
539
  id: document.id,
416
540
  data: projectedData,
@@ -438,16 +562,42 @@ function createDatabaseHandle(definition) {
438
562
  return {
439
563
  id: document.id,
440
564
  data: structuredClone(document.data),
565
+ heads: document.heads ? [...document.heads] : void 0,
441
566
  attachments: document.attachments ? structuredClone(document.attachments) : [],
442
567
  updatedAt: document.updatedAt
443
568
  };
444
569
  },
445
570
  async create(input) {
446
- createCounter += 1;
571
+ const callerId = typeof input.id === "string" && input.id.length > 0 ? input.id : null;
572
+ if (callerId) {
573
+ const existing = storedDocuments.get(callerId);
574
+ if (existing) {
575
+ if (existing.isDeleted) {
576
+ existing.isDeleted = false;
577
+ existing.updatedAt = (/* @__PURE__ */ new Date()).toISOString();
578
+ existing.heads = [`mock-head-${++changeCounter}`];
579
+ }
580
+ return {
581
+ id: existing.id,
582
+ data: structuredClone(existing.data),
583
+ heads: existing.heads ? [...existing.heads] : void 0,
584
+ attachments: existing.attachments ? structuredClone(existing.attachments) : [],
585
+ updatedAt: existing.updatedAt
586
+ };
587
+ }
588
+ }
589
+ let id;
590
+ if (callerId) {
591
+ id = callerId;
592
+ } else {
593
+ createCounter += 1;
594
+ id = `doc-${createCounter}`;
595
+ }
447
596
  const createdAt = (/* @__PURE__ */ new Date()).toISOString();
448
597
  const created = {
449
- id: `doc-${createCounter}`,
598
+ id,
450
599
  data: { ...input.set },
600
+ heads: [`mock-head-${++changeCounter}`],
451
601
  attachments: [],
452
602
  updatedAt: createdAt
453
603
  };
@@ -467,6 +617,7 @@ function createDatabaseHandle(definition) {
467
617
  const updated = {
468
618
  id: docId,
469
619
  data: applyDocumentUpdatePatch(existing?.data ?? {}, patch),
620
+ heads: [`mock-head-${++changeCounter}`],
470
621
  attachments: existing?.attachments ? structuredClone(existing.attachments) : [],
471
622
  updatedAt
472
623
  };
@@ -489,6 +640,18 @@ function createDatabaseHandle(definition) {
489
640
  }
490
641
  return { ok: true };
491
642
  },
643
+ async undelete(_docId) {
644
+ const existing = storedDocuments.get(_docId);
645
+ if (existing) {
646
+ storedDocuments.set(_docId, {
647
+ ...existing,
648
+ isDeleted: false,
649
+ heads: [`mock-head-${++changeCounter}`],
650
+ updatedAt: (/* @__PURE__ */ new Date()).toISOString()
651
+ });
652
+ }
653
+ return { ok: true };
654
+ },
492
655
  async listHistory(_docId) {
493
656
  return [];
494
657
  },
@@ -497,7 +660,19 @@ function createDatabaseHandle(definition) {
497
660
  id: docId,
498
661
  timestamp,
499
662
  state: "missing",
500
- data: null
663
+ data: null,
664
+ attachments: []
665
+ };
666
+ },
667
+ async getAtRevision(docId, revisionId) {
668
+ return {
669
+ id: docId,
670
+ revisionId,
671
+ timestamp: Date.now(),
672
+ heads: [],
673
+ state: "missing",
674
+ data: null,
675
+ attachments: []
501
676
  };
502
677
  }
503
678
  };
@@ -510,18 +685,29 @@ function createDatabaseHandle(definition) {
510
685
  }
511
686
  };
512
687
  const defaultAttachments = {
513
- async list(_docId) {
688
+ async list(_docId, _options) {
514
689
  return [];
515
690
  },
516
691
  async remove(_docId, _attachmentName) {
517
692
  return { ok: true };
518
693
  },
519
- async openReadStream(_docId, _attachmentName) {
694
+ async openReadStream(_docId, _attachmentName, _options) {
520
695
  return createDefaultReadableAttachmentStream();
521
696
  },
522
697
  async openWriteStream(_docId, _attachmentName, _contentType) {
523
698
  return createDefaultWritableAttachmentStream();
524
699
  },
700
+ async scan(_docId, options) {
701
+ return {
702
+ ok: true,
703
+ attachment: {
704
+ attachmentId: "scan-attachment-1",
705
+ fileName: options?.defaultFileName ?? "scan.jpg",
706
+ mimeType: options?.mimeType ?? "image/jpeg",
707
+ size: 0
708
+ }
709
+ };
710
+ },
525
711
  async preparePreviewSession(_docId, _attachmentName, _options) {
526
712
  return {
527
713
  sessionId: "preview-session-1",
@@ -535,7 +721,10 @@ function createDatabaseHandle(definition) {
535
721
  const methods = definition.methods ?? {};
536
722
  return {
537
723
  async info() {
538
- return { ...definition.info, capabilities: [...definition.info.capabilities] };
724
+ return {
725
+ ...definition.info,
726
+ capabilities: [...definition.info.capabilities]
727
+ };
539
728
  },
540
729
  documents: {
541
730
  ...defaultDocuments,
@@ -596,7 +785,9 @@ function createMockSessionState(options = {}) {
596
785
  ...definition.methods?.views ?? {}
597
786
  });
598
787
  }
599
- launchContext = mergeLaunchContext(launchContext, { databases: databaseInfos });
788
+ launchContext = mergeLaunchContext(launchContext, {
789
+ databases: databaseInfos
790
+ });
600
791
  };
601
792
  setDatabases(options.databases ?? []);
602
793
  const session = {
@@ -625,11 +816,15 @@ function createMockSessionState(options = {}) {
625
816
  async createViewNavigator(input) {
626
817
  const firstDatabaseId = input.databaseIds[0];
627
818
  if (!firstDatabaseId) {
628
- throw new Error("At least one test database is required for view creation.");
819
+ throw new Error(
820
+ "At least one test database is required for view creation."
821
+ );
629
822
  }
630
823
  const api = databaseViewApis.get(firstDatabaseId);
631
824
  if (!api) {
632
- throw new Error(`Unknown test database for view creation: ${firstDatabaseId}`);
825
+ throw new Error(
826
+ `Unknown test database for view creation: ${firstDatabaseId}`
827
+ );
633
828
  }
634
829
  const view = await api.create(input);
635
830
  const viewId = input.definition.id || crypto.randomUUID();
@@ -641,13 +836,17 @@ function createMockSessionState(options = {}) {
641
836
  if (existing) {
642
837
  return existing;
643
838
  }
644
- const sourceDatabaseId = launchContext.views.find((view2) => view2.id === viewId)?.sources[0]?.databaseId;
839
+ const sourceDatabaseId = launchContext.views.find(
840
+ (view2) => view2.id === viewId
841
+ )?.sources[0]?.databaseId;
645
842
  if (!sourceDatabaseId) {
646
843
  throw new Error(`Unknown test view: ${viewId}`);
647
844
  }
648
845
  const api = databaseViewApis.get(sourceDatabaseId);
649
846
  if (!api) {
650
- throw new Error(`Unknown test database for view ${viewId}: ${sourceDatabaseId}`);
847
+ throw new Error(
848
+ `Unknown test database for view ${viewId}: ${sourceDatabaseId}`
849
+ );
651
850
  }
652
851
  const view = await api.open(viewId, options2);
653
852
  sessionViews.set(viewId, view);
@@ -709,7 +908,9 @@ function createMockSessionState(options = {}) {
709
908
  session,
710
909
  emitThemeChange(theme) {
711
910
  launchContext = mergeLaunchContext(launchContext, { theme });
712
- themeListeners.forEach((listener) => listener({ ...launchContext.theme }));
911
+ themeListeners.forEach(
912
+ (listener) => listener({ ...launchContext.theme })
913
+ );
713
914
  },
714
915
  emitViewportChange(viewport) {
715
916
  launchContext = mergeLaunchContext(launchContext, { viewport });
@@ -717,7 +918,9 @@ function createMockSessionState(options = {}) {
717
918
  },
718
919
  emitUiPreferencesChange(uiPreferences) {
719
920
  launchContext = mergeLaunchContext(launchContext, { uiPreferences });
720
- uiPreferencesListeners.forEach((listener) => listener({ ...launchContext.uiPreferences }));
921
+ uiPreferencesListeners.forEach(
922
+ (listener) => listener({ ...launchContext.uiPreferences })
923
+ );
721
924
  }
722
925
  };
723
926
  }
@@ -740,7 +943,9 @@ function createMockMindooDBAppBridge(options = {}) {
740
943
  }
741
944
  function createFakeBridgeHost(options = {}) {
742
945
  const state = createMockSessionState(options);
743
- const customRequestHandlers = new Map(Object.entries(options.requestHandlers ?? {}));
946
+ const customRequestHandlers = new Map(
947
+ Object.entries(options.requestHandlers ?? {})
948
+ );
744
949
  const requests = [];
745
950
  const connectedPorts = /* @__PURE__ */ new Set();
746
951
  const viewSessions = /* @__PURE__ */ new Map();
@@ -748,7 +953,10 @@ function createFakeBridgeHost(options = {}) {
748
953
  const writeStreams = /* @__PURE__ */ new Map();
749
954
  let viewCounter = 0;
750
955
  let streamCounter = 0;
751
- let previousWindowDescriptor = Object.getOwnPropertyDescriptor(globalThis, "window");
956
+ let previousWindowDescriptor = Object.getOwnPropertyDescriptor(
957
+ globalThis,
958
+ "window"
959
+ );
752
960
  let previousWindowValue = typeof window === "undefined" ? void 0 : window;
753
961
  let installed = false;
754
962
  const hostWindow = {
@@ -762,7 +970,9 @@ function createFakeBridgeHost(options = {}) {
762
970
  }
763
971
  const port = transfer?.[0];
764
972
  if (!port) {
765
- throw new Error("Expected the bridge connection to transfer a MessagePort.");
973
+ throw new Error(
974
+ "Expected the bridge connection to transfer a MessagePort."
975
+ );
766
976
  }
767
977
  connectedPorts.add(port);
768
978
  port.addEventListener("message", (event) => {
@@ -804,7 +1014,10 @@ function createFakeBridgeHost(options = {}) {
804
1014
  if (installed) {
805
1015
  return;
806
1016
  }
807
- previousWindowDescriptor = Object.getOwnPropertyDescriptor(globalThis, "window");
1017
+ previousWindowDescriptor = Object.getOwnPropertyDescriptor(
1018
+ globalThis,
1019
+ "window"
1020
+ );
808
1021
  previousWindowValue = typeof window === "undefined" ? void 0 : window;
809
1022
  const baseWindow = typeof window === "undefined" ? {} : window;
810
1023
  const nextWindow = Object.create(baseWindow);
@@ -894,6 +1107,7 @@ function createFakeBridgeHost(options = {}) {
894
1107
  const navigator = await state.createViewNavigator({
895
1108
  databaseIds: Array.isArray(params.databaseIds) ? params.databaseIds.map((entry) => String(entry)) : [],
896
1109
  definition: params.definition,
1110
+ categorizationStyle: params.categorizationStyle === "category_then_document" ? "category_then_document" : "document_then_category",
897
1111
  options: params.options
898
1112
  });
899
1113
  viewSessions.set(navigatorId, navigator);
@@ -909,7 +1123,9 @@ function createFakeBridgeHost(options = {}) {
909
1123
  return { navigatorId };
910
1124
  }
911
1125
  case "menus.show":
912
- return await state.session.menus.show(request.params);
1126
+ return await state.session.menus.show(
1127
+ request.params
1128
+ );
913
1129
  case "menus.hide":
914
1130
  await state.session.menus.hide();
915
1131
  return { ok: true };
@@ -917,13 +1133,17 @@ function createFakeBridgeHost(options = {}) {
917
1133
  await state.session.disconnect();
918
1134
  return { ok: true };
919
1135
  case "documents.list":
920
- return await state.getDatabase(String(params.databaseId)).documents.list(params.query);
1136
+ return await state.getDatabase(String(params.databaseId)).documents.list(
1137
+ params.query
1138
+ );
921
1139
  case "documents.getHeadCursor":
922
1140
  return await state.getDatabase(String(params.databaseId)).documents.getHeadCursor();
923
1141
  case "documents.get":
924
1142
  return await state.getDatabase(String(params.databaseId)).documents.get(String(params.docId));
925
1143
  case "documents.create":
926
- return await state.getDatabase(String(params.databaseId)).documents.create(params.input);
1144
+ return await state.getDatabase(String(params.databaseId)).documents.create(
1145
+ params.input
1146
+ );
927
1147
  case "documents.update":
928
1148
  return await state.getDatabase(String(params.databaseId)).documents.update(
929
1149
  String(params.docId),
@@ -931,6 +1151,8 @@ function createFakeBridgeHost(options = {}) {
931
1151
  );
932
1152
  case "documents.delete":
933
1153
  return await state.getDatabase(String(params.databaseId)).documents.delete(String(params.docId));
1154
+ case "documents.undelete":
1155
+ return await state.getDatabase(String(params.databaseId)).documents.undelete(String(params.docId));
934
1156
  case "documents.history.list":
935
1157
  return await state.getDatabase(String(params.databaseId)).documents.listHistory(String(params.docId));
936
1158
  case "documents.history.getAtTimestamp":
@@ -938,8 +1160,16 @@ function createFakeBridgeHost(options = {}) {
938
1160
  String(params.docId),
939
1161
  Number(params.timestamp)
940
1162
  );
1163
+ case "documents.history.getAtRevision":
1164
+ return await state.getDatabase(String(params.databaseId)).documents.getAtRevision(
1165
+ String(params.docId),
1166
+ String(params.revisionId)
1167
+ );
941
1168
  case "attachments.list":
942
- return await state.getDatabase(String(params.databaseId)).attachments.list(String(params.docId));
1169
+ return await state.getDatabase(String(params.databaseId)).attachments.list(
1170
+ String(params.docId),
1171
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1172
+ );
943
1173
  case "attachments.remove":
944
1174
  return await state.getDatabase(String(params.databaseId)).attachments.remove(
945
1175
  String(params.docId),
@@ -948,7 +1178,8 @@ function createFakeBridgeHost(options = {}) {
948
1178
  case "attachments.openReadStream": {
949
1179
  const stream = await state.getDatabase(String(params.databaseId)).attachments.openReadStream(
950
1180
  String(params.docId),
951
- String(params.attachmentName)
1181
+ String(params.attachmentName),
1182
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
952
1183
  );
953
1184
  const streamId = `read-${streamCounter += 1}`;
954
1185
  readStreams.set(streamId, stream);
@@ -964,17 +1195,23 @@ function createFakeBridgeHost(options = {}) {
964
1195
  writeStreams.set(streamId, stream);
965
1196
  return { streamId };
966
1197
  }
1198
+ case "attachments.scanAndWrite":
1199
+ return await state.getDatabase(String(params.databaseId)).attachments.scan(String(params.docId), {
1200
+ defaultFileName: typeof params.defaultFileName === "string" ? params.defaultFileName : void 0,
1201
+ preset: typeof params.preset === "string" ? params.preset : void 0,
1202
+ mimeType: params.mimeType === "image/png" || params.mimeType === "image/jpeg" || params.mimeType === "application/pdf" ? params.mimeType : void 0
1203
+ });
967
1204
  case "attachments.openPreview":
968
1205
  return await state.getDatabase(String(params.databaseId)).attachments.openPreview(
969
1206
  String(params.docId),
970
1207
  String(params.attachmentName),
971
- typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1208
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
972
1209
  );
973
1210
  case "attachments.preparePreviewSession":
974
1211
  return await state.getDatabase(String(params.databaseId)).attachments.preparePreviewSession(
975
1212
  String(params.docId),
976
1213
  String(params.attachmentName),
977
- typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
1214
+ typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
978
1215
  );
979
1216
  case "viewNavigators.getDefinition":
980
1217
  return await (await resolveViewNavigator(String(params.navigatorId))).getDefinition();
@@ -1112,7 +1349,10 @@ function createFakeBridgeHost(options = {}) {
1112
1349
  if (message.kind === "stream-read") {
1113
1350
  const stream = readStreams.get(message.streamId);
1114
1351
  if (!stream) {
1115
- throw Object.assign(new Error(`Unknown read stream: ${message.streamId}`), { name: "stream-not-found" });
1352
+ throw Object.assign(
1353
+ new Error(`Unknown read stream: ${message.streamId}`),
1354
+ { name: "stream-not-found" }
1355
+ );
1116
1356
  }
1117
1357
  const chunk = await stream.read();
1118
1358
  port.postMessage({
@@ -1130,7 +1370,10 @@ function createFakeBridgeHost(options = {}) {
1130
1370
  if (message.kind === "stream-write") {
1131
1371
  const stream = writeStreams.get(message.streamId);
1132
1372
  if (!stream) {
1133
- throw Object.assign(new Error(`Unknown write stream: ${message.streamId}`), { name: "stream-not-found" });
1373
+ throw Object.assign(
1374
+ new Error(`Unknown write stream: ${message.streamId}`),
1375
+ { name: "stream-not-found" }
1376
+ );
1134
1377
  }
1135
1378
  await stream.write(new Uint8Array(message.chunk));
1136
1379
  postStreamAck(port, message.streamId);
@@ -1151,12 +1394,17 @@ function createFakeBridgeHost(options = {}) {
1151
1394
  postStreamAck(port, message.streamId);
1152
1395
  return true;
1153
1396
  }
1154
- throw Object.assign(new Error(`Unknown stream: ${message.streamId}`), { name: "stream-not-found" });
1397
+ throw Object.assign(new Error(`Unknown stream: ${message.streamId}`), {
1398
+ name: "stream-not-found"
1399
+ });
1155
1400
  }
1156
1401
  if (message.kind === "stream-abort") {
1157
1402
  const stream = writeStreams.get(message.streamId);
1158
1403
  if (!stream) {
1159
- throw Object.assign(new Error(`Unknown write stream: ${message.streamId}`), { name: "stream-not-found" });
1404
+ throw Object.assign(
1405
+ new Error(`Unknown write stream: ${message.streamId}`),
1406
+ { name: "stream-not-found" }
1407
+ );
1160
1408
  }
1161
1409
  await stream.abort();
1162
1410
  writeStreams.delete(message.streamId);
@@ -1175,7 +1423,11 @@ function createFakeBridgeHost(options = {}) {
1175
1423
  try {
1176
1424
  const customHandler = customRequestHandlers.get(message.method);
1177
1425
  if (customHandler) {
1178
- const result = await customHandler(message.params, { host: controller, request: message, port });
1426
+ const result = await customHandler(message.params, {
1427
+ host: controller,
1428
+ request: message,
1429
+ port
1430
+ });
1179
1431
  postRpcSuccess(port, message.id, result);
1180
1432
  return;
1181
1433
  }
@@ -1194,15 +1446,23 @@ function createFakeBridgeHost(options = {}) {
1194
1446
  return;
1195
1447
  }
1196
1448
  try {
1197
- const handledByCustom = await options.onPortMessage?.(message, { host: controller, port });
1449
+ const handledByCustom = await options.onPortMessage?.(message, {
1450
+ host: controller,
1451
+ port
1452
+ });
1198
1453
  if (handledByCustom) {
1199
1454
  return;
1200
1455
  }
1201
1456
  const handled = await handleStreamMessage(port, message);
1202
1457
  if (!handled) {
1203
- throw Object.assign(new Error(`No fake bridge port handler is configured for ${message.kind}.`), {
1204
- name: "unsupported-message"
1205
- });
1458
+ throw Object.assign(
1459
+ new Error(
1460
+ `No fake bridge port handler is configured for ${message.kind}.`
1461
+ ),
1462
+ {
1463
+ name: "unsupported-message"
1464
+ }
1465
+ );
1206
1466
  }
1207
1467
  } catch (error) {
1208
1468
  const streamId = "streamId" in message ? String(message.streamId) : "unknown";