@altertable/data-app 0.61.0 → 0.63.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 (159) hide show
  1. package/AGENTS.md +4 -32
  2. package/CONTRIBUTING.md +63 -72
  3. package/README.md +14 -38
  4. package/dist/chunks/{contract-d9skd1n7.js → contract-8wdybxj7.js} +163 -16
  5. package/dist/chunks/contract-8wdybxj7.js.map +13 -0
  6. package/dist/chunks/{contract-ryyf6dme.js → contract-cxr9t12b.js} +2 -5
  7. package/dist/chunks/contract-cxr9t12b.js.map +10 -0
  8. package/dist/chunks/{contract-14vxdcrs.js → contract-farfe948.js} +17 -21
  9. package/dist/chunks/contract-farfe948.js.map +10 -0
  10. package/dist/chunks/contract-mev09s5v.js.map +2 -2
  11. package/dist/chunks/{contract-ehk50k7e.js → contract-tf8c3qpv.js} +34 -4
  12. package/dist/chunks/contract-tf8c3qpv.js.map +11 -0
  13. package/dist/chunks/{contract-zr4s2g7m.js → contract-tkc552ze.js} +75 -36
  14. package/dist/chunks/contract-tkc552ze.js.map +12 -0
  15. package/dist/chunks/{contract-nt819swq.js → contract-wd8qe3mt.js} +6 -1
  16. package/dist/chunks/{contract-nt819swq.js.map → contract-wd8qe3mt.js.map} +3 -3
  17. package/dist/chunks/contract-wz59z8pq.js.map +1 -1
  18. package/dist/chunks/{contract-7gpsee0v.js → contract-zr3jd7mr.js} +51 -22
  19. package/dist/chunks/contract-zr3jd7mr.js.map +12 -0
  20. package/dist/client/index.js +7 -6
  21. package/dist/client/index.js.map +1 -1
  22. package/dist/core/appearance.js +1 -1
  23. package/dist/core/contract.js +6 -4
  24. package/dist/core/contract.js.map +1 -1
  25. package/dist/embed/index.js +41 -9
  26. package/dist/embed/index.js.map +5 -4
  27. package/dist/local.js +172 -84
  28. package/dist/local.js.map +7 -8
  29. package/dist/react/embed/index.js +83 -99
  30. package/dist/react/embed/index.js.map +4 -5
  31. package/dist/react/index.js +5701 -324
  32. package/dist/react/index.js.map +74 -65
  33. package/dist/server.js +153 -81
  34. package/dist/server.js.map +6 -7
  35. package/dist/types/client/data-client.d.ts +33 -0
  36. package/dist/types/client/iframe.d.ts +14 -0
  37. package/dist/types/client/index.d.ts +4 -34
  38. package/dist/types/client/location.d.ts +4 -6
  39. package/dist/types/client/navigation.d.ts +2 -1
  40. package/dist/types/core/appearance.d.ts +7 -6
  41. package/dist/types/core/bridge.d.ts +2 -8
  42. package/dist/types/core/config.d.ts +1 -1
  43. package/dist/types/core/contract.d.ts +9 -56
  44. package/dist/types/core/format.d.ts +0 -1
  45. package/dist/types/core/messages.d.ts +11 -30
  46. package/dist/types/core/navigation.d.ts +11 -0
  47. package/dist/types/core/operation-types.d.ts +76 -0
  48. package/dist/types/core/operation.d.ts +21 -0
  49. package/dist/types/core/presentation.d.ts +7 -0
  50. package/dist/types/core/variables.d.ts +2 -2
  51. package/dist/types/embed/bridge.d.ts +12 -0
  52. package/dist/types/embed/host.d.ts +14 -5
  53. package/dist/types/embed/index.d.ts +6 -4
  54. package/dist/types/embed/source.d.ts +15 -0
  55. package/dist/types/embed/sql.d.ts +4 -0
  56. package/dist/types/react/content.d.ts +3 -3
  57. package/dist/types/react/embed/bridge.d.ts +19 -10
  58. package/dist/types/react/embed/index.d.ts +0 -2
  59. package/dist/types/react/hooks.d.ts +65 -64
  60. package/dist/types/react/index.d.ts +135 -2
  61. package/dist/types/react/injectStyles.d.ts +7 -0
  62. package/dist/types/react/shellStyles.d.ts +3 -0
  63. package/dist/types/react/styles.d.ts +8 -0
  64. package/dist/types/react/ui/AboutData.d.ts +0 -1
  65. package/dist/types/react/ui/AppFooter.d.ts +0 -1
  66. package/dist/types/react/ui/AppHeader.d.ts +0 -1
  67. package/dist/types/react/ui/AppLayout.d.ts +0 -1
  68. package/dist/types/react/ui/AppScope.d.ts +0 -1
  69. package/dist/types/react/ui/AppToolbar.d.ts +0 -1
  70. package/dist/types/react/ui/Breakdown.d.ts +0 -1
  71. package/dist/types/react/ui/Button.d.ts +0 -1
  72. package/dist/types/react/ui/Checkbox.d.ts +0 -1
  73. package/dist/types/react/ui/Combobox.d.ts +0 -1
  74. package/dist/types/react/ui/ComparisonVisual.d.ts +0 -1
  75. package/dist/types/react/ui/ContentSkeleton.d.ts +2 -5
  76. package/dist/types/react/ui/DataApp.d.ts +2 -2
  77. package/dist/types/react/ui/DataAppSkeleton.d.ts +7 -0
  78. package/dist/types/react/ui/DataBoundary.d.ts +0 -1
  79. package/dist/types/react/ui/DataSection.d.ts +2 -4
  80. package/dist/types/react/ui/DataTable.d.ts +2 -3
  81. package/dist/types/react/ui/DataViewToast.d.ts +0 -1
  82. package/dist/types/react/ui/DataWidget.d.ts +4 -14
  83. package/dist/types/react/ui/DateRangePicker.d.ts +0 -1
  84. package/dist/types/react/ui/DateTimeTooltip.d.ts +0 -1
  85. package/dist/types/react/ui/EmptyState.d.ts +2 -5
  86. package/dist/types/react/ui/GettingStarted.d.ts +0 -1
  87. package/dist/types/react/ui/GlossaryDefinition.d.ts +0 -1
  88. package/dist/types/react/ui/GlossaryExplanation.d.ts +0 -1
  89. package/dist/types/react/ui/GradientScroll.d.ts +0 -1
  90. package/dist/types/react/ui/Grid.d.ts +0 -1
  91. package/dist/types/react/ui/HelpPopover.d.ts +0 -2
  92. package/dist/types/react/ui/Kbd.d.ts +0 -1
  93. package/dist/types/react/ui/LiveControl.d.ts +0 -1
  94. package/dist/types/react/ui/MetricWidget.d.ts +0 -2
  95. package/dist/types/react/ui/PeriodSummary.d.ts +0 -1
  96. package/dist/types/react/ui/PresentStory.d.ts +0 -1
  97. package/dist/types/react/ui/QueryList.d.ts +0 -1
  98. package/dist/types/react/ui/Ranking.d.ts +0 -1
  99. package/dist/types/react/ui/RefreshControl.d.ts +0 -1
  100. package/dist/types/react/ui/RefreshRegion.d.ts +0 -1
  101. package/dist/types/react/ui/RequestHint.d.ts +0 -1
  102. package/dist/types/react/ui/SearchField.d.ts +0 -1
  103. package/dist/types/react/ui/SearchInput.d.ts +1 -2
  104. package/dist/types/react/ui/SearchMatch.d.ts +0 -1
  105. package/dist/types/react/ui/SelectableBarChart.d.ts +0 -1
  106. package/dist/types/react/ui/SelectionMark.d.ts +0 -1
  107. package/dist/types/react/ui/Sheet.d.ts +0 -1
  108. package/dist/types/react/ui/Skeleton.d.ts +0 -1
  109. package/dist/types/react/ui/Stack.d.ts +0 -1
  110. package/dist/types/react/ui/StatusPanel.d.ts +0 -1
  111. package/dist/types/react/ui/TableWidget.d.ts +2 -3
  112. package/dist/types/react/ui/Tabs.d.ts +0 -1
  113. package/dist/types/react/ui/TextContent.d.ts +4 -0
  114. package/dist/types/react/ui/TextWidget.d.ts +19 -0
  115. package/dist/types/react/ui/ThemeSelector.d.ts +0 -1
  116. package/dist/types/react/ui/Tooltip.d.ts +0 -1
  117. package/dist/types/react/ui/UpdatedAt.d.ts +0 -1
  118. package/dist/types/react/ui/VariableBar.d.ts +0 -1
  119. package/dist/types/react/ui/VisualizationWidget.d.ts +5 -13
  120. package/dist/types/react/ui/WidgetDisclosure.d.ts +0 -1
  121. package/dist/types/react/ui/WidgetViewTabs.d.ts +2 -3
  122. package/dist/types/react/ui/data-identifiers.d.ts +0 -1
  123. package/dist/types/react/ui/presentation.d.ts +19 -0
  124. package/dist/types/react/ui/useAppAppearance.d.ts +3 -0
  125. package/dist/types/react/ui/useDataAppPresentation.d.ts +3 -0
  126. package/dist/types/react/view-controls.d.ts +2 -2
  127. package/dist/types/react/view.d.ts +2 -2
  128. package/dist/{bootstrap.js → worker.js} +144 -12
  129. package/docs/app-authoring.md +60 -24
  130. package/docs/client.md +48 -19
  131. package/docs/contract.md +10 -10
  132. package/docs/embed.md +94 -26
  133. package/docs/hosted-apps.md +39 -0
  134. package/docs/local-data-apps.md +14 -0
  135. package/docs/react-embed.md +75 -24
  136. package/docs/react.md +118 -93
  137. package/docs/server-bun.md +4 -1
  138. package/docs/server.md +2 -2
  139. package/docs/worker.md +55 -0
  140. package/examples/starter-data-app/index.tsx +159 -0
  141. package/package.json +18 -12
  142. package/dist/chunks/contract-14vxdcrs.js.map +0 -10
  143. package/dist/chunks/contract-7gpsee0v.js.map +0 -11
  144. package/dist/chunks/contract-d9skd1n7.js.map +0 -12
  145. package/dist/chunks/contract-ehk50k7e.js.map +0 -10
  146. package/dist/chunks/contract-ryyf6dme.js.map +0 -10
  147. package/dist/chunks/contract-zr4s2g7m.js.map +0 -12
  148. package/dist/react/index.css +0 -4478
  149. package/dist/react.css.d.ts +0 -1
  150. package/dist/types/embed/shell.d.ts +0 -21
  151. package/dist/types/embed/standalone.d.ts +0 -1
  152. package/dist/types/react/embed/shell.d.ts +0 -10
  153. package/dist/types/react/ui/index.d.ts +0 -129
  154. package/docs/appearance.md +0 -30
  155. package/docs/bootstrap.md +0 -76
  156. package/docs/config.md +0 -21
  157. package/docs/format.md +0 -29
  158. package/docs/react-styles.md +0 -17
  159. package/docs/starter-agent-instructions.md +0 -53
