@altertable/data-app 0.65.0 → 0.66.0

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.
Files changed (138) hide show
  1. package/AGENTS.md +38 -1
  2. package/CONTRIBUTING.md +37 -3
  3. package/README.md +1 -1
  4. package/dist/chunks/{contract-sm7j7k95.js → contract-13j5zb3c.js} +2 -144
  5. package/dist/chunks/contract-13j5zb3c.js.map +13 -0
  6. package/dist/chunks/contract-19ckn3n7.js +78 -0
  7. package/dist/chunks/contract-19ckn3n7.js.map +10 -0
  8. package/dist/chunks/{contract-a061yj6r.js → contract-e11m4y7f.js} +34 -70
  9. package/dist/chunks/contract-e11m4y7f.js.map +12 -0
  10. package/dist/chunks/{contract-g6hky7x6.js → contract-h8a6f559.js} +8 -4
  11. package/dist/chunks/contract-h8a6f559.js.map +12 -0
  12. package/dist/chunks/contract-havnjmdr.js +13011 -0
  13. package/dist/chunks/contract-havnjmdr.js.map +99 -0
  14. package/dist/chunks/{contract-txjy0en2.js → contract-m6n8ctfc.js} +64 -72
  15. package/dist/chunks/contract-m6n8ctfc.js.map +10 -0
  16. package/dist/chunks/contract-pk603qj7.js +146 -0
  17. package/dist/chunks/contract-pk603qj7.js.map +10 -0
  18. package/dist/chunks/{contract-yxbjea23.js → contract-rfbakka4.js} +179 -2
  19. package/dist/chunks/contract-rfbakka4.js.map +13 -0
  20. package/dist/client/index.js +11 -6
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/core/appearance.js +1 -1
  23. package/dist/core/contract.js +13 -3
  24. package/dist/core/contract.js.map +1 -1
  25. package/dist/embed/index.js +9 -7
  26. package/dist/embed/index.js.map +2 -2
  27. package/dist/local.js +1 -1
  28. package/dist/local.js.map +2 -2
  29. package/dist/react/embed/index.js +1 -1
  30. package/dist/react/index.js +2532 -11545
  31. package/dist/react/index.js.map +16 -91
  32. package/dist/react/ui/index.js +1614 -0
  33. package/dist/react/ui/index.js.map +22 -0
  34. package/dist/server.js +1 -1
  35. package/dist/server.js.map +2 -2
  36. package/dist/types/client/annotations.d.ts +23 -0
  37. package/dist/types/client/index.d.ts +1 -0
  38. package/dist/types/core/annotations.d.ts +92 -0
  39. package/dist/types/core/appearance.d.ts +2 -2
  40. package/dist/types/core/contract.d.ts +2 -0
  41. package/dist/types/core/presentation.d.ts +2 -0
  42. package/dist/types/core/variables.d.ts +2 -5
  43. package/dist/types/react/annotations/AnnotationBar.d.ts +24 -0
  44. package/dist/types/react/annotations/AnnotationControls.d.ts +10 -0
  45. package/dist/types/react/annotations/AnnotationEditor.d.ts +15 -0
  46. package/dist/types/react/annotations/AnnotationMarkers.d.ts +19 -0
  47. package/dist/types/react/annotations/AnnotationSelectionLayer.d.ts +12 -0
  48. package/dist/types/react/annotations/AnnotationTarget.d.ts +9 -0
  49. package/dist/types/react/annotations/AnnotationTooltip.d.ts +9 -0
  50. package/dist/types/react/annotations/AnnotationTrigger.d.ts +10 -0
  51. package/dist/types/react/annotations/annotation-editor-state.d.ts +56 -0
  52. package/dist/types/react/annotations/annotation-screenshot.d.ts +4 -0
  53. package/dist/types/react/annotations/annotation-targets.d.ts +33 -0
  54. package/dist/types/react/annotations/getAnnotationProps.d.ts +15 -0
  55. package/dist/types/react/annotations/styles.d.ts +3 -0
  56. package/dist/types/react/annotations/useAnnotationGeometry.d.ts +22 -0
  57. package/dist/types/react/annotations/useDataAppAnnotations.d.ts +19 -0
  58. package/dist/types/react/bindings.d.ts +110 -0
  59. package/dist/types/react/content.d.ts +24 -11
  60. package/dist/types/react/hooks.d.ts +29 -787
  61. package/dist/types/react/index.d.ts +30 -105
  62. package/dist/types/react/source-owner.d.ts +2 -0
  63. package/dist/types/react/style-contract.d.ts +60 -0
  64. package/dist/types/react/style-validation.d.ts +2 -0
  65. package/dist/types/react/ui/AboutData.d.ts +9 -1
  66. package/dist/types/react/ui/AppHeader.d.ts +1 -2
  67. package/dist/types/react/ui/AppLayout.d.ts +3 -9
  68. package/dist/types/react/ui/AppToolbar.d.ts +5 -8
  69. package/dist/types/react/ui/AreaChart.d.ts +7 -0
  70. package/dist/types/react/ui/BarChart.d.ts +6 -0
  71. package/dist/types/react/ui/{ComparisonVisual.d.ts → Comparison.d.ts} +3 -3
  72. package/dist/types/react/ui/ContentSkeleton.d.ts +2 -0
  73. package/dist/types/react/ui/DataApp.d.ts +17 -58
  74. package/dist/types/react/ui/DataAppFrame.d.ts +42 -0
  75. package/dist/types/react/ui/DataBoundary.d.ts +4 -5
  76. package/dist/types/react/ui/DataSection.d.ts +6 -18
  77. package/dist/types/react/ui/DataSectionBoundary.d.ts +30 -0
  78. package/dist/types/react/ui/DataValue.d.ts +9 -0
  79. package/dist/types/react/ui/DataWidget.d.ts +2 -1
  80. package/dist/types/react/ui/DateTimeTooltip.d.ts +1 -1
  81. package/dist/types/react/ui/ExportControl.d.ts +1 -1
  82. package/dist/types/react/ui/HelpPopover.d.ts +3 -4
  83. package/dist/types/react/ui/InspectionContext.d.ts +2 -0
  84. package/dist/types/react/ui/InspectionProvider.d.ts +29 -0
  85. package/dist/types/react/ui/LineChart.d.ts +7 -0
  86. package/dist/types/react/ui/MetricWidget.d.ts +4 -3
  87. package/dist/types/react/ui/PieChart.d.ts +8 -0
  88. package/dist/types/react/ui/PresentStory.d.ts +2 -5
  89. package/dist/types/react/ui/RefreshControl.d.ts +1 -2
  90. package/dist/types/react/ui/ScatterChart.d.ts +17 -0
  91. package/dist/types/react/ui/SearchField.d.ts +1 -2
  92. package/dist/types/react/ui/SearchInput.d.ts +3 -1
  93. package/dist/types/react/ui/Sheet.d.ts +2 -1
  94. package/dist/types/react/ui/Skeleton.d.ts +5 -2
  95. package/dist/types/react/ui/StaticDataApp.d.ts +4 -0
  96. package/dist/types/react/ui/TableWidget.d.ts +19 -16
  97. package/dist/types/react/ui/Tabs.d.ts +6 -2
  98. package/dist/types/react/ui/TextWidget.d.ts +2 -1
  99. package/dist/types/react/ui/Tooltip.d.ts +4 -3
  100. package/dist/types/react/ui/TrendChart.d.ts +5 -0
  101. package/dist/types/react/ui/UpdatedAt.d.ts +1 -1
  102. package/dist/types/react/ui/VisualizationWidget.d.ts +12 -13
  103. package/dist/types/react/ui/WidgetViewTabs.d.ts +1 -1
  104. package/dist/types/react/ui/chart-data.d.ts +25 -0
  105. package/dist/types/react/ui/data-context.d.ts +18 -7
  106. package/dist/types/react/ui/icons.d.ts +1 -0
  107. package/dist/types/react/ui/index.d.ts +74 -0
  108. package/dist/types/react/ui/metric.d.ts +1 -1
  109. package/dist/types/react/ui/presentation.d.ts +5 -1
  110. package/dist/types/react/ui/shortcuts.d.ts +7 -1
  111. package/dist/types/react/view-runtime.d.ts +29 -0
  112. package/dist/types/react/view.d.ts +21 -4
  113. package/dist/types/react/widgets.d.ts +79 -0
  114. package/docs/app-authoring.md +58 -50
  115. package/docs/data-context.md +89 -0
  116. package/docs/formatting-and-appearance.md +52 -0
  117. package/docs/hosted-apps.md +0 -13
  118. package/docs/layout.md +4 -2
  119. package/docs/react-embed.md +2 -2
  120. package/docs/react.md +20 -316
  121. package/docs/stories-and-export.md +52 -0
  122. package/docs/styling.md +55 -0
  123. package/docs/ui-quality.md +20 -0
  124. package/docs/ui.md +41 -0
  125. package/docs/variables.md +98 -0
  126. package/docs/views.md +127 -0
  127. package/docs/widgets.md +142 -0
  128. package/examples/starter-data-app/index.tsx +82 -55
  129. package/package.json +12 -4
  130. package/dist/chunks/contract-a061yj6r.js.map +0 -12
  131. package/dist/chunks/contract-g6hky7x6.js.map +0 -12
  132. package/dist/chunks/contract-sm7j7k95.js.map +0 -14
  133. package/dist/chunks/contract-txjy0en2.js.map +0 -10
  134. package/dist/chunks/contract-yxbjea23.js.map +0 -12
  135. package/dist/types/react/ui/RefreshRegion.d.ts +0 -9
  136. package/dist/types/react/ui/SelectableBarChart.d.ts +0 -15
  137. package/docs/releasing.md +0 -79
  138. /package/dist/types/react/ui/{comparison.d.ts → metric-comparison.d.ts} +0 -0
