mindoodb-app-sdk 0.0.4 → 0.0.5

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
@@ -98,6 +98,8 @@ console.log(launchContext.theme.mode); // "light" | "dark"
98
98
  console.log(launchContext.viewport); // { width, height } | null
99
99
  console.log(launchContext.user.username);
100
100
  console.log(launchContext.launchParameters);
101
+ console.log(launchContext.databases);
102
+ console.log(launchContext.views);
101
103
  ```
102
104
 
103
105
  `launchContext.viewport` is especially useful for responsive layouts inside embedded iframes. It is the initial viewport snapshot; later changes arrive through `onViewportChange()`.
@@ -126,19 +128,19 @@ The intended pattern is:
126
128
  ### 6. Discover the databases Haven exposed
127
129
 
128
130
  ```ts
129
- const databases = await session.listDatabases();
131
+ const databases = launchContext.databases;
130
132
 
131
133
  for (const database of databases) {
132
134
  console.log(database.id, database.title, database.capabilities);
133
135
  }
134
136
  ```
135
137
 
136
- Do not hard-code assumptions about available databases or permissions. Always discover them from the session.
138
+ Prefer `launchContext.databases` for the initial snapshot so your app discovers databases and views from the same source. `session.listDatabases()` is still available when you want to refresh database metadata later.
137
139
 
138
140
  ### 7. Open a database and work with documents
139
141
 
140
142
  ```ts
141
- const databases = await session.listDatabases();
143
+ const databases = launchContext.databases;
142
144
  const db = await session.openDatabase(databases[0]!.id);
143
145
 
144
146
  const list = await db.documents.list({ limit: 25 });
@@ -195,14 +197,16 @@ session.onViewportChange((viewport) => {
195
197
  console.log("Resize:", viewport.width, viewport.height);
196
198
  });
197
199
 
198
- const databases = await session.listDatabases();
200
+ const databases = launchContext.databases;
199
201
  const db = await session.openDatabase(databases[0]!.id);
200
202
 
201
203
  const list = await db.documents.list({ limit: 25 });
202
204
  const firstDoc = list.items[0] ? await db.documents.get(list.items[0].id) : null;
203
205
 
204
206
  const v = createViewLanguage<{ employee: string; hours: number; rate?: number }>();
