mindoodb-app-sdk 0.0.48 → 0.0.51
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 +151 -1
- package/TESTING.md +1 -0
- package/dist/{chunk-TPYDERAK.js → chunk-R76XXRJ6.js} +150 -2
- package/dist/index.d.ts +67 -3
- package/dist/index.js +26 -2
- package/dist/testing/index.d.ts +11 -1
- package/dist/testing/index.js +219 -5
- package/dist/{types-C-eyC839.d.ts → types-BLyV6Ejy.d.ts} +205 -5
- package/package.json +3 -3
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { au as MindooDBAppCreateViewNavigatorInput, cw as MindooDBAppViewNavigator, bg as MindooDBAppLaunchContext, av as MindooDBAppDatabaseInfo, aD as MindooDBAppDocumentApi, cy as MindooDBAppViewNavigatorOpenOptions, w as MindooDBAppAttachmentApi, b3 as MindooDBAppIdentityApi, cm as MindooDBAppTimestampApi, aB as MindooDBAppDirectoryApi, j as MindooDBAppDocument, a$ as MindooDBAppFulltextSetup, a_ as MindooDBAppExtractionSetup, ce as MindooDBAppSummarySetup, by as MindooDBAppProposeAppInput, bz as MindooDBAppProposeAppResult, e as MindooDBAppBridge, c6 as MindooDBAppSession, X as MindooDBAppBridgeRpcRequest, b2 as MindooDBAppHostTheme, cE as MindooDBAppViewport, cq as MindooDBAppUiPreferences, bE as MindooDBAppQueryResult, cD as MindooDBAppViewUpdateStats, T as MindooDBAppBridgePortMessage, c as MindooDBAppDragStartResult, aU as MindooDBAppDragProfile } from '../types-BLyV6Ejy.js';
|
|
2
2
|
import * as mindoodb from 'mindoodb';
|
|
3
3
|
import 'mindoodb-view-language';
|
|
4
4
|
|
|
@@ -72,6 +72,13 @@ interface MockMindooDBAppDatabaseDefinition {
|
|
|
72
72
|
* their setup/bootstrap logic.
|
|
73
73
|
*/
|
|
74
74
|
extractionSetup?: MindooDBAppExtractionSetup | null;
|
|
75
|
+
/**
|
|
76
|
+
* Initial summary buffer configuration returned by `getSummarySetup()`.
|
|
77
|
+
* `setSummarySetup()` overwrites it for the lifetime of the handle. The
|
|
78
|
+
* mock's `query()` reads the seeded documents directly and ignores this
|
|
79
|
+
* config — it exists so apps can test their setup/bootstrap logic.
|
|
80
|
+
*/
|
|
81
|
+
summarySetup?: MindooDBAppSummarySetup | null;
|
|
75
82
|
}
|
|
76
83
|
/**
|
|
77
84
|
* Stands in for the host-owned sealed channel.
|
|
@@ -122,6 +129,8 @@ interface MockMindooDBAppSessionController {
|
|
|
122
129
|
emitLocaleChange(locale: string): void;
|
|
123
130
|
/** Runs the app's `onBeforeClose` listeners, as the host does before a teardown. */
|
|
124
131
|
emitBeforeClose(): Promise<void>;
|
|
132
|
+
/** Sets whether this mock launch has host focus and notifies listeners. */
|
|
133
|
+
emitHostFocusChange(focused: boolean): void;
|
|
125
134
|
resolveDrag(result: MindooDBAppDragStartResult): void;
|
|
126
135
|
getDragProfile(): MindooDBAppDragProfile | null;
|
|
127
136
|
}
|
|
@@ -155,6 +164,7 @@ interface FakeBridgeHostController {
|
|
|
155
164
|
emitViewportChange(viewport: MindooDBAppViewport): void;
|
|
156
165
|
emitUiPreferencesChange(uiPreferences: MindooDBAppUiPreferences): void;
|
|
157
166
|
emitLocaleChange(locale: string): void;
|
|
167
|
+
emitHostFocusChange(focused: boolean): void;
|
|
158
168
|
/** Push a live-query result to connected apps, as the Haven host would. */
|
|
159
169
|
emitQueryResult(subscriptionId: string, result: MindooDBAppQueryResult): void;
|
|
160
170
|
/** Push a navigator view-changed event to connected apps. */
|
package/dist/testing/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
|
+
MINDOODB_APP_VALUE_TAG,
|
|
2
3
|
releaseMindooDBAppBridgeSessions
|
|
3
|
-
} from "../chunk-
|
|
4
|
+
} from "../chunk-R76XXRJ6.js";
|
|
4
5
|
|
|
5
6
|
// src/testing/index.ts
|
|
6
7
|
import * as Automerge from "@automerge/automerge";
|
|
@@ -473,7 +474,7 @@ function cloneBytes(chunk) {
|
|
|
473
474
|
function applyDocumentUpdatePatch(current, patch) {
|
|
474
475
|
const next = {
|
|
475
476
|
...structuredClone(current),
|
|
476
|
-
...patch.set ?
|
|
477
|
+
...patch.set ? readMockTypedValues(patch.set) : {}
|
|
477
478
|
};
|
|
478
479
|
for (const key of patch.unset ?? []) {
|
|
479
480
|
Reflect.deleteProperty(next, key);
|
|
@@ -496,7 +497,7 @@ function applyMockJsonPatch(target, patch) {
|
|
|
496
497
|
return;
|
|
497
498
|
}
|
|
498
499
|
for (const operation of patch.set ?? []) {
|
|
499
|
-
setValueAtPath(target, operation.path,
|
|
500
|
+
setValueAtPath(target, operation.path, readMockTypedValues(operation.value));
|
|
500
501
|
}
|
|
501
502
|
for (const operation of patch.unset ?? []) {
|
|
502
503
|
unsetValueAtPath(target, operation.path);
|
|
@@ -506,8 +507,13 @@ function applyMockJsonPatch(target, patch) {
|
|
|
506
507
|
list.splice(operation.index, operation.deleteCount);
|
|
507
508
|
}
|
|
508
509
|
for (const operation of patch.listInsert ?? []) {
|
|
510
|
+
const parent = ensureParentAtPath(target, operation.path);
|
|
511
|
+
const leaf = operation.path[operation.path.length - 1];
|
|
512
|
+
if (parent[leaf] == null) {
|
|
513
|
+
parent[leaf] = [];
|
|
514
|
+
}
|
|
509
515
|
const list = readListAtPath(target, operation.path);
|
|
510
|
-
list.splice(operation.index, 0, ...
|
|
516
|
+
list.splice(operation.index, 0, ...readMockTypedValues(operation.values));
|
|
511
517
|
}
|
|
512
518
|
for (const operation of patch.textSplice ?? []) {
|
|
513
519
|
applyMockTextPatch(target, operation.path, [{
|
|
@@ -522,6 +528,81 @@ function applyMockJsonPatch(target, patch) {
|
|
|
522
528
|
for (const operation of patch.textUnmark ?? []) {
|
|
523
529
|
applyMockTextMarks(target, operation.path, operation.index, operation.length, Object.fromEntries(operation.names.map((name) => [name, null])), true);
|
|
524
530
|
}
|
|
531
|
+
for (const operation of patch.counterIncrement ?? []) {
|
|
532
|
+
assertMockCounterAmount(operation.delta, "JSON counterIncrement delta");
|
|
533
|
+
const parent = ensureParentAtPath(target, operation.path);
|
|
534
|
+
const leaf = operation.path[operation.path.length - 1];
|
|
535
|
+
const current = parent[leaf];
|
|
536
|
+
if (current == null) {
|
|
537
|
+
parent[leaf] = operation.delta;
|
|
538
|
+
} else if (typeof current === "number") {
|
|
539
|
+
parent[leaf] = current + operation.delta;
|
|
540
|
+
} else {
|
|
541
|
+
throw new Error(
|
|
542
|
+
`Cannot increment non-counter value at ${operation.path.map(String).join(".")}`
|
|
543
|
+
);
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
var MOCK_CURSOR_PREFIX = "mock-cursor:";
|
|
548
|
+
function readMockCursorText(data, path) {
|
|
549
|
+
let value = data;
|
|
550
|
+
for (const segment of path) {
|
|
551
|
+
value = value?.[segment];
|
|
552
|
+
}
|
|
553
|
+
if (typeof value !== "string") {
|
|
554
|
+
throw new Error(
|
|
555
|
+
`Text cursors require an Automerge text field at '${path.map(String).join(".")}'`
|
|
556
|
+
);
|
|
557
|
+
}
|
|
558
|
+
return value;
|
|
559
|
+
}
|
|
560
|
+
function readMockTypedValues(value) {
|
|
561
|
+
if (value === null || typeof value !== "object") {
|
|
562
|
+
return value;
|
|
563
|
+
}
|
|
564
|
+
if (value instanceof Uint8Array) {
|
|
565
|
+
return value.slice();
|
|
566
|
+
}
|
|
567
|
+
if (Array.isArray(value)) {
|
|
568
|
+
return value.map((entry) => readMockTypedValues(entry));
|
|
569
|
+
}
|
|
570
|
+
const record = value;
|
|
571
|
+
if (Object.prototype.hasOwnProperty.call(record, MINDOODB_APP_VALUE_TAG)) {
|
|
572
|
+
switch (record[MINDOODB_APP_VALUE_TAG]) {
|
|
573
|
+
case "atomic":
|
|
574
|
+
if (typeof record.value !== "string") {
|
|
575
|
+
throw new Error('Typed value "atomic" needs a string value');
|
|
576
|
+
}
|
|
577
|
+
return record.value;
|
|
578
|
+
case "counter":
|
|
579
|
+
assertMockCounterAmount(record.value, 'Typed value "counter"');
|
|
580
|
+
return record.value;
|
|
581
|
+
case "timestamp":
|
|
582
|
+
return toMockTimestamp(record.value);
|
|
583
|
+
default:
|
|
584
|
+
throw new Error(
|
|
585
|
+
`Unknown typed value ${JSON.stringify(record[MINDOODB_APP_VALUE_TAG])}; the "${MINDOODB_APP_VALUE_TAG}" key is reserved`
|
|
586
|
+
);
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return Object.fromEntries(
|
|
590
|
+
Object.entries(record).map(([key, entry]) => [key, readMockTypedValues(entry)])
|
|
591
|
+
);
|
|
592
|
+
}
|
|
593
|
+
function toMockTimestamp(value) {
|
|
594
|
+
const date = typeof value === "number" || typeof value === "string" && value.trim() !== "" ? new Date(value) : null;
|
|
595
|
+
if (!date || Number.isNaN(date.getTime())) {
|
|
596
|
+
throw new Error(
|
|
597
|
+
'Typed value "timestamp" must be epoch milliseconds or an ISO 8601 date-time string'
|
|
598
|
+
);
|
|
599
|
+
}
|
|
600
|
+
return date.toISOString();
|
|
601
|
+
}
|
|
602
|
+
function assertMockCounterAmount(amount, label) {
|
|
603
|
+
if (typeof amount !== "number" || !Number.isSafeInteger(amount)) {
|
|
604
|
+
throw new Error(`${label} must be a safe integer`);
|
|
605
|
+
}
|
|
525
606
|
}
|
|
526
607
|
function setValueAtPath(target, path, value) {
|
|
527
608
|
if (path.length === 0) {
|
|
@@ -1737,6 +1818,45 @@ function createDatabaseHandle(definition, peers) {
|
|
|
1737
1818
|
spans: structuredClone(readRichTextSpansAtPath(document.data, path))
|
|
1738
1819
|
};
|
|
1739
1820
|
},
|
|
1821
|
+
// Mock cursors store the index they were created at and do not follow
|
|
1822
|
+
// later edits; Haven's Automerge-backed cursors do.
|
|
1823
|
+
async getTextCursors(docId, path, positions, options) {
|
|
1824
|
+
const document = storedDocuments.get(docId);
|
|
1825
|
+
if (!document || document.isDeleted) {
|
|
1826
|
+
throw new Error(`Document ${docId} was not found.`);
|
|
1827
|
+
}
|
|
1828
|
+
const text = readMockCursorText(document.data, path);
|
|
1829
|
+
return {
|
|
1830
|
+
path: [...path],
|
|
1831
|
+
heads: options?.heads ? [...options.heads] : [...document.heads ?? []],
|
|
1832
|
+
cursors: positions.map((position) => {
|
|
1833
|
+
if (position === "start") return `${MOCK_CURSOR_PREFIX}0`;
|
|
1834
|
+
if (position === "end") return `${MOCK_CURSOR_PREFIX}end`;
|
|
1835
|
+
if (typeof position !== "number" || !Number.isFinite(position)) {
|
|
1836
|
+
throw new Error('Text cursor positions must be numbers, "start" or "end"');
|
|
1837
|
+
}
|
|
1838
|
+
return `${MOCK_CURSOR_PREFIX}${Math.max(0, Math.min(Math.trunc(position), text.length))}`;
|
|
1839
|
+
})
|
|
1840
|
+
};
|
|
1841
|
+
},
|
|
1842
|
+
async resolveTextCursors(docId, path, cursors, options) {
|
|
1843
|
+
const document = storedDocuments.get(docId);
|
|
1844
|
+
if (!document || document.isDeleted) {
|
|
1845
|
+
throw new Error(`Document ${docId} was not found.`);
|
|
1846
|
+
}
|
|
1847
|
+
const text = readMockCursorText(document.data, path);
|
|
1848
|
+
return {
|
|
1849
|
+
path: [...path],
|
|
1850
|
+
heads: options?.heads ? [...options.heads] : [...document.heads ?? []],
|
|
1851
|
+
positions: cursors.map((cursor) => {
|
|
1852
|
+
if (typeof cursor !== "string" || !cursor.startsWith(MOCK_CURSOR_PREFIX)) {
|
|
1853
|
+
throw new Error(`Unknown text cursor ${String(cursor)}`);
|
|
1854
|
+
}
|
|
1855
|
+
const raw = cursor.slice(MOCK_CURSOR_PREFIX.length);
|
|
1856
|
+
return raw === "end" ? text.length : Math.min(Number(raw), text.length);
|
|
1857
|
+
})
|
|
1858
|
+
};
|
|
1859
|
+
},
|
|
1740
1860
|
async getAutomergeSnapshot(docId, _options) {
|
|
1741
1861
|
const document = storedDocuments.get(docId);
|
|
1742
1862
|
if (!document || document.isDeleted) {
|
|
@@ -1785,6 +1905,13 @@ function createDatabaseHandle(definition, peers) {
|
|
|
1785
1905
|
changesSince
|
|
1786
1906
|
};
|
|
1787
1907
|
},
|
|
1908
|
+
async applyAutomergeChangesBatch(items) {
|
|
1909
|
+
const results = [];
|
|
1910
|
+
for (const item of items) {
|
|
1911
|
+
results.push(await this.applyAutomergeChanges(item.docId, item.patch));
|
|
1912
|
+
}
|
|
1913
|
+
return results;
|
|
1914
|
+
},
|
|
1788
1915
|
async create(input) {
|
|
1789
1916
|
if (input.id !== void 0 && input.idPrefix !== void 0) {
|
|
1790
1917
|
throw new Error("documents.create: id and idPrefix are mutually exclusive");
|
|
@@ -1831,7 +1958,7 @@ function createDatabaseHandle(definition, peers) {
|
|
|
1831
1958
|
const created = {
|
|
1832
1959
|
id,
|
|
1833
1960
|
data: {
|
|
1834
|
-
...input.set,
|
|
1961
|
+
...readMockTypedValues(input.set ?? {}),
|
|
1835
1962
|
...Array.isArray(input.recipients) ? { _encryptFor: mockEncryptForMap(input.recipients) } : {}
|
|
1836
1963
|
},
|
|
1837
1964
|
heads: [`mock-head-${++changeCounter}`],
|
|
@@ -2119,6 +2246,7 @@ function createDatabaseHandle(definition, peers) {
|
|
|
2119
2246
|
const methods = definition.methods ?? {};
|
|
2120
2247
|
let fulltextSetup = definition.fulltextSetup ?? null;
|
|
2121
2248
|
let extractionSetup = definition.extractionSetup ?? null;
|
|
2249
|
+
let summarySetup = definition.summarySetup ?? null;
|
|
2122
2250
|
const databaseHandle = {
|
|
2123
2251
|
async info() {
|
|
2124
2252
|
return {
|
|
@@ -2157,6 +2285,12 @@ function createDatabaseHandle(definition, peers) {
|
|
|
2157
2285
|
},
|
|
2158
2286
|
async setExtractionSetup(config) {
|
|
2159
2287
|
extractionSetup = config === null ? null : { ...config };
|
|
2288
|
+
},
|
|
2289
|
+
async getSummarySetup() {
|
|
2290
|
+
return summarySetup === null ? null : structuredClone(summarySetup);
|
|
2291
|
+
},
|
|
2292
|
+
async setSummarySetup(config) {
|
|
2293
|
+
summarySetup = config === null ? null : structuredClone(config);
|
|
2160
2294
|
}
|
|
2161
2295
|
};
|
|
2162
2296
|
return {
|
|
@@ -2174,6 +2308,8 @@ function createDatabaseHandle(definition, peers) {
|
|
|
2174
2308
|
function createMockSessionState(options = {}) {
|
|
2175
2309
|
let launchContext = createDefaultLaunchContext(options.launchContext);
|
|
2176
2310
|
const themeListeners = /* @__PURE__ */ new Set();
|
|
2311
|
+
const hostFocusListeners = /* @__PURE__ */ new Set();
|
|
2312
|
+
let hostFocused = false;
|
|
2177
2313
|
const viewportListeners = /* @__PURE__ */ new Set();
|
|
2178
2314
|
const uiPreferencesListeners = /* @__PURE__ */ new Set();
|
|
2179
2315
|
const localeListeners = /* @__PURE__ */ new Set();
|
|
@@ -2465,6 +2601,23 @@ function createMockSessionState(options = {}) {
|
|
|
2465
2601
|
beforeCloseListeners.delete(listener);
|
|
2466
2602
|
};
|
|
2467
2603
|
},
|
|
2604
|
+
async requestHostFocus() {
|
|
2605
|
+
hostFocused = true;
|
|
2606
|
+
hostFocusListeners.forEach((listener) => listener(true));
|
|
2607
|
+
},
|
|
2608
|
+
async hasHostFocus() {
|
|
2609
|
+
return hostFocused;
|
|
2610
|
+
},
|
|
2611
|
+
onHostFocusChange(listener) {
|
|
2612
|
+
hostFocusListeners.add(listener);
|
|
2613
|
+
return () => {
|
|
2614
|
+
hostFocusListeners.delete(listener);
|
|
2615
|
+
};
|
|
2616
|
+
},
|
|
2617
|
+
async notify(input) {
|
|
2618
|
+
const id = input.id?.trim() || crypto.randomUUID();
|
|
2619
|
+
return { id };
|
|
2620
|
+
},
|
|
2468
2621
|
async disconnect() {
|
|
2469
2622
|
await options.onDisconnect?.();
|
|
2470
2623
|
}
|
|
@@ -2527,6 +2680,10 @@ function createMockSessionState(options = {}) {
|
|
|
2527
2680
|
async emitBeforeClose() {
|
|
2528
2681
|
await Promise.all([...beforeCloseListeners].map(async (listener) => listener()));
|
|
2529
2682
|
},
|
|
2683
|
+
setHostFocused(focused) {
|
|
2684
|
+
hostFocused = focused;
|
|
2685
|
+
hostFocusListeners.forEach((listener) => listener(focused));
|
|
2686
|
+
},
|
|
2530
2687
|
resolveDrag(result) {
|
|
2531
2688
|
activeDragResolve?.(result);
|
|
2532
2689
|
activeDragResolve = null;
|
|
@@ -2552,6 +2709,9 @@ function createMockMindooDBAppSession(options = {}) {
|
|
|
2552
2709
|
emitUiPreferencesChange: state.emitUiPreferencesChange,
|
|
2553
2710
|
emitLocaleChange: state.emitLocaleChange,
|
|
2554
2711
|
emitBeforeClose: state.emitBeforeClose,
|
|
2712
|
+
emitHostFocusChange(focused) {
|
|
2713
|
+
state.setHostFocused(focused);
|
|
2714
|
+
},
|
|
2555
2715
|
resolveDrag: state.resolveDrag,
|
|
2556
2716
|
getDragProfile: state.getDragProfile
|
|
2557
2717
|
};
|
|
@@ -2755,6 +2915,15 @@ function createFakeBridgeHost(options = {}) {
|
|
|
2755
2915
|
case "menus.hide":
|
|
2756
2916
|
await state.session.menus.hide();
|
|
2757
2917
|
return { ok: true };
|
|
2918
|
+
case "session.requestHostFocus":
|
|
2919
|
+
await state.session.requestHostFocus();
|
|
2920
|
+
return null;
|
|
2921
|
+
case "session.hasHostFocus":
|
|
2922
|
+
return { focused: await state.session.hasHostFocus() };
|
|
2923
|
+
case "notifications.show":
|
|
2924
|
+
return await state.session.notify(
|
|
2925
|
+
request.params
|
|
2926
|
+
);
|
|
2758
2927
|
case "session.disconnect":
|
|
2759
2928
|
await state.session.disconnect();
|
|
2760
2929
|
return { ok: true };
|
|
@@ -2799,6 +2968,15 @@ function createFakeBridgeHost(options = {}) {
|
|
|
2799
2968
|
params.config ?? null
|
|
2800
2969
|
);
|
|
2801
2970
|
return { ok: true };
|
|
2971
|
+
case "database.getSummarySetup":
|
|
2972
|
+
return {
|
|
2973
|
+
config: await state.getDatabase(String(params.databaseId)).getSummarySetup()
|
|
2974
|
+
};
|
|
2975
|
+
case "database.setSummarySetup":
|
|
2976
|
+
await state.getDatabase(String(params.databaseId)).setSummarySetup(
|
|
2977
|
+
params.config ?? null
|
|
2978
|
+
);
|
|
2979
|
+
return { ok: true };
|
|
2802
2980
|
case "documents.query":
|
|
2803
2981
|
return await state.getDatabase(String(params.databaseId)).documents.query(
|
|
2804
2982
|
params.query
|
|
@@ -2844,6 +3022,23 @@ function createFakeBridgeHost(options = {}) {
|
|
|
2844
3022
|
String(params.docId),
|
|
2845
3023
|
params.path
|
|
2846
3024
|
);
|
|
3025
|
+
case "documents.textCursors.get":
|
|
3026
|
+
return await state.getDatabase(String(params.databaseId)).documents.getTextCursors(
|
|
3027
|
+
String(params.docId),
|
|
3028
|
+
params.path,
|
|
3029
|
+
params.positions,
|
|
3030
|
+
{
|
|
3031
|
+
heads: params.heads,
|
|
3032
|
+
move: params.move
|
|
3033
|
+
}
|
|
3034
|
+
);
|
|
3035
|
+
case "documents.textCursors.resolve":
|
|
3036
|
+
return await state.getDatabase(String(params.databaseId)).documents.resolveTextCursors(
|
|
3037
|
+
String(params.docId),
|
|
3038
|
+
params.path,
|
|
3039
|
+
params.cursors,
|
|
3040
|
+
{ heads: params.heads }
|
|
3041
|
+
);
|
|
2847
3042
|
case "documents.automerge.getSnapshot":
|
|
2848
3043
|
return await state.getDatabase(String(params.databaseId)).documents.getAutomergeSnapshot(
|
|
2849
3044
|
String(params.docId),
|
|
@@ -3205,6 +3400,16 @@ function createFakeBridgeHost(options = {}) {
|
|
|
3205
3400
|
beforeCloseWaiters.get(message.closeId)?.();
|
|
3206
3401
|
return;
|
|
3207
3402
|
}
|
|
3403
|
+
if (message.kind === "workspace-focus-requested") {
|
|
3404
|
+
state.setHostFocused(true);
|
|
3405
|
+
const payload = {
|
|
3406
|
+
protocol: PROTOCOL,
|
|
3407
|
+
kind: "host-focus-changed",
|
|
3408
|
+
focused: true
|
|
3409
|
+
};
|
|
3410
|
+
port.postMessage(payload);
|
|
3411
|
+
return;
|
|
3412
|
+
}
|
|
3208
3413
|
if (message.kind === "request") {
|
|
3209
3414
|
requests.push(message);
|
|
3210
3415
|
try {
|
|
@@ -3315,6 +3520,15 @@ function createFakeBridgeHost(options = {}) {
|
|
|
3315
3520
|
};
|
|
3316
3521
|
connectedPorts.forEach((port) => port.postMessage(payload));
|
|
3317
3522
|
},
|
|
3523
|
+
emitHostFocusChange(focused) {
|
|
3524
|
+
state.setHostFocused(focused);
|
|
3525
|
+
const payload = {
|
|
3526
|
+
protocol: PROTOCOL,
|
|
3527
|
+
kind: "host-focus-changed",
|
|
3528
|
+
focused
|
|
3529
|
+
};
|
|
3530
|
+
connectedPorts.forEach((port) => port.postMessage(payload));
|
|
3531
|
+
},
|
|
3318
3532
|
emitQueryResult(subscriptionId, result) {
|
|
3319
3533
|
const payload = {
|
|
3320
3534
|
protocol: PROTOCOL,
|