package/AGENTS.md CHANGED
@@ -3,8 +3,45 @@
3
3
  Build Altertable data apps with `@altertable/data-app`. They render in an iframe
4
4
  in Altertable, a chat app, or locally in a browser.
5
5
 
6
- Every analytical app includes CSV export and a story in the built-in toolbar,
6
+ Every data app includes CSV export and a story in the built-in toolbar,
7
7
  both derived from the displayed result. Setup and static screens may omit them.
8
8
 
9
9
  Follow [app authoring](docs/app-authoring.md) for the shared workflow, the data app
10
10
  and local data app paths, and task-specific documentation.
11
+
12
+ ## Styling
13
+
14
+ Use components and typed props first; customize through app-owned `className`
15
+ and public tokens. Follow [Styling](docs/styling.md)
16
+ and [UI quality](docs/ui-quality.md).
17
+ Do not copy package classes onto markup or select private descendants.
18
+
19
+ ## Documentation
20
+
21
+ Use `<Component>` notation for React components. Keep guidance concise; leave
22
+ prop details to TypeScript and JSDoc. Describe the current API without migration
23
+ or legacy instructions.
24
+
25
+ ## App authoring
26
+
27
+ Read the matching guide before generating an app. Package contributors follow
28
+ [Contributing](CONTRIBUTING.md).
29
+
30
+ | Task | Read |
31
+ | -------------------------------------- | -------------------------------------------------------------- |
32
+ | Choose hosted or local execution | [App authoring](docs/app-authoring.md) |
33
+ | Load data and compose loading states | [Views](docs/views.md) |
34
+ | Add filters | [Variables](docs/variables.md) |
35
+ | Compose visuals, tables, and narrative | [Widgets](docs/widgets.md), [layout](docs/layout.md) |
36
+ | Define sources and evidence | [Data context](docs/data-context.md) |
37
+ | Present findings and export results | [Stories and export](docs/stories-and-export.md) |
38
+ | Format values and appearance | [Formatting and appearance](docs/formatting-and-appearance.md) |
39
+
40
+ Use `/react` with declared views and bound widgets. `/react/ui` is for setup,
41
+ static displays, and deliberately custom UI; see [direct composition](docs/ui.md).
42
+ Prefer derivation over repeated configuration. Keep static context outside loading boundaries. Derive labels, findings, and
43
+ exports from the displayed result and its input. Edit app-owned files; installed
44
+ package files are dependencies.
45
+
46
+ Keep `docs/` focused on knowledge agents need to build data apps. Put package
47
+ implementation, testing, and release guidance in `CONTRIBUTING.md`.
package/CONTRIBUTING.md CHANGED
@@ -56,6 +56,7 @@ checks. Build before running consumer tests individually.
56
56
  | Command | Purpose |
57
57
  | ------------------------------ | --------------------------------------------------- |
58
58
  | `bun run build` | Build JavaScript, declarations, and injected styles |
59
+ | `bun run check:styles` | Validate authored styling hooks |
59
60
  | `bun run typecheck` | Check source, tests, and scripts |
60
61
  | `bun run lint` | Run type-aware lint checks |
61
62
  | `bun run lint:md` | Check Markdown structure and syntax |
@@ -79,9 +80,42 @@ validation. It stays outside required checks because third-party availability an
79
80
  rate limits can cause failures unrelated to a change.
80
81
 
81
82
  For browser changes, run `bash scripts/install-test-browser.sh` once, then