205
- const view = await db.views.create({
207
+ const view = await session.createView({
208
+ databaseId: databases[0]!.id,
209
+ definition: {
206
210
  title: "Hours by employee",
207
211
  defaultExpand: "collapsed",
208
212
  filter: {
@@ -230,6 +234,7 @@ const view = await db.views.create({
230
234
  ),
231
235
  },
232
236
  ],
237
+ },
233
238
  });
234
239
 
235
240
  const page = await view.page({ pageSize: 100 });
@@ -239,7 +244,7 @@ await view.dispose();
239
244
 
240
245
  ## Views and expression language
241
246
 
242
- Views are app-defined and session-scoped. Create a definition, page through rows, inspect categories, manage expansion state, then dispose the handle when done.
247
+ Views are app-defined and session-scoped. Create a definition with `session.createView()`, open Haven-configured mappings with `session.openView()`, page through rows, inspect categories, manage expansion state, then dispose the handle when done.
243
248
 
244
249
  ```ts
245
250
  import { createViewLanguage } from "mindoodb-app-sdk";
@@ -252,7 +257,9 @@ const v = createViewLanguage<{
252
257
  note?: string;
253
258
  }>();
254
259
 
255
- const view = await db.views.create({
260
+ const view = await session.createView({
261
+ databaseId: "main",
262
+ definition: {
256
263
  title: "By employee",
257
264
  defaultExpand: "collapsed",
258
265
  filter: {
@@ -281,6 +288,7 @@ const view = await db.views.create({
281
288
  sorting: "descending",
282
289
  },
283
290
  ],
291
+ },
284
292
  });
285
293
 
286
294
  const page = await view.page({ pageSize: 100 });
package/TESTING.md CHANGED
@@ -85,11 +85,13 @@ Both accept the same options:
85
85
  - `databases`
86
86
  - `onDisconnect`
87
87
 
88
+ When you pass `databases`, the mock session also exposes them through `session.getLaunchContext().databases`.
89
+
88
90
  Each database entry can provide:
89
91
 
90
92
  - `info`
91
93
  - `methods.documents`
92
- - `methods.views`
94
+ - `methods.views` for session-level `createView()` and `openView()` calls
93
95
  - `methods.attachments`
94
96
 
95
97
  ## Level 2 example
package/dist/index.d.ts CHANGED
@@ -1,7 +1,15 @@
1
- import { M as MindooDBAppBridge } from './types-BGdIfp-D.js';
2
- export { a as MindooDBAppAttachmentApi, b as MindooDBAppAttachmentChunk, c as MindooDBAppAttachmentInfo, d as MindooDBAppBridgeConnectMessage, e as MindooDBAppBridgeConnectOptions, f as MindooDBAppBridgeConnectedMessage, g as MindooDBAppBridgeErrorPayload, h as MindooDBAppBridgePortMessage, i as MindooDBAppBridgeRpcError, j as MindooDBAppBridgeRpcMessage, k as MindooDBAppBridgeRpcRequest, l as MindooDBAppBridgeRpcSuccess, m as MindooDBAppBridgeStreamAbortRequest, n as MindooDBAppBridgeStreamAck, o as MindooDBAppBridgeStreamCloseRequest, p as MindooDBAppBridgeStreamError, q as MindooDBAppBridgeStreamMessage, r as MindooDBAppBridgeStreamOpenResult, s as MindooDBAppBridgeStreamReadRequest, t as MindooDBAppBridgeStreamWriteRequest, u as MindooDBAppBridgeThemeChangedMessage, v as MindooDBAppBridgeViewportChangedMessage, w as MindooDBAppCapability, x as MindooDBAppConfiguredViewCategorizationStyle, y as MindooDBAppConfiguredViewColumn, z as MindooDBAppConfiguredViewColumnRole, A as MindooDBAppConfiguredViewExpressionMode, B as MindooDBAppConfiguredViewFieldExpression, C as MindooDBAppConfiguredViewFilterDefinition, D as MindooDBAppConfiguredViewFilterMode, E as MindooDBAppConfiguredViewFilterRule, F as MindooDBAppConfiguredViewFormulaExpression, G as MindooDBAppConfiguredViewFormulaFilterDefinition, H as MindooDBAppConfiguredViewPreviewMode, I as MindooDBAppConfiguredViewRuleFilterDefinition, J as MindooDBAppConfiguredViewRuleMatchMode, K as MindooDBAppConfiguredViewRuleOperator, L as MindooDBAppConfiguredViewValueExpression, N as MindooDBAppCreateDocumentInput, O as MindooDBAppDatabase, P as MindooDBAppDatabaseInfo, Q as MindooDBAppDocument, R as MindooDBAppDocumentApi, S as MindooDBAppDocumentHistoryEntry, T as MindooDBAppDocumentListQuery, U as MindooDBAppDocumentListResult, V as MindooDBAppDocumentSummary, W as MindooDBAppHistoricalDocument, X as MindooDBAppHistoryQuery, Y as MindooDBAppHostTheme, Z as MindooDBAppLaunchContext, _ as MindooDBAppReadableAttachmentStream, $ as MindooDBAppResolvedViewDefinition, a0 as MindooDBAppResolvedViewSource, a1 as MindooDBAppRuntime, a2 as MindooDBAppSession, a3 as MindooDBAppThemeMode, a4 as MindooDBAppUpdateDocumentInput, a5 as MindooDBAppViewApi, a6 as MindooDBAppViewHandle, a7 as MindooDBAppViewport, a8 as MindooDBAppWritableAttachmentStream } from './types-BGdIfp-D.js';
1
+ import { M as MindooDBAppAttachmentPreviewMode, a as MindooDBAppBridge } from './types-Cvlkh3vJ.js';
2
+ export { b as MindooDBAppAttachmentApi, c as MindooDBAppAttachmentChunk, d as MindooDBAppAttachmentInfo, e as MindooDBAppAttachmentPreviewOptions, f as MindooDBAppBridgeConnectMessage, g as MindooDBAppBridgeConnectOptions, h as MindooDBAppBridgeConnectedMessage, i as MindooDBAppBridgeErrorPayload, j as MindooDBAppBridgePortMessage, k as MindooDBAppBridgeRpcError, l as MindooDBAppBridgeRpcMessage, m as MindooDBAppBridgeRpcRequest, n as MindooDBAppBridgeRpcSuccess, o as MindooDBAppBridgeStreamAbortRequest, p as MindooDBAppBridgeStreamAck, q as MindooDBAppBridgeStreamCloseRequest, r as MindooDBAppBridgeStreamError, s as MindooDBAppBridgeStreamMessage, t as MindooDBAppBridgeStreamOpenResult, u as MindooDBAppBridgeStreamReadRequest, v as MindooDBAppBridgeStreamWriteRequest, w as MindooDBAppBridgeThemeChangedMessage, x as MindooDBAppBridgeViewportChangedMessage, y as MindooDBAppCapability, z as MindooDBAppConfiguredViewCategorizationStyle, A as MindooDBAppConfiguredViewColumn, B as MindooDBAppConfiguredViewColumnRole, C as MindooDBAppConfiguredViewExpressionMode, D as MindooDBAppConfiguredViewFieldExpression, E as MindooDBAppConfiguredViewFilterDefinition, F as MindooDBAppConfiguredViewFilterMode, G as MindooDBAppConfiguredViewFilterRule, H as MindooDBAppConfiguredViewFormulaExpression, I as MindooDBAppConfiguredViewFormulaFilterDefinition, J as MindooDBAppConfiguredViewPreviewMode, K as MindooDBAppConfiguredViewRuleFilterDefinition, L as MindooDBAppConfiguredViewRuleMatchMode, N as MindooDBAppConfiguredViewRuleOperator, O as MindooDBAppConfiguredViewValueExpression, P as MindooDBAppCreateDocumentInput, Q as MindooDBAppCreateViewInput, R as MindooDBAppDatabase, S as MindooDBAppDatabaseInfo, T as MindooDBAppDocument, U as MindooDBAppDocumentApi, V as MindooDBAppDocumentHistoryEntry, W as MindooDBAppDocumentListQuery, X as MindooDBAppDocumentListResult, Y as MindooDBAppDocumentSummary, Z as MindooDBAppHistoricalDocument, _ as MindooDBAppHistoryQuery, $ as MindooDBAppHostTheme, a0 as MindooDBAppLaunchContext, a1 as MindooDBAppReadableAttachmentStream, a2 as MindooDBAppResolvedViewDefinition, a3 as MindooDBAppResolvedViewSource, a4 as MindooDBAppRuntime, a5 as MindooDBAppSession, a6 as MindooDBAppThemeMode, a7 as MindooDBAppUpdateDocumentInput, a8 as MindooDBAppViewHandle, a9 as MindooDBAppViewport, aa as MindooDBAppWritableAttachmentStream } from './types-Cvlkh3vJ.js';
3
3
  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';
4
4
 
5
+ /**
6
+ * Resolves whether Haven can render a built-in preview for an attachment.
7
+ *
8
+ * Apps can use this as a fast local check before calling
9
+ * `attachments.openPreview()`.
10
+ */
11
+ declare function canPreviewAttachment(fileName: string, mimeType: string): MindooDBAppAttachmentPreviewMode | null;
12
+
5
13
  /**
6
14
  * Creates the browser-side bridge entry point used by MindooDB apps.
7
15
  *
@@ -11,4 +19,4 @@ export { MindooDBAppBooleanExpression, MindooDBAppExpression, MindooDBAppFilterD
11
19
  */
12
20
  declare function createMindooDBAppBridge(): MindooDBAppBridge;
13
21
 
14
- export { MindooDBAppBridge, createMindooDBAppBridge };
22
+ export { MindooDBAppAttachmentPreviewMode, MindooDBAppBridge, canPreviewAttachment, createMindooDBAppBridge };
package/dist/index.js CHANGED
@@ -1,3 +1,34 @@
1
+ // src/attachmentPreview.ts
2
+ function canPreviewAttachment(fileName, mimeType) {
3
+ const normalizedMimeType = mimeType.toLowerCase();
4
+ const normalizedFileName = fileName.toLowerCase();
5
+ if (normalizedMimeType.startsWith("image/")) {
6
+ return "image";
7
+ }
8
+ if (normalizedMimeType.startsWith("video/")) {
9
+ return "video";
10
+ }
11
+ if (normalizedMimeType.startsWith("audio/")) {
12
+ return "audio";
13
+ }
14
+ if (normalizedMimeType === "application/pdf" || normalizedFileName.endsWith(".pdf")) {
15
+ return "pdf";
16
+ }
17
+ if (normalizedMimeType === "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" || normalizedMimeType === "application/vnd.ms-excel" || normalizedMimeType === "application/vnd.ms-excel.sheet.macroenabled.12" || normalizedMimeType === "application/vnd.ms-excel.sheet.binary.macroenabled.12" || normalizedFileName.endsWith(".xlsx") || normalizedFileName.endsWith(".xls") || normalizedFileName.endsWith(".xlsm") || normalizedFileName.endsWith(".xlsb")) {
18
+ return "spreadsheet";
19
+ }
20
+ if (normalizedMimeType === "application/vnd.openxmlformats-officedocument.wordprocessingml.document" || normalizedFileName.endsWith(".docx")) {
21
+ return "docx";
22
+ }
23
+ if (normalizedMimeType === "application/vnd.openxmlformats-officedocument.presentationml.presentation" || normalizedFileName.endsWith(".pptx")) {
24
+ return "pptx";
25
+ }
26
+ if (normalizedMimeType.startsWith("text/") || normalizedMimeType === "application/json" || normalizedMimeType === "application/xml" || normalizedMimeType === "image/svg+xml" || normalizedFileName.endsWith(".json") || normalizedFileName.endsWith(".txt") || normalizedFileName.endsWith(".md") || normalizedFileName.endsWith(".csv") || normalizedFileName.endsWith(".log") || normalizedFileName.endsWith(".xml") || normalizedFileName.endsWith(".yaml") || normalizedFileName.endsWith(".yml") || normalizedFileName.endsWith(".svg")) {
27
+ return "text";
28
+ }
29
+ return null;
30
+ }
31
+
1
32
  // src/client/portRpcClient.ts
2
33
  var PROTOCOL = "mindoodb-app-bridge";
3
34
  function normalizeRpcValue(value, seen = /* @__PURE__ */ new WeakMap()) {
@@ -235,86 +266,73 @@ function waitForConnectedPort(options, launchId) {
235
266
  });
236
267
  }
237
268
  var MindooDBAppViewHandleImpl = class {
238
- constructor(rpc, databaseId, viewId) {
269
+ constructor(rpc, viewId) {
239
270
  this.rpc = rpc;
240
- this.databaseId = databaseId;
241
271
  this.viewId = viewId;
242
272
  }
243
273
  async getDefinition() {
244
274
  return await this.rpc.call("views.getDefinition", {
245
- databaseId: this.databaseId,
246
275
  viewId: this.viewId
247
276
  });
248
277
  }
249
278
  async refresh() {
250
279
  await this.rpc.call("views.refresh", {
251
- databaseId: this.databaseId,
252
280
  viewId: this.viewId
253
281
  });
254
282
  }
255
283
  async page(input) {
256
284
  return await this.rpc.call("views.page", {
257
- databaseId: this.databaseId,
258
285
  viewId: this.viewId,
259
286
  request: input ?? {}
260
287
  });
261
288
  }
262
289
  async getExpansionState() {
263
290
  return await this.rpc.call("views.expansion.get", {
264
- databaseId: this.databaseId,
265
291
  viewId: this.viewId
266
292
  });
267
293
  }
268
294
  async setExpansionState(state) {
269
295
  return await this.rpc.call("views.expansion.set", {
270
- databaseId: this.databaseId,
271
296
  viewId: this.viewId,
272
297
  expansion: state
273
298
  });
274
299
  }
275
300
  async expand(rowKey) {
276
301
  return await this.rpc.call("views.expansion.expand", {
277
- databaseId: this.databaseId,
278
302
  viewId: this.viewId,
279
303
  rowKey
280
304
  });
281
305
  }
282
306
  async collapse(rowKey) {
283
307
  return await this.rpc.call("views.expansion.collapse", {
284
- databaseId: this.databaseId,
285
308
  viewId: this.viewId,
286
309
  rowKey
287
310
  });
288
311
  }
289
312
  async expandAll() {
290
313
  return await this.rpc.call("views.expansion.expandAll", {
291
- databaseId: this.databaseId,
292
314
  viewId: this.viewId
293
315
  });
294
316
  }
295
317
  async collapseAll() {
296
318
  return await this.rpc.call("views.expansion.collapseAll", {
297
- databaseId: this.databaseId,
298
319
  viewId: this.viewId
299
320
  });
300
321
  }
301
322
  async getRow(rowKey) {
302
323
  return await this.rpc.call("views.row.get", {
303
- databaseId: this.databaseId,
304
324
  viewId: this.viewId,
305
325
  rowKey
306
326
  });
307
327
  }
308
328
  async getCategory(input) {
309
329
  return await this.rpc.call("views.category.get", {
310
- databaseId: this.databaseId,
311
330
  viewId: this.viewId,
312
331
  lookup: input
313
332
  });
314
333
  }
315
334
  async pageCategory(categoryKey, input) {
316
335
  return await this.rpc.call("views.category.page", {
317
- databaseId: this.databaseId,
318
336
  viewId: this.viewId,
319
337
  categoryKey,
320
338
  request: input ?? {}
@@ -322,14 +340,12 @@ var MindooDBAppViewHandleImpl = class {
322
340
  }
323
341
  async listCategoryDocumentIds(categoryKey) {
324
342
  return await this.rpc.call("views.category.documentIds", {
325
- databaseId: this.databaseId,
326
343
  viewId: this.viewId,
327
344
  categoryKey
328
345
  });
329
346
  }
330
347
  async dispose() {
331
348
  await this.rpc.call("views.dispose", {
332
- databaseId: this.databaseId,
333
349
  viewId: this.viewId
334
350
  });
335
351
  }
@@ -522,16 +538,6 @@ var MindooDBAppDatabaseImpl = class {
522
538
  timestamp
523
539
  })
524
540
  };
525
- this.views = {
526
- create: async (definition) => {
527
- const result = await this.rpc.call("views.create", {
528
- databaseId: this.databaseId,
529
- definition
530
- });
531
- return new MindooDBAppViewHandleImpl(this.rpc, this.databaseId, result.viewId);
532
- },
533
- open: async (viewId) => new MindooDBAppViewHandleImpl(this.rpc, this.databaseId, viewId)
534
- };
535
541
  this.attachments = {
536
542
  list: async (docId) => await this.rpc.call("attachments.list", {
537
543
  databaseId: this.databaseId,
@@ -558,11 +564,16 @@ var MindooDBAppDatabaseImpl = class {
558
564
  contentType
559
565
  });
560
566
  return new MindooDBAppWritableAttachmentStreamImpl(this.rpc, result.streamId);
561
- }
567
+ },
568
+ openPreview: async (docId, attachmentName, options) => await this.rpc.call("attachments.openPreview", {
569
+ databaseId: this.databaseId,
570
+ docId,
571
+ attachmentName,
572
+ timestamp: options?.timestamp
573
+ })
562
574
  };
563
575
  }
564
576
  documents;
565
- views;
566
577
  attachments;
567
578
  /** Returns database metadata for the currently opened binding. */
568
579
  async info() {
@@ -587,6 +598,14 @@ var MindooDBAppSessionImpl = class {
587
598
  await this.rpc.call("session.openDatabase", { databaseId });
588
599
  return new MindooDBAppDatabaseImpl(this.rpc, databaseId);
589
600
  }
601
+ async createView(input) {
602
+ const result = await this.rpc.call("session.createView", input);
603
+ return new MindooDBAppViewHandleImpl(this.rpc, result.viewId);
604
+ }
605
+ async openView(viewId) {
606
+ await this.rpc.call("session.openView", { viewId });
607
+ return new MindooDBAppViewHandleImpl(this.rpc, viewId);
608
+ }
590
609
  onThemeChange(listener) {
591
610
  return this.rpc.addMessageListener((message) => {
592
611
  if (isThemeChangedMessage(message)) {
@@ -629,6 +648,7 @@ import {
629
648
  mindooDBViewLanguageHelpersByName
630
649
  } from "mindoodb-view-language";
631
650
  export {
651
+ canPreviewAttachment,
632
652
  createMindooDBAppBridge,
633
653
  createViewLanguage
634
654
  };
@@ -1,10 +1,14 @@
1
- import { Z as MindooDBAppLaunchContext, P as MindooDBAppDatabaseInfo, R as MindooDBAppDocumentApi, a5 as MindooDBAppViewApi, a as MindooDBAppAttachmentApi, M as MindooDBAppBridge, a2 as MindooDBAppSession, k as MindooDBAppBridgeRpcRequest, Y as MindooDBAppHostTheme, a7 as MindooDBAppViewport, h as MindooDBAppBridgePortMessage } from '../types-BGdIfp-D.js';
2
- import 'mindoodb-view-language';
1
+ import { a0 as MindooDBAppLaunchContext, S as MindooDBAppDatabaseInfo, U as MindooDBAppDocumentApi, a8 as MindooDBAppViewHandle, b as MindooDBAppAttachmentApi, a as MindooDBAppBridge, a5 as MindooDBAppSession, m as MindooDBAppBridgeRpcRequest, $ as MindooDBAppHostTheme, a9 as MindooDBAppViewport, j as MindooDBAppBridgePortMessage } from '../types-Cvlkh3vJ.js';
2
+ import { MindooDBAppViewDefinition } from 'mindoodb-view-language';
3
3
 
4
4
  type MaybePromise<T> = T | Promise<T>;
5
+ type MockViewApi = {
6
+ create(definition: MindooDBAppViewDefinition): MaybePromise<MindooDBAppViewHandle>;
7
+ open(viewId: string): MaybePromise<MindooDBAppViewHandle>;
8
+ };
5
9
  type MockDatabaseMethods = {
6
10
  documents?: Partial<MindooDBAppDocumentApi>;
7
- views?: Partial<MindooDBAppViewApi>;
11
+ views?: Partial<MockViewApi>;
8
12
  attachments?: Partial<MindooDBAppAttachmentApi>;
9
13
  };
10
14
  interface MockMindooDBAppDatabaseDefinition {
@@ -20,6 +20,10 @@ function mergeLaunchContext(current, patch) {
20
20
  viewport: current.viewport ? { ...current.viewport } : null,
21
21
  user: { ...current.user },
22
22
  launchParameters: { ...current.launchParameters },
23
+ databases: current.databases.map((database) => ({
24
+ ...database,
25
+ capabilities: [...database.capabilities]
26
+ })),
23
27
  views: current.views.map((view) => ({
24
28
  ...view,
25
29
  sources: view.sources.map((source) => ({ ...source })),
@@ -45,6 +49,13 @@ function mergeLaunchContext(current, patch) {
45
49
  viewport: patch.viewport === void 0 ? current.viewport ? { ...current.viewport } : null : patch.viewport ? { ...patch.viewport } : null,
46
50
  user: patch.user ? { ...current.user, ...patch.user } : { ...current.user },
47
51
  launchParameters: patch.launchParameters ? { ...current.launchParameters, ...patch.launchParameters } : { ...current.launchParameters },
52
+ databases: patch.databases ? patch.databases.map((database) => ({
53
+ ...database,
54
+ capabilities: [...database.capabilities]
55
+ })) : current.databases.map((database) => ({
56
+ ...database,
57
+ capabilities: [...database.capabilities]
58
+ })),
48
59
  views: patch.views ? patch.views.map((view) => ({
49
60
  ...view,
50
61
  sources: view.sources.map((source) => ({ ...source })),
@@ -98,6 +109,7 @@ function createDefaultLaunchContext(patch) {
98
109
  username: "Test User"
99
110
  },
100
111
  launchParameters: {},
112
+ databases: [],
101
113
  views: []
102
114
  };
103
115
  return mergeLaunchContext(base, patch);
@@ -265,6 +277,9 @@ function createDatabaseHandle(definition) {
265
277
  },
266
278
  async openWriteStream(_docId, _attachmentName, _contentType) {
267
279
  return createDefaultWritableAttachmentStream();
280
+ },
281
+ async openPreview(_docId, _attachmentName, _options) {
282
+ return { ok: true };
268
283
  }
269
284
  };
270
285
  const methods = definition.methods ?? {};
@@ -276,10 +291,6 @@ function createDatabaseHandle(definition) {
276
291
  ...defaultDocuments,
277
292
  ...methods.documents
278
293
  },
279
- views: {
280
- ...defaultViews,
281
- ...methods.views
282
- },
283
294
  attachments: {
284
295
  ...defaultAttachments,
285
296
  ...methods.attachments
@@ -291,16 +302,29 @@ function createMockSessionState(options = {}) {
291
302
  const themeListeners = /* @__PURE__ */ new Set();
292
303
  const viewportListeners = /* @__PURE__ */ new Set();
293
304
  const databaseHandles = /* @__PURE__ */ new Map();
305
+ const databaseViewApis = /* @__PURE__ */ new Map();
306
+ const sessionViews = /* @__PURE__ */ new Map();
294
307
  let databaseInfos = [];
295
308
  const setDatabases = (definitions) => {
296
309
  databaseHandles.clear();
310
+ databaseViewApis.clear();
297
311
  databaseInfos = definitions.map((definition) => ({
298
312
  ...definition.info,
299
313
  capabilities: [...definition.info.capabilities]
300
314
  }));
301
315
  for (const definition of definitions) {
302
316
  databaseHandles.set(definition.info.id, createDatabaseHandle(definition));
317
+ databaseViewApis.set(definition.info.id, {
318
+ async create(_definition) {
319
+ return await createDefaultViewHandle();
320
+ },
321
+ async open(_viewId) {
322
+ return await createDefaultViewHandle();
323
+ },
324
+ ...definition.methods?.views ?? {}
325
+ });
303
326
  }
327
+ launchContext = mergeLaunchContext(launchContext, { databases: databaseInfos });
304
328
  };
305
329
  setDatabases(options.databases ?? []);
306
330
  const session = {
@@ -320,6 +344,33 @@ function createMockSessionState(options = {}) {
320
344
  }
321
345
  return database;
322
346
  },
347
+ async createView(input) {
348
+ const api = databaseViewApis.get(input.databaseId);
349
+ if (!api) {
350
+ throw new Error(`Unknown test database for view creation: ${input.databaseId}`);
351
+ }
352
+ const view = await api.create(input.definition);
353
+ const viewId = input.definition.id || crypto.randomUUID();
354
+ sessionViews.set(viewId, view);
355
+ return view;
356
+ },
357
+ async openView(viewId) {
358
+ const existing = sessionViews.get(viewId);
359
+ if (existing) {
360
+ return existing;
361
+ }
362
+ const sourceDatabaseId = launchContext.views.find((view2) => view2.id === viewId)?.sources[0]?.databaseId;
363
+ if (!sourceDatabaseId) {
364
+ throw new Error(`Unknown test view: ${viewId}`);
365
+ }
366
+ const api = databaseViewApis.get(sourceDatabaseId);
367
+ if (!api) {
368
+ throw new Error(`Unknown test database for view ${viewId}: ${sourceDatabaseId}`);
369
+ }
370
+ const view = await api.open(viewId);
371
+ sessionViews.set(viewId, view);
372
+ return view;
373
+ },
323
374
  onThemeChange(listener) {
324
375
  themeListeners.add(listener);
325
376
  return () => {
@@ -363,6 +414,8 @@ function createMockSessionState(options = {}) {
363
414
  }
364
415
  return database;
365
416
  },
417
+ createView: session.createView,
418
+ openView: session.openView,
366
419
  bridge,
367
420
  session,
368
421
  emitThemeChange(theme) {
@@ -492,15 +545,13 @@ function createFakeBridgeHost(options = {}) {
492
545
  });
493
546
  installed = true;
494
547
  }
495
- async function resolveViewHandle(databaseId, viewId) {
496
- const key = `${databaseId}::${viewId}`;
497
- const existing = viewSessions.get(key);
548
+ async function resolveViewHandle(viewId) {
549
+ const existing = viewSessions.get(viewId);
498
550
  if (existing) {
499
551
  return existing;
500
552
  }
501
- const database = state.getDatabase(databaseId);
502
- const handle = await database.views.open(viewId);
503
- viewSessions.set(key, handle);
553
+ const handle = await state.openView(viewId);
554
+ viewSessions.set(viewId, handle);
504
555
  return handle;
505
556
  }
506
557
  function postRpcSuccess(port, requestId, result) {
@@ -544,6 +595,18 @@ function createFakeBridgeHost(options = {}) {
544
595
  case "session.openDatabase":
545
596
  state.getDatabase(String(params.databaseId));
546
597
  return { ok: true };
598
+ case "session.createView": {
599
+ const viewId = `view-${viewCounter += 1}`;
600
+ const handle = await state.createView({
601
+ databaseId: String(params.databaseId),
602
+ definition: params.definition
603
+ });
604
+ viewSessions.set(viewId, handle);
605
+ return { viewId };
606
+ }
607
+ case "session.openView":
608
+ await state.openView(String(params.viewId));
609
+ return { ok: true };
547
610
  case "session.disconnect":
548
611
  await state.session.disconnect();
549
612
  return { ok: true };
@@ -593,52 +656,52 @@ function createFakeBridgeHost(options = {}) {
593
656
  writeStreams.set(streamId, stream);
594
657
  return { streamId };
595
658
  }
596
- case "views.create": {
597
- const handle = await state.getDatabase(String(params.databaseId)).views.create(params.definition);
598
- const viewId = `view-${viewCounter += 1}`;
599
- viewSessions.set(`${String(params.databaseId)}::${viewId}`, handle);
600
- return { viewId };
601
- }
659
+ case "attachments.openPreview":
660
+ return await state.getDatabase(String(params.databaseId)).attachments.openPreview(
661
+ String(params.docId),
662
+ String(params.attachmentName),
663
+ typeof params.timestamp === "number" ? { timestamp: params.timestamp } : void 0
664
+ );
602
665
  case "views.getDefinition":
603
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).getDefinition();
666
+ return await (await resolveViewHandle(String(params.viewId))).getDefinition();
604
667
  case "views.refresh":
605
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).refresh();
668
+ return await (await resolveViewHandle(String(params.viewId))).refresh();
606
669
  case "views.page":
607
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).page(
670
+ return await (await resolveViewHandle(String(params.viewId))).page(
608
671
  params.request
609
672
  );
610
673
  case "views.expansion.get":
611
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).getExpansionState();
674
+ return await (await resolveViewHandle(String(params.viewId))).getExpansionState();
612
675
  case "views.expansion.set":
613
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).setExpansionState(
676
+ return await (await resolveViewHandle(String(params.viewId))).setExpansionState(
614
677
  params.expansion
615
678
  );
616
679
  case "views.expansion.expand":
617
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).expand(String(params.rowKey));
680
+ return await (await resolveViewHandle(String(params.viewId))).expand(String(params.rowKey));
618
681
  case "views.expansion.collapse":
619
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).collapse(String(params.rowKey));
682
+ return await (await resolveViewHandle(String(params.viewId))).collapse(String(params.rowKey));
620
683
  case "views.expansion.expandAll":
621
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).expandAll();
684
+ return await (await resolveViewHandle(String(params.viewId))).expandAll();
622
685
  case "views.expansion.collapseAll":
623
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).collapseAll();
686
+ return await (await resolveViewHandle(String(params.viewId))).collapseAll();
624
687
  case "views.row.get":
625
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).getRow(String(params.rowKey));
688
+ return await (await resolveViewHandle(String(params.viewId))).getRow(String(params.rowKey));
626
689
  case "views.category.get":
627
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).getCategory(
690
+ return await (await resolveViewHandle(String(params.viewId))).getCategory(
628
691
  params.lookup
629
692
  );
630
693
  case "views.category.page":
631
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).pageCategory(
694
+ return await (await resolveViewHandle(String(params.viewId))).pageCategory(
632
695
  String(params.categoryKey),
633
696
  params.request
634
697
  );
635
698
  case "views.category.documentIds":
636
- return await (await resolveViewHandle(String(params.databaseId), String(params.viewId))).listCategoryDocumentIds(
699
+ return await (await resolveViewHandle(String(params.viewId))).listCategoryDocumentIds(
637
700
  String(params.categoryKey)
638
701
  );
639
702
  case "views.dispose": {
640
- const key = `${String(params.databaseId)}::${String(params.viewId)}`;
641
- const handle = await resolveViewHandle(String(params.databaseId), String(params.viewId));
703
+ const key = String(params.viewId);
704
+ const handle = await resolveViewHandle(String(params.viewId));
642
705
  await handle.dispose();
643
706
  viewSessions.delete(key);
644
707
  return void 0;
@@ -109,6 +109,7 @@ interface MindooDBAppLaunchContext {
109
109
  username: string;
110
110
  };
111
111
  launchParameters: Record<string, string>;
112
+ databases: MindooDBAppDatabaseInfo[];
112
113
  views: MindooDBAppResolvedViewDefinition[];
113
114
  }
114
115
  /** Attachment metadata returned by the attachment APIs. */
@@ -118,6 +119,13 @@ interface MindooDBAppAttachmentInfo {
118
119
  mimeType: string;
119
120
  size: number;
120
121
  }
122
+ /** Preview modes supported by the Haven-hosted attachment preview dialog. */
123
+ type MindooDBAppAttachmentPreviewMode = "image" | "pdf" | "text" | "docx" | "pptx" | "spreadsheet" | "video" | "audio";
124
+ /** Optional parameters for opening an attachment preview in Haven. */
125
+ interface MindooDBAppAttachmentPreviewOptions {
126
+ /** Historical snapshot timestamp previously obtained from `documents.history.getAtTimestamp()`. */
127
+ timestamp?: number;
128
+ }
121
129
  /** Database entry visible to the app during launch and database listing. */
122
130
  interface MindooDBAppDatabaseInfo {
123
131
  id: string;
@@ -334,10 +342,10 @@ interface MindooDBAppViewHandle {
334
342
  listCategoryDocumentIds(categoryKey: string): Promise<string[]>;
335
343
  dispose(): Promise<void>;
336
344
  }
337
- /** Entry point for creating or opening views in a database. */
338
- interface MindooDBAppViewApi {
339
- create(definition: MindooDBAppViewDefinition): Promise<MindooDBAppViewHandle>;
340
- open(viewId: string): Promise<MindooDBAppViewHandle>;
345
+ /** Payload used when creating one dynamic view inside the current app session. */
346
+ interface MindooDBAppCreateViewInput {
347
+ databaseId: string;
348
+ definition: MindooDBAppViewDefinition;
341
349
  }
342
350
  /** Attachment operations exposed by an opened database handle. */
343
351
  interface MindooDBAppAttachmentApi {
@@ -347,12 +355,14 @@ interface MindooDBAppAttachmentApi {
347
355
  }>;
348
356
  openReadStream(docId: string, attachmentName: string): Promise<MindooDBAppReadableAttachmentStream>;
349
357
  openWriteStream(docId: string, attachmentName: string, contentType?: string): Promise<MindooDBAppWritableAttachmentStream>;
358
+ openPreview(docId: string, attachmentName: string, options?: MindooDBAppAttachmentPreviewOptions): Promise<{
359
+ ok: true;
360
+ }>;
350
361
  }
351
362
  /** Database handle returned from `session.openDatabase()`. */
352
363
  interface MindooDBAppDatabase {
353
364
  info(): Promise<MindooDBAppDatabaseInfo>;
354
365
  documents: MindooDBAppDocumentApi;
355
- views: MindooDBAppViewApi;
356
366
  attachments: MindooDBAppAttachmentApi;
357
367
  }
358
368
  /** Connected session between the running app and the Administrator host. */
@@ -360,6 +370,8 @@ interface MindooDBAppSession {
360
370
  getLaunchContext(): Promise<MindooDBAppLaunchContext>;
361
371
  listDatabases(): Promise<MindooDBAppDatabaseInfo[]>;
362
372
  openDatabase(databaseId: string): Promise<MindooDBAppDatabase>;
373
+ createView(input: MindooDBAppCreateViewInput): Promise<MindooDBAppViewHandle>;
374
+ openView(viewId: string): Promise<MindooDBAppViewHandle>;
363
375
  onThemeChange(listener: (theme: MindooDBAppHostTheme) => void): () => void;
364
376
  onViewportChange(listener: (viewport: MindooDBAppViewport) => void): () => void;
365
377
  disconnect(): Promise<void>;
@@ -369,4 +381,4 @@ interface MindooDBAppBridge {
369
381
  connect(options?: MindooDBAppBridgeConnectOptions): Promise<MindooDBAppSession>;
370
382
  }
371
383
 
372
- export type { MindooDBAppResolvedViewDefinition as $, MindooDBAppConfiguredViewExpressionMode as A, MindooDBAppConfiguredViewFieldExpression as B, MindooDBAppConfiguredViewFilterDefinition as C, MindooDBAppConfiguredViewFilterMode as D, MindooDBAppConfiguredViewFilterRule as E, MindooDBAppConfiguredViewFormulaExpression as F, MindooDBAppConfiguredViewFormulaFilterDefinition as G, MindooDBAppConfiguredViewPreviewMode as H, MindooDBAppConfiguredViewRuleFilterDefinition as I, MindooDBAppConfiguredViewRuleMatchMode as J, MindooDBAppConfiguredViewRuleOperator as K, MindooDBAppConfiguredViewValueExpression as L, MindooDBAppBridge as M, MindooDBAppCreateDocumentInput as N, MindooDBAppDatabase as O, MindooDBAppDatabaseInfo as P, MindooDBAppDocument as Q, MindooDBAppDocumentApi as R, MindooDBAppDocumentHistoryEntry as S, MindooDBAppDocumentListQuery as T, MindooDBAppDocumentListResult as U, MindooDBAppDocumentSummary as V, MindooDBAppHistoricalDocument as W, MindooDBAppHistoryQuery as X, MindooDBAppHostTheme as Y, MindooDBAppLaunchContext as Z, MindooDBAppReadableAttachmentStream as _, MindooDBAppAttachmentApi as a, MindooDBAppResolvedViewSource as a0, MindooDBAppRuntime as a1, MindooDBAppSession as a2, MindooDBAppThemeMode as a3, MindooDBAppUpdateDocumentInput as a4, MindooDBAppViewApi as a5, MindooDBAppViewHandle as a6, MindooDBAppViewport as a7, MindooDBAppWritableAttachmentStream as a8, MindooDBAppAttachmentChunk as b, MindooDBAppAttachmentInfo as c, MindooDBAppBridgeConnectMessage as d, MindooDBAppBridgeConnectOptions as e, MindooDBAppBridgeConnectedMessage as f, MindooDBAppBridgeErrorPayload as g, MindooDBAppBridgePortMessage as h, MindooDBAppBridgeRpcError as i, MindooDBAppBridgeRpcMessage as j, MindooDBAppBridgeRpcRequest as k, MindooDBAppBridgeRpcSuccess as l, MindooDBAppBridgeStreamAbortRequest as m, MindooDBAppBridgeStreamAck as n, MindooDBAppBridgeStreamCloseRequest as o, MindooDBAppBridgeStreamError as p, MindooDBAppBridgeStreamMessage as q, MindooDBAppBridgeStreamOpenResult as r, MindooDBAppBridgeStreamReadRequest as s, MindooDBAppBridgeStreamWriteRequest as t, MindooDBAppBridgeThemeChangedMessage as u, MindooDBAppBridgeViewportChangedMessage as v, MindooDBAppCapability as w, MindooDBAppConfiguredViewCategorizationStyle as x, MindooDBAppConfiguredViewColumn as y, MindooDBAppConfiguredViewColumnRole as z };
384
+ export type { MindooDBAppHostTheme as $, MindooDBAppConfiguredViewColumn as A, MindooDBAppConfiguredViewColumnRole as B, MindooDBAppConfiguredViewExpressionMode as C, MindooDBAppConfiguredViewFieldExpression as D, MindooDBAppConfiguredViewFilterDefinition as E, MindooDBAppConfiguredViewFilterMode as F, MindooDBAppConfiguredViewFilterRule as G, MindooDBAppConfiguredViewFormulaExpression as H, MindooDBAppConfiguredViewFormulaFilterDefinition as I, MindooDBAppConfiguredViewPreviewMode as J, MindooDBAppConfiguredViewRuleFilterDefinition as K, MindooDBAppConfiguredViewRuleMatchMode as L, MindooDBAppAttachmentPreviewMode as M, MindooDBAppConfiguredViewRuleOperator as N, MindooDBAppConfiguredViewValueExpression as O, MindooDBAppCreateDocumentInput as P, MindooDBAppCreateViewInput as Q, MindooDBAppDatabase as R, MindooDBAppDatabaseInfo as S, MindooDBAppDocument as T, MindooDBAppDocumentApi as U, MindooDBAppDocumentHistoryEntry as V, MindooDBAppDocumentListQuery as W, MindooDBAppDocumentListResult as X, MindooDBAppDocumentSummary as Y, MindooDBAppHistoricalDocument as Z, MindooDBAppHistoryQuery as _, MindooDBAppBridge as a, MindooDBAppLaunchContext as a0, MindooDBAppReadableAttachmentStream as a1, MindooDBAppResolvedViewDefinition as a2, MindooDBAppResolvedViewSource as a3, MindooDBAppRuntime as a4, MindooDBAppSession as a5, MindooDBAppThemeMode as a6, MindooDBAppUpdateDocumentInput as a7, MindooDBAppViewHandle as a8, MindooDBAppViewport as a9, MindooDBAppWritableAttachmentStream as aa, MindooDBAppAttachmentApi as b, MindooDBAppAttachmentChunk as c, MindooDBAppAttachmentInfo as d, MindooDBAppAttachmentPreviewOptions as e, MindooDBAppBridgeConnectMessage as f, MindooDBAppBridgeConnectOptions as g, MindooDBAppBridgeConnectedMessage as h, MindooDBAppBridgeErrorPayload as i, MindooDBAppBridgePortMessage as j, MindooDBAppBridgeRpcError as k, MindooDBAppBridgeRpcMessage as l, MindooDBAppBridgeRpcRequest as m, MindooDBAppBridgeRpcSuccess as n, MindooDBAppBridgeStreamAbortRequest as o, MindooDBAppBridgeStreamAck as p, MindooDBAppBridgeStreamCloseRequest as q, MindooDBAppBridgeStreamError as r, MindooDBAppBridgeStreamMessage as s, MindooDBAppBridgeStreamOpenResult as t, MindooDBAppBridgeStreamReadRequest as u, MindooDBAppBridgeStreamWriteRequest as v, MindooDBAppBridgeThemeChangedMessage as w, MindooDBAppBridgeViewportChangedMessage as x, MindooDBAppCapability as y, MindooDBAppConfiguredViewCategorizationStyle as z };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mindoodb-app-sdk",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "MindooDB app SDK for building apps that connect to the Haven host bridge",
5
5
  "license": "ISC",
6
6
  "author": "Mindoo GmbH",
@@ -40,7 +40,7 @@
40
40
  "prepublishOnly": "npm run build && npm run test"
41
41
  },
42
42
  "dependencies": {
43
- "mindoodb-view-language": "^0.0.4"
43
+ "mindoodb-view-language": "file:../mindoodb-view-language"
44
44
  },
45
45
  "devDependencies": {
46
46
  "@types/node": "^25.5.0",