@@ -3,40 +3,10 @@
3
3
  * @module @altertable/data-app/client
4
4
  * @see https://github.com/altertable-ai/data-app/blob/main/docs/client.md
5
5
  */
6
- import { type DataTransport } from './transport.js';
6
+ export { createDataClient } from './data-client.js';
7
+ export type { InputOf, OutputOf, DataResponse, DataClient, DataClientOptions, } from './data-client.js';
8
+ export type { DataAppLocation, AppLocation } from './location.js';
9
+ export { createDataAppNavigation, getDataAppNavigation, type DataAppNavigation, } from './navigation.js';
7
10
  export { createHttpTransport, DataAppError, type DataTransport, } from './transport.js';
8
11
  export { createIframeTransport, installDataAppTransport, getDataAppTransport, type IframeTransport, } from './iframe.js';
9
12
  export { createMessageClient } from './messages.js';
10
- import type { DataOperations, DisclosedQuery } from '../core/contract.js';
11
- export type InputOf<T> = T extends {
12
- input: (value: unknown) => infer Input;
13
- } ? Input : never;
14
- export type OutputOf<T> = T extends {
15
- output: (value: unknown) => infer Output;
16
- } ? Output : never;
17
- /**
18
- * Parsed operation data and query evidence. `queries` is present only when SQL disclosure is
19
- * allowed.
20
- */
21
- export type DataResponse<Output, Input = unknown> = {
22
- data: Output;
23
- /** The exact browser input that produced this response. Never infer it from current controls. */
24
- input: Input;
25
- requestId: string;
26
- queriedAt: string;
27
- queryIds: string[];
28
- queries?: DisclosedQuery[];
29
- };
30
- export type DataClient<Operations extends DataOperations> = {
31
- query<Name extends keyof Operations & string>(name: Name, input: InputOf<Operations[Name]>, options?: {
32
- signal?: AbortSignal;
33
- }): Promise<DataResponse<OutputOf<Operations[Name]>, InputOf<Operations[Name]>>>;
34
- };
35
- /** Browser client for named operations; it sends inputs, never SQL or lakehouse credentials. */
36
- export declare function createDataClient<Operations extends DataOperations>(options?: {
37
- transport?: DataTransport;
38
- endpoint?: string;
39
- fetch?: typeof fetch;
40
- }): DataClient<Operations>;
41
- export type { DataAppLocation, AppLocation } from './location.js';
42
- export { createDataAppNavigation, getDataAppNavigation, type DataAppNavigation, } from './navigation.js';
@@ -1,14 +1,12 @@
1
- export type AppLocation = {
2
- search: string;
3
- hash: string;
4
- };
1
+ import type { AppLocation, HistoryMode } from '../core/navigation.js';
2
+ export type { AppLocation } from '../core/navigation.js';
5
3
  export type DataAppLocation = {
6
4
  snapshot(): AppLocation;
7
5
  subscribe(listener: () => void): () => void;
8
- update(location: AppLocation, mode?: 'push' | 'replace'): void;
6
+ update(location: AppLocation, mode?: HistoryMode): void;
9
7
  };
