mindoodb-app-sdk 0.0.33 → 0.0.36
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 +51 -4
- package/TESTING.md +59 -3
- package/dist/index.d.ts +2 -2
- package/dist/index.js +18 -2
- package/dist/testing/index.d.ts +37 -2
- package/dist/testing/index.js +544 -13
- package/dist/{types-c6uTlJnB.d.ts → types-qW1XwmiZ.d.ts} +75 -2
- package/package.json +10 -6
package/README.md
CHANGED
|
@@ -418,7 +418,8 @@ const history = await db.documents.listHistory(docId);
|
|
|
418
418
|
// identityLabel?,
|
|
419
419
|
// isDeleted,
|
|
420
420
|
// isCurrent,
|
|
421
|
-
// summary
|
|
421
|
+
// summary?,
|
|
422
|
+
// dependencyIds?
|
|
422
423
|
// }
|
|
423
424
|
|
|
424
425
|
// Load the document state at an exact DAG revision
|
|
@@ -446,6 +447,27 @@ const pointInTime = await db.documents.getAtTimestamp(
|
|
|
446
447
|
|
|
447
448
|
Historical snapshots include the document data payload as it existed at that revision. When the snapshot has attachments, `attachments` reflects the historical `_attachments` array for that same revision, including the attachment reference that Haven needs to stop at the correct historical `lastChunkId`.
|
|
448
449
|
|
|
450
|
+
#### What one revision changed
|
|
451
|
+
|
|
452
|
+
To show a diff, you need both sides of a revision. Pass `{ phase: "before" }` to read the state the revision was written against instead of the state it produced:
|
|
453
|
+
|
|
454
|
+
```ts
|
|
455
|
+
const after = await db.documents.getAtRevision(docId, revisionId);
|
|
456
|
+
const before = await db.documents.getAtRevision(docId, revisionId, {
|
|
457
|
+
phase: "before",
|
|
458
|
+
});
|
|
459
|
+
```
|
|
460
|
+
|
|
461
|
+
`before` is always a single document, even when the revision merged concurrent branches: it is the merge of all its parents, which is exactly what its author had loaded. For the document's creation there is no prior state, so `before` reports `state: "missing"`.
|
|
462
|
+
|
|
463
|
+
The `dependencyIds` on each history entry are that revision's parents — the edges of the signed change graph. Since a timeline is only one linearization of that graph, use them to draw or walk the graph itself, and `getAtHeads` to materialize any point in it:
|
|
464
|
+
|
|
465
|
+
```ts
|
|
466
|
+
const merged = await db.documents.getAtHeads(docId, entry.dependencyIds ?? []);
|
|
467
|
+
```
|
|
468
|
+
|
|
469
|
+
An id in `dependencyIds` may name a revision the timeline does not list, because a change that left the document state untouched produces no timeline row. Draw only the edges whose endpoints you have; `getAtHeads` still resolves the full list.
|
|
470
|
+
|
|
449
471
|
### Granular JSON edits
|
|
450
472
|
|
|
451
473
|
When you need to edit nested objects or lists inside a document — not just top-level fields — describe the change as a **granular JSON patch** rather than rewriting the whole document. This is the model behind structured collaborative editing in apps like [`mindoodb-app-teamgrid`](https://github.com/klehmann/mindoodb-app-teamgrid), where two users can insert different rows into the same worksheet on different devices and the merge keeps both sides cleanly.
|
|
@@ -968,9 +990,33 @@ const setup = await db.getFulltextSetup(); // null when never configured
|
|
|
968
990
|
```
|
|
969
991
|
|
|
970
992
|
- 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
|
|
993
|
+
- `attachments: true` indexes attachment text under the synthetic `_attachments` field using the host's extractors (Haven ships anydoc for Office/PDF/… plus plain-text extractors). Restrict a query to attachment content with `text: { query, fields: ["_attachments"] }`.
|
|
972
994
|
- Changing the configuration (including `language`) rebuilds the index in the background; queries during the rebuild report `coverage: "rebuilding"`.
|
|
973
995
|
|
|
996
|
+
**Extracting text from bytes you already have** (requires `attachments`):
|
|
997
|
+
|
|
998
|
+
```ts
|
|
999
|
+
const stream = await db.attachments.openReadStream(docId, fileName);
|
|
1000
|
+
const chunks: Uint8Array[] = [];
|
|
1001
|
+
for (;;) {
|
|
1002
|
+
const chunk = await stream.read();
|
|
1003
|
+
if (chunk === null) break;
|
|
1004
|
+
chunks.push(chunk);
|
|
1005
|
+
}
|
|
1006
|
+
await stream.close();
|
|
1007
|
+
const bytes = concatUint8Arrays(chunks); // your helper
|
|
1008
|
+
|
|
1009
|
+
const { text, handled, format, engine } = await db.attachments.extractText({
|
|
1010
|
+
bytes,
|
|
1011
|
+
mimeType: "application/pdf",
|
|
1012
|
+
fileName,
|
|
1013
|
+
format: "markdown", // default — or "plainText"
|
|
1014
|
+
});
|
|
1015
|
+
if (handled) {
|
|
1016
|
+
console.log(engine, format, text.slice(0, 200));
|
|
1017
|
+
}
|
|
1018
|
+
```
|
|
1019
|
+
|
|
974
1020
|
**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
1021
|
|
|
976
1022
|
```ts
|
|
@@ -1365,7 +1411,7 @@ You do **not** need a full Haven environment to test apps that use `mindoodb-app
|
|
|
1365
1411
|
|
|
1366
1412
|
The SDK ships a dedicated `mindoodb-app-sdk/testing` entrypoint with two levels of test helpers:
|
|
1367
1413
|
|
|
1368
|
-
- **Level 1 -- app tests:** Returns a fake `MindooDBAppSession` and bridge for unit, composable, store, and component tests. No `postMessage` or `MessageChannel` involved.
|
|
1414
|
+
- **Level 1 -- app tests:** Returns a fake `MindooDBAppSession` and bridge for unit, composable, store, and component tests. No `postMessage` or `MessageChannel` involved. With the optional `mindoodb` peer, `createViewNavigator` evaluates view definitions against seeded documents (same VirtualView engine as Haven).
|
|
1369
1415
|
- **Level 2 -- bridge protocol tests:** A fake host harness that exercises the real `createMindooDBAppBridge()` handshake over `postMessage` and `MessageChannel`. Useful for integration-style tests.
|
|
1370
1416
|
|
|
1371
1417
|
Use Level 1 when you are testing app behavior. Use Level 2 when you want to validate the bridge transport itself.
|
|
@@ -1451,7 +1497,8 @@ Connect options: `launchId?`, `targetOrigin?`, `connectTimeoutMs?`.
|
|
|
1451
1497
|
| `undelete(docId)` | `Promise<{ ok: true }>` |
|
|
1452
1498
|
| `listHistory(docId)` | `Promise<MindooDBAppDocumentHistoryEntry[]>` |
|
|
1453
1499
|
| `getAtTimestamp(docId, timestamp)` | `Promise<MindooDBAppHistoricalDocument>` |
|
|
1454
|
-
| `getAtRevision(docId, revisionId)` | `Promise<MindooDBAppHistoricalDocument>`
|
|
1500
|
+
| `getAtRevision(docId, revisionId, opts?)` | `Promise<MindooDBAppHistoricalDocument>` |
|
|
1501
|
+
| `getAtHeads(docId, headIds)` | `Promise<MindooDBAppHistoricalDocument>` |
|
|
1455
1502
|
|
|
1456
1503
|
`getAutomergeSnapshot` and `applyAutomergeChanges` are **discouraged** escape-hatch APIs for binary Automerge sync. Prefer `set`/`unset` and JSON patches (`text`, `richText`, `json`) instead. See [Automerge binary sync (advanced)](#automerge-binary-sync-advanced).
|
|
1457
1504
|
|
package/TESTING.md
CHANGED
|
@@ -15,10 +15,13 @@ import {
|
|
|
15
15
|
The testing entrypoint emulates document storage with real Automerge documents,
|
|
16
16
|
so `@automerge/automerge` is declared as an optional peer dependency. Add it to
|
|
17
17
|
your app's `devDependencies` when you import `mindoodb-app-sdk/testing`
|
|
18
|
-
(the runtime SDK entrypoint does not need it)
|
|
18
|
+
(the runtime SDK entrypoint does not need it).
|
|
19
|
+
|
|
20
|
+
Evaluating VirtualViews also need the optional `mindoodb` peer (same core engine
|
|
21
|
+
Haven uses):
|
|
19
22
|
|
|
20
23
|
```bash
|
|
21
|
-
pnpm add -D @automerge/automerge
|
|
24
|
+
pnpm add -D @automerge/automerge mindoodb
|
|
22
25
|
```
|
|
23
26
|
|
|
24
27
|
## Pick a level
|
|
@@ -99,11 +102,64 @@ When you pass `databases`, the mock session also exposes them through `session.g
|
|
|
99
102
|
Each database entry can provide:
|
|
100
103
|
|
|
101
104
|
- `info`
|
|
105
|
+
- `documents` — seed documents into the mock store (used by `list`/`query` and by evaluating VirtualViews)
|
|
102
106
|
- `methods.documents`
|
|
103
|
-
- `methods.views` for session-level `createView()` and `openView()` calls
|
|
107
|
+
- `methods.views` for session-level `createView()` and `openView()` calls (overrides the default evaluating navigator)
|
|
104
108
|
- `methods.attachments`
|
|
105
109
|
- `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
110
|
|
|
111
|
+
### Evaluating VirtualViews
|
|
112
|
+
|
|
113
|
+
With the optional `mindoodb` peer installed (`pnpm add -D mindoodb`),
|
|
114
|
+
`session.createViewNavigator({ definition, databaseIds })` evaluates the view
|
|
115
|
+
definition against seeded (and later created) documents using the same
|
|
116
|
+
VirtualView engine Haven uses. That means class-scoped filters,
|
|
117
|
+
`childDocumentsBetween`, and multi-database origins work in Vitest without a
|
|
118
|
+
full Haven host:
|
|
119
|
+
|
|
120
|
+
```ts
|
|
121
|
+
import { createViewLanguage } from "mindoodb-view-language";
|
|
122
|
+
import { createMockMindooDBAppSession } from "mindoodb-app-sdk/testing";
|
|
123
|
+
|
|
124
|
+
const v = createViewLanguage();
|
|
125
|
+
const mock = createMockMindooDBAppSession({
|
|
126
|
+
databases: [{
|
|
127
|
+
info: { id: "teacher_core", title: "Core", capabilities: ["read", "views"] },
|
|
128
|
+
documents: [
|
|
129
|
+
{ id: "obs_a", data: { type: "observation", classGroupId: "cls_a" } },
|
|
130
|
+
{ id: "obs_b", data: { type: "observation", classGroupId: "cls_b" } },
|
|
131
|
+
],
|
|
132
|
+
}],
|
|
133
|
+
});
|
|
134
|
+
|
|
135
|
+
const navigator = await mock.session.createViewNavigator({
|
|
136
|
+
databaseIds: ["teacher_core"],
|
|
137
|
+
definition: {
|
|
138
|
+
id: "class-detail-v1",
|
|
139
|
+
title: "Class",
|
|
140
|
+
filter: {
|
|
141
|
+
mode: "expression",
|
|
142
|
+
expression: v.and(
|
|
143
|
+
v.eq(v.field("type"), "observation"),
|
|
144
|
+
v.eq(v.field("classGroupId"), "cls_a"),
|
|
145
|
+
),
|
|
146
|
+
},
|
|
147
|
+
columns: [
|
|
148
|
+
{ name: "type", role: "category", expression: v.field("type") },
|
|
149
|
+
{ name: "sourceType", role: "display", expression: v.field("type") },
|
|
150
|
+
],
|
|
151
|
+
},
|
|
152
|
+
options: { includeCategories: false, includeDocuments: true },
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
await navigator.expandAll();
|
|
156
|
+
const page = await navigator.entriesForward({ limit: 100 });
|
|
157
|
+
// page.entries → only obs_a
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Without `mindoodb`, the testing entrypoint falls back to an empty navigator and
|
|
161
|
+
logs a warning — install the peer for realistic view tests.
|
|
162
|
+
|
|
107
163
|
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
164
|
|
|
109
165
|
```ts
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-
|
|
2
|
-
export { f as MINDOODB_APP_SEAL_SIGNING_DOMAIN, g as MindooDBAppAccessDecision, h as MindooDBAppAccessTier, i as MindooDBAppAttachmentApi, j as MindooDBAppAttachmentChunk, k as MindooDBAppAttachmentInfo, l as MindooDBAppAttachmentPreviewOptions, m as MindooDBAppAttachmentPreviewSession, n as MindooDBAppAutomergeChangesPatch, o as MindooDBAppAutomergeChangesSince, p as MindooDBAppAutomergeGetOptions, q as MindooDBAppAutomergePatchResult, r as MindooDBAppAutomergeSnapshot, s as MindooDBAppBridgeConnectMessage, t as MindooDBAppBridgeConnectOptions, u as MindooDBAppBridgeConnectedMessage, v as MindooDBAppBridgeErrorPayload, w as MindooDBAppBridgeHandshakeErrorMessage, x as MindooDBAppBridgeLocaleChangedMessage, y as MindooDBAppBridgePortMessage, z as MindooDBAppBridgeQueryResultMessage, A as MindooDBAppBridgeRpcError, B as MindooDBAppBridgeRpcMessage, C as MindooDBAppBridgeRpcRequest, D as MindooDBAppBridgeRpcSuccess, E as MindooDBAppBridgeStreamAbortRequest, F as MindooDBAppBridgeStreamAck, G as MindooDBAppBridgeStreamCloseRequest, H as MindooDBAppBridgeStreamError, I as MindooDBAppBridgeStreamMessage, J as MindooDBAppBridgeStreamOpenResult, K as MindooDBAppBridgeStreamReadRequest, L as MindooDBAppBridgeStreamWriteRequest, N as MindooDBAppBridgeThemeChangedMessage, O as MindooDBAppBridgeUiPreferencesChangedMessage, P as MindooDBAppBridgeViewChangedMessage, Q as MindooDBAppBridgeViewportChangedMessage, R as MindooDBAppCapability, S as MindooDBAppConfiguredViewCategorizationStyle, T as MindooDBAppConfiguredViewColumn, U as MindooDBAppConfiguredViewColumnRole, V as MindooDBAppConfiguredViewExpressionMode, W as MindooDBAppConfiguredViewFieldExpression, X as MindooDBAppConfiguredViewFilterDefinition, Y as MindooDBAppConfiguredViewFilterMode, Z as MindooDBAppConfiguredViewFilterRule, _ as MindooDBAppConfiguredViewFormulaExpression, $ as MindooDBAppConfiguredViewFormulaFilterDefinition, a0 as MindooDBAppConfiguredViewPreviewMode, a1 as MindooDBAppConfiguredViewRuleFilterDefinition, a2 as MindooDBAppConfiguredViewRuleMatchMode, a3 as MindooDBAppConfiguredViewRuleOperator, a4 as MindooDBAppConfiguredViewValueExpression, a5 as MindooDBAppCreateDocumentInput, a6 as MindooDBAppCreateViewInput, a7 as MindooDBAppCreateViewNavigatorInput, a8 as MindooDBAppDatabaseInfo, a9 as MindooDBAppDirectoryApi, aa as MindooDBAppDirectoryEntry, ab as MindooDBAppDocumentApi, ac as MindooDBAppDocumentHeadCursorResult, ad as MindooDBAppDocumentHistoryEntry, ae as MindooDBAppDocumentListQuery, af as MindooDBAppDocumentListResult, ag as MindooDBAppDocumentQuery, ah as MindooDBAppDocumentRevisionId, ai as MindooDBAppDocumentScanPreset, aj as MindooDBAppDocumentSummary, ak as MindooDBAppEntryAttachmentRef, al as MindooDBAppEntryProvenance, am as
|
|
1
|
+
import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge, b as MindooDBAppDatabase, c as MindooDBAppDocument, d as MindooDBAppRichTextSpan, e as MindooDBAppRichTextSnapshot } from './types-qW1XwmiZ.js';
|
|
2
|
+
export { f as MINDOODB_APP_SEAL_SIGNING_DOMAIN, g as MindooDBAppAccessDecision, h as MindooDBAppAccessTier, i as MindooDBAppAttachmentApi, j as MindooDBAppAttachmentChunk, k as MindooDBAppAttachmentInfo, l as MindooDBAppAttachmentPreviewOptions, m as MindooDBAppAttachmentPreviewSession, n as MindooDBAppAutomergeChangesPatch, o as MindooDBAppAutomergeChangesSince, p as MindooDBAppAutomergeGetOptions, q as MindooDBAppAutomergePatchResult, r as MindooDBAppAutomergeSnapshot, s as MindooDBAppBridgeConnectMessage, t as MindooDBAppBridgeConnectOptions, u as MindooDBAppBridgeConnectedMessage, v as MindooDBAppBridgeErrorPayload, w as MindooDBAppBridgeHandshakeErrorMessage, x as MindooDBAppBridgeLocaleChangedMessage, y as MindooDBAppBridgePortMessage, z as MindooDBAppBridgeQueryResultMessage, A as MindooDBAppBridgeRpcError, B as MindooDBAppBridgeRpcMessage, C as MindooDBAppBridgeRpcRequest, D as MindooDBAppBridgeRpcSuccess, E as MindooDBAppBridgeStreamAbortRequest, F as MindooDBAppBridgeStreamAck, G as MindooDBAppBridgeStreamCloseRequest, H as MindooDBAppBridgeStreamError, I as MindooDBAppBridgeStreamMessage, J as MindooDBAppBridgeStreamOpenResult, K as MindooDBAppBridgeStreamReadRequest, L as MindooDBAppBridgeStreamWriteRequest, N as MindooDBAppBridgeThemeChangedMessage, O as MindooDBAppBridgeUiPreferencesChangedMessage, P as MindooDBAppBridgeViewChangedMessage, Q as MindooDBAppBridgeViewportChangedMessage, R as MindooDBAppCapability, S as MindooDBAppConfiguredViewCategorizationStyle, T as MindooDBAppConfiguredViewColumn, U as MindooDBAppConfiguredViewColumnRole, V as MindooDBAppConfiguredViewExpressionMode, W as MindooDBAppConfiguredViewFieldExpression, X as MindooDBAppConfiguredViewFilterDefinition, Y as MindooDBAppConfiguredViewFilterMode, Z as MindooDBAppConfiguredViewFilterRule, _ as MindooDBAppConfiguredViewFormulaExpression, $ as MindooDBAppConfiguredViewFormulaFilterDefinition, a0 as MindooDBAppConfiguredViewPreviewMode, a1 as MindooDBAppConfiguredViewRuleFilterDefinition, a2 as MindooDBAppConfiguredViewRuleMatchMode, a3 as MindooDBAppConfiguredViewRuleOperator, a4 as MindooDBAppConfiguredViewValueExpression, a5 as MindooDBAppCreateDocumentInput, a6 as MindooDBAppCreateViewInput, a7 as MindooDBAppCreateViewNavigatorInput, a8 as MindooDBAppDatabaseInfo, a9 as MindooDBAppDirectoryApi, aa as MindooDBAppDirectoryEntry, ab as MindooDBAppDocumentApi, ac as MindooDBAppDocumentHeadCursorResult, ad as MindooDBAppDocumentHistoryEntry, ae as MindooDBAppDocumentListQuery, af as MindooDBAppDocumentListResult, ag as MindooDBAppDocumentQuery, ah as MindooDBAppDocumentRevisionId, ai as MindooDBAppDocumentScanPreset, aj as MindooDBAppDocumentSummary, ak as MindooDBAppEntryAttachmentRef, al as MindooDBAppEntryProvenance, am as MindooDBAppExtractDocumentTextInput, an as MindooDBAppExtractDocumentTextResult, ao as MindooDBAppExtractTextFormat, ap as MindooDBAppExtractionSetup, aq as MindooDBAppFulltextSetup, ar as MindooDBAppHistoricalDocument, as as MindooDBAppHistoryQuery, at as MindooDBAppHostTheme, au as MindooDBAppIdentityApi, av as MindooDBAppJsonListDeletePatch, aw as MindooDBAppJsonListInsertPatch, ax as MindooDBAppJsonPatch, ay as MindooDBAppJsonSetPatch, az as MindooDBAppJsonTextMarkPatch, aA as MindooDBAppJsonTextSplicePatch, aB as MindooDBAppJsonTextUnmarkPatch, aC as MindooDBAppJsonUnsetPatch, aD as MindooDBAppLaunchContext, aE as MindooDBAppLiveQuerySubscription, aF as MindooDBAppMenuAnchor, aG as MindooDBAppMenuApi, aH as MindooDBAppMenuCommandItem, aI as MindooDBAppMenuDismissReason, aJ as MindooDBAppMenuDismissedResult, aK as MindooDBAppMenuItem, aL as MindooDBAppMenuKind, aM as MindooDBAppMenuPlacement, aN as MindooDBAppMenuPointAnchor, aO as MindooDBAppMenuRect, aP as MindooDBAppMenuRectAnchor, aQ as MindooDBAppMenuSelectionResult, aR as MindooDBAppMenuSeparatorItem, aS as MindooDBAppQueryCoverage, aT as MindooDBAppQueryResult, aU as MindooDBAppQueryRow, aV as MindooDBAppQuerySortKey, aW as MindooDBAppQueryTextClause, aX as MindooDBAppReadableAttachmentStream, aY as MindooDBAppResolvedViewDefinition, aZ as MindooDBAppResolvedViewSource, a_ as MindooDBAppRevisionPhase, a$ as MindooDBAppRevisionVerification, b0 as MindooDBAppRichTextBlockSpan, b1 as MindooDBAppRichTextGetOptions, b2 as MindooDBAppRichTextImmutableString, b3 as MindooDBAppRichTextMarkRange, b4 as MindooDBAppRichTextMaterializeValue, b5 as MindooDBAppRichTextPatch, b6 as MindooDBAppRichTextScalar, b7 as MindooDBAppRichTextSpliceStep, b8 as MindooDBAppRichTextStep, b9 as MindooDBAppRichTextStepPatch, ba as MindooDBAppRichTextTextSpan, bb as MindooDBAppRuntime, bc as MindooDBAppScanAttachmentOptions, bd as MindooDBAppScanAttachmentResult, be as MindooDBAppScopedDocId, bf as MindooDBAppScopedDocumentSummary, bg as MindooDBAppSealIntent, bh as MindooDBAppSession, bi as MindooDBAppShowMenuInput, bj as MindooDBAppShowMenuResult, bk as MindooDBAppSignPreview, bl as MindooDBAppSignPreviewScope, bm as MindooDBAppSignStatementInput, bn as MindooDBAppSignStatementResult, bo as MindooDBAppTextEdit, bp as MindooDBAppTextPatch, bq as MindooDBAppThemeMode, br as MindooDBAppTimestampApi, bs as MindooDBAppTimestampInput, bt as MindooDBAppTimestampProvider, bu as MindooDBAppTimestampResult, bv as MindooDBAppUiPreferences, bw as MindooDBAppUpdateDocumentInput, bx as MindooDBAppViewCursorDocumentListResult, by as MindooDBAppViewCursorResult, bz as MindooDBAppViewEntry, bA as MindooDBAppViewEntryKind, bB as MindooDBAppViewNavigator, bC as MindooDBAppViewNavigatorExpansionState, bD as MindooDBAppViewNavigatorOpenOptions, bE as MindooDBAppViewNavigatorPageOptions, bF as MindooDBAppViewNavigatorPageResult, bG as MindooDBAppViewNavigatorRangeQuery, bH as MindooDBAppViewNavigatorSelectionState, bI as MindooDBAppViewUpdateStats, bJ as MindooDBAppViewport, bK as MindooDBAppWritableAttachmentStream } from './types-qW1XwmiZ.js';
|
|
3
3
|
import { MindooDBAppBooleanExpression } from 'mindoodb-view-language';
|
|
4
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
5
|
import { MindooDB, MindooQuerySortKey, MindooQueryOptions, MindooQueryResult } from 'mindoodb';
|
package/dist/index.js
CHANGED
|
@@ -910,10 +910,16 @@ var MindooDBAppDatabaseImpl = class {
|
|
|
910
910
|
docId,
|
|
911
911
|
timestamp
|
|
912
912
|
}),
|
|
913
|
-
getAtRevision: async (docId, revisionId) => await this.rpc.call("documents.history.getAtRevision", {
|
|
913
|
+
getAtRevision: async (docId, revisionId, options) => await this.rpc.call("documents.history.getAtRevision", {
|
|
914
914
|
databaseId: this.databaseId,
|
|
915
915
|
docId,
|
|
916
|
-
revisionId
|
|
916
|
+
revisionId,
|
|
917
|
+
phase: options?.phase
|
|
918
|
+
}),
|
|
919
|
+
getAtHeads: async (docId, headIds) => await this.rpc.call("documents.history.getAtHeads", {
|
|
920
|
+
databaseId: this.databaseId,
|
|
921
|
+
docId,
|
|
922
|
+
headIds
|
|
917
923
|
}),
|
|
918
924
|
listVerification: async (docId, revisionIds) => await this.rpc.call("documents.history.listVerification", {
|
|
919
925
|
databaseId: this.databaseId,
|
|
@@ -1054,6 +1060,16 @@ var MindooDBAppDatabaseImpl = class {
|
|
|
1054
1060
|
timestamp: options?.timestamp,
|
|
1055
1061
|
revisionId: options?.revisionId
|
|
1056
1062
|
});
|
|
1063
|
+
},
|
|
1064
|
+
extractText: async (input) => {
|
|
1065
|
+
return await this.rpc.call("attachments.extractText", {
|
|
1066
|
+
databaseId: this.databaseId,
|
|
1067
|
+
bytes: input.bytes,
|
|
1068
|
+
mimeType: input.mimeType,
|
|
1069
|
+
fileName: input.fileName,
|
|
1070
|
+
format: input.format,
|
|
1071
|
+
languages: input.languages
|
|
1072
|
+
});
|
|
1057
1073
|
}
|
|
1058
1074
|
};
|
|
1059
1075
|
}
|
package/dist/testing/index.d.ts
CHANGED
|
@@ -1,6 +1,26 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { a7 as MindooDBAppCreateViewNavigatorInput, bB as MindooDBAppViewNavigator, aD as MindooDBAppLaunchContext, a8 as MindooDBAppDatabaseInfo, ab as MindooDBAppDocumentApi, bD as MindooDBAppViewNavigatorOpenOptions, i as MindooDBAppAttachmentApi, au as MindooDBAppIdentityApi, br as MindooDBAppTimestampApi, a9 as MindooDBAppDirectoryApi, c as MindooDBAppDocument, aq as MindooDBAppFulltextSetup, ap as MindooDBAppExtractionSetup, a as MindooDBAppBridge, bh as MindooDBAppSession, C as MindooDBAppBridgeRpcRequest, at as MindooDBAppHostTheme, bJ as MindooDBAppViewport, bv as MindooDBAppUiPreferences, aT as MindooDBAppQueryResult, bI as MindooDBAppViewUpdateStats, y as MindooDBAppBridgePortMessage } from '../types-qW1XwmiZ.js';
|
|
2
|
+
import * as mindoodb from 'mindoodb';
|
|
2
3
|
import 'mindoodb-view-language';
|
|
3
4
|
|
|
5
|
+
type EvaluatingViewDocument = {
|
|
6
|
+
origin: string;
|
|
7
|
+
docId: string;
|
|
8
|
+
data: Record<string, unknown>;
|
|
9
|
+
createdAt?: string | null;
|
|
10
|
+
lastModifiedAt?: string | null;
|
|
11
|
+
witnessed?: boolean;
|
|
12
|
+
awaitingWitness?: boolean;
|
|
13
|
+
};
|
|
14
|
+
type MindoodbVirtualViews = typeof mindoodb;
|
|
15
|
+
declare function loadMindoodbForTesting(): Promise<MindoodbVirtualViews | null>;
|
|
16
|
+
/**
|
|
17
|
+
* Build an async SDK navigator that evaluates `input.definition` against the
|
|
18
|
+
* provided materialised documents (same engine Haven uses for bridge views).
|
|
19
|
+
*
|
|
20
|
+
* Returns `null` when the optional `mindoodb` peer is not installed.
|
|
21
|
+
*/
|
|
22
|
+
declare function createEvaluatingViewNavigator(input: MindooDBAppCreateViewNavigatorInput, documents: EvaluatingViewDocument[]): Promise<MindooDBAppViewNavigator | null>;
|
|
23
|
+
|
|
4
24
|
type MaybePromise<T> = T | Promise<T>;
|
|
5
25
|
type MockViewApi = {
|
|
6
26
|
create(input: MindooDBAppCreateViewNavigatorInput): MaybePromise<MindooDBAppViewNavigator>;
|
|
@@ -14,9 +34,23 @@ type MockDatabaseMethods = {
|
|
|
14
34
|
timestamps?: Partial<MindooDBAppTimestampApi>;
|
|
15
35
|
directory?: Partial<MindooDBAppDirectoryApi>;
|
|
16
36
|
};
|
|
37
|
+
interface MockSeedDocument {
|
|
38
|
+
id: string;
|
|
39
|
+
data: Record<string, unknown>;
|
|
40
|
+
updatedAt?: string;
|
|
41
|
+
isDeleted?: boolean;
|
|
42
|
+
heads?: string[];
|
|
43
|
+
attachments?: MindooDBAppDocument["attachments"];
|
|
44
|
+
}
|
|
17
45
|
interface MockMindooDBAppDatabaseDefinition {
|
|
18
46
|
info: MindooDBAppDatabaseInfo;
|
|
19
47
|
methods?: MockDatabaseMethods;
|
|
48
|
+
/**
|
|
49
|
+
* Documents pre-loaded into the mock database store. Used by
|
|
50
|
+
* `documents.list` / `query` and by the evaluating VirtualView navigator
|
|
51
|
+
* (`session.createViewNavigator`).
|
|
52
|
+
*/
|
|
53
|
+
documents?: MockSeedDocument[];
|
|
20
54
|
/**
|
|
21
55
|
* Initial full-text configuration returned by `getFulltextSetup()`.
|
|
22
56
|
* `setFulltextSetup()` overwrites it for the lifetime of the handle.
|
|
@@ -51,6 +85,7 @@ interface MockMindooDBAppSessionController {
|
|
|
51
85
|
emitUiPreferencesChange(uiPreferences: MindooDBAppUiPreferences): void;
|
|
52
86
|
emitLocaleChange(locale: string): void;
|
|
53
87
|
}
|
|
88
|
+
|
|
54
89
|
declare function createMockMindooDBAppSession(options?: CreateMockMindooDBAppSessionOptions): MockMindooDBAppSessionController;
|
|
55
90
|
declare function createMockMindooDBAppBridge(options?: CreateMockMindooDBAppSessionOptions): MockMindooDBAppSessionController;
|
|
56
91
|
type FakeBridgeRequestHandler = (params: unknown, context: {
|
|
@@ -88,4 +123,4 @@ interface FakeBridgeHostController {
|
|
|
88
123
|
}
|
|
89
124
|
declare function createFakeBridgeHost(options?: CreateFakeBridgeHostOptions): FakeBridgeHostController;
|
|
90
125
|
|
|
91
|
-
export { type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, createFakeBridgeHost, createMockMindooDBAppBridge, createMockMindooDBAppSession };
|
|
126
|
+
export { type CreateFakeBridgeHostOptions, type CreateMockMindooDBAppSessionOptions, type EvaluatingViewDocument, type FakeBridgeHostController, type FakeBridgePortMessageHandler, type FakeBridgeRequestHandler, type MockMindooDBAppDatabaseDefinition, type MockMindooDBAppSessionController, type MockSeedDocument, createEvaluatingViewNavigator, createFakeBridgeHost, createMockMindooDBAppBridge, createMockMindooDBAppSession, loadMindoodbForTesting };
|
package/dist/testing/index.js
CHANGED
|
@@ -1,9 +1,470 @@
|
|
|
1
1
|
// src/testing/index.ts
|
|
2
2
|
import * as Automerge from "@automerge/automerge";
|
|
3
3
|
import {
|
|
4
|
-
evaluateExpression,
|
|
4
|
+
evaluateExpression as evaluateExpression2,
|
|
5
5
|
parseMindooDBFormulaBooleanExpression
|
|
6
6
|
} from "mindoodb-view-language";
|
|
7
|
+
|
|
8
|
+
// src/testing/evaluatingViewNavigator.ts
|
|
9
|
+
import { evaluateExpression, getFieldValue } from "mindoodb-view-language";
|
|
10
|
+
var mindoodbModulePromise = null;
|
|
11
|
+
async function loadMindoodbForTesting() {
|
|
12
|
+
if (!mindoodbModulePromise) {
|
|
13
|
+
mindoodbModulePromise = import("mindoodb").then((mod) => mod).catch(() => null);
|
|
14
|
+
}
|
|
15
|
+
return mindoodbModulePromise;
|
|
16
|
+
}
|
|
17
|
+
function toFormulaBoolean(value) {
|
|
18
|
+
if (typeof value === "boolean") return value;
|
|
19
|
+
if (typeof value === "number") return value !== 0;
|
|
20
|
+
if (typeof value === "string") {
|
|
21
|
+
const normalized = value.trim().toLowerCase();
|
|
22
|
+
return normalized !== "" && normalized !== "false" && normalized !== "0" && normalized !== "no";
|
|
23
|
+
}
|
|
24
|
+
return Boolean(value);
|
|
25
|
+
}
|
|
26
|
+
function matchesFilter(mindoodb, definition, doc, origin, createdAt, lastModifiedAt, witnessed, awaitingWitness) {
|
|
27
|
+
void mindoodb;
|
|
28
|
+
if (!definition.filter) return true;
|
|
29
|
+
return toFormulaBoolean(
|
|
30
|
+
evaluateExpression(definition.filter.expression, {
|
|
31
|
+
doc,
|
|
32
|
+
values: doc,
|
|
33
|
+
origin,
|
|
34
|
+
createdAt,
|
|
35
|
+
lastModifiedAt,
|
|
36
|
+
witnessed,
|
|
37
|
+
awaitingWitness,
|
|
38
|
+
variables: {}
|
|
39
|
+
})
|
|
40
|
+
);
|
|
41
|
+
}
|
|
42
|
+
function computeColumnValues(definition, doc, origin, createdAt, lastModifiedAt, witnessed, awaitingWitness) {
|
|
43
|
+
const values = {};
|
|
44
|
+
for (const [key, value] of Object.entries(doc)) {
|
|
45
|
+
if (!key.startsWith("_")) values[key] = value;
|
|
46
|
+
}
|
|
47
|
+
for (const column of definition.columns) {
|
|
48
|
+
const expression = column.expression;
|
|
49
|
+
const value = expression.kind === "field" ? getFieldValue(doc, expression.path) ?? getFieldValue(values, expression.path) : evaluateExpression(expression, {
|
|
50
|
+
doc,
|
|
51
|
+
values,
|
|
52
|
+
origin,
|
|
53
|
+
createdAt,
|
|
54
|
+
lastModifiedAt,
|
|
55
|
+
witnessed,
|
|
56
|
+
awaitingWitness,
|
|
57
|
+
variables: {}
|
|
58
|
+
});
|
|
59
|
+
values[column.name] = value;
|
|
60
|
+
}
|
|
61
|
+
return values;
|
|
62
|
+
}
|
|
63
|
+
function mapSorting(mindoodb, direction) {
|
|
64
|
+
switch (direction) {
|
|
65
|
+
case "ascending":
|
|
66
|
+
return mindoodb.ColumnSorting.ASCENDING;
|
|
67
|
+
case "descending":
|
|
68
|
+
return mindoodb.ColumnSorting.DESCENDING;
|
|
69
|
+
default:
|
|
70
|
+
return mindoodb.ColumnSorting.NONE;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
function mapTotalMode(mindoodb, mode) {
|
|
74
|
+
switch (mode) {
|
|
75
|
+
case "sum":
|
|
76
|
+
return mindoodb.TotalMode.SUM;
|
|
77
|
+
case "average":
|
|
78
|
+
return mindoodb.TotalMode.AVERAGE;
|
|
79
|
+
default:
|
|
80
|
+
return mindoodb.TotalMode.NONE;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
function getCategoryPath(entry) {
|
|
84
|
+
const path = [];
|
|
85
|
+
let current = entry.isCategory() ? entry : entry.getParent();
|
|
86
|
+
while (current && !current.isRoot()) {
|
|
87
|
+
if (current.isCategory()) path.unshift(current.getCategoryValue());
|
|
88
|
+
current = current.getParent();
|
|
89
|
+
}
|
|
90
|
+
return path;
|
|
91
|
+
}
|
|
92
|
+
function serializeEntry(navigator, entry) {
|
|
93
|
+
const parent = entry.getParent();
|
|
94
|
+
return {
|
|
95
|
+
key: entry.getPositionStr(),
|
|
96
|
+
kind: entry.isCategory() ? "category" : "document",
|
|
97
|
+
origin: entry.origin,
|
|
98
|
+
docId: entry.docId,
|
|
99
|
+
level: entry.getLevel(),
|
|
100
|
+
parentKey: parent && !parent.isRoot() ? parent.getPositionStr() : null,
|
|
101
|
+
categoryPath: getCategoryPath(entry),
|
|
102
|
+
categoryValue: entry.isCategory() ? entry.getCategoryValue() : null,
|
|
103
|
+
columnValues: entry.getColumnValues(),
|
|
104
|
+
childCount: entry.getChildCount(),
|
|
105
|
+
descendantDocumentCount: entry.getDescendantDocumentCount(),
|
|
106
|
+
descendantCount: entry.getDescendantCount(),
|
|
107
|
+
descendantCategoryCount: entry.getDescendantCategoryCount(),
|
|
108
|
+
siblingCount: entry.getSiblingCount(),
|
|
109
|
+
childCategoryCount: entry.getChildCategoryCount(),
|
|
110
|
+
childDocumentCount: entry.getChildDocumentCount(),
|
|
111
|
+
position: entry.getPositionStr(),
|
|
112
|
+
expanded: entry.isCategory() ? navigator.isExpanded(entry) : false,
|
|
113
|
+
selected: navigator.isSelected(entry.origin, entry.docId),
|
|
114
|
+
isVisible: true
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async function buildVirtualView(mindoodb, definition, documents, categorizationStyle) {
|
|
118
|
+
const builder = mindoodb.VirtualViewFactory.createView().withCategorizationStyle(
|
|
119
|
+
categorizationStyle === "category_then_document" ? mindoodb.CategorizationStyle.CATEGORY_THEN_DOCUMENT : mindoodb.CategorizationStyle.DOCUMENT_THEN_CATEGORY
|
|
120
|
+
);
|
|
121
|
+
for (const column of definition.columns) {
|
|
122
|
+
const commonOptions = {
|
|
123
|
+
title: column.title,
|
|
124
|
+
isHidden: column.hidden,
|
|
125
|
+
expression: column.expression
|
|
126
|
+
};
|
|
127
|
+
switch (column.role) {
|
|
128
|
+
case "category":
|
|
129
|
+
builder.addCategoryColumn(column.name, {
|
|
130
|
+
...commonOptions,
|
|
131
|
+
sorting: mapSorting(
|
|
132
|
+
mindoodb,
|
|
133
|
+
column.sorting === "none" ? "ascending" : column.sorting
|
|
134
|
+
)
|
|
135
|
+
});
|
|
136
|
+
break;
|
|
137
|
+
case "sort":
|
|
138
|
+
builder.addSortedColumn(
|
|
139
|
+
column.name,
|
|
140
|
+
mapSorting(
|
|
141
|
+
mindoodb,
|
|
142
|
+
!column.sorting || column.sorting === "none" ? "ascending" : column.sorting
|
|
143
|
+
),
|
|
144
|
+
commonOptions
|
|
145
|
+
);
|
|
146
|
+
break;
|
|
147
|
+
case "display":
|
|
148
|
+
if (column.sorting && column.sorting !== "none") {
|
|
149
|
+
builder.addSortedColumn(column.name, mapSorting(mindoodb, column.sorting), commonOptions);
|
|
150
|
+
} else {
|
|
151
|
+
builder.addDisplayColumn(column.name, commonOptions);
|
|
152
|
+
}
|
|
153
|
+
break;
|
|
154
|
+
case "total":
|
|
155
|
+
builder.addTotalColumn(
|
|
156
|
+
column.name,
|
|
157
|
+
mapTotalMode(mindoodb, column.totalMode === "none" ? "sum" : column.totalMode),
|
|
158
|
+
commonOptions
|
|
159
|
+
);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const view = await builder.build();
|
|
164
|
+
const changes = /* @__PURE__ */ new Map();
|
|
165
|
+
for (const document of documents) {
|
|
166
|
+
if (!matchesFilter(
|
|
167
|
+
mindoodb,
|
|
168
|
+
definition,
|
|
169
|
+
document.data,
|
|
170
|
+
document.origin,
|
|
171
|
+
document.createdAt,
|
|
172
|
+
document.lastModifiedAt,
|
|
173
|
+
document.witnessed,
|
|
174
|
+
document.awaitingWitness
|
|
175
|
+
)) {
|
|
176
|
+
continue;
|
|
177
|
+
}
|
|
178
|
+
const change = changes.get(document.origin) ?? new mindoodb.VirtualViewDataChange(document.origin);
|
|
179
|
+
change.addEntry(
|
|
180
|
+
document.docId,
|
|
181
|
+
computeColumnValues(
|
|
182
|
+
definition,
|
|
183
|
+
document.data,
|
|
184
|
+
document.origin,
|
|
185
|
+
document.createdAt,
|
|
186
|
+
document.lastModifiedAt,
|
|
187
|
+
document.witnessed,
|
|
188
|
+
document.awaitingWitness
|
|
189
|
+
)
|
|
190
|
+
);
|
|
191
|
+
changes.set(document.origin, change);
|
|
192
|
+
}
|
|
193
|
+
for (const change of changes.values()) {
|
|
194
|
+
if (change.hasChanges()) view.applyChanges(change);
|
|
195
|
+
}
|
|
196
|
+
view.getRoot();
|
|
197
|
+
return view;
|
|
198
|
+
}
|
|
199
|
+
function createCoreNavigator(mindoodb, view, options) {
|
|
200
|
+
const builder = mindoodb.VirtualViewFactory.createNavigator(view);
|
|
201
|
+
const includeCategories = options?.includeCategories ?? true;
|
|
202
|
+
const includeDocuments = options?.includeDocuments ?? true;
|
|
203
|
+
if (!includeCategories && includeDocuments) builder.documentsOnly();
|
|
204
|
+
else if (includeCategories && !includeDocuments) builder.categoriesOnly();
|
|
205
|
+
if (options?.hideEmptyCategories) builder.hideEmptyCategories();
|
|
206
|
+
if (Array.isArray(options?.rootCategoryPath) && options.rootCategoryPath.length > 0) {
|
|
207
|
+
builder.fromCategory(options.rootCategoryPath.map((part) => String(part)).join("\\"));
|
|
208
|
+
} else if (options?.rootEntryKey) {
|
|
209
|
+
const temp = mindoodb.VirtualViewFactory.createSimpleNavigator(view);
|
|
210
|
+
const rootEntry = temp.getPos(options.rootEntryKey);
|
|
211
|
+
if (rootEntry) builder.fromEntry(rootEntry);
|
|
212
|
+
}
|
|
213
|
+
return builder.build();
|
|
214
|
+
}
|
|
215
|
+
function normalizePageLimit(limit) {
|
|
216
|
+
return Math.max(1, Math.min(1e3, Math.trunc(limit ?? 100)));
|
|
217
|
+
}
|
|
218
|
+
function pageEntries(navigator, direction, options = {}) {
|
|
219
|
+
const entries = [];
|
|
220
|
+
const startOk = options.startPosition ? navigator.gotoPos(options.startPosition) : direction === "forward" ? navigator.gotoFirst() : navigator.gotoLast();
|
|
221
|
+
if (!startOk) {
|
|
222
|
+
return { entries, nextPosition: null, hasMore: false };
|
|
223
|
+
}
|
|
224
|
+
const moveNext = () => {
|
|
225
|
+
if (direction === "forward") {
|
|
226
|
+
return options.selectedOnly ? navigator.gotoNextSelected() : navigator.gotoNext();
|
|
227
|
+
}
|
|
228
|
+
return options.selectedOnly ? navigator.gotoPrevSelected() : navigator.gotoPrev();
|
|
229
|
+
};
|
|
230
|
+
if (options.selectedOnly) {
|
|
231
|
+
const current = navigator.getCurrentEntry();
|
|
232
|
+
if (!current || !navigator.isSelected(current.origin, current.docId)) {
|
|
233
|
+
if (!moveNext()) return { entries, nextPosition: null, hasMore: false };
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
const limit = normalizePageLimit(options.limit);
|
|
237
|
+
let nextPosition = null;
|
|
238
|
+
let hasMore = false;
|
|
239
|
+
while (true) {
|
|
240
|
+
const current = navigator.getCurrentEntry();
|
|
241
|
+
if (!current) break;
|
|
242
|
+
entries.push(serializeEntry(navigator, current));
|
|
243
|
+
if (entries.length >= limit) {
|
|
244
|
+
hasMore = moveNext();
|
|
245
|
+
nextPosition = hasMore ? navigator.getCurrentEntry()?.getPositionStr() ?? null : null;
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
if (!moveNext()) break;
|
|
249
|
+
}
|
|
250
|
+
return { entries, nextPosition, hasMore };
|
|
251
|
+
}
|
|
252
|
+
function resolveEntry(navigator, entryKey) {
|
|
253
|
+
const entry = navigator.getPos(entryKey);
|
|
254
|
+
if (!entry) {
|
|
255
|
+
throw new Error(`Unknown view entry: ${entryKey}`);
|
|
256
|
+
}
|
|
257
|
+
return entry;
|
|
258
|
+
}
|
|
259
|
+
function wrapNavigator(definition, navigator) {
|
|
260
|
+
const updateListeners = /* @__PURE__ */ new Set();
|
|
261
|
+
let viewCursor = null;
|
|
262
|
+
return {
|
|
263
|
+
async getDefinition() {
|
|
264
|
+
return definition;
|
|
265
|
+
},
|
|
266
|
+
async getViewCursor() {
|
|
267
|
+
return viewCursor;
|
|
268
|
+
},
|
|
269
|
+
async refresh() {
|
|
270
|
+
return viewCursor;
|
|
271
|
+
},
|
|
272
|
+
onDidUpdate(listener) {
|
|
273
|
+
updateListeners.add(listener);
|
|
274
|
+
return () => updateListeners.delete(listener);
|
|
275
|
+
},
|
|
276
|
+
async getCurrentEntry() {
|
|
277
|
+
const entry = navigator.getCurrentEntry();
|
|
278
|
+
return entry ? serializeEntry(navigator, entry) : null;
|
|
279
|
+
},
|
|
280
|
+
async gotoFirst() {
|
|
281
|
+
return navigator.gotoFirst();
|
|
282
|
+
},
|
|
283
|
+
async gotoLast() {
|
|
284
|
+
return navigator.gotoLast();
|
|
285
|
+
},
|
|
286
|
+
async gotoNext() {
|
|
287
|
+
return navigator.gotoNext();
|
|
288
|
+
},
|
|
289
|
+
async gotoPrev() {
|
|
290
|
+
return navigator.gotoPrev();
|
|
291
|
+
},
|
|
292
|
+
async gotoNextSibling() {
|
|
293
|
+
return navigator.gotoNextSibling();
|
|
294
|
+
},
|
|
295
|
+
async gotoPrevSibling() {
|
|
296
|
+
return navigator.gotoPrevSibling();
|
|
297
|
+
},
|
|
298
|
+
async gotoParent() {
|
|
299
|
+
return navigator.gotoParent();
|
|
300
|
+
},
|
|
301
|
+
async gotoFirstChild() {
|
|
302
|
+
return navigator.gotoFirstChild();
|
|
303
|
+
},
|
|
304
|
+
async gotoLastChild() {
|
|
305
|
+
return navigator.gotoLastChild();
|
|
306
|
+
},
|
|
307
|
+
async gotoPos(position) {
|
|
308
|
+
return navigator.gotoPos(position);
|
|
309
|
+
},
|
|
310
|
+
async getPos(position) {
|
|
311
|
+
const entry = navigator.getPos(position);
|
|
312
|
+
return entry ? serializeEntry(navigator, entry) : null;
|
|
313
|
+
},
|
|
314
|
+
async findCategoryEntryByParts(parts) {
|
|
315
|
+
const entry = navigator.findCategoryEntryByParts(parts);
|
|
316
|
+
return entry ? serializeEntry(navigator, entry) : null;
|
|
317
|
+
},
|
|
318
|
+
async entriesForward(options) {
|
|
319
|
+
return pageEntries(navigator, "forward", options);
|
|
320
|
+
},
|
|
321
|
+
async entriesBackward(options) {
|
|
322
|
+
return pageEntries(navigator, "backward", options);
|
|
323
|
+
},
|
|
324
|
+
async gotoNextSelected() {
|
|
325
|
+
return navigator.gotoNextSelected();
|
|
326
|
+
},
|
|
327
|
+
async gotoPrevSelected() {
|
|
328
|
+
return navigator.gotoPrevSelected();
|
|
329
|
+
},
|
|
330
|
+
async select(origin, docId, selectParentCategories = false) {
|
|
331
|
+
navigator.select(origin, docId, selectParentCategories);
|
|
332
|
+
},
|
|
333
|
+
async deselect(origin, docId) {
|
|
334
|
+
navigator.deselect(origin, docId);
|
|
335
|
+
},
|
|
336
|
+
async selectAllEntries() {
|
|
337
|
+
navigator.selectAllEntries();
|
|
338
|
+
},
|
|
339
|
+
async deselectAllEntries() {
|
|
340
|
+
navigator.deselectAllEntries();
|
|
341
|
+
},
|
|
342
|
+
async isSelected(origin, docId) {
|
|
343
|
+
return navigator.isSelected(origin, docId);
|
|
344
|
+
},
|
|
345
|
+
async getSelectionState() {
|
|
346
|
+
return {
|
|
347
|
+
selectAllByDefault: navigator.isSelectAllByDefault(),
|
|
348
|
+
entryKeys: Array.from(navigator.getSelectedOrDeselectedEntries())
|
|
349
|
+
};
|
|
350
|
+
},
|
|
351
|
+
async setSelectionState(state) {
|
|
352
|
+
if (state.selectAllByDefault) navigator.selectAllEntries();
|
|
353
|
+
else navigator.deselectAllEntries();
|
|
354
|
+
navigator.setSelectedOrDeselectedEntries(new Set(state.entryKeys));
|
|
355
|
+
},
|
|
356
|
+
async expand(origin, docId) {
|
|
357
|
+
navigator.expand(origin, docId);
|
|
358
|
+
},
|
|
359
|
+
async collapse(origin, docId) {
|
|
360
|
+
navigator.collapse(origin, docId);
|
|
361
|
+
},
|
|
362
|
+
async expandAll() {
|
|
363
|
+
navigator.expandAll();
|
|
364
|
+
},
|
|
365
|
+
async collapseAll() {
|
|
366
|
+
navigator.collapseAll();
|
|
367
|
+
},
|
|
368
|
+
async expandToLevel(level) {
|
|
369
|
+
navigator.expandToLevel(level);
|
|
370
|
+
},
|
|
371
|
+
async isExpanded(entryKey) {
|
|
372
|
+
const entry = navigator.getPos(entryKey);
|
|
373
|
+
return entry ? navigator.isExpanded(entry) : false;
|
|
374
|
+
},
|
|
375
|
+
async getExpansionState() {
|
|
376
|
+
return {
|
|
377
|
+
expandAllByDefault: navigator.isExpandAllByDefault(),
|
|
378
|
+
expandLevel: navigator.getExpandLevel(),
|
|
379
|
+
entryKeys: Array.from(navigator.getExpandedOrCollapsedEntries())
|
|
380
|
+
};
|
|
381
|
+
},
|
|
382
|
+
async setExpansionState(state) {
|
|
383
|
+
if (state.expandAllByDefault) navigator.expandAll();
|
|
384
|
+
else navigator.collapseAll();
|
|
385
|
+
navigator.expandToLevel(state.expandLevel);
|
|
386
|
+
navigator.setExpandedOrCollapsedEntries(new Set(state.entryKeys));
|
|
387
|
+
},
|
|
388
|
+
async childEntries(entryKey, descending) {
|
|
389
|
+
return navigator.childEntries(resolveEntry(navigator, entryKey), descending).map((entry) => serializeEntry(navigator, entry));
|
|
390
|
+
},
|
|
391
|
+
async childCategories(entryKey, descending) {
|
|
392
|
+
return navigator.childCategories(resolveEntry(navigator, entryKey), descending).map((entry) => serializeEntry(navigator, entry));
|
|
393
|
+
},
|
|
394
|
+
async childDocuments(entryKey, descending) {
|
|
395
|
+
return navigator.childDocuments(resolveEntry(navigator, entryKey), descending).map((entry) => serializeEntry(navigator, entry));
|
|
396
|
+
},
|
|
397
|
+
async childCategoriesByKey(entryKey, key, exact, descending) {
|
|
398
|
+
return navigator.childCategoriesByKey(
|
|
399
|
+
resolveEntry(navigator, entryKey),
|
|
400
|
+
String(key ?? ""),
|
|
401
|
+
Boolean(exact),
|
|
402
|
+
descending
|
|
403
|
+
).map((entry) => serializeEntry(navigator, entry));
|
|
404
|
+
},
|
|
405
|
+
async childDocumentsByKey(entryKey, key, exact, descending) {
|
|
406
|
+
return navigator.childDocumentsByKey(
|
|
407
|
+
resolveEntry(navigator, entryKey),
|
|
408
|
+
String(key ?? ""),
|
|
409
|
+
Boolean(exact),
|
|
410
|
+
descending
|
|
411
|
+
).map((entry) => serializeEntry(navigator, entry));
|
|
412
|
+
},
|
|
413
|
+
async childCategoriesBetween(entryKey, range) {
|
|
414
|
+
return navigator.childCategoriesBetween(
|
|
415
|
+
resolveEntry(navigator, entryKey),
|
|
416
|
+
range.startKey,
|
|
417
|
+
range.endKey,
|
|
418
|
+
range.descending
|
|
419
|
+
).map((entry) => serializeEntry(navigator, entry));
|
|
420
|
+
},
|
|
421
|
+
async childDocumentsBetween(entryKey, range) {
|
|
422
|
+
return navigator.childDocumentsBetween(
|
|
423
|
+
resolveEntry(navigator, entryKey),
|
|
424
|
+
range.startKey,
|
|
425
|
+
range.endKey,
|
|
426
|
+
range.descending
|
|
427
|
+
).map((entry) => serializeEntry(navigator, entry));
|
|
428
|
+
},
|
|
429
|
+
async getSortedDocIds(descending) {
|
|
430
|
+
const page = pageEntries(navigator, descending ? "backward" : "forward", { limit: 1e3 });
|
|
431
|
+
return collectSortedDocIds(page.entries);
|
|
432
|
+
},
|
|
433
|
+
async getSortedDocIdsScoped(entryKey, descending) {
|
|
434
|
+
const docs = navigator.childDocuments(resolveEntry(navigator, entryKey), descending);
|
|
435
|
+
return docs.map((entry) => ({ origin: entry.origin, docId: entry.docId }));
|
|
436
|
+
},
|
|
437
|
+
async dispose() {
|
|
438
|
+
updateListeners.clear();
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
function collectSortedDocIds(entries) {
|
|
443
|
+
const results = [];
|
|
444
|
+
const seen = /* @__PURE__ */ new Set();
|
|
445
|
+
for (const entry of entries) {
|
|
446
|
+
if (entry.kind !== "document" || !entry.docId) continue;
|
|
447
|
+
const key = `${entry.origin}:${entry.docId}`;
|
|
448
|
+
if (seen.has(key)) continue;
|
|
449
|
+
seen.add(key);
|
|
450
|
+
results.push({ origin: entry.origin, docId: entry.docId });
|
|
451
|
+
}
|
|
452
|
+
return results;
|
|
453
|
+
}
|
|
454
|
+
async function createEvaluatingViewNavigator(input, documents) {
|
|
455
|
+
const mindoodb = await loadMindoodbForTesting();
|
|
456
|
+
if (!mindoodb) return null;
|
|
457
|
+
const view = await buildVirtualView(
|
|
458
|
+
mindoodb,
|
|
459
|
+
input.definition,
|
|
460
|
+
documents,
|
|
461
|
+
input.categorizationStyle
|
|
462
|
+
);
|
|
463
|
+
const navigator = createCoreNavigator(mindoodb, view, input.options);
|
|
464
|
+
return wrapNavigator(input.definition, navigator);
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
// src/testing/index.ts
|
|
7
468
|
var PROTOCOL = "mindoodb-app-bridge";
|
|
8
469
|
var MOCK_SIGNING_PUBLIC_KEY_PEM = "-----BEGIN PUBLIC KEY-----\nMCowBQYDK2VwAyEAmockmockmockmockmockmockmockmockmockmockmoc=\n-----END PUBLIC KEY-----\n";
|
|
9
470
|
function createBridgeErrorPayload(error, fallbackCode = "bridge-error") {
|
|
@@ -378,7 +839,7 @@ function persistMockAutomergeDocument(document, automergeDoc) {
|
|
|
378
839
|
document.data = structuredClone(automergeDoc);
|
|
379
840
|
document.heads = Automerge.getHeads(automergeDoc);
|
|
380
841
|
}
|
|
381
|
-
function
|
|
842
|
+
function getFieldValue2(source, field) {
|
|
382
843
|
return field.split(".").reduce((current, part) => {
|
|
383
844
|
if (current && typeof current === "object" && part in current) {
|
|
384
845
|
return current[part];
|
|
@@ -391,7 +852,7 @@ function matchesDocumentFilter(document, filter) {
|
|
|
391
852
|
return true;
|
|
392
853
|
}
|
|
393
854
|
return Object.entries(filter).every(
|
|
394
|
-
([field, expected]) =>
|
|
855
|
+
([field, expected]) => getFieldValue2(document.data, field) === expected
|
|
395
856
|
);
|
|
396
857
|
}
|
|
397
858
|
function matchesMockIdPrefix(docId, idPrefix) {
|
|
@@ -454,7 +915,7 @@ function computeMockTextScore(document, clause) {
|
|
|
454
915
|
if (terms.length === 0) {
|
|
455
916
|
return void 0;
|
|
456
917
|
}
|
|
457
|
-
const haystack = clause.fields ? clause.fields.map((field) => collectMockText(
|
|
918
|
+
const haystack = clause.fields ? clause.fields.map((field) => collectMockText(getFieldValue2(document.data, field))).join(" ") : collectMockText(
|
|
458
919
|
Object.fromEntries(
|
|
459
920
|
Object.entries(document.data).filter(([key]) => !key.startsWith("_"))
|
|
460
921
|
)
|
|
@@ -497,14 +958,14 @@ function runMockDocumentQuery(storedDocuments, databaseId, query) {
|
|
|
497
958
|
origin: databaseId,
|
|
498
959
|
variables: {}
|
|
499
960
|
};
|
|
500
|
-
if (filter && !mockExpressionToBoolean(
|
|
961
|
+
if (filter && !mockExpressionToBoolean(evaluateExpression2(filter, context))) {
|
|
501
962
|
continue;
|
|
502
963
|
}
|
|
503
964
|
const sortValues = sortBy.map((key) => {
|
|
504
965
|
if (key.special === "textScore") {
|
|
505
966
|
return textScore ?? 0;
|
|
506
967
|
}
|
|
507
|
-
return key.expression ?
|
|
968
|
+
return key.expression ? evaluateExpression2(key.expression, context) : getFieldValue2(document.data, key.field ?? "");
|
|
508
969
|
});
|
|
509
970
|
matches.push({ document, sortValues, textScore });
|
|
510
971
|
}
|
|
@@ -531,7 +992,7 @@ function runMockDocumentQuery(storedDocuments, databaseId, query) {
|
|
|
531
992
|
fields: query?.fields ? Object.fromEntries(
|
|
532
993
|
query.fields.map((field) => [
|
|
533
994
|
field,
|
|
534
|
-
|
|
995
|
+
getFieldValue2(document.data, field)
|
|
535
996
|
])
|
|
536
997
|
) : structuredClone(document.data),
|
|
537
998
|
lastModified: document.updatedAt ? Date.parse(document.updatedAt) || 0 : 0,
|
|
@@ -760,6 +1221,16 @@ function createDatabaseHandle(definition) {
|
|
|
760
1221
|
let changeCounter = 0;
|
|
761
1222
|
const defaultViewFactory = async () => createDefaultViewNavigator();
|
|
762
1223
|
const storedDocuments = /* @__PURE__ */ new Map();
|
|
1224
|
+
for (const seed of definition.documents ?? []) {
|
|
1225
|
+
storedDocuments.set(seed.id, {
|
|
1226
|
+
id: seed.id,
|
|
1227
|
+
data: structuredClone(seed.data),
|
|
1228
|
+
heads: seed.heads ? [...seed.heads] : void 0,
|
|
1229
|
+
attachments: seed.attachments ? structuredClone(seed.attachments) : [],
|
|
1230
|
+
updatedAt: seed.updatedAt ?? (/* @__PURE__ */ new Date()).toISOString(),
|
|
1231
|
+
isDeleted: seed.isDeleted ?? false
|
|
1232
|
+
});
|
|
1233
|
+
}
|
|
763
1234
|
const liveQuerySubscriptions = /* @__PURE__ */ new Set();
|
|
764
1235
|
const notifyLiveQueries = () => {
|
|
765
1236
|
for (const subscription of liveQuerySubscriptions) {
|
|
@@ -832,7 +1303,7 @@ function createDatabaseHandle(definition) {
|
|
|
832
1303
|
const projectedData = query?.fields ? Object.fromEntries(
|
|
833
1304
|
query.fields.map((field) => [
|
|
834
1305
|
field,
|
|
835
|
-
|
|
1306
|
+
getFieldValue2(document.data, field)
|
|
836
1307
|
])
|
|
837
1308
|
) : document.data;
|
|
838
1309
|
return {
|
|
@@ -1077,6 +1548,16 @@ function createDatabaseHandle(definition) {
|
|
|
1077
1548
|
attachments: []
|
|
1078
1549
|
};
|
|
1079
1550
|
},
|
|
1551
|
+
async getAtHeads(docId, _headIds) {
|
|
1552
|
+
return {
|
|
1553
|
+
id: docId,
|
|
1554
|
+
timestamp: Date.now(),
|
|
1555
|
+
heads: [],
|
|
1556
|
+
state: "missing",
|
|
1557
|
+
data: null,
|
|
1558
|
+
attachments: []
|
|
1559
|
+
};
|
|
1560
|
+
},
|
|
1080
1561
|
async listVerification() {
|
|
1081
1562
|
return [];
|
|
1082
1563
|
}
|
|
@@ -1171,12 +1652,22 @@ function createDatabaseHandle(definition) {
|
|
|
1171
1652
|
},
|
|
1172
1653
|
async openPreview(_docId, _attachmentName, _options) {
|
|
1173
1654
|
return { ok: true };
|
|
1655
|
+
},
|
|
1656
|
+
async extractText(input) {
|
|
1657
|
+
const format = input.format ?? "markdown";
|
|
1658
|
+
const text = new TextDecoder("utf-8", { fatal: false }).decode(input.bytes);
|
|
1659
|
+
return {
|
|
1660
|
+
text,
|
|
1661
|
+
handled: true,
|
|
1662
|
+
format,
|
|
1663
|
+
engine: "mock-utf-8"
|
|
1664
|
+
};
|
|
1174
1665
|
}
|
|
1175
1666
|
};
|
|
1176
1667
|
const methods = definition.methods ?? {};
|
|
1177
1668
|
let fulltextSetup = definition.fulltextSetup ?? null;
|
|
1178
1669
|
let extractionSetup = definition.extractionSetup ?? null;
|
|
1179
|
-
|
|
1670
|
+
const databaseHandle = {
|
|
1180
1671
|
async info() {
|
|
1181
1672
|
return {
|
|
1182
1673
|
...definition.info,
|
|
@@ -1216,6 +1707,15 @@ function createDatabaseHandle(definition) {
|
|
|
1216
1707
|
extractionSetup = config === null ? null : { ...config };
|
|
1217
1708
|
}
|
|
1218
1709
|
};
|
|
1710
|
+
return {
|
|
1711
|
+
handle: databaseHandle,
|
|
1712
|
+
listViewDocuments: () => Array.from(storedDocuments.values()).filter((document) => !document.isDeleted).map((document) => ({
|
|
1713
|
+
origin: definition.info.id,
|
|
1714
|
+
docId: document.id,
|
|
1715
|
+
data: structuredClone(document.data),
|
|
1716
|
+
createdAt: document.updatedAt ?? null
|
|
1717
|
+
}))
|
|
1718
|
+
};
|
|
1219
1719
|
}
|
|
1220
1720
|
function createMockSessionState(options = {}) {
|
|
1221
1721
|
let launchContext = createDefaultLaunchContext(options.launchContext);
|
|
@@ -1224,6 +1724,7 @@ function createMockSessionState(options = {}) {
|
|
|
1224
1724
|
const uiPreferencesListeners = /* @__PURE__ */ new Set();
|
|
1225
1725
|
const localeListeners = /* @__PURE__ */ new Set();
|
|
1226
1726
|
const databaseHandles = /* @__PURE__ */ new Map();
|
|
1727
|
+
const databaseViewDocumentLists = /* @__PURE__ */ new Map();
|
|
1227
1728
|
const databaseViewApis = /* @__PURE__ */ new Map();
|
|
1228
1729
|
const sessionViews = /* @__PURE__ */ new Map();
|
|
1229
1730
|
let activeMenuResolve = null;
|
|
@@ -1250,15 +1751,27 @@ function createMockSessionState(options = {}) {
|
|
|
1250
1751
|
};
|
|
1251
1752
|
const setDatabases = (definitions) => {
|
|
1252
1753
|
databaseHandles.clear();
|
|
1754
|
+
databaseViewDocumentLists.clear();
|
|
1253
1755
|
databaseViewApis.clear();
|
|
1254
1756
|
databaseInfos = definitions.map((definition) => ({
|
|
1255
1757
|
...definition.info,
|
|
1256
1758
|
capabilities: [...definition.info.capabilities]
|
|
1257
1759
|
}));
|
|
1258
1760
|
for (const definition of definitions) {
|
|
1259
|
-
|
|
1761
|
+
const created = createDatabaseHandle(definition);
|
|
1762
|
+
databaseHandles.set(definition.info.id, created.handle);
|
|
1763
|
+
databaseViewDocumentLists.set(definition.info.id, created.listViewDocuments);
|
|
1260
1764
|
databaseViewApis.set(definition.info.id, {
|
|
1261
|
-
async create(
|
|
1765
|
+
async create(input) {
|
|
1766
|
+
const documents = input.databaseIds.flatMap((databaseId) => {
|
|
1767
|
+
const list = databaseViewDocumentLists.get(databaseId);
|
|
1768
|
+
return list ? list() : [];
|
|
1769
|
+
});
|
|
1770
|
+
const evaluating = await createEvaluatingViewNavigator(input, documents);
|
|
1771
|
+
if (evaluating) return evaluating;
|
|
1772
|
+
console.warn(
|
|
1773
|
+
"[mindoodb-app-sdk/testing] mindoodb peer not available; using empty view navigator. Install mindoodb as a devDependency for evaluating VirtualViews."
|
|
1774
|
+
);
|
|
1262
1775
|
return await createDefaultViewNavigator();
|
|
1263
1776
|
},
|
|
1264
1777
|
async open(_viewId) {
|
|
@@ -1750,7 +2263,13 @@ function createFakeBridgeHost(options = {}) {
|
|
|
1750
2263
|
case "documents.history.getAtRevision":
|
|
1751
2264
|
return await state.getDatabase(String(params.databaseId)).documents.getAtRevision(
|
|
1752
2265
|
String(params.docId),
|
|
1753
|
-
String(params.revisionId)
|
|
2266
|
+
String(params.revisionId),
|
|
2267
|
+
params.phase === "before" ? { phase: "before" } : void 0
|
|
2268
|
+
);
|
|
2269
|
+
case "documents.history.getAtHeads":
|
|
2270
|
+
return await state.getDatabase(String(params.databaseId)).documents.getAtHeads(
|
|
2271
|
+
String(params.docId),
|
|
2272
|
+
Array.isArray(params.headIds) ? params.headIds.map(String) : []
|
|
1754
2273
|
);
|
|
1755
2274
|
case "documents.history.listVerification":
|
|
1756
2275
|
return await state.getDatabase(String(params.databaseId)).documents.listVerification(
|
|
@@ -1815,6 +2334,16 @@ function createFakeBridgeHost(options = {}) {
|
|
|
1815
2334
|
String(params.attachmentName),
|
|
1816
2335
|
typeof params.revisionId === "string" ? { revisionId: params.revisionId } : typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
|
|
1817
2336
|
);
|
|
2337
|
+
case "attachments.extractText":
|
|
2338
|
+
return await state.getDatabase(String(params.databaseId)).attachments.extractText({
|
|
2339
|
+
bytes: params.bytes instanceof Uint8Array ? params.bytes : new Uint8Array(
|
|
2340
|
+
params.bytes instanceof ArrayBuffer ? params.bytes : Array.isArray(params.bytes) ? params.bytes : []
|
|
2341
|
+
),
|
|
2342
|
+
mimeType: typeof params.mimeType === "string" ? params.mimeType : "",
|
|
2343
|
+
fileName: typeof params.fileName === "string" ? params.fileName : void 0,
|
|
2344
|
+
format: params.format === "plainText" || params.format === "markdown" ? params.format : void 0,
|
|
2345
|
+
languages: Array.isArray(params.languages) ? params.languages.filter((entry) => typeof entry === "string") : void 0
|
|
2346
|
+
});
|
|
1818
2347
|
case "attachments.preparePreviewSession":
|
|
1819
2348
|
return await state.getDatabase(String(params.databaseId)).attachments.preparePreviewSession(
|
|
1820
2349
|
String(params.docId),
|
|
@@ -2164,7 +2693,9 @@ function createFakeBridgeHost(options = {}) {
|
|
|
2164
2693
|
return controller;
|
|
2165
2694
|
}
|
|
2166
2695
|
export {
|
|
2696
|
+
createEvaluatingViewNavigator,
|
|
2167
2697
|
createFakeBridgeHost,
|
|
2168
2698
|
createMockMindooDBAppBridge,
|
|
2169
|
-
createMockMindooDBAppSession
|
|
2699
|
+
createMockMindooDBAppSession,
|
|
2700
|
+
loadMindoodbForTesting
|
|
2170
2701
|
};
|
|
@@ -208,7 +208,29 @@ interface MindooDBAppDocumentHistoryEntry {
|
|
|
208
208
|
isDeleted: boolean;
|
|
209
209
|
isCurrent: boolean;
|
|
210
210
|
summary?: string;
|
|
211
|
+
/**
|
|
212
|
+
* The revisions this one was written on top of — the edges of the signed
|
|
213
|
+
* change graph, in the same id space as {@link revisionId}. More than one id
|
|
214
|
+
* means this revision merged concurrent branches.
|
|
215
|
+
*
|
|
216
|
+
* A timeline is a linearization of that graph, so an id here may name a
|
|
217
|
+
* revision the timeline does not list (a change that left the document state
|
|
218
|
+
* untouched produces no timeline row). Draw only the edges whose endpoints you
|
|
219
|
+
* have; use {@link MindooDBAppDocumentHistoryApi.getAtHeads} to reconstruct
|
|
220
|
+
* state from the full list.
|
|
221
|
+
*/
|
|
222
|
+
dependencyIds?: string[];
|
|
211
223
|
}
|
|
224
|
+
/**
|
|
225
|
+
* Which side of a revision to read: the state it produced (`after`, the
|
|
226
|
+
* default), or the state it was written against (`before`).
|
|
227
|
+
*
|
|
228
|
+
* `before` is a single document even for a revision that merged several
|
|
229
|
+
* branches: it is the merge of all its parents, which is what its author had
|
|
230
|
+
* loaded. For the document's creation there is no prior state, so `before`
|
|
231
|
+
* reports a `missing` snapshot.
|
|
232
|
+
*/
|
|
233
|
+
type MindooDBAppRevisionPhase = "before" | "after";
|
|
212
234
|
/**
|
|
213
235
|
* The cryptographic record behind one revision, as it sits in the append-only
|
|
214
236
|
* store — what a seal or an audit needs and what {@link MindooDBAppDocumentHistoryEntry}
|
|
@@ -1274,8 +1296,26 @@ interface MindooDBAppDocumentApi {
|
|
|
1274
1296
|
* identifiers — the preferred way to load historical states and the value
|
|
1275
1297
|
* to pass to historical attachment APIs. Requires the `history`
|
|
1276
1298
|
* capability.
|
|
1299
|
+
*
|
|
1300
|
+
* Pass `{ phase: "before" }` to read the state the revision was written
|
|
1301
|
+
* against instead of the state it produced, which is how you show what one
|
|
1302
|
+
* revision changed. See {@link MindooDBAppRevisionPhase}.
|
|
1303
|
+
*/
|
|
1304
|
+
getAtRevision(docId: string, revisionId: MindooDBAppDocumentRevisionId, options?: {
|
|
1305
|
+
phase?: MindooDBAppRevisionPhase;
|
|
1306
|
+
}): Promise<MindooDBAppHistoricalDocument>;
|
|
1307
|
+
/**
|
|
1308
|
+
* Read-only snapshot of the document as it stood at a set of concurrent
|
|
1309
|
+
* revisions: the merge of those heads, with nothing that came after them.
|
|
1310
|
+
*
|
|
1311
|
+
* Use it to reconstruct a specific point in the change graph rather than in
|
|
1312
|
+
* the timeline — for example, pass a revision's
|
|
1313
|
+
* {@link MindooDBAppDocumentHistoryEntry.dependencyIds} to see exactly the
|
|
1314
|
+
* document its author was editing. An empty or unresolvable head list means
|
|
1315
|
+
* there was no document yet and reports a `missing` snapshot. Requires the
|
|
1316
|
+
* `history` capability.
|
|
1277
1317
|
*/
|
|
1278
|
-
|
|
1318
|
+
getAtHeads(docId: string, headIds: MindooDBAppDocumentRevisionId[]): Promise<MindooDBAppHistoricalDocument>;
|
|
1279
1319
|
/**
|
|
1280
1320
|
* The signatures and witness receipts behind a document's revisions —
|
|
1281
1321
|
* everything {@link listHistory} leaves out because a timeline UI does not
|
|
@@ -1693,6 +1733,32 @@ interface MindooDBAppViewNavigator {
|
|
|
1693
1733
|
* `timestamp`/`revisionId` options) additionally require `history`, and
|
|
1694
1734
|
* mutations (`openWriteStream`, `remove`, `scan`) require `update`.
|
|
1695
1735
|
*/
|
|
1736
|
+
/**
|
|
1737
|
+
* Output format for {@link MindooDBAppAttachmentApi.extractText}.
|
|
1738
|
+
* `"markdown"` (default) keeps anydoc's GFM; `"plainText"` strips markup.
|
|
1739
|
+
* OCR / plain-file paths return the same string for either value.
|
|
1740
|
+
*/
|
|
1741
|
+
type MindooDBAppExtractTextFormat = "markdown" | "plainText";
|
|
1742
|
+
/** Bytes-in extraction request for {@link MindooDBAppAttachmentApi.extractText}. */
|
|
1743
|
+
interface MindooDBAppExtractDocumentTextInput {
|
|
1744
|
+
bytes: Uint8Array;
|
|
1745
|
+
mimeType: string;
|
|
1746
|
+
fileName?: string;
|
|
1747
|
+
/** Default `"markdown"`. */
|
|
1748
|
+
format?: MindooDBAppExtractTextFormat;
|
|
1749
|
+
/** Optional OCR language hints when the host falls back to OCR. */
|
|
1750
|
+
languages?: string[];
|
|
1751
|
+
}
|
|
1752
|
+
/** Result of {@link MindooDBAppAttachmentApi.extractText}. */
|
|
1753
|
+
interface MindooDBAppExtractDocumentTextResult {
|
|
1754
|
+
text: string;
|
|
1755
|
+
/** False when the host has no extractor for this format. */
|
|
1756
|
+
handled: boolean;
|
|
1757
|
+
/** Resolved output format (defaults to `"markdown"`). */
|
|
1758
|
+
format: MindooDBAppExtractTextFormat;
|
|
1759
|
+
/** Engine label, e.g. `anydoc@0.1.2` or `tesseract`. */
|
|
1760
|
+
engine?: string;
|
|
1761
|
+
}
|
|
1696
1762
|
interface MindooDBAppAttachmentApi {
|
|
1697
1763
|
/**
|
|
1698
1764
|
* Attachment metadata of a document. Pass `options.revisionId` (preferred
|
|
@@ -1738,6 +1804,13 @@ interface MindooDBAppAttachmentApi {
|
|
|
1738
1804
|
openPreview(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<{
|
|
1739
1805
|
ok: true;
|
|
1740
1806
|
}>;
|
|
1807
|
+
/**
|
|
1808
|
+
* Extract searchable / displayable text from document bytes the app already
|
|
1809
|
+
* holds (e.g. after {@link openReadStream}). Haven runs anydoc for Office/PDF
|
|
1810
|
+
* (Markdown by default), UTF-8 decode for plain text, and OCR for images /
|
|
1811
|
+
* scanned PDFs. Requires the `attachments` capability.
|
|
1812
|
+
*/
|
|
1813
|
+
extractText(input: MindooDBAppExtractDocumentTextInput): Promise<MindooDBAppExtractDocumentTextResult>;
|
|
1741
1814
|
}
|
|
1742
1815
|
/** Database handle returned from `session.openDatabase()`. */
|
|
1743
1816
|
interface MindooDBAppDatabase {
|
|
@@ -1885,4 +1958,4 @@ interface MindooDBAppBridge {
|
|
|
1885
1958
|
connect(options?: MindooDBAppBridgeConnectOptions): Promise<MindooDBAppSession>;
|
|
1886
1959
|
}
|
|
1887
1960
|
|
|
1888
|
-
export { type MindooDBAppConfiguredViewFormulaFilterDefinition as $, type MindooDBAppBridgeRpcError as A, type MindooDBAppBridgeRpcMessage as B, type MindooDBAppBridgeRpcRequest as C, type MindooDBAppBridgeRpcSuccess as D, type MindooDBAppBridgeStreamAbortRequest as E, type MindooDBAppBridgeStreamAck as F, type MindooDBAppBridgeStreamCloseRequest as G, type MindooDBAppBridgeStreamError as H, type MindooDBAppBridgeStreamMessage as I, type MindooDBAppBridgeStreamOpenResult as J, type MindooDBAppBridgeStreamReadRequest as K, type MindooDBAppBridgeStreamWriteRequest as L, type MindooDBAppAttachmentPreviewMode as M, type MindooDBAppBridgeThemeChangedMessage as N, type MindooDBAppBridgeUiPreferencesChangedMessage as O, type MindooDBAppBridgeViewChangedMessage as P, type MindooDBAppBridgeViewportChangedMessage as Q, type MindooDBAppCapability as R, type MindooDBAppConfiguredViewCategorizationStyle as S, type MindooDBAppConfiguredViewColumn as T, type MindooDBAppConfiguredViewColumnRole as U, type MindooDBAppConfiguredViewExpressionMode as V, type MindooDBAppConfiguredViewFieldExpression as W, type MindooDBAppConfiguredViewFilterDefinition as X, type MindooDBAppConfiguredViewFilterMode as Y, type MindooDBAppConfiguredViewFilterRule as Z, type MindooDBAppConfiguredViewFormulaExpression as _, type MindooDBAppBridge as a, type
|
|
1961
|
+
export { type MindooDBAppConfiguredViewFormulaFilterDefinition as $, type MindooDBAppBridgeRpcError as A, type MindooDBAppBridgeRpcMessage as B, type MindooDBAppBridgeRpcRequest as C, type MindooDBAppBridgeRpcSuccess as D, type MindooDBAppBridgeStreamAbortRequest as E, type MindooDBAppBridgeStreamAck as F, type MindooDBAppBridgeStreamCloseRequest as G, type MindooDBAppBridgeStreamError as H, type MindooDBAppBridgeStreamMessage as I, type MindooDBAppBridgeStreamOpenResult as J, type MindooDBAppBridgeStreamReadRequest as K, type MindooDBAppBridgeStreamWriteRequest as L, type MindooDBAppAttachmentPreviewMode as M, type MindooDBAppBridgeThemeChangedMessage as N, type MindooDBAppBridgeUiPreferencesChangedMessage as O, type MindooDBAppBridgeViewChangedMessage as P, type MindooDBAppBridgeViewportChangedMessage as Q, type MindooDBAppCapability as R, type MindooDBAppConfiguredViewCategorizationStyle as S, type MindooDBAppConfiguredViewColumn as T, type MindooDBAppConfiguredViewColumnRole as U, type MindooDBAppConfiguredViewExpressionMode as V, type MindooDBAppConfiguredViewFieldExpression as W, type MindooDBAppConfiguredViewFilterDefinition as X, type MindooDBAppConfiguredViewFilterMode as Y, type MindooDBAppConfiguredViewFilterRule as Z, type MindooDBAppConfiguredViewFormulaExpression as _, type MindooDBAppBridge as a, type MindooDBAppRevisionVerification as a$, type MindooDBAppConfiguredViewPreviewMode as a0, type MindooDBAppConfiguredViewRuleFilterDefinition as a1, type MindooDBAppConfiguredViewRuleMatchMode as a2, type MindooDBAppConfiguredViewRuleOperator as a3, type MindooDBAppConfiguredViewValueExpression as a4, type MindooDBAppCreateDocumentInput as a5, type MindooDBAppCreateViewInput as a6, type MindooDBAppCreateViewNavigatorInput as a7, type MindooDBAppDatabaseInfo as a8, type MindooDBAppDirectoryApi as a9, type MindooDBAppJsonTextSplicePatch as aA, type MindooDBAppJsonTextUnmarkPatch as aB, type MindooDBAppJsonUnsetPatch as aC, type MindooDBAppLaunchContext as aD, type MindooDBAppLiveQuerySubscription as aE, type MindooDBAppMenuAnchor as aF, type MindooDBAppMenuApi as aG, type MindooDBAppMenuCommandItem as aH, type MindooDBAppMenuDismissReason as aI, type MindooDBAppMenuDismissedResult as aJ, type MindooDBAppMenuItem as aK, type MindooDBAppMenuKind as aL, type MindooDBAppMenuPlacement as aM, type MindooDBAppMenuPointAnchor as aN, type MindooDBAppMenuRect as aO, type MindooDBAppMenuRectAnchor as aP, type MindooDBAppMenuSelectionResult as aQ, type MindooDBAppMenuSeparatorItem as aR, type MindooDBAppQueryCoverage as aS, type MindooDBAppQueryResult as aT, type MindooDBAppQueryRow as aU, type MindooDBAppQuerySortKey as aV, type MindooDBAppQueryTextClause as aW, type MindooDBAppReadableAttachmentStream as aX, type MindooDBAppResolvedViewDefinition as aY, type MindooDBAppResolvedViewSource as aZ, type MindooDBAppRevisionPhase as a_, type MindooDBAppDirectoryEntry as aa, type MindooDBAppDocumentApi as ab, type MindooDBAppDocumentHeadCursorResult as ac, type MindooDBAppDocumentHistoryEntry as ad, type MindooDBAppDocumentListQuery as ae, type MindooDBAppDocumentListResult as af, type MindooDBAppDocumentQuery as ag, type MindooDBAppDocumentRevisionId as ah, type MindooDBAppDocumentScanPreset as ai, type MindooDBAppDocumentSummary as aj, type MindooDBAppEntryAttachmentRef as ak, type MindooDBAppEntryProvenance as al, type MindooDBAppExtractDocumentTextInput as am, type MindooDBAppExtractDocumentTextResult as an, type MindooDBAppExtractTextFormat as ao, type MindooDBAppExtractionSetup as ap, type MindooDBAppFulltextSetup as aq, type MindooDBAppHistoricalDocument as ar, type MindooDBAppHistoryQuery as as, type MindooDBAppHostTheme as at, type MindooDBAppIdentityApi as au, type MindooDBAppJsonListDeletePatch as av, type MindooDBAppJsonListInsertPatch as aw, type MindooDBAppJsonPatch as ax, type MindooDBAppJsonSetPatch as ay, type MindooDBAppJsonTextMarkPatch as az, type MindooDBAppDatabase as b, type MindooDBAppRichTextBlockSpan as b0, type MindooDBAppRichTextGetOptions as b1, type MindooDBAppRichTextImmutableString as b2, type MindooDBAppRichTextMarkRange as b3, type MindooDBAppRichTextMaterializeValue as b4, type MindooDBAppRichTextPatch as b5, type MindooDBAppRichTextScalar as b6, type MindooDBAppRichTextSpliceStep as b7, type MindooDBAppRichTextStep as b8, type MindooDBAppRichTextStepPatch as b9, type MindooDBAppViewEntryKind as bA, type MindooDBAppViewNavigator as bB, type MindooDBAppViewNavigatorExpansionState as bC, type MindooDBAppViewNavigatorOpenOptions as bD, type MindooDBAppViewNavigatorPageOptions as bE, type MindooDBAppViewNavigatorPageResult as bF, type MindooDBAppViewNavigatorRangeQuery as bG, type MindooDBAppViewNavigatorSelectionState as bH, type MindooDBAppViewUpdateStats as bI, type MindooDBAppViewport as bJ, type MindooDBAppWritableAttachmentStream as bK, type MindooDBAppRichTextTextSpan as ba, type MindooDBAppRuntime as bb, type MindooDBAppScanAttachmentOptions as bc, type MindooDBAppScanAttachmentResult as bd, type MindooDBAppScopedDocId as be, type MindooDBAppScopedDocumentSummary as bf, type MindooDBAppSealIntent as bg, type MindooDBAppSession as bh, type MindooDBAppShowMenuInput as bi, type MindooDBAppShowMenuResult as bj, type MindooDBAppSignPreview as bk, type MindooDBAppSignPreviewScope as bl, type MindooDBAppSignStatementInput as bm, type MindooDBAppSignStatementResult as bn, type MindooDBAppTextEdit as bo, type MindooDBAppTextPatch as bp, type MindooDBAppThemeMode as bq, type MindooDBAppTimestampApi as br, type MindooDBAppTimestampInput as bs, type MindooDBAppTimestampProvider as bt, type MindooDBAppTimestampResult as bu, type MindooDBAppUiPreferences as bv, type MindooDBAppUpdateDocumentInput as bw, type MindooDBAppViewCursorDocumentListResult as bx, type MindooDBAppViewCursorResult as by, type MindooDBAppViewEntry as bz, type MindooDBAppDocument as c, type MindooDBAppRichTextSpan as d, type MindooDBAppRichTextSnapshot as e, MINDOODB_APP_SEAL_SIGNING_DOMAIN as f, type MindooDBAppAccessDecision as g, type MindooDBAppAccessTier as h, type MindooDBAppAttachmentApi as i, type MindooDBAppAttachmentChunk as j, type MindooDBAppAttachmentInfo as k, type MindooDBAppAttachmentPreviewOptions as l, type MindooDBAppAttachmentPreviewSession as m, type MindooDBAppAutomergeChangesPatch as n, type MindooDBAppAutomergeChangesSince as o, type MindooDBAppAutomergeGetOptions as p, type MindooDBAppAutomergePatchResult as q, type MindooDBAppAutomergeSnapshot as r, type MindooDBAppBridgeConnectMessage as s, type MindooDBAppBridgeConnectOptions as t, type MindooDBAppBridgeConnectedMessage as u, type MindooDBAppBridgeErrorPayload as v, type MindooDBAppBridgeHandshakeErrorMessage as w, type MindooDBAppBridgeLocaleChangedMessage as x, type MindooDBAppBridgePortMessage as y, type MindooDBAppBridgeQueryResultMessage as z };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "mindoodb-app-sdk",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.36",
|
|
4
4
|
"engines": {
|
|
5
5
|
"node": ">=22.13.0"
|
|
6
6
|
},
|
|
@@ -36,26 +36,30 @@
|
|
|
36
36
|
}
|
|
37
37
|
},
|
|
38
38
|
"dependencies": {
|
|
39
|
-
"mindoodb-view-language": "0.0.
|
|
39
|
+
"mindoodb-view-language": "0.0.15"
|
|
40
40
|
},
|
|
41
41
|
"peerDependencies": {
|
|
42
|
-
"@automerge/automerge": "^3.2
|
|
42
|
+
"@automerge/automerge": "^3.3.2",
|
|
43
|
+
"mindoodb": ">=0.0.48"
|
|
43
44
|
},
|
|
44
45
|
"peerDependenciesMeta": {
|
|
45
46
|
"@automerge/automerge": {
|
|
46
47
|
"optional": true
|
|
48
|
+
},
|
|
49
|
+
"mindoodb": {
|
|
50
|
+
"optional": true
|
|
47
51
|
}
|
|
48
52
|
},
|
|
49
53
|
"devDependencies": {
|
|
50
|
-
"@automerge/automerge": "^3.2
|
|
51
|
-
"mindoodb": "^0.0.
|
|
54
|
+
"@automerge/automerge": "^3.3.2",
|
|
55
|
+
"mindoodb": "^0.0.48",
|
|
52
56
|
"@types/node": "25.5.0",
|
|
53
57
|
"tsup": "^8.5.1",
|
|
54
58
|
"typescript": "^6.0.2",
|
|
55
59
|
"vitest": "^4.1.2"
|
|
56
60
|
},
|
|
57
61
|
"scripts": {
|
|
58
|
-
"build": "tsup src/index.ts src/testing/index.ts --format esm --dts --clean --external @automerge/automerge --tsconfig tsconfig.build.json",
|
|
62
|
+
"build": "tsup src/index.ts src/testing/index.ts --format esm --dts --clean --external @automerge/automerge --external mindoodb --tsconfig tsconfig.build.json",
|
|
59
63
|
"typecheck": "tsc --noEmit -p tsconfig.json",
|
|
60
64
|
"test": "vitest run",
|
|
61
65
|
"test:watch": "vitest"
|