mindoodb-app-sdk 0.0.20 → 0.0.26

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 CHANGED
@@ -1,12 +1,12 @@
1
1
  # mindoodb-app-sdk
2
2
 
3
- Build apps that run inside **MindooDB Haven** -- the browser-based workspace for end-to-end encrypted, offline-first data.
3
+ Build apps that run inside **MindooDB Haven** -- the browser-based workspace for end-to-end encrypted, local-first data.
4
4
 
5
5
  `mindoodb-app-sdk` is the TypeScript SDK that connects your web application to Haven through a secure message bridge. Your app runs in a sandboxed iframe (or a separate browser window) and gains access to databases, documents, attachments, virtual views, and live host events -- all without ever touching encryption keys or raw sync state.
6
6
 
7
7
  ## What is a MindooDB App?
8
8
 
9
- [MindooDB](https://mindoodb.com) is an **end-to-end encrypted, offline-first sync database**. Data is encrypted on the client before it ever leaves the device. Under the hood it uses [Automerge](https://automerge.org/) CRDTs so multiple users can edit concurrently and conflicts resolve automatically.
9
+ [MindooDB](https://mindoodb.com) is an **end-to-end encrypted, local-first sync database**. Data is encrypted on the client before it ever leaves the device. Under the hood it uses [Automerge](https://automerge.org/) CRDTs so multiple users can edit concurrently and conflicts resolve automatically.
10
10
 
11
11
  **Haven** is the browser-based workspace that sits on top of MindooDB. Users organize databases, applications, notes, and media on a visual grid -- think of it as a customizable home screen for encrypted data that works offline and syncs in the background.
12
12
 
@@ -893,9 +893,106 @@ Requires the `update` capability (same as other write operations). For historica
893
893
 
894
894
  TeamEdit's Word/.docx mode is why these RPCs exist — see `wordAutomergeHandle.ts` in [`mindoodb-app-teamedit`](https://github.com/klehmann/mindoodb-app-teamedit). Treat it as a reference for an unsupported edge case, not as a pattern to copy into new apps.
895
895
 
896
+ ### Queries & Live Queries
897
+
898
+ `documents.query()` runs ad-hoc queries against the database's **document summary buffer** on the host: declarative filtering, dynamic sorting, paging, and field projection — without materializing documents. This is the fastest way to find and order documents from an app and the right default for lists, search results, and dashboards.
899
+
900
+ ```ts
901
+ import { createViewLanguage } from "mindoodb-app-sdk";
902
+
903
+ const v = createViewLanguage<{ type: string; total: number }>();
904
+
905
+ const result = await db.documents.query({
906
+ filter: v.and(
907
+ v.eq(v.field("type"), v.string("invoice")),
908
+ v.gt(v.toNumber(v.field("total")), v.number(100)),
909
+ ),
910
+ sortBy: [{ field: "total", direction: "descending" }],
911
+ limit: 50,
912
+ offset: 0,
913
+ fields: ["total", "customer"],
914
+ });
915
+
916
+ console.log(result.total); // matching docs before paging
917
+ console.log(result.coverage); // "full" | "rebuilding" | "full-scan"
918
+ for (const row of result.rows) {
919
+ console.log(row.docId, row.fields, row.lastModified);
920
+ }
921
+ ```
922
+
923
+ The `filter` also accepts formula source text, which the SDK parses locally before it crosses the bridge (only the JSON expression AST travels):
924
+
925
+ ```ts
926
+ const invoices = await db.documents.query({
927
+ filter: 'v.eq(v.field("type"), "invoice")',
928
+ });
929
+ ```
930
+
931
+ Notes:
932
+
933
+ - The host caps `limit` (default 200, maximum 1000) so result payloads stay bounded. Page with `offset` for more rows.
934
+ - `coverage: "rebuilding"` means the summary buffer is still backfilling — results may be incomplete and will improve on their own.
935
+ - Queries that reference encrypted fields or fields outside the summary configuration are rejected with a `query-not-supported` bridge error. Use a view with `useFullDocuments` (see below) or `documents.list()` for those cases.
936
+ - Queries require the `read` capability and are not available in time-travel launches (the summary buffer reflects the live state only).
937
+
938
+ **Full-text search** — a query can additionally carry a `text` clause, evaluated against the database's client-side full-text index on the host and combined with `filter` as a logical AND:
939
+
940
+ ```ts
941
+ const result = await db.documents.query({
942
+ text: { query: "solar panels" }, // full-text match + relevance score
943
+ filter: 'v.eq(v.field("type"), "article")', // optional structured filter
944
+ });
945
+
946
+ for (const row of result.rows) {
947
+ console.log(row.docId, row.textScore); // higher score = better match
948
+ }
949
+ ```
950
+
951
+ - Options: `fields` (restrict matching to specific index fields), `prefix` (default `true` — `"sol"` matches `"solar"`), `fuzzy` (edit-distance tolerance, default off), `combineWith` (`"AND"` default | `"OR"`).
952
+ - Rows gain a `textScore`; without an explicit `sortBy`, results come best score first. Sorting can reference the score explicitly with `sortBy: [{ special: "textScore", direction: "descending" }]`.
953
+ - Full-text indexing is **opt-in per database** (`fulltextSetup` in the `dbsetup` document). A `text` clause against a database without it is rejected with a `fulltext-not-enabled` bridge error — catch it and hide/disable the search UI.
954
+ - `liveQuery` supports `text` clauses unchanged; the host rounds scores in its result fingerprint so minor relevance drift does not spam your callback.
955
+
956
+ **Enabling full-text indexing** — apps turn indexing on themselves through the database handle. The configuration is stored in the synced `dbsetup` document, so it applies on every replica (each device builds its own local, encrypted index):
957
+
958
+ ```ts
959
+ // Idempotent — safe to call on every app start (no write when unchanged).
960
+ // Requires the `update` capability.
961
+ await db.setFulltextSetup({
962
+ enabled: true,
963
+ attachments: true, // index text extracted from attachments (PDF, Office, …)
964
+ language: "de", // BCP-47 tag steering tokenization; omit for language-neutral
965
+ });
966
+
967
+ const setup = await db.getFulltextSetup(); // null when never configured
968
+ ```
969
+
970
+ - Without `include`, every non-underscore top-level field with extractable text is indexed (auto mode). Pass `include: ["subject", "body"]` to pin the indexed fields, including nested/long-text fields outside the summary buffer.
971
+ - `attachments: true` indexes attachment text under the synthetic `_attachments` field using the host's extractors (Haven ships PDF, Office, and plain-text extractors). Restrict a query to attachment content with `text: { query, fields: ["_attachments"] }`.
972
+ - Changing the configuration (including `language`) rebuilds the index in the background; queries during the rebuild report `coverage: "rebuilding"`.
973
+
974
+ **Live queries** keep a query result up to date. The callback receives the initial result and runs again whenever the result actually changed — the host coalesces bursts of writes and fingerprints results, so you only hear about real changes:
975
+
976
+ ```ts
977
+ const subscription = await db.documents.liveQuery(
978
+ { filter: 'v.eq(v.field("status"), "open")', limit: 100 },
979
+ (result) => {
980
+ renderList(result.rows);
981
+ },
982
+ );
983
+
984
+ // Force a re-evaluation (delivers a result even when nothing changed):
985
+ await subscription.refresh();
986
+
987
+ // Always dispose when the consuming UI goes away:
988
+ await subscription.dispose();
989
+ ```
990
+
991
+ Live query results are pushed from the host over the bridge port — no polling. Subscriptions are cleaned up automatically when the app disconnects, but dispose them explicitly when the UI that consumes them unmounts.
992
+
896
993
  ### Incremental sync
897
994
 
898
- The changefeed-backed `documents.list()` API is also the right primitive for app-side indexes, search, and other derived caches.
995
+ The changefeed-backed `documents.list()` API is also the right primitive for app-side indexes, search, and other derived caches. For plain "show me matching documents" use cases, prefer [`documents.query()`](#queries--live-queries); the changefeed shines when you need deletions and a durable resume checkpoint for derived state.
899
996
 
900
997
  **Initial scan from the beginning:**
901
998
 
@@ -1225,13 +1322,28 @@ await navigator.setExpansionState(expansion);
1225
1322
  await navigator.setSelectionState(selection);
1226
1323
  ```
1227
1324
 
1325
+ **Live updates** -- the host keeps the view bound to its source databases' change feeds. Subscribe with `onDidUpdate` and re-read the visible page when it fires; there is no need to poll or call `refresh()`:
1326
+
1327
+ ```ts
1328
+ const unsubscribe = navigator.onDidUpdate(({ addedCount, removedCount }) => {
1329
+ console.log(`view changed: +${addedCount} / -${removedCount}`);
1330
+ void rerenderVisiblePage();
1331
+ });
1332
+
1333
+ // later, when the consuming UI unmounts:
1334
+ unsubscribe();
1335
+ ```
1336
+
1228
1337
  The expression language is fully declarative: apps define filter and column logic through a typed builder API that compiles to JSON-safe expression objects. No app-provided JavaScript runs inside the bridge host.
1229
1338
 
1230
1339
  #### Performance notes
1231
1340
 
1341
+ - Navigator views are built **summary-first**: whenever the view definition (filter + column expressions) can be answered from the database's document summary buffer, the host feeds the view from the summary without materializing a single document. Views fall back to the (slower) document path automatically when they need decrypted fields, JS value functions, or fields outside the summary configuration.
1342
+ - Pass `useFullDocuments: true` in `createViewNavigator` input to force the document path explicitly — the escape hatch for views that deliberately need full document data.
1232
1343
  - `goto*()` and `getCurrentEntry()` are lightweight stateful cursor operations. They may still produce many bridge round-trips if you call them for every rendered row.
1233
1344
  - `entriesForward()` and `entriesBackward()` exist specifically to reduce those round-trips for UI rendering.
1234
- - `refresh()` rebuilds or invalidates the host-side navigator state and should be treated as an expensive operation compared to simple cursor movement.
1345
+ - `refresh()` performs an incremental catch-up on the host-side view (no pipeline rebuild). With `onDidUpdate` in place you rarely need it — the host pushes updates on its own.
1346
+ - `session.listDocumentsSinceViewCursor(cursor)` remains available as a **legacy polling/delta-sync path**; prefer `onDidUpdate` pushes and `documents.liveQuery()` for keeping UI current.
1235
1347
  - Child/key/range helpers operate on the same host-side navigator session. They do not create a separate query engine.
1236
1348
 
1237
1349
  Available expression helpers:
@@ -1243,7 +1355,7 @@ Available expression helpers:
1243
1355
  - **String helpers:** `concat()`, `lower()`, `upper()`, `trim()`, `contains()`, `startsWith()`, `endsWith()`
1244
1356
  - **Null/existence:** `coalesce()`, `exists()`, `notExists()`
1245
1357
  - **Date/path:** `datePart()`, `pathJoin()`
1246
- - **Control flow:** `ifElse()`, `let()`
1358
+ - **Control flow:** `ifElse()`, `let()` — `ifElse()` accepts multiple condition/value pairs followed by a default, like Domino's `@If`: `v.ifElse(cond1, val1, cond2, val2, default)`
1247
1359
 
1248
1360
  The full language guide lives in the `mindoodb-view-language` package. The SDK re-exports `createViewLanguage()` for convenience.
1249
1361
 
@@ -1314,16 +1426,20 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
1314
1426
 
1315
1427
  ### MindooDBAppDatabase
1316
1428
 
1317
- | Property / Method | Returns |
1318
- | ----------------- | ---------------------------------- |
1319
- | `info()` | `Promise<MindooDBAppDatabaseInfo>` |
1320
- | `documents` | `MindooDBAppDocumentApi` |
1321
- | `attachments` | `MindooDBAppAttachmentApi` |
1429
+ | Property / Method | Returns |
1430
+ | ---------------------------- | ---------------------------------------------- |
1431
+ | `info()` | `Promise<MindooDBAppDatabaseInfo>` |
1432
+ | `documents` | `MindooDBAppDocumentApi` |
1433
+ | `attachments` | `MindooDBAppAttachmentApi` |
1434
+ | `getFulltextSetup()` | `Promise<MindooDBAppFulltextSetup \| null>` |
1435
+ | `setFulltextSetup(config)` | `Promise<void>` |
1322
1436
 
1323
1437
  ### MindooDBAppDocumentApi
1324
1438
 
1325
1439
  | Method | Returns |
1326
1440
  | ---------------------------------- | -------------------------------------------- |
1441
+ | `query(query?)` | `Promise<MindooDBAppQueryResult>` |
1442
+ | `liveQuery(query, onResult)` | `Promise<MindooDBAppLiveQuerySubscription>` |
1327
1443
  | `list(query?)` | `Promise<MindooDBAppDocumentListResult>` |
1328
1444
  | `get(docId)` | `Promise<MindooDBAppDocument \| null>` |
1329
1445
  | `getRichText(docId, path, opts?)` | `Promise<MindooDBAppRichTextSnapshot>` |
@@ -1378,7 +1494,9 @@ interface MindooDBAppUpdateDocumentInput {
1378
1494
  | Method | Returns |
1379
1495
  | ---------------------------------------------------------- | ------------------------------------------------- |
1380
1496
  | `getDefinition()` | `Promise<MindooDBAppViewDefinition>` |
1381
- | `refresh()` | `Promise<void>` |
1497
+ | `refresh()` | `Promise<string \| null>` (new view cursor) |
1498
+ | `onDidUpdate(listener)` | `() => void` (unsubscribe) |
1499
+ | `getViewCursor()` | `Promise<string \| null>` |
1382
1500
  | `getCurrentEntry()` | `Promise<MindooDBAppViewEntry \| null>` |
1383
1501
  | `gotoFirst()` / `gotoLast()` | `Promise<boolean>` |
1384
1502
  | `gotoNext()` / `gotoPrev()` | `Promise<boolean>` |
package/TESTING.md CHANGED
@@ -12,6 +12,15 @@ import {
12
12
  } from "mindoodb-app-sdk/testing";
13
13
  ```
14
14
 
15
+ The testing entrypoint emulates document storage with real Automerge documents,
16
+ so `@automerge/automerge` is declared as an optional peer dependency. Add it to
17
+ your app's `devDependencies` when you import `mindoodb-app-sdk/testing`
18
+ (the runtime SDK entrypoint does not need it):
19
+
20
+ ```bash
21
+ pnpm add -D @automerge/automerge
22
+ ```
23
+
15
24
  ## Pick a level
16
25
 
17
26
  ### Level 1: simple app tests
@@ -93,6 +102,30 @@ Each database entry can provide:
93
102
  - `methods.documents`
94
103
  - `methods.views` for session-level `createView()` and `openView()` calls
95
104
  - `methods.attachments`
105
+ - `fulltextSetup` — the initial config returned by `db.getFulltextSetup()`; `db.setFulltextSetup()` overwrites it for the lifetime of the handle. Use this to test your app's full-text bootstrap logic. Note the mock evaluates `text` query clauses regardless of this config.
106
+
107
+ The default in-memory document store also implements `documents.query()` and `documents.liveQuery()`: expression and formula-string filters are evaluated against the seeded documents, `sortBy`/`limit`/`offset` work as documented, and live query callbacks fire automatically after `create`/`update`/`delete`/`undelete` mutations. Full-text `text` clauses are supported with a deterministic mock implementation (token matching with prefix/AND semantics and an occurrence-count `textScore`) — assert on membership and relative ordering, not absolute scores, since real hosts use a BM25-style engine. That means app code built on queries and live queries is testable at Level 1 without any extra setup:
108
+
109
+ ```ts
110
+ const session = await mock.bridge.connect();
111
+ const db = await session.openDatabase("main");
112
+
113
+ await db.documents.create({ set: { type: "invoice", total: 120 } });
114
+
115
+ const result = await db.documents.query({
116
+ filter: 'v.eq(v.field("type"), "invoice")',
117
+ sortBy: [{ field: "total", direction: "descending" }],
118
+ });
119
+ expect(result.rows).toHaveLength(1);
120
+
121
+ const updates: number[] = [];
122
+ const sub = await db.documents.liveQuery(
123
+ { filter: 'v.eq(v.field("type"), "invoice")' },
124
+ (r) => updates.push(r.total),
125
+ );
126
+ await db.documents.create({ set: { type: "invoice", total: 50 } });
127
+ await sub.dispose();
128
+ ```
96
129
 
97
130
  ## Level 2 example
98
131
 
@@ -161,10 +194,14 @@ Useful Level 2 methods:
161
194
  - `dispose()`
162
195
  - `emitThemeChange()`
163
196
  - `emitViewportChange()`
197
+ - `emitQueryResult()` — push a `query-result` message to live query subscribers
198
+ - `emitViewChanged()` — push a `view-changed` message to navigator `onDidUpdate` listeners
164
199
  - `setRequestHandler()`
165
200
  - `clearRequestHandler()`
166
201
  - `postPortMessage()`
167
202
 
203
+ The built-in request handling also covers `documents.query` and the `documents.liveQuery.*` RPCs against the seeded documents, so `db.documents.query()` / `db.documents.liveQuery()` and `navigator.onDidUpdate()` work end-to-end over the real bridge transport in Level 2 tests.
204
+
168
205
  ## When to use which level
169
206
 
170
207
  Choose Level 1 when:
package/dist/index.d.ts CHANGED
@@ -1,6 +1,8 @@
1
- import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-CQt2ObMu.js';
2
- export { f as MindooDBAppAttachmentApi, g as MindooDBAppAttachmentChunk, h as MindooDBAppAttachmentInfo, i as MindooDBAppAttachmentPreviewOptions, j as MindooDBAppAttachmentPreviewSession, k as MindooDBAppAutomergeChangesPatch, l as MindooDBAppAutomergeChangesSince, m as MindooDBAppAutomergeGetOptions, n as MindooDBAppAutomergePatchResult, o as MindooDBAppAutomergeSnapshot, p as MindooDBAppBridgeConnectMessage, q as MindooDBAppBridgeConnectOptions, r as MindooDBAppBridgeConnectedMessage, s as MindooDBAppBridgeErrorPayload, t as MindooDBAppBridgeHandshakeErrorMessage, u as MindooDBAppBridgePortMessage, v as MindooDBAppBridgeRpcError, w as MindooDBAppBridgeRpcMessage, x as MindooDBAppBridgeRpcRequest, y as MindooDBAppBridgeRpcSuccess, z as MindooDBAppBridgeStreamAbortRequest, A as MindooDBAppBridgeStreamAck, B as MindooDBAppBridgeStreamCloseRequest, C as MindooDBAppBridgeStreamError, D as MindooDBAppBridgeStreamMessage, E as MindooDBAppBridgeStreamOpenResult, F as MindooDBAppBridgeStreamReadRequest, G as MindooDBAppBridgeStreamWriteRequest, H as MindooDBAppBridgeThemeChangedMessage, I as MindooDBAppBridgeUiPreferencesChangedMessage, J as MindooDBAppBridgeViewportChangedMessage, K as MindooDBAppCapability, L as MindooDBAppConfiguredViewCategorizationStyle, N as MindooDBAppConfiguredViewColumn, O as MindooDBAppConfiguredViewColumnRole, P as MindooDBAppConfiguredViewExpressionMode, Q as MindooDBAppConfiguredViewFieldExpression, R as MindooDBAppConfiguredViewFilterDefinition, S as MindooDBAppConfiguredViewFilterMode, T as MindooDBAppConfiguredViewFilterRule, U as MindooDBAppConfiguredViewFormulaExpression, V as MindooDBAppConfiguredViewFormulaFilterDefinition, W as MindooDBAppConfiguredViewPreviewMode, X as MindooDBAppConfiguredViewRuleFilterDefinition, Y as MindooDBAppConfiguredViewRuleMatchMode, Z as MindooDBAppConfiguredViewRuleOperator, _ as MindooDBAppConfiguredViewValueExpression, $ as MindooDBAppCreateDocumentInput, a0 as MindooDBAppCreateViewInput, a1 as MindooDBAppCreateViewNavigatorInput, a2 as MindooDBAppDatabaseInfo, a3 as MindooDBAppDocumentApi, a4 as MindooDBAppDocumentHeadCursorResult, a5 as MindooDBAppDocumentHistoryEntry, a6 as MindooDBAppDocumentListQuery, a7 as MindooDBAppDocumentListResult, a8 as MindooDBAppDocumentRevisionId, a9 as MindooDBAppDocumentScanPreset, aa as MindooDBAppDocumentSummary, ab as MindooDBAppHistoricalDocument, ac as MindooDBAppHistoryQuery, ad as MindooDBAppHostTheme, ae as MindooDBAppJsonListDeletePatch, af as MindooDBAppJsonListInsertPatch, ag as MindooDBAppJsonPatch, ah as MindooDBAppJsonSetPatch, ai as MindooDBAppJsonTextMarkPatch, aj as MindooDBAppJsonTextSplicePatch, ak as MindooDBAppJsonTextUnmarkPatch, al as MindooDBAppJsonUnsetPatch, am as MindooDBAppLaunchContext, an as MindooDBAppMenuAnchor, ao as MindooDBAppMenuApi, ap as MindooDBAppMenuCommandItem, aq as MindooDBAppMenuDismissReason, ar as MindooDBAppMenuDismissedResult, as as MindooDBAppMenuItem, at as MindooDBAppMenuKind, au as MindooDBAppMenuPlacement, av as MindooDBAppMenuPointAnchor, aw as MindooDBAppMenuRect, ax as MindooDBAppMenuRectAnchor, ay as MindooDBAppMenuSelectionResult, az as MindooDBAppMenuSeparatorItem, aA as MindooDBAppReadableAttachmentStream, aB as MindooDBAppResolvedViewDefinition, aC as MindooDBAppResolvedViewSource, aD as MindooDBAppRichTextBlockSpan, aE as MindooDBAppRichTextGetOptions, aF as MindooDBAppRichTextImmutableString, aG as MindooDBAppRichTextMarkRange, aH as MindooDBAppRichTextMaterializeValue, aI as MindooDBAppRichTextPatch, aJ as MindooDBAppRichTextScalar, aK as MindooDBAppRichTextSpliceStep, aL as MindooDBAppRichTextStep, aM as MindooDBAppRichTextStepPatch, aN as MindooDBAppRichTextTextSpan, aO as MindooDBAppRuntime, aP as MindooDBAppScanAttachmentOptions, aQ as MindooDBAppScanAttachmentResult, aR as MindooDBAppScopedDocId, aS as MindooDBAppScopedDocumentSummary, aT as MindooDBAppSession, aU as MindooDBAppShowMenuInput, aV as MindooDBAppShowMenuResult, aW as MindooDBAppTextEdit, aX as MindooDBAppTextPatch, aY as MindooDBAppThemeMode, aZ as MindooDBAppUiPreferences, a_ as MindooDBAppUpdateDocumentInput, a$ as MindooDBAppViewCursorDocumentListResult, b0 as MindooDBAppViewCursorResult, b1 as MindooDBAppViewEntry, b2 as MindooDBAppViewEntryKind, b3 as MindooDBAppViewNavigator, b4 as MindooDBAppViewNavigatorExpansionState, b5 as MindooDBAppViewNavigatorOpenOptions, b6 as MindooDBAppViewNavigatorPageOptions, b7 as MindooDBAppViewNavigatorPageResult, b8 as MindooDBAppViewNavigatorRangeQuery, b9 as MindooDBAppViewNavigatorSelectionState, ba as MindooDBAppViewport, bb as MindooDBAppWritableAttachmentStream } from './types-CQt2ObMu.js';
1
+ import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-B6vEy1VC.js';
2
+ export { f as MindooDBAppAccessDecision, g as MindooDBAppAccessTier, h as MindooDBAppAttachmentApi, i as MindooDBAppAttachmentChunk, j as MindooDBAppAttachmentInfo, k as MindooDBAppAttachmentPreviewOptions, l as MindooDBAppAttachmentPreviewSession, m as MindooDBAppAutomergeChangesPatch, n as MindooDBAppAutomergeChangesSince, o as MindooDBAppAutomergeGetOptions, p as MindooDBAppAutomergePatchResult, q as MindooDBAppAutomergeSnapshot, r as MindooDBAppBridgeConnectMessage, s as MindooDBAppBridgeConnectOptions, t as MindooDBAppBridgeConnectedMessage, u as MindooDBAppBridgeErrorPayload, v as MindooDBAppBridgeHandshakeErrorMessage, w as MindooDBAppBridgeLocaleChangedMessage, x as MindooDBAppBridgePortMessage, y as MindooDBAppBridgeQueryResultMessage, z as MindooDBAppBridgeRpcError, A as MindooDBAppBridgeRpcMessage, B as MindooDBAppBridgeRpcRequest, C as MindooDBAppBridgeRpcSuccess, D as MindooDBAppBridgeStreamAbortRequest, E as MindooDBAppBridgeStreamAck, F as MindooDBAppBridgeStreamCloseRequest, G as MindooDBAppBridgeStreamError, H as MindooDBAppBridgeStreamMessage, I as MindooDBAppBridgeStreamOpenResult, J as MindooDBAppBridgeStreamReadRequest, K as MindooDBAppBridgeStreamWriteRequest, L as MindooDBAppBridgeThemeChangedMessage, N as MindooDBAppBridgeUiPreferencesChangedMessage, O as MindooDBAppBridgeViewChangedMessage, P as MindooDBAppBridgeViewportChangedMessage, Q as MindooDBAppCapability, R as MindooDBAppConfiguredViewCategorizationStyle, S as MindooDBAppConfiguredViewColumn, T as MindooDBAppConfiguredViewColumnRole, U as MindooDBAppConfiguredViewExpressionMode, V as MindooDBAppConfiguredViewFieldExpression, W as MindooDBAppConfiguredViewFilterDefinition, X as MindooDBAppConfiguredViewFilterMode, Y as MindooDBAppConfiguredViewFilterRule, Z as MindooDBAppConfiguredViewFormulaExpression, _ as MindooDBAppConfiguredViewFormulaFilterDefinition, $ as MindooDBAppConfiguredViewPreviewMode, a0 as MindooDBAppConfiguredViewRuleFilterDefinition, a1 as MindooDBAppConfiguredViewRuleMatchMode, a2 as MindooDBAppConfiguredViewRuleOperator, a3 as MindooDBAppConfiguredViewValueExpression, a4 as MindooDBAppCreateDocumentInput, a5 as MindooDBAppCreateViewInput, a6 as MindooDBAppCreateViewNavigatorInput, a7 as MindooDBAppDatabaseInfo, a8 as MindooDBAppDocumentApi, a9 as MindooDBAppDocumentHeadCursorResult, aa as MindooDBAppDocumentHistoryEntry, ab as MindooDBAppDocumentListQuery, ac as MindooDBAppDocumentListResult, ad as MindooDBAppDocumentQuery, ae as MindooDBAppDocumentRevisionId, af as MindooDBAppDocumentScanPreset, ag as MindooDBAppDocumentSummary, ah as MindooDBAppExtractionSetup, ai as MindooDBAppFulltextSetup, aj as MindooDBAppHistoricalDocument, ak as MindooDBAppHistoryQuery, al as MindooDBAppHostTheme, am as MindooDBAppJsonListDeletePatch, an as MindooDBAppJsonListInsertPatch, ao as MindooDBAppJsonPatch, ap as MindooDBAppJsonSetPatch, aq as MindooDBAppJsonTextMarkPatch, ar as MindooDBAppJsonTextSplicePatch, as as MindooDBAppJsonTextUnmarkPatch, at as MindooDBAppJsonUnsetPatch, au as MindooDBAppLaunchContext, av as MindooDBAppLiveQuerySubscription, aw as MindooDBAppMenuAnchor, ax as MindooDBAppMenuApi, ay as MindooDBAppMenuCommandItem, az as MindooDBAppMenuDismissReason, aA as MindooDBAppMenuDismissedResult, aB as MindooDBAppMenuItem, aC as MindooDBAppMenuKind, aD as MindooDBAppMenuPlacement, aE as MindooDBAppMenuPointAnchor, aF as MindooDBAppMenuRect, aG as MindooDBAppMenuRectAnchor, aH as MindooDBAppMenuSelectionResult, aI as MindooDBAppMenuSeparatorItem, aJ as MindooDBAppQueryCoverage, aK as MindooDBAppQueryResult, aL as MindooDBAppQueryRow, aM as MindooDBAppQuerySortKey, aN as MindooDBAppQueryTextClause, aO as MindooDBAppReadableAttachmentStream, aP as MindooDBAppResolvedViewDefinition, aQ as MindooDBAppResolvedViewSource, aR as MindooDBAppRichTextBlockSpan, aS as MindooDBAppRichTextGetOptions, aT as MindooDBAppRichTextImmutableString, aU as MindooDBAppRichTextMarkRange, aV as MindooDBAppRichTextMaterializeValue, aW as MindooDBAppRichTextPatch, aX as MindooDBAppRichTextScalar, aY as MindooDBAppRichTextSpliceStep, aZ as MindooDBAppRichTextStep, a_ as MindooDBAppRichTextStepPatch, a$ as MindooDBAppRichTextTextSpan, b0 as MindooDBAppRuntime, b1 as MindooDBAppScanAttachmentOptions, b2 as MindooDBAppScanAttachmentResult, b3 as MindooDBAppScopedDocId, b4 as MindooDBAppScopedDocumentSummary, b5 as MindooDBAppSession, b6 as MindooDBAppShowMenuInput, b7 as MindooDBAppShowMenuResult, b8 as MindooDBAppTextEdit, b9 as MindooDBAppTextPatch, ba as MindooDBAppThemeMode, bb as MindooDBAppUiPreferences, bc as MindooDBAppUpdateDocumentInput, bd as MindooDBAppViewCursorDocumentListResult, be as MindooDBAppViewCursorResult, bf as MindooDBAppViewEntry, bg as MindooDBAppViewEntryKind, bh as MindooDBAppViewNavigator, bi as MindooDBAppViewNavigatorExpansionState, bj as MindooDBAppViewNavigatorOpenOptions, bk as MindooDBAppViewNavigatorPageOptions, bl as MindooDBAppViewNavigatorPageResult, bm as MindooDBAppViewNavigatorRangeQuery, bn as MindooDBAppViewNavigatorSelectionState, bo as MindooDBAppViewUpdateStats, bp as MindooDBAppViewport, bq as MindooDBAppWritableAttachmentStream } from './types-B6vEy1VC.js';
3
+ import { MindooDBAppBooleanExpression } from 'mindoodb-view-language';
3
4
  export { MindooDBAppBooleanExpression, MindooDBAppExpression, MindooDBAppFilterDefinition, MindooDBAppViewCategoryChildrenPageRequest, MindooDBAppViewColumn, MindooDBAppViewColumnRole, MindooDBAppViewDefinition, MindooDBAppViewExpansionState, MindooDBAppViewExpressionBase, MindooDBAppViewExpressionDatePart, MindooDBAppViewExpressionOperation, MindooDBAppViewFieldExpression, MindooDBAppViewIfExpression, MindooDBAppViewLetExpression, MindooDBAppViewLiteralExpression, MindooDBAppViewLookupByPath, MindooDBAppViewOperationExpression, MindooDBAppViewOriginExpression, MindooDBAppViewPageRequest, MindooDBAppViewPageResult, MindooDBAppViewRow, MindooDBAppViewSortDirection, MindooDBAppViewTotalMode, MindooDBAppViewValueExpressionRef, MindooDBAppViewVariableExpression, createViewLanguage } from 'mindoodb-view-language';
5
+ import { MindooDB, MindooQuerySortKey, MindooQueryOptions, MindooQueryResult } from 'mindoodb';
4
6
 
5
7
  /**
6
8
  * Resolves whether Haven can render a built-in preview for an attachment.
@@ -177,4 +179,11 @@ declare class MindooDBTextBuffer {
177
179
  /** Create a local text buffer for one string field in a document. */
178
180
  declare function createMindooDBTextBuffer(options: CreateMindooDBTextBufferOptions): MindooDBTextBuffer;
179
181
 
180
- export { type CreateMindooDBRichTextHandleOptions, type CreateMindooDBTextBufferOptions, MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, MindooDBAppDatabase, MindooDBAppDocument, MindooDBAppRichTextSnapshot, MindooDBAppRichTextSpan, MindooDBRichTextHandle, type MindooDBRichTextHandleChangeListener, type MindooDBRichTextHandleFlushResult, MindooDBTextBuffer, type MindooDBTextBufferFlushResult, abbreviateCanonicalName, canPreviewAttachment, createMindooDBAppBridge, createMindooDBRichTextHandle, createMindooDBTextBuffer, expandAbbreviatedName };
182
+ /**
183
+ * Thin convenience wrapper around `db.query()`: accepts the filter either
184
+ * as a prebuilt expression (from `createViewLanguage()`) or as formula
185
+ * source text, which is parsed with the shared formula parser.
186
+ */
187
+ declare function queryDocuments(db: Pick<MindooDB, "query">, filter: MindooDBAppBooleanExpression | string, sortBy?: MindooQuerySortKey[], options?: MindooQueryOptions): Promise<MindooQueryResult>;
188
+
189
+ export { type CreateMindooDBRichTextHandleOptions, type CreateMindooDBTextBufferOptions, MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, MindooDBAppDatabase, MindooDBAppDocument, MindooDBAppRichTextSnapshot, MindooDBAppRichTextSpan, MindooDBRichTextHandle, type MindooDBRichTextHandleChangeListener, type MindooDBRichTextHandleFlushResult, MindooDBTextBuffer, type MindooDBTextBufferFlushResult, abbreviateCanonicalName, canPreviewAttachment, createMindooDBAppBridge, createMindooDBRichTextHandle, createMindooDBTextBuffer, expandAbbreviatedName, queryDocuments };
package/dist/index.js CHANGED
@@ -1,5 +1,3 @@
1
- import "./chunk-QGM4M3NI.js";
2
-
3
1
  // src/attachmentPreview.ts
4
2
  function canPreviewAttachment(fileName, mimeType) {
5
3
  const normalizedMimeType = mimeType.toLowerCase();
@@ -82,6 +80,9 @@ function expandAbbreviatedName(value) {
82
80
  ].join("/");
83
81
  }
84
82
 
83
+ // src/client/createMindooDBAppBridge.ts
84
+ import { parseMindooDBFormulaBooleanExpression } from "mindoodb-view-language";
85
+
85
86
  // src/client/portRpcClient.ts
86
87
  var PROTOCOL = "mindoodb-app-bridge";
87
88
  function normalizeRpcValue(value, seen = /* @__PURE__ */ new WeakMap()) {
@@ -234,6 +235,9 @@ var PortRpcClient = class {
234
235
  // src/client/createMindooDBAppBridge.ts
235
236
  var PROTOCOL2 = "mindoodb-app-bridge";
236
237
  var DEFAULT_CONNECT_TIMEOUT_MS = 1e4;
238
+ function isMethodNotFoundError(error) {
239
+ return error instanceof Error && error.name === "method-not-found";
240
+ }
237
241
  function toTransferableArrayBuffer(chunk) {
238
242
  return chunk.buffer.slice(
239
243
  chunk.byteOffset,
@@ -249,6 +253,24 @@ function isStreamAckFor(streamId, message) {
249
253
  function isStreamErrorFor(streamId, message) {
250
254
  return message.kind === "stream-error" && message.streamId === streamId;
251
255
  }
256
+ function isQueryResultFor(subscriptionId, message) {
257
+ return message.kind === "query-result" && message.subscriptionId === subscriptionId;
258
+ }
259
+ function isViewChangedFor(navigatorId, message) {
260
+ return message.kind === "view-changed" && message.navigatorId === navigatorId;
261
+ }
262
+ function normalizeDocumentQuery(query) {
263
+ if (!query) {
264
+ return {};
265
+ }
266
+ const { filter, ...rest } = query;
267
+ return {
268
+ ...rest,
269
+ ...filter !== void 0 ? {
270
+ filter: typeof filter === "string" ? parseMindooDBFormulaBooleanExpression(filter) : filter
271
+ } : {}
272
+ };
273
+ }
252
274
  function isThemeChangedMessage(message) {
253
275
  return message.kind === "theme-changed";
254
276
  }
@@ -258,6 +280,9 @@ function isViewportChangedMessage(message) {
258
280
  function isUiPreferencesChangedMessage(message) {
259
281
  return message.kind === "ui-preferences-changed";
260
282
  }
283
+ function isLocaleChangedMessage(message) {
284
+ return message.kind === "locale-changed";
285
+ }
261
286
  function toStreamError(message) {
262
287
  const error = new Error(message.error.message);
263
288
  error.name = message.error.code || "MindooDBAppBridgeStreamError";
@@ -380,6 +405,13 @@ var MindooDBAppViewNavigatorImpl = class {
380
405
  this.viewCursor = result.viewCursor;
381
406
  return this.viewCursor;
382
407
  }
408
+ onDidUpdate(listener) {
409
+ return this.rpc.addMessageListener((message) => {
410
+ if (isViewChangedFor(this.navigatorId, message)) {
411
+ listener(message.stats);
412
+ }
413
+ });
414
+ }
383
415
  async getCurrentEntry() {
384
416
  return await this.call("viewNavigators.current.get");
385
417
  }
@@ -721,6 +753,44 @@ var MindooDBAppDatabaseImpl = class {
721
753
  databaseId: this.databaseId,
722
754
  query: query ?? {}
723
755
  }),
756
+ query: async (query) => await this.rpc.call("documents.query", {
757
+ databaseId: this.databaseId,
758
+ query: normalizeDocumentQuery(query)
759
+ }),
760
+ liveQuery: async (query, onResult) => {
761
+ const { subscriptionId, result } = await this.rpc.call("documents.liveQuery.subscribe", {
762
+ databaseId: this.databaseId,
763
+ query: normalizeDocumentQuery(query)
764
+ });
765
+ let disposed = false;
766
+ const unsubscribe = this.rpc.addMessageListener((message) => {
767
+ if (!disposed && isQueryResultFor(subscriptionId, message)) {
768
+ onResult(message.result);
769
+ }
770
+ });
771
+ onResult(result);
772
+ const subscription = {
773
+ refresh: async () => {
774
+ if (disposed) {
775
+ return;
776
+ }
777
+ await this.rpc.call("documents.liveQuery.refresh", {
778
+ subscriptionId
779
+ });
780
+ },
781
+ dispose: async () => {
782
+ if (disposed) {
783
+ return;
784
+ }
785
+ disposed = true;
786
+ unsubscribe();
787
+ await this.rpc.call("documents.liveQuery.unsubscribe", {
788
+ subscriptionId
789
+ });
790
+ }
791
+ };
792
+ return subscription;
793
+ },
724
794
  getHeadCursor: async () => await this.rpc.call("documents.getHeadCursor", {
725
795
  databaseId: this.databaseId
726
796
  }),
@@ -748,6 +818,30 @@ var MindooDBAppDatabaseImpl = class {
748
818
  databaseId: this.databaseId,
749
819
  input
750
820
  }),
821
+ createMany: async (inputs) => {
822
+ if (inputs.length === 0) {
823
+ return { ids: [] };
824
+ }
825
+ try {
826
+ return await this.rpc.call("documents.createMany", {
827
+ databaseId: this.databaseId,
828
+ inputs
829
+ });
830
+ } catch (error) {
831
+ if (!isMethodNotFoundError(error)) {
832
+ throw error;
833
+ }
834
+ const ids = [];
835
+ for (const input of inputs) {
836
+ const document = await this.rpc.call("documents.create", {
837
+ databaseId: this.databaseId,
838
+ input
839
+ });
840
+ ids.push(document.id);
841
+ }
842
+ return { ids };
843
+ }
844
+ },
751
845
  update: async (docId, patch) => await this.rpc.call("documents.update", {
752
846
  databaseId: this.databaseId,
753
847
  docId,
@@ -757,10 +851,51 @@ var MindooDBAppDatabaseImpl = class {
757
851
  databaseId: this.databaseId,
758
852
  docId
759
853
  }),
854
+ deleteMany: async (docIds) => {
855
+ if (docIds.length === 0) {
856
+ return { ok: true };
857
+ }
858
+ try {
859
+ return await this.rpc.call("documents.deleteMany", {
860
+ databaseId: this.databaseId,
861
+ docIds
862
+ });
863
+ } catch (error) {
864
+ if (!isMethodNotFoundError(error)) {
865
+ throw error;
866
+ }
867
+ for (const docId of docIds) {
868
+ await this.rpc.call("documents.delete", {
869
+ databaseId: this.databaseId,
870
+ docId
871
+ });
872
+ }
873
+ return { ok: true };
874
+ }
875
+ },
760
876
  undelete: async (docId) => await this.rpc.call("documents.undelete", {
761
877
  databaseId: this.databaseId,
762
878
  docId
763
879
  }),
880
+ canCreate: async (input) => await this.rpc.call("documents.canCreate", {
881
+ databaseId: this.databaseId,
882
+ input: input ?? {}
883
+ }),
884
+ canChange: async (docId) => await this.rpc.call("documents.canChange", {
885
+ databaseId: this.databaseId,
886
+ docId
887
+ }),
888
+ canDelete: async (docId) => await this.rpc.call("documents.canDelete", {
889
+ databaseId: this.databaseId,
890
+ docId
891
+ }),
892
+ canUndelete: async (docId) => await this.rpc.call("documents.canUndelete", {
893
+ databaseId: this.databaseId,
894
+ docId
895
+ }),
896
+ getDefaultCreateKeyId: async () => await this.rpc.call("documents.getDefaultCreateKeyId", {
897
+ databaseId: this.databaseId
898
+ }),
764
899
  listHistory: async (docId) => await this.rpc.call("documents.history.list", {
765
900
  databaseId: this.databaseId,
766
901
  docId
@@ -901,6 +1036,36 @@ var MindooDBAppDatabaseImpl = class {
901
1036
  databaseId: this.databaseId
902
1037
  });
903
1038
  }
1039
+ /** Reads the full-text configuration from the synced `dbsetup` document. */
1040
+ async getFulltextSetup() {
1041
+ const result = await this.rpc.call(
1042
+ "database.getFulltextSetup",
1043
+ { databaseId: this.databaseId }
1044
+ );
1045
+ return result.config;
1046
+ }
1047
+ /** Writes (or removes, with `null`) the full-text configuration. */
1048
+ async setFulltextSetup(config) {
1049
+ await this.rpc.call("database.setFulltextSetup", {
1050
+ databaseId: this.databaseId,
1051
+ config
1052
+ });
1053
+ }
1054
+ /** Reads the attachment extraction configuration from the synced `dbsetup` document. */
1055
+ async getExtractionSetup() {
1056
+ const result = await this.rpc.call(
1057
+ "database.getExtractionSetup",
1058
+ { databaseId: this.databaseId }
1059
+ );
1060
+ return result.config;
1061
+ }
1062
+ /** Writes (or removes, with `null`) the attachment extraction configuration. */
1063
+ async setExtractionSetup(config) {
1064
+ await this.rpc.call("database.setExtractionSetup", {
1065
+ databaseId: this.databaseId,
1066
+ config
1067
+ });
1068
+ }
904
1069
  };
905
1070
  var MindooDBAppSessionImpl = class {
906
1071
  constructor(rpc) {
@@ -918,6 +1083,10 @@ var MindooDBAppSessionImpl = class {
918
1083
  async getLaunchContext() {
919
1084
  return await this.rpc.call("session.getLaunchContext", {});
920
1085
  }
1086
+ /** Returns the product names currently licensed in the Haven host. */
1087
+ async getLicensedProducts() {
1088
+ return await this.rpc.call("session.getLicensedProducts", {});
1089
+ }
921
1090
  /** Lists the databases that the host has made available for this app session. */
922
1091
  async listDatabases() {
923
1092
  return await this.rpc.call("session.listDatabases", {});
@@ -985,6 +1154,14 @@ var MindooDBAppSessionImpl = class {
985
1154
  }
986
1155
  });
987
1156
  }
1157
+ /** Subscribe to host-pushed UI language changes. */
1158
+ onLocaleChange(listener) {
1159
+ return this.rpc.addMessageListener((message) => {
1160
+ if (isLocaleChangedMessage(message)) {
1161
+ listener(message.locale);
1162
+ }
1163
+ });
1164
+ }
988
1165
  /** Disconnects from the host and always disposes the underlying port client. */
989
1166
  async disconnect() {
990
1167
  try {
@@ -1345,12 +1522,20 @@ function computeSingleSplice2(previous, next) {
1345
1522
  }
1346
1523
 
1347
1524
  // src/viewLanguage.ts
1525
+ import { parseMindooDBFormulaBooleanExpression as parseMindooDBFormulaBooleanExpression2 } from "mindoodb-view-language";
1348
1526
  import {
1349
1527
  createViewLanguage,
1350
1528
  getMindooDBViewLanguageHelper,
1351
1529
  mindooDBViewLanguageHelpers,
1352
1530
  mindooDBViewLanguageHelpersByName
1353
1531
  } from "mindoodb-view-language";
1532
+ async function queryDocuments(db, filter, sortBy, options) {
1533
+ if (!db.query) {
1534
+ throw new Error("This MindooDB instance does not support ad-hoc queries.");
1535
+ }
1536
+ const expression = typeof filter === "string" ? parseMindooDBFormulaBooleanExpression2(filter) : filter;
1537
+ return db.query({ filter: expression, sortBy }, options);
1538
+ }
1354
1539
  export {
1355
1540
  MindooDBRichTextHandle,
1356
1541
  MindooDBTextBuffer,
@@ -1360,5 +1545,6 @@ export {
1360
1545
  createMindooDBRichTextHandle,
1361
1546
  createMindooDBTextBuffer,
1362
1547
  createViewLanguage,
1363
- expandAbbreviatedName
1548
+ expandAbbreviatedName,
1549
+ queryDocuments
1364
1550
  };
@@ -1,4 +1,4 @@
1
- import { am as MindooDBAppLaunchContext, a2 as MindooDBAppDatabaseInfo, a3 as MindooDBAppDocumentApi, a1 as MindooDBAppCreateViewNavigatorInput, b3 as MindooDBAppViewNavigator, b5 as MindooDBAppViewNavigatorOpenOptions, f as MindooDBAppAttachmentApi, a as MindooDBAppBridge, aT as MindooDBAppSession, x as MindooDBAppBridgeRpcRequest, ad as MindooDBAppHostTheme, ba as MindooDBAppViewport, aZ as MindooDBAppUiPreferences, u as MindooDBAppBridgePortMessage } from '../types-CQt2ObMu.js';
1
+ import { au as MindooDBAppLaunchContext, a7 as MindooDBAppDatabaseInfo, a8 as MindooDBAppDocumentApi, a6 as MindooDBAppCreateViewNavigatorInput, bh as MindooDBAppViewNavigator, bj as MindooDBAppViewNavigatorOpenOptions, h as MindooDBAppAttachmentApi, ai as MindooDBAppFulltextSetup, ah as MindooDBAppExtractionSetup, a as MindooDBAppBridge, b5 as MindooDBAppSession, B as MindooDBAppBridgeRpcRequest, al as MindooDBAppHostTheme, bp as MindooDBAppViewport, bb as MindooDBAppUiPreferences, aK as MindooDBAppQueryResult, bo as MindooDBAppViewUpdateStats, x as MindooDBAppBridgePortMessage } from '../types-B6vEy1VC.js';
2
2
  import 'mindoodb-view-language';
3
3
 
4
4
  type MaybePromise<T> = T | Promise<T>;
@@ -14,6 +14,21 @@ type MockDatabaseMethods = {
14
14
  interface MockMindooDBAppDatabaseDefinition {
15
15
  info: MindooDBAppDatabaseInfo;
16
16
  methods?: MockDatabaseMethods;
17
+ /**
18
+ * Initial full-text configuration returned by `getFulltextSetup()`.
19
+ * `setFulltextSetup()` overwrites it for the lifetime of the handle.
20
+ * Note the mock evaluates `text` query clauses regardless of this
21
+ * config (see TESTING.md) — it exists so apps can test their setup/
22
+ * bootstrap logic.
23
+ */
24
+ fulltextSetup?: MindooDBAppFulltextSetup | null;
25
+ /**
26
+ * Initial extraction configuration returned by `getExtractionSetup()`.
27
+ * `setExtractionSetup()` overwrites it for the lifetime of the handle.
28
+ * The mock runs no extraction service — this exists so apps can test
29
+ * their setup/bootstrap logic.
30
+ */
31
+ extractionSetup?: MindooDBAppExtractionSetup | null;
17
32
  }
18
33
  interface CreateMockMindooDBAppSessionOptions {
19
34
  launchContext?: Partial<MindooDBAppLaunchContext>;
@@ -25,11 +40,13 @@ interface MockMindooDBAppSessionController {
25
40
  session: MindooDBAppSession;
26
41
  getLaunchContext(): MindooDBAppLaunchContext;
27
42
  setLaunchContext(patch?: Partial<MindooDBAppLaunchContext>): MindooDBAppLaunchContext;
43
+ getLicensedProducts(): string[];
28
44
  listDatabases(): MindooDBAppDatabaseInfo[];
29
45
  setDatabases(definitions: MockMindooDBAppDatabaseDefinition[]): void;
30
46
  emitThemeChange(theme: MindooDBAppHostTheme): void;
31
47
  emitViewportChange(viewport: MindooDBAppViewport): void;
32
48
  emitUiPreferencesChange(uiPreferences: MindooDBAppUiPreferences): void;
49
+ emitLocaleChange(locale: string): void;
33
50
  }
34
51
  declare function createMockMindooDBAppSession(options?: CreateMockMindooDBAppSessionOptions): MockMindooDBAppSessionController;
35
52
  declare function createMockMindooDBAppBridge(options?: CreateMockMindooDBAppSessionOptions): MockMindooDBAppSessionController;
@@ -57,6 +74,11 @@ interface FakeBridgeHostController {
57
74
  emitThemeChange(theme: MindooDBAppHostTheme): void;
58
75
  emitViewportChange(viewport: MindooDBAppViewport): void;
59
76
  emitUiPreferencesChange(uiPreferences: MindooDBAppUiPreferences): void;
77
+ emitLocaleChange(locale: string): void;
78
+ /** Push a live-query result to connected apps, as the Haven host would. */
79
+ emitQueryResult(subscriptionId: string, result: MindooDBAppQueryResult): void;
80
+ /** Push a navigator view-changed event to connected apps. */
81
+ emitViewChanged(navigatorId: string, stats: MindooDBAppViewUpdateStats): void;
60
82
  postPortMessage(message: MindooDBAppBridgePortMessage, transfer?: Transferable[]): void;
61
83
  setRequestHandler(method: string, handler: FakeBridgeRequestHandler): void;
62
84
  clearRequestHandler(method: string): void;