10
8
  /** Opaque sandboxes keep app state in memory; URL frames retain their real URL for HMR. */
11
- export declare function createAppLocation(frame: Window, virtual: boolean, publish: (location: AppLocation, mode: 'push' | 'replace') => void): {
9
+ export declare function createAppLocation(frame: Window, virtual: boolean, publish: (location: AppLocation, mode: HistoryMode) => void): {
12
10
  location: DataAppLocation;
13
11
  apply: (next: AppLocation) => void;
14
12
  dispose: () => void;
@@ -1,8 +1,9 @@
1
+ import type { HistoryMode } from '../core/navigation.js';
1
2
  import { type DataAppLocation } from './location.js';
2
3
  import { type IframeTransport } from './iframe.js';
3
4
  export type DataAppNavigation = DataAppLocation & {
4
5
  /** Publish URL changes made outside the adapter, including the document title. */
5
- publish(mode?: 'push' | 'replace'): void;
6
+ publish(mode?: HistoryMode): void;
6
7
  dispose(): void;
7
8
  };
8
9
  /** Attach app URL behavior to an already authenticated bridge. */
@@ -1,5 +1,7 @@
1
+ export type Theme = 'light' | 'dark';
2
+ export type ThemePreference = Theme | 'system';
1
3
  export type AppearanceSettings = {
2
- mode: 'light' | 'dark' | 'system';
4
+ theme: ThemePreference;
3
5
  baseColor: 'neutral' | 'slate' | 'warm';
4
6
  accentColor: string;
5
7
  darkAccentColor?: string;
@@ -12,10 +14,9 @@ export type AppearanceSettings = {
12
14
  heading: string;
13
15
  };
14
16
  };
15
- export type ThemeMode = AppearanceSettings['mode'];
16
17
  export type ThemeController = {
17
- getMode: () => ThemeMode;
18
- setMode: (mode: ThemeMode) => void;
18
+ getTheme: () => ThemePreference;
19
+ setTheme: (theme: ThemePreference) => void;
19
20
  subscribe: (listener: () => void) => () => void;
20
21
  };
21
22
  export declare function parseAppearance(value: unknown): AppearanceSettings;
@@ -24,5 +25,5 @@ export declare function parseAppearance(value: unknown): AppearanceSettings;
24
25
  * system-theme listening.
25
26
  */
26
27
  export declare function applyAppearance(value: unknown): () => void;
27
- /** Viewer color mode persists independently of app-authored brand tokens. */
28
- export declare function createThemeController(value: unknown): ThemeController;
28
+ /** Persist a viewer theme preference. Applying appearance belongs to the UI owner. */
29
+ export declare function createThemeController(initialTheme?: ThemePreference): ThemeController;
@@ -5,10 +5,7 @@ export declare const PARENT_PARAM = "__altertable_parent";
5
5
  * The host enforces its own limit because frames can send messages directly. */
6
6
  export declare const MAX_PENDING = 128;
7
7
  export declare const REQUEST_TIMEOUT_MS = 60000;
8
- export type TransportResponse = {
9
- status: number;
10
- body: unknown;
11
- };
8
+ export type { TransportResponse } from './operation-types.js';
12
9
  export type BridgeMessage = {
13
10
  channel: typeof BRIDGE;
14
11
  version: 1;
@@ -29,7 +26,4 @@ export type BridgeMessage = {
29
26
  };
30
27
  export declare function isBridgeMessage(value: unknown): value is BridgeMessage;
31
28
  export declare function validId(value: unknown): value is string;
32
- export declare function validLocation(message: {
33
- search?: unknown;
34
- hash?: unknown;
35
- }): boolean;
29
+ export { validLocation } from './navigation.js';
@@ -1,10 +1,10 @@
1
1
  /**
2
2
  * App identity and display scope shared by browser and server.
3
3
  * @module @altertable/data-app/config
4
- * @see https://github.com/altertable-ai/data-app/blob/main/docs/config.md
5
4
  */
6
5
  export type DataAppConfig = {
7
6
  title: string;
7
+ /** Display labels; scope does not grant data access. */
8
8
  scope: {
9
9
  organization: string;
10
10
  environment: string;
@@ -1,17 +1,9 @@
1
- export type QueryResult = {
2
- columns: {
3
- name: string;
4
- type?: string;
5
- }[];
6
- rows: unknown[][];
7
- queryId?: string;
8
- };
1
+ import type { DateRange as DateRangeInput } from './date-range.js';
2
+ import type { QueryResult, DataOperation, OperationContext } from './operation-types.js';
3
+ export type { QueryResult, DisclosedQuery, Lakehouse, OperationContext, DataOperation, DataOperations, } from './operation-types.js';
9
4
  export declare function parseEmptyInput(value: unknown): Record<string, never>;
10
5
  export declare function parseTrue(value: unknown): true;
11
- export type DateRangeInput = {
12
- start: string;
13
- end: string;
14
- };
6
+ export type { DateRange as DateRangeInput } from './date-range.js';
15
7
  export type DateRangeRequest = {
16
8
  range: DateRangeInput;
17
9
  comparison: DateRangeInput | null;
@@ -67,48 +59,16 @@ export declare function parseCount(value: unknown): number;
67
59
  export declare function parseLabel(value: unknown, maxLength?: number): string;
68
60
  /** Rejects missing or duplicate columns and rows whose width differs from the column list. */
69
61
  export declare function rowsAsRecords(result: QueryResult, requiredColumns: readonly string[]): Record<string, unknown>[];
70
- /** One named statement an operation ran. Returned only when SQL disclosure is allowed. */
71
- export type DisclosedQuery = {
72
- name: string;
73
- statement: string;
74
- queryId?: string;
75
- };
76
62
  export declare function defineQueryNames<const Names extends Record<string, string>>(names: Names): Names;
63
+ declare const sourceErrorBrand: unique symbol;
77
64
  export declare class DataSourceError extends Error {
78
65
  readonly reason: 'unauthorized' | 'forbidden' | 'rate_limited' | 'query_rejected' | 'unavailable';
79
66
  readonly status?: number | undefined;
67
+ readonly [sourceErrorBrand] = true;
80
68
  queryName?: string;
69
+ static [Symbol.hasInstance](value: unknown): boolean;
81
70
  constructor(reason: 'unauthorized' | 'forbidden' | 'rate_limited' | 'query_rejected' | 'unavailable', status?: number | undefined);
82
71
  }
83
- /** Server-only query interface supplied by a local or hosted adapter. */
84
- export type Lakehouse = {
85
- queryAll(statement: string, options: {
86
- limit: number;
87
- signal: AbortSignal;
88
- name?: string;
89
- }): Promise<QueryResult>;
90
- };
91
- export type OperationContext = {
92
- lakehouse: Lakehouse;
93
- signal: AbortSignal;
94
- };
95
- /**
96
- * Both parsers run on the server before results cross the JSON boundary. Schema libraries can be
97
- * used inside either parser.
98
- */
99
- export type DataOperation<Input, Output> = {
100
- input: (value: unknown) => Input;
101
- output: (value: unknown) => Output;
102
- run: (context: OperationContext, input: Input) => Promise<Output>;
103
- checks: readonly Input[];
104
- queryNames?: Readonly<Record<string, string>>;
105
- policy: {
106
- maxQueryRows: number;
107
- maxDurationMs: number;
108
- maxResponseBytes?: number;
109
- exposeSql?: boolean;
110
- };
111
- };
112
72
  export type OperationQuery<Names extends Readonly<Record<string, string>>> = (name: Names[keyof Names], statement: string, options?: {
113
73
  limit?: number;
114
74
  }) => Promise<QueryResult>;
@@ -125,15 +85,8 @@ export declare const connectionQueryNames: {
125
85
  };
126
86
  /** Success requires a bounded SQL query; it does not establish access to a particular dataset. */
127
87
  export declare function connectionCheck(): DataOperation<Record<string, never>, true>;
128
- export type DataOperations = Record<string, {
129
- input: (value: unknown) => unknown;
130
- output: (value: unknown) => unknown;
131
- run: (context: OperationContext, input: never) => Promise<unknown>;
132
- checks: readonly unknown[];
133
- queryNames?: Readonly<Record<string, string>>;
134
- policy: DataOperation<never, unknown>['policy'];
135
- }>;
136
88
  export { dimensionFilter, parseDimensionSelection, parseFacetOptions, dimensionPredicate, } from './dimension.js';
137
89
  export type { DimensionSelection, DimensionMember, DimensionOption, DimensionVariable, DimensionFilterOptions, } from './dimension.js';
138
- export * from './messages.js';
90
+ export { createMessageRouter, defineMessageRoute, defineDataQueryRoute, MessageRoutingError, dataAppRoutes, navigationUpdateRoute, sqlQueryRoute, } from './messages.js';
91
+ export type { MessageContext, RoutedMessage, MessageDispatcher, MessageTransport, MessageRoute, MessageRoutes, MessageInput, MessageHandlers, MessageOutput, OperationContracts, DataQueryInput, DataQueryBody, DataQueryRoute, NavigationUpdate, SqlQueryInput, } from './messages.js';
139
92
  export type { TransportResponse } from './bridge.js';
@@ -1,7 +1,6 @@
1
1
  /**
2
2
  * Date and number formatting with explicit units and missing-value behavior.
3
3
  * @module @altertable/data-app/format
4
- * @see https://github.com/altertable-ai/data-app/blob/main/docs/format.md
5
4
  */
6
5
  type CommonOptions = {
7
6
  locale?: string;
@@ -1,5 +1,7 @@
1
- import type { TransportResponse } from './bridge.js';
2
- import type { DisclosedQuery } from './contract.js';
1
+ import type { TransportResponse, QueryResult, OperationContracts, DataQueryInput, DataQueryBody, OutputOf } from './operation-types.js';
2
+ export type { OperationContracts, DataQueryInput, DataQueryBody, } from './operation-types.js';
3
+ import { type NavigationUpdate } from './navigation.js';
4
+ export type { NavigationUpdate } from './navigation.js';
3
5
  export type MessageContext = {
4
6
  signal: AbortSignal;
5
7
  };
@@ -35,43 +37,22 @@ export declare function defineMessageRoute<Input, Output>(route: MessageRoute<In
35
37
  export declare function createMessageRouter<const Routes extends MessageRoutes>(routes: Routes, handlers: MessageHandlers<NoInfer<Routes>>): {
36
38
  dispatch: (value: unknown, context: MessageContext) => Promise<unknown>;
37
39
  };
38
- export type OperationContracts = Record<string, {
39
- input: (value: unknown) => unknown;
40
- output: (value: unknown) => unknown;
41
- }>;
42
- export type DataQueryInput<Operations extends OperationContracts> = {
43
- [Name in keyof Operations & string]: {
44
- operation: Name;
45
- input: ReturnType<Operations[Name]['input']>;
46
- };
47
- }[keyof Operations & string];
48
- export type DataQueryBody<Output> = {
49
- data: Output;
50
- requestId: string;
51
- queriedAt: string;
52
- queryIds: string[];
53
- queries?: DisclosedQuery[];
54
- };
55
40
  export type DataQueryRoute<Operations extends OperationContracts> = MessageRoute<DataQueryInput<Operations>, TransportResponse> & {
56
41
  operations: Operations | undefined;
57
42
  };
58
43
  export type MessageOutput<Route extends MessageRoutes[string], Input> = Route extends DataQueryRoute<infer Operations> ? Input extends {
59
44
  operation: infer Name extends keyof Operations;
60
- } ? {
61
- status: number;
62
- body: DataQueryBody<ReturnType<Operations[Name]['output']>>;
63
- } : never : ReturnType<Route['output']>;
45
+ } ? TransportResponse<DataQueryBody<OutputOf<Operations[Name]>>> : never : ReturnType<Route['output']>;
64
46
  /** Omit contracts only in generic hosts such as the CLI shell, where Bun validates operations. */
65
47
  export declare function defineDataQueryRoute<Operations extends OperationContracts = OperationContracts>(operations?: Operations): DataQueryRoute<Operations>;
66
- export type NavigationUpdate = {
67
- search: string;
68
- hash: string;
69
- mode: 'push' | 'replace';
70
- title?: string;
71
- };
72
48
  export declare const navigationUpdateRoute: MessageRoute<NavigationUpdate, null>;
49
+ export type SqlQueryInput = {
50
+ statement: string;
51
+ limit: number;
52
+ };
53
+ /** SQL delivery for browser-owned operations. Hosts must enforce backend access and resource limits. */
54
+ export declare const sqlQueryRoute: MessageRoute<SqlQueryInput, QueryResult>;
73
55
  export declare const dataAppRoutes: {
74
56
  'data:query': DataQueryRoute<OperationContracts>;
75
57
  'navigation:update': MessageRoute<NavigationUpdate, null>;
76
58
  };
77
- export {};
@@ -0,0 +1,11 @@
1
+ /** App-owned URL state shared by controls, frame adapters, and host navigation. */
2
+ export type AppLocation = {
3
+ search: string;
4
+ hash: string;
5
+ };
6
+ export type HistoryMode = 'push' | 'replace';
7
+ export type NavigationUpdate = AppLocation & {
8
+ mode: HistoryMode;
9
+ title?: string;
10
+ };
11
+ export declare function validLocation(value: unknown): value is AppLocation;
@@ -0,0 +1,76 @@
1
+ /** Shared operation, query, and response contracts; independent of delivery adapters. */
2
+ export type OperationContracts = Record<string, {
3
+ input: (value: unknown) => unknown;
4
+ output: (value: unknown) => unknown;
5
+ }>;
6
+ export type InputOf<T> = T extends {
7
+ input: (value: unknown) => infer Input;
8
+ } ? Input : never;
9
+ export type OutputOf<T> = T extends {
10
+ output: (value: unknown) => infer Output;
11
+ } ? Output : never;
12
+ export type QueryResult = {
13
+ columns: {
14
+ name: string;
15
+ type?: string;
16
+ }[];
17
+ rows: unknown[][];
18
+ queryId?: string;
19
+ };
20
+ /** One named statement an operation ran. Returned only when SQL disclosure is allowed. */
21
+ export type DisclosedQuery = {
22
+ name: string;
23
+ statement: string;
24
+ queryId?: string;
25
+ };
26
+ /** Query interface supplied by a server adapter or an authorized iframe bridge. */
27
+ export type Lakehouse = {
28
+ queryAll(statement: string, options: {
29
+ limit: number;
30
+ signal: AbortSignal;
31
+ name?: string;
32
+ }): Promise<QueryResult>;
33
+ };
34
+ export type OperationContext = {
35
+ lakehouse: Lakehouse;
36
+ signal: AbortSignal;
37
+ };
38
+ /**
39
+ * Parsers run in the operation executor's runtime: server for HTTP apps, browser for bundle apps.
40
+ * Browser validation does not replace backend authorization or query limits.
41
+ */
42
+ export type DataOperation<Input, Output> = {
43
+ input: (value: unknown) => Input;
44
+ output: (value: unknown) => Output;
45
+ run: (context: OperationContext, input: Input) => Promise<Output>;
46
+ checks: readonly Input[];
47
+ queryNames?: Readonly<Record<string, string>>;
48
+ policy: {
49
+ maxQueryRows: number;
50
+ maxDurationMs: number;
51
+ maxResponseBytes?: number;
52
+ exposeSql?: boolean;
53
+ };
54
+ };
55
+ /** Heterogeneous registry: inputs vary per operation, so checks retain unknown values. */
56
+ export type DataOperations = Record<string, OperationContracts[string] & Omit<DataOperation<never, unknown>, 'input' | 'output' | 'checks'> & {
57
+ checks: readonly unknown[];
58
+ }>;
59
+ export type DataQueryInput<Operations extends OperationContracts> = {
60
+ [Name in keyof Operations & string]: {
61
+ operation: Name;
62
+ input: InputOf<Operations[Name]>;
63
+ };
64
+ }[keyof Operations & string];
65
+ export type DataQueryBody<Output> = {
66
+ data: Output;
67
+ requestId: string;
68
+ queriedAt: string;
69
+ queryIds: string[];
70
+ queries?: DisclosedQuery[];
71
+ };
72
+ /** Delivery envelope shared by HTTP and iframe transports. */
73
+ export type TransportResponse<Body = unknown> = {
74
+ status: number;
75
+ body: Body;
76
+ };
@@ -0,0 +1,21 @@
1
+ import type { DataOperations, Lakehouse, DataQueryBody } from './operation-types.js';
2
+ type Operation = DataOperations[string];
3
+ type OperationExecutionOptions = {
4
+ operationName: string;
5
+ lakehouse: Lakehouse;
6
+ signal: AbortSignal;
7
+ /** Include query evidence in the response; this does not keep browser-owned SQL private. */
8
+ includeSql: boolean;
9
+ requestId: string;
10
+ };
11
+ /** Shared operation execution. Adapters own authorization, delivery, and public errors. */
12
+ export declare function executeDataOperation(operation: Operation, value: unknown, { operationName, lakehouse, signal: requestSignal, includeSql, requestId, }: OperationExecutionOptions): Promise<{
13
+ body: DataQueryBody<unknown>;
14
+ serializedBody: string;
15
+ }>;
16
+ export declare function toDataOperationFailure(error: unknown, aborted?: boolean): {
17
+ status: number;
18
+ code: string;
19
+ message: string;
20
+ };
21
+ export {};
@@ -0,0 +1,7 @@
1
+ import type { Theme } from './appearance.js';
2
+ /** Presentation owned by the parent shell, delivered only over a trusted bridge. */
3
+ export type DataAppPresentation = {
4
+ surface: 'embedded' | 'standalone';
5
+ theme: Theme;
6
+ };
7
+ export declare function isDataAppPresentation(value: unknown): value is DataAppPresentation;
@@ -1,7 +1,8 @@
1
1
  import { type DatePresetId, type DateRange } from './date-range.js';
2
2
  import type { DateRangeContract, DateRangeRequest } from './contract.js';
3
3
  import type { DimensionSelection, DimensionVariable } from './dimension.js';
4
- export type HistoryMode = 'push' | 'replace';
4
+ import type { HistoryMode } from './navigation.js';
5
+ export type { HistoryMode } from './navigation.js';
5
6
  /** An app-owned value with one URL representation. Controls never parse or write routes. */
6
7
  export type AppVariable<Value, Kind extends string = Value extends string ? 'text' | 'select' : 'dateRange'> = {
7
8
  kind: Kind;
@@ -79,4 +80,3 @@ export type DateRangeVariable = AppVariable<DateRangeSelection> & {
79
80
  };
80
81
  /** A date variable keeps relative presets relative and validates exact dates against source coverage. */
81
82
  export declare function dateRangeVariable({ key, label, startKey, endKey, defaultValue, contract, history, comparison, comparisonKey, }: DateRangeVariableOptions): DateRangeVariable;
82
- export {};
@@ -0,0 +1,12 @@
1
+ import { type DataAppConnectionOptions } from './host.js';
2
+ import { type DataAppSourceOptions } from './source.js';
3
+ export type DataAppBridgeOptions = (DataAppSourceOptions & {
4
+ connection?: never;
5
+ window?: never;
6
+ javascript?: never;
7
+ }) | (DataAppConnectionOptions & {
8
+ source?: never;
9
+ startupTimeoutMs?: never;
10
+ });
11
+ /** Source mode configures and loads the iframe; connection mode attaches to a host-owned document. */
12
+ export declare function attachDataAppBridge(options: DataAppBridgeOptions): import("./host.js").DataAppHost;
@@ -1,3 +1,4 @@
1
+ import type { DataAppPresentation } from '../core/presentation.js';
1
2
  import { type MessageDispatcher } from '../core/messages.js';
2
3
  export type DataAppConnection = {
3
4
  type: 'origin';
@@ -11,13 +12,21 @@ export type DataAppDiagnostic = {
11
12
  direction: 'send' | 'receive';
12
13
  type: string;
13
14
  };
14
- /** The bridge owns delivery and cancellation; the routed handler owns validation, authorization and execution. */
15
- export declare function attachDataAppBridge({ iframe, connection, javascript, onStatusChange, onDiagnostic, onMessage, window: host, }: {
15
+ export type DataAppHost = {
16
+ dispose: () => void;
17
+ setPresentation: (presentation?: DataAppPresentation) => void;
18
+ };
19
+ export type DataAppHostOptions = {
16
20
  iframe: HTMLIFrameElement;
17
- connection: DataAppConnection;
18
- javascript?: string;
21
+ presentation?: DataAppPresentation;
19
22
  onStatusChange?: (status: DataAppStatus) => void;
20
23
  onDiagnostic?: (event: DataAppDiagnostic) => void;
21
24
  onMessage: MessageDispatcher;
25
+ };
26
+ export type DataAppConnectionOptions = DataAppHostOptions & {
27
+ connection: DataAppConnection;
28
+ javascript?: string;
22
29
  window?: Window;
23
- }): () => void;
30
+ };
31
+ /** The bridge owns delivery and cancellation; the routed handler owns validation, authorization and execution. */
32
+ export declare function attachDataAppConnection({ iframe, connection, javascript, presentation, onStatusChange, onDiagnostic, onMessage, window: host, }: DataAppConnectionOptions): DataAppHost;
@@ -3,9 +3,11 @@
3
3
  * @module @altertable/data-app/embed
4
4
  * @see https://github.com/altertable-ai/data-app/blob/main/docs/embed.md
5
5
  */
6
- export { attachDataAppBridge } from './host.js';
7
- export type { DataAppConnection, DataAppStatus, DataAppDiagnostic, } from './host.js';
8
- export { attachDataAppShell } from './shell.js';
9
- export type { DataAppSource, DataAppShellOptions } from './shell.js';
6
+ export { attachDataAppBridge } from './bridge.js';
7
+ export type { DataAppBridgeOptions } from './bridge.js';
8
+ export type { DataAppHost, DataAppConnection, DataAppStatus, DataAppDiagnostic, } from './host.js';
9
+ export type { DataAppSource } from './source.js';
10
10
  export { startDataAppBootstrap } from './bootstrap.js';
11
11
  export { createNavigationHandler } from './navigation.js';
12
+ export { createSqlQueryHandler } from './sql.js';
13
+ export type { DataAppPresentation } from '../core/presentation.js';
@@ -0,0 +1,15 @@
1
+ import { type DataAppHost, type DataAppHostOptions } from './host.js';
2
+ export type DataAppSource = {
3
+ type: 'url';
4
+ url: string;
5
+ } | {
6
+ type: 'bundle';
7
+ bootstrapUrl: string;
8
+ javascript: string;
9
+ };
10
+ export type DataAppSourceOptions = DataAppHostOptions & {
11
+ source: DataAppSource;
12
+ startupTimeoutMs?: number;
13
+ };
14
+ /** Owns loading and sandbox policy. Dispose before replacing the source or retrying. */
15
+ export declare function attachDataAppSource({ iframe, source, presentation, onMessage, onStatusChange, onDiagnostic, startupTimeoutMs, }: DataAppSourceOptions): DataAppHost;
@@ -0,0 +1,4 @@
1
+ import type { Lakehouse } from '../core/contract.js';
2
+ import { type MessageContext, type SqlQueryInput } from '../core/messages.js';
3
+ /** Authorize every SQL request and supply a backend that independently enforces access and query limits. */
4
+ export declare function createSqlQueryHandler(authorize: (query: SqlQueryInput, context: MessageContext) => Promise<Lakehouse>): (input: SqlQueryInput, context: MessageContext) => Promise<import("../core/contract.js").QueryResult>;
@@ -1,11 +1,11 @@
1
1
  import type { ReactNode } from 'react';
2
2
  import type { DataReading, MetricReading, MetricValues } from '../core/reading.js';
3
3
  import type { DateRangeRequest } from '../core/contract.js';
4
- export type DataContentHelpers<Data> = {
5
- select: <Value>(select: (data: Data) => Value) => DataReading<Value>;
4
+ export type DataContentHelpers<Data, Input> = {
5
+ select: <Value>(select: (data: Data, input: Input) => Value) => DataReading<Value>;
6
6
  metric: (select: (data: Data) => MetricValues) => MetricReading;
7
7
  };
8
- export type DataContentState<Data, Input> = DataContentHelpers<Data> & ({
8
+ export type DataContentState<Data, Input> = DataContentHelpers<Data, Input> & ({
9
9
  loading: true;
10
10
  data?: never;
11
11
  input?: never;
@@ -1,12 +1,21 @@
1
- import { type ComponentRef } from 'react';
2
- import { type DataAppConnection, type DataAppStatus, type DataAppDiagnostic } from '../../embed/host.js';
3
- import type { MessageDispatcher } from '../../core/messages.js';
4
- export type DataAppBridgeProps = {
1
+ import { type ComponentRef, type ComponentPropsWithoutRef } from 'react';
2
+ import { type DataAppBridgeOptions } from '../../embed/bridge.js';
3
+ import type { DataAppConnection } from '../../embed/host.js';
4
+ import type { DataAppSource } from '../../embed/source.js';
5
+ export type DataAppBridgeProps = Pick<DataAppBridgeOptions, 'onMessage' | 'onStatusChange' | 'onDiagnostic' | 'presentation'> & ({
6
+ source: DataAppSource;
7
+ title: string;
8
+ startupTimeoutMs?: number;
9
+ iframeProps?: Omit<ComponentPropsWithoutRef<'iframe'>, 'src' | 'srcDoc' | 'sandbox' | 'referrerPolicy' | 'loading' | 'children' | 'title'>;
10
+ iframe?: never;
11
+ connection?: never;
12
+ } | {
5
13
  iframe: ComponentRef<'iframe'> | null;
6
14
  connection: DataAppConnection;
7
- onMessage: MessageDispatcher;
8
- onStatusChange?: (status: DataAppStatus) => void;
9
- onDiagnostic?: (event: DataAppDiagnostic) => void;
10
- };
11
- /** Delivery only; the host owns the iframe and route handlers, including navigation. */
12
- export declare function DataAppBridge({ iframe, connection, onMessage, onStatusChange, onDiagnostic, }: DataAppBridgeProps): null;
15
+ source?: never;
16
+ title?: never;
17
+ startupTimeoutMs?: never;
18
+ iframeProps?: never;
19
+ });
20
+ /** Owns iframe setup and delivery. The consuming shell owns loading, error UI, and retries. */
21
+ export declare function DataAppBridge(props: DataAppBridgeProps): import("react").JSX.Element;
@@ -5,5 +5,3 @@
5
5
  */
6
6
  export { DataAppBridge } from './bridge.js';
7
7
  export type { DataAppBridgeProps } from './bridge.js';
8
- export { DataAppShell } from './shell.js';
9
- export type { DataAppShellProps } from './shell.js';