82
- `bun run test:browser`. Preview UI examples at `/gallery` with
83
- `bun browser-tests/server.ts`.
83
+ `bun run test:browser`.
84
+
85
+ Run `bun run dev` to preview UI examples at `http://127.0.0.1:27418/gallery`
86
+ and a playground at `/playground` (`dev/playground.tsx`, querying the demo
87
+ tables `scripts/dev.ts` seeds). It builds once, then rebuilds `dist` when `src`
88
+ changes; open pages reload on package, fixture, and playground edits. Restart it after changing
89
+ `browser-tests/server.ts`; rerun `bun run build` to refresh declarations. Add `?delay=2000` to a host page URL
90
+ to delay its SQL responses and inspect loading states. It needs Docker: SQL runs
91
+ against a mocked Altertable API
92
+ ([altertable-mock](https://github.com/altertable-ai/altertable-mock), DuckDB)
93
+ started with Testcontainers and stopped on exit. Browser tests keep fixtures.
94
+
95
+ Open the **Widgets** tab (`/gallery?view=widgets`) for one ready example of each
96
+ composable data display inside `<VisualizationWidget>`. The other tabs cover
97
+ composed apps, variants, and request states.
84
98
 
85
99
  Use Conventional Commits and describe behavior changes and verification in PRs.
86
100
  Flag breaking API changes. Release Please owns `CHANGELOG.md`; see
87
- [Releasing](docs/releasing.md) for release setup and recovery.
101
+ [Releasing](https://github.com/altertable-ai/data-app/blob/main/.github/RELEASING.md) for release setup and recovery.
102
+
103
+ ## Focused public API
104
+
105
+ Keep exports and options focused on concrete app needs. Prefer defaults and
106
+ derivation from existing state over new knobs; keep implementation details private.
107
+
108
+ For public changes, update the relevant guide, migrate callers and starters,
109
+ and verify published usage. Flag breaking changes in commits and PRs.
110
+
111
+ Docs help agents generate data apps: show current usage and focused examples.
112
+ Keep package architecture and contributor rules here.
113
+
114
+ ## Component CSS
115
+
116
+ Keep defaults in authored CSS: inherited values in `tokens.css`, presets in
117
+ `appearance.css`, and optional overrides in native `var()` fallbacks at use sites.
118
+ Use the four layers (`atbl.tokens`, `atbl.base`, `atbl.components`,
119
+ `atbl.interaction`) and shared focus/state rules rather than duplicate control
120
+ paint. Keep geometry local. Document public variables beside declarations or
121
+ consumption sites; update the name contract in `style-contract.ts` when adding hooks.
package/README.md CHANGED
@@ -38,7 +38,7 @@ For integrating apps into a host, see [embedding](docs/embed.md).
38
38
  ## Development
39
39
 
40
40
  See [Contributing](CONTRIBUTING.md) for repository structure and focused checks.
41
- Releases use [Release Please and npm trusted publishing](docs/releasing.md).
41
+ Releases use [Release Please and npm trusted publishing](https://github.com/altertable-ai/data-app/blob/main/.github/RELEASING.md).
42
42
 
43
43
  ## License
44
44
 
@@ -1,6 +1,3 @@
1
- import {
2
- DataSourceError2
3
- } from "./contract-yxbjea23.js";
4
1
  import {
5
2
  PARENT_PARAM,
6
3
  MAX_PENDING,
@@ -414,145 +411,6 @@ function getDataAppTransport2(frame = window) {
414
411
  return frame[installedKey];
415
412
  }
416
413
 
417
- // src/core/operation.ts
418
- async function executeDataOperation(operation, value, {
419
- operationName,
420
- lakehouse,
421
- signal: requestSignal,
422
- includeSql,
423
- requestId
424
- }) {
425
- requestSignal.throwIfAborted();
426
- let input;
427
- try {
428
- input = operation.input(value);
429
- } catch {
430
- throw new OperationInputError;
431
- }
432
- const signal = AbortSignal.any([
433
- requestSignal,
434
- AbortSignal.timeout(operation.policy.maxDurationMs)
435
- ]);
436
- const execution = createOperationLakehouse(operation, lakehouse, signal, operationName);
437
- try {
438
- const output = await runOperation(operation, input, {
439
- lakehouse: execution.lakehouse,
440
- signal
441
- });
442
- const body = {
443
- data: operation.output(output),
444
- requestId,
445
- queriedAt: new Date().toISOString(),
446
- queryIds: execution.queryIds,
447
- ...operation.policy.exposeSql && includeSql ? { queries: execution.queries } : {}
448
- };
449
- const serializedBody = JSON.stringify(body);
450
- const responseBytes = new TextEncoder().encode(serializedBody).byteLength;
451
- if (responseBytes > (operation.policy.maxResponseBytes ?? 1e6))
452
- throw new Error("Response exceeds byte limit.");
453
- return { body, serializedBody };
454
- } catch (error) {
455
- if (signal.aborted && !(error instanceof DataSourceError2))
456
- throw new OperationTimeoutError;
457
- throw error;
458
- }
459
- }
460
- function createOperationLakehouse(operation, source, signal, operationName) {
461
- const queryIds = [];
462
- const queries = [];
463
- const lakehouse = {
464
- async queryAll(statement, options) {
465
- if (!Number.isInteger(options.limit) || options.limit < 1)
466
- throw new Error("Query needs a positive row limit.");
467
- if (operation.queryNames && !Object.values(operation.queryNames).includes(options.name ?? ""))
468
- throw new Error(`Query name is not registered for operation ${operationName}.`);
469
- const query = {
470
- name: options.name ?? `Query ${queries.length + 1}`,
471
- statement
472
- };
473
- queries.push(query);
474
- const limit = Math.min(options.limit, operation.policy.maxQueryRows);
475
- let result;
476
- try {
477
- result = await source.queryAll(statement, {
478
- limit,
479
- signal: AbortSignal.any([signal, options.signal])
480
- });
481
- } catch (error) {
482
- if (error instanceof DataSourceError2)
483
- error.queryName = query.name;
484
- throw error;
485
- }
486
- if (result.rows.length > limit)
487
- throw new Error("Result exceeds row limit.");
488
- if (result.queryId) {
489
- query.queryId = result.queryId;
490
- queryIds.push(result.queryId);
491
- }
492
- return result;
493
- }
494
- };
495
- return { lakehouse, queries, queryIds };
496
- }
497
- async function runOperation(operation, input, { lakehouse, signal }) {
498
- let abort;
499
- try {
500
- signal.throwIfAborted();
501
- const cancelled = new Promise((_, reject) => {
502
- function rejectAborted() {
503
- reject(new Error("Request aborted."));
504
- }
505
- abort = rejectAborted;
506
- signal.addEventListener("abort", rejectAborted, { once: true });
507
- if (signal.aborted)
508
- rejectAborted();
509
- });
510
- return await Promise.race([
511
- cancelled,
512
- Promise.resolve().then(() => {
513
- signal.throwIfAborted();
514
- return operation.run({ lakehouse, signal }, input);
515
- })
516
- ]);
517
- } finally {
518
- if (abort)
519
- signal.removeEventListener("abort", abort);
520
- }
521
- }
522
-
523
- class OperationTimeoutError extends Error {
524
- }
525
-
526
- class OperationInputError extends Error {
527
- }
528
- var sourceErrorMessages = {
529
- unauthorized: "This app could not authenticate its data connection. Contact the app owner.",
530
- forbidden: "This app cannot access the requested data. Contact the app owner.",
531
- rate_limited: "The lakehouse is busy. Wait a moment and retry.",
532
- query_rejected: "A lakehouse query was rejected. Check the app's data operation.",
533
- unavailable: "The lakehouse is unavailable. Check the connection and retry."
534
- };
535
- function toDataOperationFailure(error, aborted = false) {
536
- if (error instanceof OperationInputError)
537
- return {
538
- status: 400,
539
- code: "invalid_input",
540
- message: "Check this operation's inputs."
541
- };
542
- if (error instanceof DataSourceError2)
543
- return {
544
- status: error.reason === "rate_limited" ? 429 : 502,
545
- code: `source_${error.reason}`,
546
- message: sourceErrorMessages[error.reason]
547
- };
548
- const timedOut = aborted || error instanceof OperationTimeoutError;
549
- return {
550
- status: timedOut ? 504 : 502,
551
- code: timedOut ? "timeout" : "query_failed",
552
- message: timedOut ? "The data request timed out." : "The data request failed."
553
- };
554
- }
555
-
556
- export { DataAppError2, createHttpTransport2, createMessageClient2, createIframeTransport2, localFrameBridge, installDataAppTransport2, getDataAppTransport2, executeDataOperation, toDataOperationFailure };
414
+ export { DataAppError2, createHttpTransport2, createMessageClient2, createIframeTransport2, localFrameBridge, installDataAppTransport2, getDataAppTransport2 };
557
415
 
558
- //# debugId=07C270EAF2B6B13764756E2164756E21
416
+ //# debugId=F13D3D498CB70AA064756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/transport.ts", "../src/client/messages.ts", "../src/client/logger.ts", "../src/client/iframe.ts"],
4
+ "sourcesContent": [
5
+ "import type { TransportResponse } from '@/src/core/bridge';\n\nexport type DataTransport = (\n operation: string,\n input: unknown,\n signal?: AbortSignal\n) => Promise<TransportResponse>;\n\n// A bootstrap and its app may bundle independent copies in the same window.\nconst errorBrand = Symbol.for('@altertable/data-app/DataAppError');\n\nexport class DataAppError extends Error {\n readonly [errorBrand] = true;\n\n static [Symbol.hasInstance](value: unknown): boolean {\n return (\n value instanceof Error &&\n (value as { [errorBrand]?: unknown })[errorBrand] === true\n );\n }\n\n constructor(\n message: string,\n public readonly code: string,\n public readonly requestId?: string\n ) {\n super(message);\n this.name = 'DataAppError';\n }\n}\n\nexport function createHttpTransport({\n endpoint = '/api/data',\n fetch: request = globalThis.fetch,\n}: {\n endpoint?: string;\n fetch?: typeof fetch;\n} = {}): DataTransport {\n async function requestData(\n operation: string,\n input: unknown,\n signal?: AbortSignal\n ): Promise<TransportResponse> {\n const response = await request(\n `${endpoint.replace(/\\/$/, '')}/${encodeURIComponent(operation)}`,\n {\n method: 'POST',\n headers: { 'content-type': 'application/json' },\n body: JSON.stringify(input),\n signal,\n }\n );\n try {\n return { status: response.status, body: await response.json() };\n } catch (error) {\n if (signal?.aborted) throw error;\n throw new DataAppError(\n response.ok ? 'The data response was invalid.' : 'Could not load data.',\n response.ok ? 'invalid_response' : 'request_failed'\n );\n }\n }\n\n return requestData;\n}\n",
6
+ "import {\n MessageRoutingError,\n type MessageInput,\n type MessageOutput,\n type MessageRoutes,\n type MessageTransport,\n} from '@/src/core/messages';\n\n/** Both ends validate using the same contracts; the transport owns delivery and cancellation. */\nexport function createMessageClient<const Routes extends MessageRoutes>(\n routes: Routes,\n transport: MessageTransport\n) {\n return {\n async request<\n Name extends keyof Routes & string,\n const Input extends MessageInput<NoInfer<Routes[Name]>>,\n >(\n route: Name,\n payload: Input,\n { signal }: { signal?: AbortSignal } = {}\n ): Promise<MessageOutput<Routes[Name], Input>> {\n signal?.throwIfAborted();\n if (!Object.hasOwn(routes, route))\n throw new MessageRoutingError(\n 'unknown_route',\n 'Unknown message route.'\n );\n const contract = routes[route]!;\n let input: unknown;\n try {\n input = contract.input(payload);\n } catch {\n throw new MessageRoutingError(\n 'invalid_payload',\n 'Invalid message payload.'\n );\n }\n const response = await transport({ route, payload: input }, signal);\n signal?.throwIfAborted();\n try {\n return contract.output(response, input as never) as MessageOutput<\n Routes[Name],\n Input\n >;\n } catch (error) {\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'invalid_response',\n 'Invalid message response.'\n );\n }\n },\n };\n}\n",
7
+ "import type { BridgeMessage } from '@/src/core/bridge';\nimport { type DataAppLogger, type LogEntry } from '@/src/core/logger';\n\n/** Lazy arguments run in the iframe; only resolved values cross the bridge. */\nexport function createBridgeLogger(\n enabled: () => boolean,\n send: (entry: LogEntry) => void\n): DataAppLogger {\n function resolve(args: unknown[]): unknown[] {\n if (args.length === 1 && typeof args[0] === 'function') {\n const value: unknown = args[0]();\n return Array.isArray(value) ? value : [value];\n }\n return args.map(arg => (typeof arg === 'function' ? arg() : arg));\n }\n\n function write(method: keyof DataAppLogger, args: unknown[]) {\n if (!enabled()) return;\n try {\n send({ method, args: resolve(args) });\n } catch {\n // Logging must not interrupt the app or recursively log delivery failures.\n }\n }\n\n return {\n log: (...args) => write('log', args),\n info: (...args) => write('info', args),\n warn: (...args) => write('warn', args),\n error: (...args) => write('error', args),\n };\n}\n\n/** Log only delivery metadata; payloads and session credentials stay private. */\nexport function logBridgeMessage(\n logger: DataAppLogger,\n message: BridgeMessage\n) {\n if (message.type === 'runtime:log') return;\n logger.log(() => {\n const metadata: {\n type: BridgeMessage['type'];\n id?: string;\n route?: string;\n operation?: string;\n } = { type: message.type };\n if ('id' in message) metadata.id = message.id;\n if (message.type === 'bridge:request') {\n metadata.route = message.route;\n const payload = message.payload;\n if (\n message.route === 'data:query' &&\n payload &&\n typeof payload === 'object' &&\n 'operation' in payload &&\n typeof payload.operation === 'string'\n )\n metadata.operation = payload.operation;\n }\n return ['Sending message to parent', metadata];\n });\n}\n",
8
+ "import { createBridgeEndpoint } from '@/src/core/bridge-endpoint';\nimport {\n PARENT_PARAM,\n MAX_PENDING,\n REQUEST_TIMEOUT_MS,\n type TransportResponse,\n} from '@/src/core/bridge';\nimport {\n defineDataQueryRoute,\n sqlQueryRoute,\n MessageRoutingError,\n type RoutedMessage,\n} from '@/src/core/messages';\nimport type { Lakehouse } from '@/src/core/contract';\nimport { createMessageClient } from '@/src/client/messages';\nimport { DataAppError } from '@/src/client/transport';\nimport { createBridgeLogger, logBridgeMessage } from '@/src/client/logger';\n\ntype Pending = {\n start: () => void;\n reject: (error: unknown) => void;\n resolve: (value: unknown) => void;\n};\n\n/** Data clients expose one error type for HTTP and message delivery. */\nfunction rethrowDataMessageError(error: unknown): never {\n if (error instanceof MessageRoutingError)\n throw new DataAppError(error.message, error.code, error.requestId);\n throw error;\n}\n\n/** One bridge per document, shared by all clients and retained across module hot replacement. */\nexport function createIframeTransport({\n parentOrigin,\n window: frame = window,\n timeoutMs = REQUEST_TIMEOUT_MS,\n mode = 'url',\n loadScript,\n}: {\n parentOrigin: string;\n window?: Window;\n timeoutMs?: number;\n mode?: 'url' | 'bundle';\n loadScript?: (javascript: string) => void;\n}) {\n if (new URL(parentOrigin).origin !== parentOrigin)\n throw new Error('Expected an exact parent origin.');\n const documentId = crypto.randomUUID();\n let token: string | undefined;\n let sessionId: string | undefined;\n let disposed = false;\n const pending = new Map<string, Pending>();\n let hostState: unknown;\n const stateListeners = new Set<(state: unknown) => void>();\n const logger = createBridgeLogger(\n () =>\n !disposed &&\n !!sessionId &&\n !!hostState &&\n typeof hostState === 'object' &&\n 'logging' in hostState &&\n hostState.logging === true,\n entry => send('runtimeLog', { payload: entry })\n );\n\n const endpoint = createBridgeEndpoint({\n role: 'app',\n origin: parentOrigin,\n source: () => frame.parent,\n opaque: mode === 'bundle',\n context: () => ({ documentId, sessionId, token }),\n post(message) {\n frame.parent.postMessage(message, parentOrigin);\n logBridgeMessage(logger, message);\n },\n handlers: {\n connect(message) {\n if (mode === 'bundle') token = message.token;\n send('ready', {});\n },\n initialize(message) {\n if (sessionId && sessionId !== message.sessionId) {\n for (const entry of pending.values())\n entry.reject(\n new DataAppError(\n 'The preview reconnected. Retry the request.',\n 'bridge_reset'\n )\n );\n }\n const first = !sessionId;\n sessionId = message.sessionId;\n receiveState(message.state);\n if (first) for (const entry of pending.values()) entry.start();\n if (disposed) return;\n if (mode === 'url') send('runtimeReady', {});\n },\n stateUpdate(message) {\n receiveState(message.state);\n },\n scriptLoad(message) {\n if (mode === 'bundle') loadScript?.(message.javascript);\n },\n result(message) {\n pending.get(message.id)?.resolve(message.response);\n },\n error(message) {\n pending\n .get(message.id)\n ?.reject(\n new MessageRoutingError(\n message.code,\n message.message,\n message.requestId\n )\n );\n },\n },\n });\n const send = endpoint.send;\n const receive = endpoint.receive;\n\n function receiveState(state: unknown) {\n hostState = state;\n for (const listener of stateListeners) listener(state);\n }\n\n frame.addEventListener('message', receive);\n\n function requestMessage(\n message: RoutedMessage,\n signal?: AbortSignal\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n if (disposed)\n return reject(\n new DataAppError('The preview has closed.', 'bridge_closed')\n );\n if (signal?.aborted) return reject(signal.reason);\n if (pending.size >= MAX_PENDING)\n return reject(\n new DataAppError('Too many pending data requests.', 'bridge_busy')\n );\n const id = crypto.randomUUID();\n let sent = false;\n\n function cleanup() {\n clearTimeout(timer);\n signal?.removeEventListener('abort', abort);\n pending.delete(id);\n }\n\n function abort() {\n if (sent) send('cancel', { id });\n cleanup();\n reject(signal?.reason);\n }\n\n const timer = setTimeout(() => {\n if (sent) send('cancel', { id });\n cleanup();\n reject(\n new DataAppError(\n sessionId\n ? 'The data request timed out.'\n : 'The preview shell is unavailable. Reload the preview.',\n sessionId ? 'timeout' : 'bridge_unavailable'\n )\n );\n }, timeoutMs);\n const entry: Pending = {\n start() {\n if (sent) return;\n try {\n send('request', {\n id,\n route: message.route,\n payload: message.payload,\n });\n sent = true;\n } catch {\n cleanup();\n reject(\n new DataAppError(\n 'The message payload could not be sent.',\n 'invalid_payload'\n )\n );\n }\n },\n resolve(value) {\n cleanup();\n resolve(value);\n },\n reject(error) {\n cleanup();\n reject(error);\n },\n };\n pending.set(id, entry);\n signal?.addEventListener('abort', abort, { once: true });\n if (sessionId) entry.start();\n else if (mode === 'url' || token) send('ready', {});\n });\n }\n\n const messages = createMessageClient(\n { 'data:query': defineDataQueryRoute(), 'data:sql': sqlQueryRoute },\n requestMessage\n );\n\n function queryOperation(\n operation: string,\n input: unknown,\n signal?: AbortSignal\n ): Promise<TransportResponse> {\n return messages\n .request('data:query', { operation, input }, { signal })\n .catch(rethrowDataMessageError);\n }\n\n function disconnect() {\n if (sessionId) send('disconnect', {});\n sessionId = undefined;\n for (const entry of pending.values())\n entry.reject(\n new DataAppError('The preview has closed.', 'bridge_closed')\n );\n }\n\n function resume(event: PageTransitionEvent) {\n if (event.persisted && (mode === 'url' || token)) send('ready', {});\n }\n\n function dispose() {\n if (disposed) return;\n disconnect();\n disposed = true;\n endpoint.dispose();\n frame.removeEventListener('message', receive);\n frame.removeEventListener('pagehide', disconnect);\n frame.removeEventListener('pageshow', resume);\n stateListeners.clear();\n }\n\n frame.addEventListener('pagehide', disconnect);\n frame.addEventListener('pageshow', resume);\n if (mode === 'url') send('ready', {});\n\n return {\n logger,\n request: requestMessage,\n transport: queryOperation,\n lakehouse: {\n queryAll(statement, { limit, signal }) {\n return messages\n .request('data:sql', { statement, limit }, { signal })\n .catch(rethrowDataMessageError);\n },\n } satisfies Lakehouse,\n dispose,\n mode,\n snapshot() {\n return hostState;\n },\n subscribe(listener: (state: unknown) => void) {\n stateListeners.add(listener);\n\n return () => {\n stateListeners.delete(listener);\n };\n },\n ready() {\n if (!disposed && sessionId) send('runtimeReady', {});\n },\n fail() {\n if (!disposed && sessionId) send('runtimeError', {});\n },\n };\n}\n\nexport type IframeTransport = ReturnType<typeof createIframeTransport>;\n\nconst bridgeKey = Symbol.for('altertable.localFrameBridge');\nconst installedKey = Symbol.for('altertable.installedTransport');\ntype LocalBridge = Pick<\n ReturnType<typeof createIframeTransport>,\n 'transport'\n> & { connect?: () => Promise<ReturnType<typeof createIframeTransport>> };\ntype FrameWindow = Window & {\n [bridgeKey]?: LocalBridge;\n [installedKey]?: ReturnType<typeof createIframeTransport>;\n};\n\n/** The URL opts into local preview; only same-origin server configuration establishes trust. */\nexport function localFrameBridge(window?: Window): LocalBridge | undefined {\n const activeWindow =\n window ??\n (typeof globalThis.window === 'undefined' ? undefined : globalThis.window);\n if (!activeWindow) return undefined;\n const frame = activeWindow as FrameWindow;\n if (frame[bridgeKey]) return frame[bridgeKey];\n const parentOrigin =\n new URL(frame.location.href).searchParams.get(PARENT_PARAM) ?? '';\n if (!parentOrigin) return undefined;\n\n async function connect(parentOrigin: string) {\n try {\n const response = await frame.fetch('/__altertable/parent', {\n signal: AbortSignal.timeout(5000),\n });\n const config = (await response.json()) as { origin?: unknown };\n if (\n !response.ok ||\n config.origin !== parentOrigin ||\n frame.parent === frame\n )\n throw new Error('Invalid local parent configuration.');\n // Another owner can install a trusted bridge while configuration is pending.\n if (frame[installedKey]) return frame[installedKey];\n if (frame[bridgeKey] !== proxy)\n throw new Error('Preview transport owner changed.');\n const bridge = createIframeTransport({ parentOrigin, window: frame });\n frame[bridgeKey] = bridge;\n frame[installedKey] = bridge;\n\n return bridge;\n } catch {\n throw new DataAppError(\n 'The preview shell could not be verified. Open the URL printed by altertable app dev.',\n 'bridge_unavailable'\n );\n }\n }\n\n let connection: Promise<ReturnType<typeof createIframeTransport>> | undefined;\n\n function getConnection() {\n const installed = frame[installedKey];\n if (installed) return Promise.resolve(installed);\n if (!connection) {\n const attempt = connect(parentOrigin);\n connection = attempt;\n // Clear only this failed attempt; retained proxy references can explicitly retry.\n void attempt.catch(() => {\n if (connection === attempt) connection = undefined;\n });\n }\n\n return connection;\n }\n\n const proxy: LocalBridge = {\n async transport(operation, input, signal) {\n signal?.throwIfAborted();\n const attempt = getConnection();\n let abort: (() => void) | undefined;\n try {\n const bridge = signal\n ? await Promise.race([\n attempt,\n new Promise<never>((_, reject) => {\n const requestSignal = signal;\n\n function handleAbort() {\n reject(requestSignal.reason);\n }\n\n abort = handleAbort;\n requestSignal.addEventListener('abort', handleAbort, {\n once: true,\n });\n }),\n ])\n : await attempt;\n signal?.throwIfAborted();\n\n return bridge.transport(operation, input, signal);\n } finally {\n if (abort) signal?.removeEventListener('abort', abort);\n }\n },\n connect: getConnection,\n };\n frame[bridgeKey] = proxy;\n // Static mounting still verifies eagerly, without an unhandled rejection.\n void getConnection().catch(() => {});\n\n return proxy;\n}\n\n/** Install an explicitly trusted transport for hosted apps and their URL-backed controls. */\nexport function installDataAppTransport(\n bridge: ReturnType<typeof createIframeTransport>,\n frame: Window = window\n) {\n const target = frame as FrameWindow;\n if (target[installedKey])\n throw new Error('A data app transport is already installed.');\n target[bridgeKey] = bridge;\n target[installedKey] = bridge;\n\n return () => {\n if (target[bridgeKey] === bridge) delete target[bridgeKey];\n if (target[installedKey] === bridge) delete target[installedKey];\n bridge.dispose();\n };\n}\n\n/** The bootstrap installs this before executing app code. URL apps can install an explicit connection. */\nexport function getDataAppTransport(frame: Window = window) {\n return (frame as FrameWindow)[installedKey];\n}\n"
9
+ ],
10
+ "mappings": "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",
11
+ "debugId": "F13D3D498CB70AA064756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,78 @@
1
+ import {
2
+ executeDataOperation,
3
+ toDataOperationFailure
4
+ } from "./contract-pk603qj7.js";
5
+ import {
6
+ DataAppError2,
7
+ createHttpTransport2,
8
+ localFrameBridge,
9
+ getDataAppTransport2
10
+ } from "./contract-13j5zb3c.js";
11
+ import {
12
+ MessageRoutingError2,
13
+ defineDataQueryRoute2
14
+ } from "./contract-tf8c3qpv.js";
15
+
16
+ // src/client/data-client.ts
17
+ var dataQueryRoute = defineDataQueryRoute2();
18
+ function createDataClient2(options = {}) {
19
+ if (options.operations)
20
+ return createOperationClient({
21
+ operations: options.operations,
22
+ lakehouse: options.lakehouse
23
+ });
24
+ const http = createHttpTransport2(options);
25
+ const useHttp = options.endpoint !== undefined || options.fetch !== undefined;
26
+ return {
27
+ async query(name, input, { signal } = {}) {
28
+ const transport = options.transport ?? (useHttp ? http : localFrameBridge()?.transport ?? http);
29
+ const response = await transport(name, input, signal);
30
+ const ok = response.status >= 200 && response.status < 300;
31
+ let body;
32
+ try {
33
+ body = dataQueryRoute.output(response, { operation: name, input }).body;
34
+ } catch (error) {
35
+ if (signal?.aborted)
36
+ throw error;
37
+ if (error instanceof MessageRoutingError2)
38
+ throw new DataAppError2(error.message, error.code, error.requestId);
39
+ throw new DataAppError2(ok ? "The data response was invalid." : "Could not load data.", ok ? "invalid_response" : "request_failed");
40
+ }
41
+ return { ...body, input };
42
+ }
43
+ };
44
+ }
45
+ function createOperationClient(options) {
46
+ return {
47
+ async query(name, input, { signal } = {}) {
48
+ signal?.throwIfAborted();
49
+ const requestId = crypto.randomUUID();
50
+ if (!Object.hasOwn(options.operations, name))
51
+ throw new DataAppError2("Unknown data operation.", "not_found", requestId);
52
+ const lakehouse = options.lakehouse ?? (typeof window === "undefined" ? undefined : getDataAppTransport2()?.lakehouse);
53
+ if (!lakehouse)
54
+ throw new DataAppError2("An authorized SQL bridge must be installed first.", "bridge_unavailable", requestId);
55
+ try {
56
+ const { body } = await executeDataOperation(options.operations[name], input, {
57
+ lakehouse,
58
+ signal: signal ?? new AbortController().signal,
59
+ includeSql: true,
60
+ requestId,
61
+ operationName: name
62
+ });
63
+ return { ...body, input };
64
+ } catch (error) {
65
+ if (signal?.aborted)
66
+ throw signal.reason;
67
+ if (error instanceof DataAppError2)
68
+ throw error;
69
+ const failure = toDataOperationFailure(error);
70
+ throw new DataAppError2(failure.message, failure.code, requestId);
71
+ }
72
+ }
73
+ };
74
+ }
75
+
76
+ export { createDataClient2 };
77
+
78
+ //# debugId=64AFD24787CC437264756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/data-client.ts"],
4
+ "sourcesContent": [
5
+ "import { createHttpTransport, DataAppError } from '@/src/client/transport';\nimport { getDataAppTransport, localFrameBridge } from '@/src/client/iframe';\nimport {\n executeDataOperation,\n toDataOperationFailure,\n} from '@/src/core/operation';\nimport type { DataOperations, Lakehouse } from '@/src/core/contract';\nimport { defineDataQueryRoute, MessageRoutingError } from '@/src/core/messages';\nimport type { DataTransport } from '@/src/client/transport';\nimport type {\n DataQueryBody,\n InputOf,\n OutputOf,\n} from '@/src/core/operation-types';\nexport type { InputOf, OutputOf } from '@/src/core/operation-types';\n\n/**\n * Parsed operation data and query evidence. `queries` is present only when SQL disclosure is\n * allowed.\n */\nexport type DataResponse<Output, Input = unknown> = DataQueryBody<Output> & {\n /** The exact browser input that produced this response. */\n input: Input;\n};\n\nexport type DataClient<Operations extends DataOperations> = {\n query<Name extends keyof Operations & string>(\n name: Name,\n input: InputOf<Operations[Name]>,\n options?: { signal?: AbortSignal }\n ): Promise<\n DataResponse<OutputOf<Operations[Name]>, InputOf<Operations[Name]>>\n >;\n};\n\n/** Browser operations and named-operation delivery are mutually exclusive configurations. */\nexport type DataClientOptions<Operations extends DataOperations> =\n | {\n operations: Operations;\n lakehouse?: Lakehouse;\n transport?: never;\n endpoint?: never;\n fetch?: never;\n }\n | {\n operations?: never;\n lakehouse?: never;\n transport?: DataTransport;\n endpoint?: string;\n fetch?: typeof fetch;\n };\n\nconst dataQueryRoute = defineDataQueryRoute();\n\n/** Named HTTP operations, or browser-owned operations executed through an authorized SQL bridge. */\nexport function createDataClient<Operations extends DataOperations>(\n options: DataClientOptions<Operations> = {}\n): DataClient<Operations> {\n if (options.operations)\n return createOperationClient({\n operations: options.operations,\n lakehouse: options.lakehouse,\n });\n const http = createHttpTransport(options);\n const useHttp = options.endpoint !== undefined || options.fetch !== undefined;\n\n return {\n async query(name, input, { signal } = {}) {\n const transport =\n options.transport ??\n (useHttp ? http : (localFrameBridge()?.transport ?? http));\n const response = await transport(name, input, signal);\n const ok = response.status >= 200 && response.status < 300;\n let body: Omit<DataResponse<OutputOf<Operations[typeof name]>>, 'input'>;\n try {\n body = dataQueryRoute.output(response, { operation: name, input })\n .body as typeof body;\n } catch (error) {\n if (signal?.aborted) throw error;\n if (error instanceof MessageRoutingError)\n throw new DataAppError(error.message, error.code, error.requestId);\n throw new DataAppError(\n ok ? 'The data response was invalid.' : 'Could not load data.',\n ok ? 'invalid_response' : 'request_failed'\n );\n }\n\n return { ...body, input };\n },\n };\n}\n\nfunction createOperationClient<Operations extends DataOperations>(options: {\n operations: Operations;\n lakehouse?: Lakehouse;\n}): DataClient<Operations> {\n return {\n async query(name, input, { signal } = {}) {\n signal?.throwIfAborted();\n const requestId = crypto.randomUUID();\n if (!Object.hasOwn(options.operations, name))\n throw new DataAppError(\n 'Unknown data operation.',\n 'not_found',\n requestId\n );\n const lakehouse =\n options.lakehouse ??\n (typeof window === 'undefined'\n ? undefined\n : getDataAppTransport()?.lakehouse);\n if (!lakehouse)\n throw new DataAppError(\n 'An authorized SQL bridge must be installed first.',\n 'bridge_unavailable',\n requestId\n );\n\n try {\n const { body } = await executeDataOperation(\n options.operations[name]!,\n input,\n {\n lakehouse,\n signal: signal ?? new AbortController().signal,\n includeSql: true,\n requestId,\n operationName: name,\n }\n );\n\n return { ...body, input } as DataResponse<\n OutputOf<Operations[typeof name]>,\n InputOf<Operations[typeof name]>\n >;\n } catch (error) {\n if (signal?.aborted) throw signal.reason;\n if (error instanceof DataAppError) throw error;\n const failure = toDataOperationFailure(error);\n throw new DataAppError(failure.message, failure.code, requestId);\n }\n },\n };\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;;;;;;;;;AAoDA,IAAM,iBAAiB,sBAAqB;AAGrC,SAAS,iBAAmD,CACjE,UAAyC,CAAC,GAClB;AAAA,EACxB,IAAI,QAAQ;AAAA,IACV,OAAO,sBAAsB;AAAA,MAC3B,YAAY,QAAQ;AAAA,MACpB,WAAW,QAAQ;AAAA,IACrB,CAAC;AAAA,EACH,MAAM,OAAO,qBAAoB,OAAO;AAAA,EACxC,MAAM,UAAU,QAAQ,aAAa,aAAa,QAAQ,UAAU;AAAA,EAEpE,OAAO;AAAA,SACC,MAAK,CAAC,MAAM,SAAS,WAAW,CAAC,GAAG;AAAA,MACxC,MAAM,YACJ,QAAQ,cACP,UAAU,OAAQ,iBAAiB,GAAG,aAAa;AAAA,MACtD,MAAM,WAAW,MAAM,UAAU,MAAM,OAAO,MAAM;AAAA,MACpD,MAAM,KAAK,SAAS,UAAU,OAAO,SAAS,SAAS;AAAA,MACvD,IAAI;AAAA,MACJ,IAAI;AAAA,QACF,OAAO,eAAe,OAAO,UAAU,EAAE,WAAW,MAAM,MAAM,CAAC,EAC9D;AAAA,QACH,OAAO,OAAO;AAAA,QACd,IAAI,QAAQ;AAAA,UAAS,MAAM;AAAA,QAC3B,IAAI,iBAAiB;AAAA,UACnB,MAAM,IAAI,cAAa,MAAM,SAAS,MAAM,MAAM,MAAM,SAAS;AAAA,QACnE,MAAM,IAAI,cACR,KAAK,mCAAmC,wBACxC,KAAK,qBAAqB,gBAC5B;AAAA;AAAA,MAGF,OAAO,KAAK,MAAM,MAAM;AAAA;AAAA,EAE5B;AAAA;AAGF,SAAS,qBAAwD,CAAC,SAGvC;AAAA,EACzB,OAAO;AAAA,SACC,MAAK,CAAC,MAAM,SAAS,WAAW,CAAC,GAAG;AAAA,MACxC,QAAQ,eAAe;AAAA,MACvB,MAAM,YAAY,OAAO,WAAW;AAAA,MACpC,IAAI,CAAC,OAAO,OAAO,QAAQ,YAAY,IAAI;AAAA,QACzC,MAAM,IAAI,cACR,2BACA,aACA,SACF;AAAA,MACF,MAAM,YACJ,QAAQ,cACP,OAAO,WAAW,cACf,YACA,qBAAoB,GAAG;AAAA,MAC7B,IAAI,CAAC;AAAA,QACH,MAAM,IAAI,cACR,qDACA,sBACA,SACF;AAAA,MAEF,IAAI;AAAA,QACF,QAAQ,SAAS,MAAM,qBACrB,QAAQ,WAAW,OACnB,OACA;AAAA,UACE;AAAA,UACA,QAAQ,UAAU,IAAI,gBAAgB,EAAE;AAAA,UACxC,YAAY;AAAA,UACZ;AAAA,UACA,eAAe;AAAA,QACjB,CACF;AAAA,QAEA,OAAO,KAAK,MAAM,MAAM;AAAA,QAIxB,OAAO,OAAO;AAAA,QACd,IAAI,QAAQ;AAAA,UAAS,MAAM,OAAO;AAAA,QAClC,IAAI,iBAAiB;AAAA,UAAc,MAAM;AAAA,QACzC,MAAM,UAAU,uBAAuB,KAAK;AAAA,QAC5C,MAAM,IAAI,cAAa,QAAQ,SAAS,QAAQ,MAAM,SAAS;AAAA;AAAA;AAAA,EAGrE;AAAA;",
8
+ "debugId": "64AFD24787CC437264756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,82 +1,22 @@
1
1
  import {
2
- DataAppError2,
3
- createHttpTransport2,
4
2
  createMessageClient2,
5
3
  localFrameBridge,
6
- getDataAppTransport2,
7
- executeDataOperation,
8
- toDataOperationFailure
9
- } from "./contract-sm7j7k95.js";
4
+ getDataAppTransport2
5
+ } from "./contract-13j5zb3c.js";
10
6
  import {
11
7
  PARENT_PARAM
12
8
  } from "./contract-awa2d5b1.js";
9
+ import {
10
+ annotationDraftRoute2,
11
+ annotationEditorStateRoute2,
12
+ annotationUpdateRoute2,
13
+ annotationModeRoute2
14
+ } from "./contract-rfbakka4.js";
13
15
  import {
14
16
  validLocation,
15
- MessageRoutingError2,
16
- defineDataQueryRoute2,
17
17
  navigationUpdateRoute2
18
18
  } from "./contract-tf8c3qpv.js";
19
19
 
20
- // src/client/data-client.ts
21
- var dataQueryRoute = defineDataQueryRoute2();
22
- function createDataClient2(options = {}) {
23
- if (options.operations)
24
- return createOperationClient({
25
- operations: options.operations,
26
- lakehouse: options.lakehouse
27
- });
28
- const http = createHttpTransport2(options);
29
- const useHttp = options.endpoint !== undefined || options.fetch !== undefined;
30
- return {
31
- async query(name, input, { signal } = {}) {
32
- const transport = options.transport ?? (useHttp ? http : localFrameBridge()?.transport ?? http);
33
- const response = await transport(name, input, signal);
34
- const ok = response.status >= 200 && response.status < 300;
35
- let body;
36
- try {
37
- body = dataQueryRoute.output(response, { operation: name, input }).body;
38
- } catch (error) {
39
- if (signal?.aborted)
40
- throw error;
41
- if (error instanceof MessageRoutingError2)
42
- throw new DataAppError2(error.message, error.code, error.requestId);
43
- throw new DataAppError2(ok ? "The data response was invalid." : "Could not load data.", ok ? "invalid_response" : "request_failed");
44
- }
45
- return { ...body, input };
46
- }
47
- };
48
- }
49
- function createOperationClient(options) {
50
- return {
51
- async query(name, input, { signal } = {}) {
52
- signal?.throwIfAborted();
53
- const requestId = crypto.randomUUID();
54
- if (!Object.hasOwn(options.operations, name))
55
- throw new DataAppError2("Unknown data operation.", "not_found", requestId);
56
- const lakehouse = options.lakehouse ?? (typeof window === "undefined" ? undefined : getDataAppTransport2()?.lakehouse);
57
- if (!lakehouse)
58
- throw new DataAppError2("An authorized SQL bridge must be installed first.", "bridge_unavailable", requestId);
59
- try {
60
- const { body } = await executeDataOperation(options.operations[name], input, {
61
- lakehouse,
62
- signal: signal ?? new AbortController().signal,
63
- includeSql: true,
64
- requestId,
65
- operationName: name
66
- });
67
- return { ...body, input };
68
- } catch (error) {
69
- if (signal?.aborted)
70
- throw signal.reason;
71
- if (error instanceof DataAppError2)
72
- throw error;
73
- const failure = toDataOperationFailure(error);
74
- throw new DataAppError2(failure.message, failure.code, requestId);
75
- }
76
- }
77
- };
78
- }
79
-
80
20
  // src/client/location.ts
81
21
  function createAppLocation(frame, virtual, publish) {
82
22
  let state = { search: "", hash: "" };
@@ -247,6 +187,30 @@ function getDataAppNavigation2(frame = window) {
247
187
  return adapter.navigation;
248
188
  }
249
189
 
250
- export { createDataClient2, createDataAppNavigation2, getDataAppNavigation2 };
190
+ // src/client/annotations.ts
191
+ function createAnnotationClient2(transport) {
192
+ const client = createMessageClient2({
193
+ "annotation:draft": annotationDraftRoute2,
194
+ "annotation:update": annotationUpdateRoute2,
195
+ "annotation:mode": annotationModeRoute2,
196
+ "annotation:editor": annotationEditorStateRoute2
197
+ }, transport);
198
+ return {
199
+ reportAnnotationEditorState(state, options) {
200
+ return client.request("annotation:editor", state, options);
201
+ },
202
+ addAnnotation(draft, options) {
203
+ return client.request("annotation:draft", draft, options);
204
+ },
205
+ updateAnnotation(id, comment, options) {
206
+ return client.request("annotation:update", { id, comment }, options);
207
+ },
208
+ requestAnnotationModeChange(request, options) {
209
+ return client.request("annotation:mode", request, options);
210
+ }
211
+ };
212
+ }
213
+
214
+ export { createDataAppNavigation2, getDataAppNavigation2, createAnnotationClient2 };
251
215
 
252
- //# debugId=B2D2C0A1B4F5737F64756E2164756E21
216
+ //# debugId=19B0E7BB9C5C8F2564756E2164756E21
@@ -0,0 +1,12 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/client/location.ts", "../src/client/navigation.ts", "../src/client/annotations.ts"],
4
+ "sourcesContent": [
5
+ "import { PARENT_PARAM } from '@/src/core/bridge';\nimport { validLocation } from '@/src/core/navigation';\n\nimport type { AppLocation, HistoryMode } from '@/src/core/navigation';\nexport type { AppLocation } from '@/src/core/navigation';\nexport type DataAppLocation = {\n snapshot(): AppLocation;\n subscribe(listener: () => void): () => void;\n update(location: AppLocation, mode?: HistoryMode): void;\n};\n\n/** Opaque sandboxes keep app state in memory; URL frames retain their real URL for HMR. */\nexport function createAppLocation(\n frame: Window,\n virtual: boolean,\n publish: (location: AppLocation, mode: HistoryMode) => void\n) {\n let state: AppLocation = { search: '', hash: '' };\n let disposed = false;\n const listeners = new Set<() => void>();\n\n function notify() {\n for (const listener of listeners) listener();\n }\n\n function snapshot(): AppLocation {\n if (virtual) return state;\n const url = new URL(frame.location.href);\n url.searchParams.delete(PARENT_PARAM);\n if (state.search !== url.search || state.hash !== url.hash)\n state = { search: url.search, hash: url.hash };\n\n return state;\n }\n\n function apply(next: AppLocation) {\n const previous = snapshot();\n if (previous.search === next.search && previous.hash === next.hash) return;\n if (virtual) state = next;\n else {\n const url = new URL(frame.location.href);\n const parent = url.searchParams.get(PARENT_PARAM);\n url.search = next.search;\n if (parent) url.searchParams.set(PARENT_PARAM, parent);\n url.hash = next.hash;\n frame.history.replaceState(null, '', url);\n frame.dispatchEvent(new Event('popstate'));\n }\n if (virtual) notify();\n }\n\n const location: DataAppLocation = {\n snapshot,\n subscribe(listener) {\n listeners.add(listener);\n if (!virtual) frame.addEventListener('popstate', listener);\n\n return () => {\n listeners.delete(listener);\n frame.removeEventListener('popstate', listener);\n };\n },\n update(next, mode = 'replace') {\n if (disposed) return;\n if (!validLocation(next)) throw new Error('Invalid app location.');\n const before = snapshot();\n if (before.search === next.search && before.hash === next.hash) return;\n apply(next);\n publish(next, mode);\n },\n };\n\n function dispose() {\n disposed = true;\n for (const listener of listeners)\n frame.removeEventListener('popstate', listener);\n listeners.clear();\n }\n\n return { location, apply, dispose };\n}\n",
6
+ "import type { AppLocation, HistoryMode } from '@/src/core/navigation';\nimport { createAppLocation, type DataAppLocation } from '@/src/client/location';\nimport { validLocation } from '@/src/core/navigation';\nimport {\n navigationUpdateRoute,\n type NavigationUpdate,\n} from '@/src/core/messages';\nimport { createMessageClient } from '@/src/client/messages';\nimport {\n getDataAppTransport,\n localFrameBridge,\n type IframeTransport,\n} from '@/src/client/iframe';\n\nexport type DataAppNavigation = DataAppLocation & {\n /** Publish URL changes made outside the adapter, including the document title. */\n publish(mode?: HistoryMode): void;\n dispose(): void;\n};\n\n/** Attach app URL behavior to an already authenticated bridge. */\nexport function createDataAppNavigation({\n bridge,\n window: frame = window,\n}: {\n bridge: IframeTransport;\n window?: Window;\n}): DataAppNavigation {\n return attachNavigation(frame, bridge.mode === 'bundle', bridge).navigation;\n}\n\nfunction attachNavigation(\n frame: Window,\n virtual: boolean,\n connection: IframeTransport | Promise<IframeTransport>\n) {\n let disposed = false;\n let unsubscribe: (() => void) | undefined;\n let send: ((update: NavigationUpdate) => void) | undefined;\n let pendingUpdate: NavigationUpdate | undefined;\n const { location, apply, dispose } = createAppLocation(\n frame,\n virtual,\n publish\n );\n\n function publish(location: AppLocation, mode: HistoryMode) {\n const update = { ...location, mode, title: frame.document.title };\n if (send) send(update);\n else pendingUpdate = update;\n }\n\n function attach(bridge: IframeTransport) {\n if (disposed) return;\n unsubscribe?.();\n const messages = createMessageClient(\n { 'navigation:update': navigationUpdateRoute },\n bridge.request\n );\n\n function sendUpdate(update: NavigationUpdate) {\n void messages.request('navigation:update', update).catch(() => {});\n }\n\n function receiveState(state: unknown) {\n if (!validLocation(state)) return;\n pendingUpdate = undefined;\n apply(state);\n }\n\n send = sendUpdate;\n unsubscribe = bridge.subscribe(receiveState);\n receiveState(bridge.snapshot());\n if (pendingUpdate) {\n sendUpdate(pendingUpdate);\n pendingUpdate = undefined;\n }\n }\n\n if ('then' in connection) void connection.then(attach).catch(() => {});\n else attach(connection);\n\n const navigation: DataAppNavigation = {\n ...location,\n publish(mode = 'replace') {\n if (!disposed) publish(location.snapshot(), mode);\n },\n dispose() {\n disposed = true;\n unsubscribe?.();\n dispose();\n send = undefined;\n pendingUpdate = undefined;\n },\n };\n\n return {\n navigation,\n attach,\n isDisposed() {\n return disposed;\n },\n };\n}\n\nconst navigationKey = Symbol.for('altertable.appNavigation');\ntype NavigationWindow = Window & {\n [navigationKey]?: ReturnType<typeof attachNavigation> & {\n bridge?: IframeTransport;\n };\n};\n\n/** URL controls attach navigation on demand; bootstrap and data-only clients do not. */\nexport function getDataAppNavigation(\n frame: Window = window\n): DataAppNavigation | undefined {\n const target = frame as NavigationWindow;\n const bridge = getDataAppTransport(frame);\n const cached = target[navigationKey]?.isDisposed()\n ? undefined\n : target[navigationKey];\n if (cached) {\n if (bridge && cached.bridge !== bridge) {\n cached.attach(bridge);\n cached.bridge = bridge;\n }\n\n return cached.navigation;\n }\n if (bridge) {\n const adapter = attachNavigation(frame, bridge.mode === 'bundle', bridge);\n target[navigationKey] = { bridge, ...adapter };\n\n return adapter.navigation;\n }\n const preview = localFrameBridge(frame);\n if (!preview?.connect) return undefined;\n const connection = preview.connect();\n const adapter = attachNavigation(frame, false, connection);\n const entry = {\n ...adapter,\n bridge: undefined as IframeTransport | undefined,\n };\n target[navigationKey] = entry;\n void connection\n .then(bridge => {\n entry.bridge = bridge;\n })\n .catch(() => {});\n\n return adapter.navigation;\n}\n",
7
+ "import {\n annotationDraftRoute,\n annotationUpdateRoute,\n annotationModeRoute,\n annotationEditorStateRoute,\n type DataAppAnnotationDraft,\n} from '@/src/core/annotations';\nimport type { MessageTransport } from '@/src/core/messages';\nimport { createMessageClient } from '@/src/client/messages';\n\n/** Deliver annotations to the authenticated host. Acknowledgement means retained, not sent to an agent. */\nexport function createAnnotationClient(transport: MessageTransport) {\n const client = createMessageClient(\n {\n 'annotation:draft': annotationDraftRoute,\n 'annotation:update': annotationUpdateRoute,\n 'annotation:mode': annotationModeRoute,\n 'annotation:editor': annotationEditorStateRoute,\n },\n transport\n );\n return {\n /** Report the iframe editor's status so the host can guard batch submission. */\n reportAnnotationEditorState(\n state: { hasUnsavedChanges: boolean },\n options?: { signal?: AbortSignal }\n ) {\n return client.request('annotation:editor', state, options);\n },\n addAnnotation(\n draft: DataAppAnnotationDraft,\n options?: { signal?: AbortSignal }\n ) {\n return client.request('annotation:draft', draft, options);\n },\n updateAnnotation(\n id: string,\n comment: string,\n options?: { signal?: AbortSignal }\n ) {\n return client.request('annotation:update', { id, comment }, options);\n },\n /** Ask the host to change its controlled annotation mode. */\n requestAnnotationModeChange(\n request: { active: boolean },\n options?: { signal?: AbortSignal }\n ) {\n return client.request('annotation:mode', request, options);\n },\n };\n}\n"
8
+ ],
9
+ "mappings": "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",
10
+ "debugId": "19B0E7BB9C5C8F2564756E2164756E21",
11
+ "names": []
12
+ }
@@ -29,6 +29,7 @@ function attachDataAppConnection({
29
29
  let token = connection.type === "opaque" ? connection.token : undefined;
30
30
  const targetOrigin = connection.type === "opaque" ? "*" : frameOrigin;
31
31
  let currentPresentation;
32
+ let presentationIdentity;
32
33
  let disposed = false;
33
34
  let documentId;
34
35
  let sessionId;
@@ -52,9 +53,11 @@ function attachDataAppConnection({
52
53
  function setPresentation(value) {
53
54
  if (disposed)
54
55
  return;
55
- if (value?.surface === currentPresentation?.surface && value?.theme === currentPresentation?.theme)
56
+ const identity = JSON.stringify(value);
57
+ if (identity === presentationIdentity)
56
58
  return;
57
- currentPresentation = value && { ...value };
59
+ presentationIdentity = identity;
60
+ currentPresentation = identity === undefined ? undefined : JSON.parse(identity);
58
61
  publishState();
59
62
  }
60
63
  function cancelAll() {
@@ -133,7 +136,8 @@ function attachDataAppConnection({
133
136
  return error(id, "bridge_busy", "Too many pending data requests.");
134
137
  try {
135
138
  const body = JSON.stringify(message.payload);
136
- if (message.payload !== undefined && (typeof body !== "string" || body.length > 16384))
139
+ const limit = message.route === "annotation:draft" ? 384000 : 16384;
140
+ if (message.payload !== undefined && (typeof body !== "string" || body.length > limit))
137
141
  throw new Error("Invalid payload");
138
142
  } catch {
139
143
  return error(id, "invalid_payload", "The message payload is invalid or too large.");
@@ -279,4 +283,4 @@ function attachDataAppBridge2(options) {
279
283
 
280
284
  export { attachDataAppBridge2 };
281
285
 
282
- //# debugId=5826F4790D0666BF64756E2164756E21
286
+ //# debugId=E598DB4534AD980C64756E2164756E21