mindoodb-app-sdk 0.0.59 → 0.0.61
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/README.md +68 -0
- package/dist/{chunk-SKPP4T6S.js → chunk-U4NXI7EH.js} +932 -0
- package/dist/index.d.ts +2 -2
- package/dist/index.js +23 -510
- package/dist/testing/index.d.ts +44 -2
- package/dist/testing/index.js +307 -6
- package/dist/{types-DkzIJKBw.d.ts → types-BKN_Zh_l.d.ts} +223 -2
- package/package.json +3 -3
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,7 +1,24 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ax as MindooDBAppComponentInfo, bo as MindooDBAppEmbedRect, aT as MindooDBAppCreateViewNavigatorInput, dc as MindooDBAppViewNavigator, ac as MindooDBAppBridgeRpcRequest, bA as MindooDBAppHostTheme, au as MindooDBAppCapability, j as MindooDBAppDefinition, J as MindooDBAppAttachmentApi, e as MindooDBAppBridge, cO as MindooDBAppSession, ce as MindooDBAppProposeAppInput, dk as MindooDBAppViewport, d6 as MindooDBAppUiPreferences, ck as MindooDBAppQueryResult, dj as MindooDBAppViewUpdateStats, a8 as MindooDBAppBridgePortMessage, aU as MindooDBAppDatabaseInfo, bk as MindooDBAppEmbedCloseReason, a3 as MindooDBAppBridgeErrorPayload, bV as MindooDBAppLaunchContext, b1 as MindooDBAppDocumentApi, de as MindooDBAppViewNavigatorOpenOptions, bB as MindooDBAppIdentityApi, d2 as MindooDBAppTimestampApi, a$ as MindooDBAppDirectoryApi, l as MindooDBAppDocument, bx as MindooDBAppFulltextSetup, bw as MindooDBAppExtractionSetup, cW as MindooDBAppSummarySetup, cf as MindooDBAppProposeAppResult, bL as MindooDBAppIncomingSource, c as MindooDBAppDragStartResult, bi as MindooDBAppDragProfile, bK as MindooDBAppIncomingResult } from '../types-BKN_Zh_l.js';
|
|
2
2
|
import * as mindoodb from 'mindoodb';
|
|
3
3
|
import 'mindoodb-view-language';
|
|
4
4
|
|
|
5
|
+
/** An embed the mock host currently shows, as tests and the test host page see it. */
|
|
6
|
+
interface MockEmbedState {
|
|
7
|
+
embedId: string;
|
|
8
|
+
component: MindooDBAppComponentInfo;
|
|
9
|
+
databaseId: string;
|
|
10
|
+
docId: string;
|
|
11
|
+
intent: "edit" | "view";
|
|
12
|
+
rect: MindooDBAppEmbedRect;
|
|
13
|
+
visible: boolean;
|
|
14
|
+
}
|
|
15
|
+
/** How an app running as an embedded component finished (`session.embedding`). */
|
|
16
|
+
interface MockEmbeddingFinish {
|
|
17
|
+
reason: "completed" | "cancelled";
|
|
18
|
+
result?: unknown;
|
|
19
|
+
message?: string;
|
|
20
|
+
}
|
|
21
|
+
|
|
5
22
|
type EvaluatingViewDocument = {
|
|
6
23
|
origin: string;
|
|
7
24
|
docId: string;
|
|
@@ -321,6 +338,16 @@ interface CreateMockMindooDBAppSessionOptions {
|
|
|
321
338
|
* `methods.directory` still wins.
|
|
322
339
|
*/
|
|
323
340
|
directoryUsers?: readonly string[];
|
|
341
|
+
/** What `session.components.list` offers; see `closeEmbed` on the controller. */
|
|
342
|
+
components?: MindooDBAppComponentInfo[];
|
|
343
|
+
/** Called whenever the app opens, moves or closes an embed. */
|
|
344
|
+
onEmbedChange?: (embeds: readonly MockEmbedState[]) => void;
|
|
345
|
+
/**
|
|
346
|
+
* Answer `embeds.open` with a `container` like a current Haven: with this page
|
|
347
|
+
* for the SDK to frame (e.g. `about:blank`). Without it the host behaves like an
|
|
348
|
+
* older Haven and the component is laid over the container.
|
|
349
|
+
*/
|
|
350
|
+
embedFrameUrl?: string;
|
|
324
351
|
}
|
|
325
352
|
/**
|
|
326
353
|
* Test usernames in Haven's canonical form: `CN=Test User 001/O=Test`, …
|
|
@@ -366,7 +393,16 @@ interface MockMindooDBAppSessionController {
|
|
|
366
393
|
* and resolves with the handler's result.
|
|
367
394
|
*/
|
|
368
395
|
emitIncomingContent(input: MockIncomingContentInput): Promise<MindooDBAppIncomingResult>;
|
|
396
|
+
/** Embeds the app has open (`session.embeds.open`). */
|
|
397
|
+
listEmbeds(): MockEmbedState[];
|
|
398
|
+
/** Closes an embed as Haven does when the component finishes or the user closes it. */
|
|
399
|
+
closeEmbed(embedId: string, reason?: MindooDBAppEmbedCloseReason, result?: unknown): void;
|
|
400
|
+
/** Replaces what `session.components.list` offers. */
|
|
401
|
+
setComponents(components: MindooDBAppComponentInfo[]): void;
|
|
402
|
+
/** For an app under test that runs as a component: its `session.embedding` call. */
|
|
403
|
+
getEmbeddingFinish(): MockEmbeddingFinish | null;
|
|
369
404
|
}
|
|
405
|
+
|
|
370
406
|
/** Content for `emitIncomingContent`. */
|
|
371
407
|
interface MockIncomingContentInput {
|
|
372
408
|
acceptId?: string;
|
|
@@ -456,7 +492,13 @@ interface FakeBridgeHostController {
|
|
|
456
492
|
/** See {@link CreateMockMindooDBAppSessionOptions.directoryUsers}. */
|
|
457
493
|
setDirectoryUsers(users: readonly string[]): void;
|
|
458
494
|
getDirectoryUsers(): string[];
|
|
495
|
+
/** Embeds the app has open (`session.embeds.open`). */
|
|
496
|
+
listEmbeds(): MockEmbedState[];
|
|
497
|
+
/** Closes an embed and pushes the `embed-event` to the app. */
|
|
498
|
+
closeEmbed(embedId: string, reason?: MindooDBAppEmbedCloseReason, result?: unknown): void;
|
|
499
|
+
/** For an app under test that runs as a component: its `session.embedding` call. */
|
|
500
|
+
getEmbeddingFinish(): MockEmbeddingFinish | null;
|
|
459
501
|
}
|
|
460
502
|
declare function createFakeBridgeHost(options?: CreateFakeBridgeHostOptions): FakeBridgeHostController;
|
|
461
503
|
|
|
462
|
-
export { ALL_CAPABILITIES, type BrowserTestHost, type BrowserTestHostLog, type BrowserTestHostScan, type BrowserTestHostScanMode, type CreateBrowserTestHostOptions, type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type EvaluatingViewDocument, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type FakeBridgeRpcResponse, type MockDatabaseOverride, type MockDatabasesFromDefinitionOptions, MockForbiddenError, type MockIncomingContentInput, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, type MockSealedChannelOptions, type MockSeedDocument, type MountHavenTestHostOptions, TEST_HOST_LOCALES, type TestHostUrlSettings, capabilitiesForDefinitionPermissions, createBrowserTestHost, createEvaluatingViewNavigator, createFakeBridgeHost, createMemoryAttachments, createMockMindooDBAppBridge, createMockMindooDBAppSession, generateDirectoryUsers, loadMindoodbForTesting, mockDatabasesFromDefinition, mountHavenTestHost, previewJson, readTestHostUrlSettings };
|
|
504
|
+
export { ALL_CAPABILITIES, type BrowserTestHost, type BrowserTestHostLog, type BrowserTestHostScan, type BrowserTestHostScanMode, type CreateBrowserTestHostOptions, type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type EvaluatingViewDocument, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type FakeBridgeRpcResponse, type MockDatabaseOverride, type MockDatabasesFromDefinitionOptions, type MockEmbedState, type MockEmbeddingFinish, MockForbiddenError, type MockIncomingContentInput, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, type MockSealedChannelOptions, type MockSeedDocument, type MountHavenTestHostOptions, TEST_HOST_LOCALES, type TestHostUrlSettings, capabilitiesForDefinitionPermissions, createBrowserTestHost, createEvaluatingViewNavigator, createFakeBridgeHost, createMemoryAttachments, createMockMindooDBAppBridge, createMockMindooDBAppSession, generateDirectoryUsers, loadMindoodbForTesting, mockDatabasesFromDefinition, mountHavenTestHost, previewJson, readTestHostUrlSettings };
|
package/dist/testing/index.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
MINDOODB_APP_VALUE_TAG,
|
|
3
3
|
assertValidMindooDBCreateIds,
|
|
4
|
+
mindooDBAppComponentFieldsMatch,
|
|
4
5
|
pageUsers,
|
|
5
6
|
releaseMindooDBAppBridgeSessions
|
|
6
|
-
} from "../chunk-
|
|
7
|
+
} from "../chunk-U4NXI7EH.js";
|
|
7
8
|
|
|
8
9
|
// src/testing/index.ts
|
|
9
10
|
import * as Automerge from "@automerge/automerge";
|
|
@@ -456,6 +457,181 @@ async function createEvaluatingViewNavigator(input, documents) {
|
|
|
456
457
|
return wrapNavigator(input.definition, navigator);
|
|
457
458
|
}
|
|
458
459
|
|
|
460
|
+
// src/testing/mockEmbeds.ts
|
|
461
|
+
function createMockEmbedHost(options, getDatabase) {
|
|
462
|
+
let components = [...options.components ?? []];
|
|
463
|
+
const embeds = /* @__PURE__ */ new Map();
|
|
464
|
+
const handles = /* @__PURE__ */ new Map();
|
|
465
|
+
const closedListeners = /* @__PURE__ */ new Set();
|
|
466
|
+
let embedCounter = 0;
|
|
467
|
+
let embeddingFinish = null;
|
|
468
|
+
function notifyChange() {
|
|
469
|
+
options.onEmbedChange?.([...embeds.values()].map((entry) => ({ ...entry, rect: { ...entry.rect } })));
|
|
470
|
+
}
|
|
471
|
+
function mockRect(input) {
|
|
472
|
+
if (input.rect) {
|
|
473
|
+
return { ...input.rect };
|
|
474
|
+
}
|
|
475
|
+
const bounds = input.container?.getBoundingClientRect();
|
|
476
|
+
return { left: bounds?.left ?? 0, top: bounds?.top ?? 0, width: bounds?.width ?? 0, height: bounds?.height ?? 0 };
|
|
477
|
+
}
|
|
478
|
+
async function openEmbed(input) {
|
|
479
|
+
const component = components.find((entry) => entry.key === input.componentKey);
|
|
480
|
+
if (!component) {
|
|
481
|
+
throw new Error(`Unknown component "${input.componentKey}".`);
|
|
482
|
+
}
|
|
483
|
+
const intent = input.intent ?? "edit";
|
|
484
|
+
if (!component.intents.includes(intent) && !(intent === "edit" && component.intents.includes("create"))) {
|
|
485
|
+
throw new Error(`Component "${component.label}" does not support "${intent}".`);
|
|
486
|
+
}
|
|
487
|
+
const document2 = await getDatabase(input.databaseId).documents.get(input.docId);
|
|
488
|
+
if (!document2) {
|
|
489
|
+
throw new Error(`Document ${input.docId} does not exist.`);
|
|
490
|
+
}
|
|
491
|
+
if (!mindooDBAppComponentFieldsMatch(component.match, document2.data)) {
|
|
492
|
+
throw new Error(`Document ${input.docId} is not a "${component.label}" document.`);
|
|
493
|
+
}
|
|
494
|
+
embedCounter += 1;
|
|
495
|
+
const embedId = `mock-embed-${embedCounter}`;
|
|
496
|
+
embeds.set(embedId, {
|
|
497
|
+
embedId,
|
|
498
|
+
component,
|
|
499
|
+
databaseId: input.databaseId,
|
|
500
|
+
docId: input.docId,
|
|
501
|
+
intent,
|
|
502
|
+
rect: mockRect(input),
|
|
503
|
+
visible: input.visible !== false
|
|
504
|
+
});
|
|
505
|
+
notifyChange();
|
|
506
|
+
return embedId;
|
|
507
|
+
}
|
|
508
|
+
function closeEmbed(embedId, reason = "closed", result) {
|
|
509
|
+
if (!embeds.delete(embedId)) {
|
|
510
|
+
return;
|
|
511
|
+
}
|
|
512
|
+
const event = {
|
|
513
|
+
embedId,
|
|
514
|
+
reason,
|
|
515
|
+
...result === void 0 ? {} : { result: JSON.parse(JSON.stringify(result)) }
|
|
516
|
+
};
|
|
517
|
+
handles.get(embedId)?.settle(event);
|
|
518
|
+
handles.delete(embedId);
|
|
519
|
+
closedListeners.forEach((listener) => listener(event));
|
|
520
|
+
notifyChange();
|
|
521
|
+
}
|
|
522
|
+
class MockEmbed {
|
|
523
|
+
constructor(embedId, componentKey, databaseId, docId) {
|
|
524
|
+
this.embedId = embedId;
|
|
525
|
+
this.componentKey = componentKey;
|
|
526
|
+
this.databaseId = databaseId;
|
|
527
|
+
this.docId = docId;
|
|
528
|
+
this.closed = new Promise((resolve) => {
|
|
529
|
+
this.resolve = resolve;
|
|
530
|
+
});
|
|
531
|
+
}
|
|
532
|
+
embedId;
|
|
533
|
+
componentKey;
|
|
534
|
+
databaseId;
|
|
535
|
+
docId;
|
|
536
|
+
placement = "overlay";
|
|
537
|
+
frame = null;
|
|
538
|
+
closed;
|
|
539
|
+
resolve;
|
|
540
|
+
listeners = /* @__PURE__ */ new Set();
|
|
541
|
+
settled = null;
|
|
542
|
+
async setRect(rect) {
|
|
543
|
+
setRect(this.embedId, rect);
|
|
544
|
+
}
|
|
545
|
+
async setVisible(visible) {
|
|
546
|
+
setVisible(this.embedId, visible);
|
|
547
|
+
}
|
|
548
|
+
async close() {
|
|
549
|
+
closeEmbed(this.embedId, "closed");
|
|
550
|
+
return await this.closed;
|
|
551
|
+
}
|
|
552
|
+
onClosed(listener) {
|
|
553
|
+
if (this.settled) {
|
|
554
|
+
const event = this.settled;
|
|
555
|
+
queueMicrotask(() => listener(event));
|
|
556
|
+
return () => {
|
|
557
|
+
};
|
|
558
|
+
}
|
|
559
|
+
this.listeners.add(listener);
|
|
560
|
+
return () => {
|
|
561
|
+
this.listeners.delete(listener);
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
settle(event) {
|
|
565
|
+
this.settled = event;
|
|
566
|
+
this.resolve(event);
|
|
567
|
+
this.listeners.forEach((listener) => listener(event));
|
|
568
|
+
this.listeners.clear();
|
|
569
|
+
}
|
|
570
|
+
}
|
|
571
|
+
function setRect(embedId, rect) {
|
|
572
|
+
const entry = embeds.get(embedId);
|
|
573
|
+
if (entry) {
|
|
574
|
+
entry.rect = { ...rect };
|
|
575
|
+
notifyChange();
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
function setVisible(embedId, visible) {
|
|
579
|
+
const entry = embeds.get(embedId);
|
|
580
|
+
if (entry) {
|
|
581
|
+
entry.visible = visible;
|
|
582
|
+
notifyChange();
|
|
583
|
+
}
|
|
584
|
+
}
|
|
585
|
+
return {
|
|
586
|
+
components: {
|
|
587
|
+
async list(query) {
|
|
588
|
+
return components.filter((entry) => !query?.intent || entry.intents.includes(query.intent)).filter((entry) => !query?.document || mindooDBAppComponentFieldsMatch(entry.match, query.document)).map((entry) => structuredClone(entry));
|
|
589
|
+
}
|
|
590
|
+
},
|
|
591
|
+
embeds: {
|
|
592
|
+
async open(input) {
|
|
593
|
+
const embedId = await openEmbed(input);
|
|
594
|
+
const handle = new MockEmbed(embedId, input.componentKey, input.databaseId, input.docId);
|
|
595
|
+
handles.set(embedId, handle);
|
|
596
|
+
return handle;
|
|
597
|
+
}
|
|
598
|
+
},
|
|
599
|
+
embedding: {
|
|
600
|
+
async complete(result) {
|
|
601
|
+
embeddingFinish = {
|
|
602
|
+
reason: "completed",
|
|
603
|
+
...result === void 0 ? {} : { result: JSON.parse(JSON.stringify(result)) }
|
|
604
|
+
};
|
|
605
|
+
},
|
|
606
|
+
async cancel(message) {
|
|
607
|
+
embeddingFinish = { reason: "cancelled", ...message ? { message } : {} };
|
|
608
|
+
}
|
|
609
|
+
},
|
|
610
|
+
openEmbed,
|
|
611
|
+
setRect,
|
|
612
|
+
setVisible,
|
|
613
|
+
closeEmbed,
|
|
614
|
+
listEmbeds() {
|
|
615
|
+
return [...embeds.values()].map((entry) => ({ ...entry, rect: { ...entry.rect } }));
|
|
616
|
+
},
|
|
617
|
+
setComponents(next) {
|
|
618
|
+
components = [...next];
|
|
619
|
+
},
|
|
620
|
+
getEmbeddingFinish() {
|
|
621
|
+
return embeddingFinish;
|
|
622
|
+
},
|
|
623
|
+
finishEmbedding(finish) {
|
|
624
|
+
embeddingFinish = finish;
|
|
625
|
+
},
|
|
626
|
+
onClosed(listener) {
|
|
627
|
+
closedListeners.add(listener);
|
|
628
|
+
return () => {
|
|
629
|
+
closedListeners.delete(listener);
|
|
630
|
+
};
|
|
631
|
+
}
|
|
632
|
+
};
|
|
633
|
+
}
|
|
634
|
+
|
|
459
635
|
// src/testing/capabilityGuard.ts
|
|
460
636
|
var NONE = [];
|
|
461
637
|
var READ = ["read"];
|
|
@@ -921,6 +1097,10 @@ var STYLE = `
|
|
|
921
1097
|
.htest{display:grid;grid-template-columns:minmax(0,1fr) 320px;height:100vh;margin:0;font:13px/1.45 system-ui,sans-serif;background:#eef1f7;color:#172033}
|
|
922
1098
|
.htest *{box-sizing:border-box}
|
|
923
1099
|
.htest__frame{width:100%;height:100%;border:0;background:#fff}
|
|
1100
|
+
.htest__stage{position:relative;min-width:0;height:100%;overflow:hidden}
|
|
1101
|
+
.htest__embed{position:absolute;display:flex;flex-direction:column;gap:8px;align-items:center;justify-content:center;border:2px dashed #6366f1;background:rgba(238,242,255,.94);color:#312e81;text-align:center;padding:12px;overflow:hidden}
|
|
1102
|
+
.htest__embed[hidden]{display:none}
|
|
1103
|
+
.htest__embed strong{font-size:14px}
|
|
924
1104
|
.htest__panel{border-left:1px solid #d7dce8;overflow:auto;padding:14px;background:#f8f9fc}
|
|
925
1105
|
.htest__badge{display:inline-block;padding:2px 8px;border-radius:999px;background:#fde68a;color:#713f12;font-weight:600;font-size:11px;letter-spacing:.04em}
|
|
926
1106
|
.htest h1{font-size:15px;margin:8px 0 12px}
|
|
@@ -1006,8 +1186,36 @@ function mountHavenTestHost(options) {
|
|
|
1006
1186
|
frame.dataset.testid = "haven-test-app-frame";
|
|
1007
1187
|
const panel = document.createElement("aside");
|
|
1008
1188
|
panel.className = "htest__panel";
|
|
1009
|
-
|
|
1189
|
+
const stage = document.createElement("div");
|
|
1190
|
+
stage.className = "htest__stage";
|
|
1191
|
+
const embedLayer = document.createElement("div");
|
|
1192
|
+
stage.append(frame, embedLayer);
|
|
1193
|
+
root.append(stage, panel);
|
|
1010
1194
|
container.replaceChildren(root);
|
|
1195
|
+
function renderEmbeds(embeds) {
|
|
1196
|
+
embedLayer.replaceChildren(
|
|
1197
|
+
...embeds.map((embed) => {
|
|
1198
|
+
const box = document.createElement("div");
|
|
1199
|
+
box.className = "htest__embed";
|
|
1200
|
+
box.dataset.testid = `haven-test-embed-${embed.embedId}`;
|
|
1201
|
+
box.hidden = !embed.visible;
|
|
1202
|
+
box.style.left = `${embed.rect.left}px`;
|
|
1203
|
+
box.style.top = `${embed.rect.top}px`;
|
|
1204
|
+
box.style.width = `${embed.rect.width}px`;
|
|
1205
|
+
box.style.height = `${embed.rect.height}px`;
|
|
1206
|
+
const name = document.createElement("strong");
|
|
1207
|
+
name.textContent = `${embed.component.appLabel}: ${embed.component.label}`;
|
|
1208
|
+
const row = document.createElement("div");
|
|
1209
|
+
row.className = "htest__row";
|
|
1210
|
+
row.append(
|
|
1211
|
+
button("Done", () => testHost.host.closeEmbed(embed.embedId, "completed", { saved: true })),
|
|
1212
|
+
button("Cancel", () => testHost.host.closeEmbed(embed.embedId, "cancelled"))
|
|
1213
|
+
);
|
|
1214
|
+
box.append(name, hint(`${embed.intent} \xB7 ${embed.databaseId}/${embed.docId}`), row);
|
|
1215
|
+
return box;
|
|
1216
|
+
})
|
|
1217
|
+
);
|
|
1218
|
+
}
|
|
1011
1219
|
if (container === document.body) {
|
|
1012
1220
|
document.body.style.margin = "0";
|
|
1013
1221
|
}
|
|
@@ -1149,7 +1357,11 @@ function mountHavenTestHost(options) {
|
|
|
1149
1357
|
enforceCapabilities: url.enforceCapabilities ?? hostOptions.enforceCapabilities,
|
|
1150
1358
|
directoryUsers: url.directoryUserCount !== void 0 ? generateDirectoryUsers(url.directoryUserCount) : hostOptions.directoryUsers,
|
|
1151
1359
|
frame,
|
|
1152
|
-
onChange: render
|
|
1360
|
+
onChange: render,
|
|
1361
|
+
onEmbedChange(embeds) {
|
|
1362
|
+
hostOptions.onEmbedChange?.(embeds);
|
|
1363
|
+
renderEmbeds(embeds);
|
|
1364
|
+
}
|
|
1153
1365
|
});
|
|
1154
1366
|
let currentLocale = url.locale;
|
|
1155
1367
|
const badge = document.createElement("span");
|
|
@@ -2008,6 +2220,23 @@ function extractMockSummaryFields(data, setup) {
|
|
|
2008
2220
|
});
|
|
2009
2221
|
}
|
|
2010
2222
|
}
|
|
2223
|
+
if ((setup?.includeRecipients ?? true) && !isExcluded("_encryptFor")) {
|
|
2224
|
+
const encryptFor = data._encryptFor;
|
|
2225
|
+
if (encryptFor && typeof encryptFor === "object" && !Array.isArray(encryptFor)) {
|
|
2226
|
+
const projected = {};
|
|
2227
|
+
for (const [id, entry] of Object.entries(encryptFor)) {
|
|
2228
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) continue;
|
|
2229
|
+
const raw = entry;
|
|
2230
|
+
const info = { kind: raw.kind === "device" ? "device" : "user" };
|
|
2231
|
+
if (typeof raw.label === "string") info.label = raw.label;
|
|
2232
|
+
for (const key of ["addedAt", "removedAt"]) {
|
|
2233
|
+
if (typeof raw[key] === "number" && Number.isFinite(raw[key])) info[key] = raw[key];
|
|
2234
|
+
}
|
|
2235
|
+
projected[id] = info;
|
|
2236
|
+
}
|
|
2237
|
+
if (Object.keys(projected).length > 0) fields._encryptFor = projected;
|
|
2238
|
+
}
|
|
2239
|
+
}
|
|
2011
2240
|
return fields;
|
|
2012
2241
|
}
|
|
2013
2242
|
function mockSummaryDocument(data, setup) {
|
|
@@ -3289,6 +3518,13 @@ function createDatabaseHandle(definition, peers, directoryUsers = () => []) {
|
|
|
3289
3518
|
}
|
|
3290
3519
|
function createMockSessionState(options = {}) {
|
|
3291
3520
|
let launchContext = createDefaultLaunchContext(options.launchContext);
|
|
3521
|
+
const embedHost = createMockEmbedHost(options, (databaseId) => {
|
|
3522
|
+
const database = databaseHandles.get(databaseId);
|
|
3523
|
+
if (!database) {
|
|
3524
|
+
throw new Error(`Unknown test database: ${databaseId}`);
|
|
3525
|
+
}
|
|
3526
|
+
return database;
|
|
3527
|
+
});
|
|
3292
3528
|
const themeListeners = /* @__PURE__ */ new Set();
|
|
3293
3529
|
let incomingHandler = null;
|
|
3294
3530
|
const pendingIncoming = [];
|
|
@@ -3561,6 +3797,9 @@ function createMockSessionState(options = {}) {
|
|
|
3561
3797
|
},
|
|
3562
3798
|
menus,
|
|
3563
3799
|
drag,
|
|
3800
|
+
components: embedHost.components,
|
|
3801
|
+
embeds: embedHost.embeds,
|
|
3802
|
+
embedding: embedHost.embedding,
|
|
3564
3803
|
storage: {
|
|
3565
3804
|
async snapshot(snapshotOptions) {
|
|
3566
3805
|
const prefixes = snapshotOptions?.prefixes;
|
|
@@ -3683,6 +3922,7 @@ function createMockSessionState(options = {}) {
|
|
|
3683
3922
|
directoryUsers = [...users];
|
|
3684
3923
|
},
|
|
3685
3924
|
getDirectoryUsers: () => [...directoryUsers],
|
|
3925
|
+
embedHost,
|
|
3686
3926
|
getDatabase(databaseId) {
|
|
3687
3927
|
const database = databaseHandles.get(databaseId);
|
|
3688
3928
|
if (!database) {
|
|
@@ -3816,12 +4056,17 @@ function createMockMindooDBAppSession(options = {}) {
|
|
|
3816
4056
|
},
|
|
3817
4057
|
resolveDrag: state.resolveDrag,
|
|
3818
4058
|
getDragProfile: state.getDragProfile,
|
|
3819
|
-
emitIncomingContent: state.emitIncomingContent
|
|
4059
|
+
emitIncomingContent: state.emitIncomingContent,
|
|
4060
|
+
listEmbeds: () => state.embedHost.listEmbeds(),
|
|
4061
|
+
closeEmbed: (embedId, reason, result) => state.embedHost.closeEmbed(embedId, reason, result),
|
|
4062
|
+
setComponents: (components) => state.embedHost.setComponents(components),
|
|
4063
|
+
getEmbeddingFinish: () => state.embedHost.getEmbeddingFinish()
|
|
3820
4064
|
};
|
|
3821
4065
|
}
|
|
3822
4066
|
function createMockMindooDBAppBridge(options = {}) {
|
|
3823
4067
|
return createMockMindooDBAppSession(options);
|
|
3824
4068
|
}
|
|
4069
|
+
var NOT_HANDLED = /* @__PURE__ */ Symbol("not-handled");
|
|
3825
4070
|
function createFakeBridgeHost(options = {}) {
|
|
3826
4071
|
const state = createMockSessionState(options);
|
|
3827
4072
|
const customRequestHandlers = new Map(
|
|
@@ -3829,6 +4074,11 @@ function createFakeBridgeHost(options = {}) {
|
|
|
3829
4074
|
);
|
|
3830
4075
|
const requests = [];
|
|
3831
4076
|
const connectedPorts = /* @__PURE__ */ new Set();
|
|
4077
|
+
state.embedHost.onClosed((event) => {
|
|
4078
|
+
connectedPorts.forEach(
|
|
4079
|
+
(port) => port.postMessage({ protocol: PROTOCOL, kind: "embed-event", event: { type: "closed", ...event } })
|
|
4080
|
+
);
|
|
4081
|
+
});
|
|
3832
4082
|
const beforeCloseWaiters = /* @__PURE__ */ new Map();
|
|
3833
4083
|
let beforeCloseCounter = 0;
|
|
3834
4084
|
const viewSessions = /* @__PURE__ */ new Map();
|
|
@@ -4034,6 +4284,54 @@ function createFakeBridgeHost(options = {}) {
|
|
|
4034
4284
|
case "menus.hide":
|
|
4035
4285
|
await state.session.menus.hide();
|
|
4036
4286
|
return { ok: true };
|
|
4287
|
+
case "appStorage.snapshot":
|
|
4288
|
+
return await state.session.storage.snapshot({
|
|
4289
|
+
prefixes: Array.isArray(params.prefixes) ? params.prefixes.map(String) : void 0
|
|
4290
|
+
});
|
|
4291
|
+
case "appStorage.get":
|
|
4292
|
+
return await state.session.storage.get(String(params.key));
|
|
4293
|
+
case "appStorage.set":
|
|
4294
|
+
await state.session.storage.set(String(params.key), String(params.value));
|
|
4295
|
+
return null;
|
|
4296
|
+
case "appStorage.remove":
|
|
4297
|
+
await state.session.storage.remove(String(params.key));
|
|
4298
|
+
return null;
|
|
4299
|
+
case "appStorage.keys":
|
|
4300
|
+
return await state.session.storage.keys({
|
|
4301
|
+
prefix: typeof params.prefix === "string" ? params.prefix : void 0
|
|
4302
|
+
});
|
|
4303
|
+
case "appStorage.clear":
|
|
4304
|
+
await state.session.storage.clear({
|
|
4305
|
+
prefix: typeof params.prefix === "string" ? params.prefix : void 0
|
|
4306
|
+
});
|
|
4307
|
+
return null;
|
|
4308
|
+
case "components.list":
|
|
4309
|
+
return {
|
|
4310
|
+
components: await state.session.components.list(
|
|
4311
|
+
params.query ?? void 0
|
|
4312
|
+
)
|
|
4313
|
+
};
|
|
4314
|
+
case "embeds.open": {
|
|
4315
|
+
const input = params.input;
|
|
4316
|
+
const embedId = await state.embedHost.openEmbed(input);
|
|
4317
|
+
return input.placement === "frame" && options.embedFrameUrl ? { embedId, frame: { url: options.embedFrameUrl } } : { embedId };
|
|
4318
|
+
}
|
|
4319
|
+
case "embeds.setRect":
|
|
4320
|
+
state.embedHost.setRect(String(params.embedId), params.rect);
|
|
4321
|
+
return { ok: true };
|
|
4322
|
+
case "embeds.setVisible":
|
|
4323
|
+
state.embedHost.setVisible(String(params.embedId), params.visible === true);
|
|
4324
|
+
return { ok: true };
|
|
4325
|
+
case "embeds.close":
|
|
4326
|
+
state.embedHost.closeEmbed(String(params.embedId), "closed");
|
|
4327
|
+
return { ok: true };
|
|
4328
|
+
case "embedding.finish":
|
|
4329
|
+
state.embedHost.finishEmbedding({
|
|
4330
|
+
reason: params.reason === "cancelled" ? "cancelled" : "completed",
|
|
4331
|
+
...params.result === void 0 ? {} : { result: params.result },
|
|
4332
|
+
...typeof params.message === "string" ? { message: params.message } : {}
|
|
4333
|
+
});
|
|
4334
|
+
return { ok: true };
|
|
4037
4335
|
case "session.requestHostFocus":
|
|
4038
4336
|
await state.session.requestHostFocus();
|
|
4039
4337
|
return null;
|
|
@@ -4459,7 +4757,7 @@ function createFakeBridgeHost(options = {}) {
|
|
|
4459
4757
|
return void 0;
|
|
4460
4758
|
}
|
|
4461
4759
|
default:
|
|
4462
|
-
return
|
|
4760
|
+
return NOT_HANDLED;
|
|
4463
4761
|
}
|
|
4464
4762
|
}
|
|
4465
4763
|
async function handleStreamMessage(port, message) {
|
|
@@ -4581,7 +4879,7 @@ function createFakeBridgeHost(options = {}) {
|
|
|
4581
4879
|
return;
|
|
4582
4880
|
}
|
|
4583
4881
|
const builtinResult = await handleBuiltinRequest(message);
|
|
4584
|
-
if (builtinResult ===
|
|
4882
|
+
if (builtinResult === NOT_HANDLED) {
|
|
4585
4883
|
fail({
|
|
4586
4884
|
code: "method-not-found",
|
|
4587
4885
|
message: `No fake bridge handler is configured for ${message.method}.`
|
|
@@ -4638,6 +4936,9 @@ function createFakeBridgeHost(options = {}) {
|
|
|
4638
4936
|
getEnforceCapabilities: state.getEnforceCapabilities,
|
|
4639
4937
|
setDirectoryUsers: state.setDirectoryUsers,
|
|
4640
4938
|
getDirectoryUsers: state.getDirectoryUsers,
|
|
4939
|
+
listEmbeds: () => state.embedHost.listEmbeds(),
|
|
4940
|
+
closeEmbed: (embedId, reason, result) => state.embedHost.closeEmbed(embedId, reason, result),
|
|
4941
|
+
getEmbeddingFinish: () => state.embedHost.getEmbeddingFinish(),
|
|
4641
4942
|
dispose() {
|
|
4642
4943
|
restoreWindow();
|
|
4643
4944
|
connectedPorts.forEach((port) => {
|