@altertable/data-app 0.65.0 → 0.67.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 (202) hide show
  1. package/AGENTS.md +38 -1
  2. package/CONTRIBUTING.md +54 -14
  3. package/README.md +1 -1
  4. package/dist/chunks/index-23dktynd.js +80 -0
  5. package/dist/chunks/index-23dktynd.js.map +10 -0
  6. package/dist/chunks/index-8qfxv0h5.js +14160 -0
  7. package/dist/chunks/index-8qfxv0h5.js.map +108 -0
  8. package/dist/chunks/index-ag0cgnvq.js +639 -0
  9. package/dist/chunks/index-ag0cgnvq.js.map +13 -0
  10. package/dist/chunks/index-dq7b35fn.js +307 -0
  11. package/dist/chunks/index-dq7b35fn.js.map +13 -0
  12. package/dist/chunks/{contract-a061yj6r.js → index-ev2b5aaf.js} +41 -72
  13. package/dist/chunks/index-ev2b5aaf.js.map +12 -0
  14. package/dist/chunks/{contract-awa2d5b1.js → index-f5cnbrjz.js} +19 -2
  15. package/dist/chunks/{contract-awa2d5b1.js.map → index-f5cnbrjz.js.map} +4 -3
  16. package/dist/chunks/{contract-sm7j7k95.js → index-ktmvs916.js} +9 -150
  17. package/dist/chunks/index-ktmvs916.js.map +13 -0
  18. package/dist/chunks/{contract-txjy0en2.js → index-m6n8ctfc.js} +64 -72
  19. package/dist/chunks/index-m6n8ctfc.js.map +10 -0
  20. package/dist/chunks/index-mt93ff2b.js +28 -0
  21. package/dist/chunks/index-mt93ff2b.js.map +10 -0
  22. package/dist/chunks/{contract-tf8c3qpv.js → index-qd5xgx6y.js} +46 -5
  23. package/dist/chunks/index-qd5xgx6y.js.map +13 -0
  24. package/dist/chunks/index-x69p7cv7.js +149 -0
  25. package/dist/chunks/index-x69p7cv7.js.map +10 -0
  26. package/dist/client/index.js +12 -7
  27. package/dist/client/index.js.map +1 -1
  28. package/dist/core/appearance.js +1 -1
  29. package/dist/core/config.js +7 -3
  30. package/dist/core/config.js.map +1 -1
  31. package/dist/core/contract.js +24 -6
  32. package/dist/core/contract.js.map +1 -1
  33. package/dist/core/format.js +1 -1
  34. package/dist/embed/index.js +16 -12
  35. package/dist/embed/index.js.map +4 -4
  36. package/dist/index.js +12 -0
  37. package/dist/index.js.map +9 -0
  38. package/dist/local.js +20 -30
  39. package/dist/local.js.map +7 -8
  40. package/dist/react/embed/index.js +1 -1
  41. package/dist/react/embed/index.js.map +2 -2
  42. package/dist/react/index.js +2567 -11542
  43. package/dist/react/index.js.map +16 -91
  44. package/dist/react/ui/index.js +2272 -0
  45. package/dist/react/ui/index.js.map +28 -0
  46. package/dist/server.js +13 -26
  47. package/dist/server.js.map +6 -7
  48. package/dist/types/client/annotations.d.ts +27 -0
  49. package/dist/types/client/data-client.d.ts +1 -2
  50. package/dist/types/client/iframe.d.ts +4 -2
  51. package/dist/types/client/index.d.ts +1 -0
  52. package/dist/types/core/annotations.d.ts +94 -0
  53. package/dist/types/core/appearance.d.ts +2 -2
  54. package/dist/types/core/config.d.ts +48 -4
  55. package/dist/types/core/contract.d.ts +21 -11
  56. package/dist/types/core/dimension.d.ts +6 -4
  57. package/dist/types/core/filters.d.ts +44 -0
  58. package/dist/types/core/messages.d.ts +2 -0
  59. package/dist/types/core/operation-types.d.ts +5 -2
  60. package/dist/types/core/operation.d.ts +3 -4
  61. package/dist/types/core/presentation.d.ts +2 -0
  62. package/dist/types/core/queries.d.ts +16 -0
  63. package/dist/types/core/uuid.d.ts +2 -0
  64. package/dist/types/core/variables.d.ts +34 -18
  65. package/dist/types/embed/runtime-html.d.ts +2 -0
  66. package/dist/types/embed/source.d.ts +2 -1
  67. package/dist/types/index.d.ts +3 -0
  68. package/dist/types/react/annotations/AnnotationBar.d.ts +30 -0
  69. package/dist/types/react/annotations/AnnotationControls.d.ts +10 -0
  70. package/dist/types/react/annotations/AnnotationEditor.d.ts +16 -0
  71. package/dist/types/react/annotations/AnnotationMarkers.d.ts +19 -0
  72. package/dist/types/react/annotations/AnnotationSelectionLayer.d.ts +12 -0
  73. package/dist/types/react/annotations/AnnotationTarget.d.ts +9 -0
  74. package/dist/types/react/annotations/AnnotationTooltip.d.ts +9 -0
  75. package/dist/types/react/annotations/AnnotationTrigger.d.ts +10 -0
  76. package/dist/types/react/annotations/annotation-editor-state.d.ts +56 -0
  77. package/dist/types/react/annotations/annotation-screenshot.d.ts +4 -0
  78. package/dist/types/react/annotations/annotation-targets.d.ts +33 -0
  79. package/dist/types/react/annotations/getAnnotationProps.d.ts +15 -0
  80. package/dist/types/react/annotations/styles.d.ts +3 -0
  81. package/dist/types/react/annotations/useAnnotationGeometry.d.ts +22 -0
  82. package/dist/types/react/annotations/useDataAppAnnotations.d.ts +22 -0
  83. package/dist/types/react/app-context.d.ts +3 -0
  84. package/dist/types/react/bindings.d.ts +110 -0
  85. package/dist/types/react/content.d.ts +24 -11
  86. package/dist/types/react/hooks.d.ts +29 -787
  87. package/dist/types/react/index.d.ts +31 -106
  88. package/dist/types/react/mount.d.ts +6 -4
  89. package/dist/types/react/source-owner.d.ts +2 -0
  90. package/dist/types/react/style-contract.d.ts +80 -0
  91. package/dist/types/react/style-validation.d.ts +2 -0
  92. package/dist/types/react/ui/AboutData.d.ts +9 -1
  93. package/dist/types/react/ui/AppHeader.d.ts +1 -2
  94. package/dist/types/react/ui/AppLayout.d.ts +3 -9
  95. package/dist/types/react/ui/AppToolbar.d.ts +5 -8
  96. package/dist/types/react/ui/AreaChart.d.ts +7 -0
  97. package/dist/types/react/ui/BarChart.d.ts +6 -0
  98. package/dist/types/react/ui/Button.d.ts +3 -3
  99. package/dist/types/react/ui/ChartLegend.d.ts +31 -0
  100. package/dist/types/react/ui/Checkbox.d.ts +15 -4
  101. package/dist/types/react/ui/CheckboxGroup.d.ts +7 -0
  102. package/dist/types/react/ui/{Combobox.d.ts → ChoicePicker.d.ts} +10 -15
  103. package/dist/types/react/ui/{ComparisonVisual.d.ts → Comparison.d.ts} +3 -3
  104. package/dist/types/react/ui/ComposedChart.d.ts +41 -0
  105. package/dist/types/react/ui/ComposedChartLegend.d.ts +8 -0
  106. package/dist/types/react/ui/ContentSkeleton.d.ts +2 -0
  107. package/dist/types/react/ui/DataApp.d.ts +17 -58
  108. package/dist/types/react/ui/DataAppFrame.d.ts +41 -0
  109. package/dist/types/react/ui/DataBoundary.d.ts +4 -5
  110. package/dist/types/react/ui/DataSection.d.ts +6 -18
  111. package/dist/types/react/ui/DataSectionBoundary.d.ts +30 -0
  112. package/dist/types/react/ui/DataValue.d.ts +9 -0
  113. package/dist/types/react/ui/DataWidget.d.ts +2 -1
  114. package/dist/types/react/ui/DateTimeTooltip.d.ts +1 -1
  115. package/dist/types/react/ui/DimensionPicker.d.ts +1 -1
  116. package/dist/types/react/ui/ExportControl.d.ts +1 -1
  117. package/dist/types/react/ui/FilterActions.d.ts +10 -0
  118. package/dist/types/react/ui/FilterBar.d.ts +3 -0
  119. package/dist/types/react/ui/GettingStarted.d.ts +2 -4
  120. package/dist/types/react/ui/HelpPopover.d.ts +3 -4
  121. package/dist/types/react/ui/InspectionContext.d.ts +2 -0
  122. package/dist/types/react/ui/InspectionProvider.d.ts +29 -0
  123. package/dist/types/react/ui/LineChart.d.ts +7 -0
  124. package/dist/types/react/ui/Menu.d.ts +12 -0
  125. package/dist/types/react/ui/MetricWidget.d.ts +4 -3
  126. package/dist/types/react/ui/NumberField.d.ts +27 -0
  127. package/dist/types/react/ui/NumberFilterPicker.d.ts +9 -0
  128. package/dist/types/react/ui/PieChart.d.ts +11 -0
  129. package/dist/types/react/ui/PresentStory.d.ts +2 -5
  130. package/dist/types/react/ui/RadioGroup.d.ts +18 -0
  131. package/dist/types/react/ui/RefreshControl.d.ts +1 -2
  132. package/dist/types/react/ui/ScatterChart.d.ts +17 -0
  133. package/dist/types/react/ui/SearchField.d.ts +1 -2
  134. package/dist/types/react/ui/SearchInput.d.ts +3 -1
  135. package/dist/types/react/ui/Select.d.ts +14 -0
  136. package/dist/types/react/ui/SelectionMark.d.ts +2 -1
  137. package/dist/types/react/ui/Sheet.d.ts +2 -1
  138. package/dist/types/react/ui/Skeleton.d.ts +5 -2
  139. package/dist/types/react/ui/StaticDataApp.d.ts +4 -0
  140. package/dist/types/react/ui/TableWidget.d.ts +19 -16
  141. package/dist/types/react/ui/Tabs.d.ts +6 -2
  142. package/dist/types/react/ui/TextWidget.d.ts +2 -1
  143. package/dist/types/react/ui/Tooltip.d.ts +4 -3
  144. package/dist/types/react/ui/TooltipSurface.d.ts +3 -0
  145. package/dist/types/react/ui/TrendChart.d.ts +5 -0
  146. package/dist/types/react/ui/UpdatedAt.d.ts +1 -1
  147. package/dist/types/react/ui/VisualizationWidget.d.ts +12 -13
  148. package/dist/types/react/ui/WidgetViewTabs.d.ts +1 -1
  149. package/dist/types/react/ui/chart-data.d.ts +25 -0
  150. package/dist/types/react/ui/chart-primitives.d.ts +20 -0
  151. package/dist/types/react/ui/data-context.d.ts +18 -7
  152. package/dist/types/react/ui/icons.d.ts +2 -0
  153. package/dist/types/react/ui/index.d.ts +98 -0
  154. package/dist/types/react/ui/keyboard.d.ts +6 -0
  155. package/dist/types/react/ui/metric.d.ts +1 -1
  156. package/dist/types/react/ui/presentation.d.ts +5 -1
  157. package/dist/types/react/ui/shortcuts.d.ts +14 -1
  158. package/dist/types/react/ui/useAppAppearance.d.ts +1 -1
  159. package/dist/types/react/ui/variables.d.ts +4 -2
  160. package/dist/types/react/view-controls.d.ts +3 -1
  161. package/dist/types/react/view-runtime.d.ts +29 -0
  162. package/dist/types/react/view.d.ts +21 -4
  163. package/dist/types/react/widgets.d.ts +79 -0
  164. package/dist/types/server/handler.d.ts +4 -4
  165. package/dist/worker.js +20 -737
  166. package/docs/app-authoring.md +72 -50
  167. package/docs/client.md +8 -8
  168. package/docs/contract.md +42 -20
  169. package/docs/data-context.md +91 -0
  170. package/docs/embed.md +10 -2
  171. package/docs/formatting-and-appearance.md +68 -0
  172. package/docs/hosted-apps.md +9 -15
  173. package/docs/layout.md +5 -3
  174. package/docs/react-embed.md +5 -4
  175. package/docs/react.md +22 -317
  176. package/docs/server-bun.md +1 -1
  177. package/docs/server.md +4 -4
  178. package/docs/stories-and-export.md +52 -0
  179. package/docs/styling.md +62 -0
  180. package/docs/ui-quality.md +20 -0
  181. package/docs/ui.md +196 -0
  182. package/docs/variables.md +171 -0
  183. package/docs/views.md +123 -0
  184. package/docs/widgets.md +145 -0
  185. package/examples/starter-data-app/index.tsx +115 -86
  186. package/package.json +25 -12
  187. package/dist/chunks/contract-a061yj6r.js.map +0 -12
  188. package/dist/chunks/contract-g6hky7x6.js +0 -282
  189. package/dist/chunks/contract-g6hky7x6.js.map +0 -12
  190. package/dist/chunks/contract-sm7j7k95.js.map +0 -14
  191. package/dist/chunks/contract-tf8c3qpv.js.map +0 -11
  192. package/dist/chunks/contract-txjy0en2.js.map +0 -10
  193. package/dist/chunks/contract-wz59z8pq.js +0 -8
  194. package/dist/chunks/contract-wz59z8pq.js.map +0 -10
  195. package/dist/chunks/contract-yxbjea23.js +0 -328
  196. package/dist/chunks/contract-yxbjea23.js.map +0 -12
  197. package/dist/types/react/ui/RefreshRegion.d.ts +0 -9
  198. package/dist/types/react/ui/SelectableBarChart.d.ts +0 -15
  199. package/docs/releasing.md +0 -79
  200. /package/dist/chunks/{contract-mev09s5v.js → index-mev09s5v.js} +0 -0
  201. /package/dist/chunks/{contract-mev09s5v.js.map → index-mev09s5v.js.map} +0 -0
  202. /package/dist/types/react/ui/{comparison.d.ts → metric-comparison.d.ts} +0 -0
@@ -69,89 +69,81 @@ function normalizeAppearance2(value = {}) {
69
69
  }
70
70
  };
71
71
  }
72
- var palettes = {
73
- neutral: {
74
- light: ["#ffffff", "#ffffff", "#f6f7f7", "#202124", "#687078", "#e3e6e8"],
75
- dark: ["#151719", "#202326", "#292d31", "#f2f3f4", "#aeb5bc", "#3b4248"]
76
- },
77
- slate: {
78
- light: ["#f8fafc", "#ffffff", "#f1f5f9", "#17212f", "#607083", "#dce3ea"],
79
- dark: ["#111820", "#1b2530", "#263340", "#f0f4f8", "#a8b5c3", "#3a4857"]
80
- },
81
- warm: {
82
- light: ["#fbfaf8", "#ffffff", "#f5f2ed", "#292723", "#736e66", "#e8e2da"],
83
- dark: ["#1b1916", "#25221e", "#302c27", "#f5f1eb", "#bcb3a8", "#494239"]
84
- }
85
- };
86
- var spaces = {
87
- compact: ["4px", "8px", "12px", "18px", "24px"],
88
- comfortable: ["5px", "10px", "16px", "24px", "32px"],
89
- spacious: ["6px", "12px", "20px", "30px", "40px"]
90
- };
91
- var radii = {
92
- none: ["0px", "0px", "0px"],
93
- small: ["4px", "7px", "9px"],
94
- medium: ["7px", "12px", "16px"],
95
- large: ["10px", "18px", "24px"]
96
- };
97
72
  function fontStack(family) {
98
73
  return family === "system" ? "-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif" : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;
99
74
  }
75
+ function accentForeground(settings, dark) {
76
+ const accent = getComputedStyle(document.documentElement).getPropertyValue("--atbl-accent") || (dark ? settings.darkAccentColor ?? `color-mix(in srgb, ${settings.accentColor} 50%, white)` : settings.accentColor);
77
+ const canvas = document.createElement("canvas");
78
+ canvas.width = canvas.height = 1;
79
+ const context = canvas.getContext("2d");
80
+ context.fillStyle = accent;
81
+ context.fillRect(0, 0, 1, 1);
82
+ const channels = [...context.getImageData(0, 0, 1, 1).data].slice(0, 3).map((value) => {
83
+ const channel = value / 255;
84
+ return channel <= 0.04045 ? channel / 12.92 : ((channel + 0.055) / 1.055) ** 2.4;
85
+ });
86
+ const luminance = channels[0] * 0.2126 + channels[1] * 0.7152 + channels[2] * 0.0722;
87
+ return (luminance + 0.05) / 0.05 > 1.05 / (luminance + 0.05) ? "#000000" : "#ffffff";
88
+ }
100
89
  function applyAppearance2(value) {
101
90
  const settings = normalizeAppearance2(value);
102
91
  const root = document.documentElement;
103
92
  const preference = window.matchMedia("(prefers-color-scheme: dark)");
104
- const [xs, sm, md, lg, xl] = spaces[settings.density];
105
- const [control, surface, overlay] = radii[settings.cornerRadius];
106
- const tokens = {
107
- "--at-font": fontStack(settings.typography.body),
108
- "--at-font-heading": fontStack(settings.typography.heading),
109
- "--at-space-xs": xs,
110
- "--at-space-sm": sm,
111
- "--at-space-md": md,
112
- "--at-space-lg": lg,
113
- "--at-space-xl": xl,
114
- "--at-layout-gap": `clamp(${md}, 2.5vw, ${lg})`,
115
- "--at-radius-control": control,
116
- "--at-radius-surface": surface,
117
- "--at-radius-overlay": overlay,
118
- "--at-shadow-overlay": settings.elevation === "flat" ? "none" : settings.elevation === "raised" ? "0 24px 72px rgb(0 0 0 / 24%)" : "0 18px 50px rgb(0 0 0 / 16%)",
119
- "--at-shadow-surface": settings.elevation === "flat" ? "none" : settings.elevation === "raised" ? "0 8px 28px rgb(20 28 40 / 10%)" : "0 3px 16px rgb(20 28 40 / 5%)"
93
+ const attributes = {
94
+ "data-atbl-appearance": "",
95
+ "data-atbl-base-color": settings.baseColor,
96
+ "data-atbl-density": settings.density,
97
+ "data-atbl-radius": settings.cornerRadius,
98
+ "data-atbl-elevation": settings.elevation,
99
+ "data-atbl-theme": ""
120
100
  };
121
- function applyColors() {
122
- const dark = settings.theme === "dark" || settings.theme === "system" && preference.matches;
123
- const [background, surfaceColor, subtle, text, muted, border] = palettes[settings.baseColor][dark ? "dark" : "light"];
124
- const accent = dark ? settings.darkAccentColor ?? `color-mix(in srgb, ${settings.accentColor} 50%, white)` : settings.accentColor;
125
- settings.chartColors.forEach((chartColor, index) => {
126
- tokens[`--at-chart-${index + 1}`] = dark ? `color-mix(in srgb, ${chartColor} 60%, white)` : chartColor;
127
- });
128
- Object.assign(tokens, {
129
- "--at-background": background,
130
- "--at-surface": surfaceColor,
131
- "--at-subtle": subtle,
132
- "--at-text": text,
133
- "--at-muted": muted,
134
- "--at-border": border,
135
- "--at-accent": accent,
136
- "--at-focus-color": muted,
137
- "--at-control-hover-border": `color-mix(in srgb, ${muted} 45%, ${border})`,
138
- "--at-accent-hover": `color-mix(in srgb, ${accent} 80%, ${dark ? "white" : "black"})`,
139
- "--at-accent-subtle": `color-mix(in srgb, ${accent} ${dark ? 22 : 12}%, ${surfaceColor})`,
140
- "--at-on-accent": dark ? background : "#ffffff",
141
- "--at-danger": dark ? "#f97066" : "#b42318",
142
- "--at-backdrop": dark ? "rgb(0 0 0 / 55%)" : "rgb(15 23 30 / 22%)",
143
- "--at-code-surface": dark ? "#242a31" : "#f4f6f9",
144
- "--at-code-text": dark ? "#e5e9ef" : "#273242"
145
- });
146
- root.style.colorScheme = dark ? "dark" : "light";
147
- for (const [name, token] of Object.entries(tokens))
101
+ const inputs = {
102
+ "--atbl-input-font": fontStack(settings.typography.body),
103
+ "--atbl-input-font-heading": fontStack(settings.typography.heading),
104
+ "--atbl-input-accent": settings.accentColor,
105
+ "--atbl-input-dark-accent": settings.darkAccentColor ?? "",
106
+ "--atbl-input-on-accent": ""
107
+ };
108
+ const chartColors = settings.chartColors.length ? settings.chartColors : defaults.chartColors;
109
+ for (let index = 0;index < 8; index++)
110
+ inputs[`--atbl-input-chart-${index + 1}`] = chartColors[index % chartColors.length];
111
+ const previousAttributes = Object.keys(attributes).map((name) => [name, root.getAttribute(name)]);
112
+ const previousInputs = Object.keys(inputs).map((name) => [
113
+ name,
114
+ root.style.getPropertyValue(name),
115
+ root.style.getPropertyPriority(name)
116
+ ]);
117
+ for (const [name, token] of Object.entries(inputs)) {
118
+ if (token)
148
119
  root.style.setProperty(name, token);
120
+ else
121
+ root.style.removeProperty(name);
122
+ }
123
+ for (const [name, attribute] of Object.entries(attributes))
124
+ root.setAttribute(name, attribute);
125
+ function applyTheme() {
126
+ const dark = settings.theme === "dark" || settings.theme === "system" && preference.matches;
127
+ root.setAttribute("data-atbl-theme", dark ? "dark" : "light");
128
+ root.style.setProperty("--atbl-input-on-accent", accentForeground(settings, dark));
149
129
  }
150
- applyColors();
130
+ applyTheme();
151
131
  if (settings.theme === "system")
152
- preference.addEventListener("change", applyColors);
132
+ preference.addEventListener("change", applyTheme);
153
133
  return () => {
154
- preference.removeEventListener("change", applyColors);
134
+ preference.removeEventListener("change", applyTheme);
135
+ for (const [name, attribute] of previousAttributes) {
136
+ if (attribute === null)
137
+ root.removeAttribute(name);
138
+ else
139
+ root.setAttribute(name, attribute);
140
+ }
141
+ for (const [name, token, priority] of previousInputs) {
142
+ if (token)
143
+ root.style.setProperty(name, token, priority);
144
+ else
145
+ root.style.removeProperty(name);
146
+ }
155
147
  };
156
148
  }
157
149
  function createThemeController2(initialTheme = "light") {
@@ -185,4 +177,4 @@ function createThemeController2(initialTheme = "light") {
185
177
 
186
178
  export { parseAppearance2, normalizeAppearance2, applyAppearance2, createThemeController2 };
187
179
 
188
- //# debugId=E968EAFDC43C9C1764756E2164756E21
180
+ //# debugId=312AAB5702AE519564756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/appearance.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * Brand settings; parsing is portable, while theme application requires the browser.\n * @module @altertable/data-app/appearance\n */\nexport type Theme = 'light' | 'dark';\nexport type ThemePreference = Theme | 'system';\n\nexport type AppearanceSettings = {\n theme: ThemePreference;\n baseColor: 'neutral' | 'slate' | 'warm';\n accentColor: string;\n darkAccentColor?: string;\n chartColors: string[];\n density: 'compact' | 'comfortable' | 'spacious';\n cornerRadius: 'none' | 'small' | 'medium' | 'large';\n elevation: 'flat' | 'subtle' | 'raised';\n typography: { body: string; heading: string };\n};\n\n/** App-authored overrides; omitted fields use the package defaults. */\nexport type AppearanceOptions = Partial<\n Omit<AppearanceSettings, 'typography'>\n> & { typography?: Partial<AppearanceSettings['typography']> };\n\nexport type ThemeController = {\n getTheme: () => ThemePreference;\n setTheme: (theme: ThemePreference) => void;\n subscribe: (listener: () => void) => () => void;\n};\n\nconst defaults: AppearanceSettings = {\n theme: 'light',\n baseColor: 'neutral',\n accentColor: '#405d47',\n darkAccentColor: '#a6c4ad',\n chartColors: [\n '#285fc0',\n '#a95319',\n '#147862',\n '#7243aa',\n '#aa3958',\n '#475569',\n ],\n density: 'comfortable',\n cornerRadius: 'medium',\n elevation: 'subtle',\n typography: { body: 'system', heading: 'system' },\n};\n\nfunction record(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value);\n}\n\nfunction oneOf<T extends string>(\n value: unknown,\n options: readonly T[]\n): value is T {\n return typeof value === 'string' && options.includes(value as T);\n}\n\nfunction color(value: unknown): value is string {\n return typeof value === 'string' && /^#[0-9a-fA-F]{6}$/.test(value);\n}\n\nfunction font(value: unknown): value is string {\n return (\n typeof value === 'string' &&\n value.length > 0 &&\n value.length <= 120 &&\n !/[;{}()]/.test(value)\n );\n}\n\n/** Preserve supported external settings and use defaults for invalid fields. */\nexport function parseAppearance(value: unknown): AppearanceSettings {\n if (!record(value)) return normalizeAppearance();\n const typography = record(value.typography) ? value.typography : {};\n\n return normalizeAppearance({\n theme: oneOf(value.theme, ['light', 'dark', 'system'])\n ? value.theme\n : undefined,\n baseColor: oneOf(value.baseColor, ['neutral', 'slate', 'warm'])\n ? value.baseColor\n : undefined,\n accentColor: color(value.accentColor) ? value.accentColor : undefined,\n darkAccentColor: color(value.darkAccentColor)\n ? value.darkAccentColor\n : undefined,\n chartColors:\n Array.isArray(value.chartColors) &&\n value.chartColors.length >= 1 &&\n value.chartColors.length <= 8 &&\n value.chartColors.every(color)\n ? value.chartColors\n : undefined,\n density: oneOf(value.density, ['compact', 'comfortable', 'spacious'])\n ? value.density\n : undefined,\n cornerRadius: oneOf(value.cornerRadius, [\n 'none',\n 'small',\n 'medium',\n 'large',\n ])\n ? value.cornerRadius\n : undefined,\n elevation: oneOf(value.elevation, ['flat', 'subtle', 'raised'])\n ? value.elevation\n : undefined,\n typography: {\n body: font(typography.body) ? typography.body : undefined,\n heading: font(typography.heading) ? typography.heading : undefined,\n },\n });\n}\n\n/** Resolve typed app settings without repeating authoring checks at runtime. */\nexport function normalizeAppearance(\n value: AppearanceOptions = {}\n): AppearanceSettings {\n return {\n theme: value.theme ?? defaults.theme,\n baseColor: value.baseColor ?? defaults.baseColor,\n accentColor: value.accentColor ?? defaults.accentColor,\n density: value.density ?? defaults.density,\n cornerRadius: value.cornerRadius ?? defaults.cornerRadius,\n elevation: value.elevation ?? defaults.elevation,\n darkAccentColor:\n value.darkAccentColor ??\n (value.accentColor === undefined ? defaults.darkAccentColor : undefined),\n chartColors: [...(value.chartColors ?? defaults.chartColors)],\n typography: {\n body: value.typography?.body ?? defaults.typography.body,\n heading: value.typography?.heading ?? defaults.typography.heading,\n },\n };\n}\n\nfunction fontStack(family: string): string {\n return family === 'system'\n ? \"-apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif\"\n : `${JSON.stringify(family)}, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, ui-sans-serif, sans-serif`;\n}\n\n/** Choose a foreground after the browser resolves the configured CSS color. */\nfunction accentForeground(settings: AppearanceSettings, dark: boolean): string {\n const accent =\n getComputedStyle(document.documentElement).getPropertyValue(\n '--atbl-accent'\n ) ||\n (dark\n ? (settings.darkAccentColor ??\n `color-mix(in srgb, ${settings.accentColor} 50%, white)`)\n : settings.accentColor);\n const canvas = document.createElement('canvas');\n canvas.width = canvas.height = 1;\n const context = canvas.getContext('2d')!;\n context.fillStyle = accent;\n context.fillRect(0, 0, 1, 1);\n const channels = [...context.getImageData(0, 0, 1, 1).data]\n .slice(0, 3)\n .map(value => {\n const channel = value / 255;\n return channel <= 0.04045\n ? channel / 12.92\n : ((channel + 0.055) / 1.055) ** 2.4;\n });\n const luminance =\n channels[0]! * 0.2126 + channels[1]! * 0.7152 + channels[2]! * 0.0722;\n return (luminance + 0.05) / 0.05 > 1.05 / (luminance + 0.05)\n ? '#000000'\n : '#ffffff';\n}\n\n/**\n * Select document-owned appearance presets and brand inputs. Public CSS tokens remain\n * overridable in stylesheets. Cleanup restores the previous document appearance.\n */\nexport function applyAppearance(value?: AppearanceOptions): () => void {\n const settings = normalizeAppearance(value);\n const root = document.documentElement;\n const preference = window.matchMedia('(prefers-color-scheme: dark)');\n const attributes: Record<string, string> = {\n 'data-atbl-appearance': '',\n 'data-atbl-base-color': settings.baseColor,\n 'data-atbl-density': settings.density,\n 'data-atbl-radius': settings.cornerRadius,\n 'data-atbl-elevation': settings.elevation,\n 'data-atbl-theme': '',\n };\n const inputs: Record<string, string> = {\n '--atbl-input-font': fontStack(settings.typography.body),\n '--atbl-input-font-heading': fontStack(settings.typography.heading),\n '--atbl-input-accent': settings.accentColor,\n '--atbl-input-dark-accent': settings.darkAccentColor ?? '',\n '--atbl-input-on-accent': '',\n };\n const chartColors = settings.chartColors.length\n ? settings.chartColors\n : defaults.chartColors;\n // Every categorical slot is defined, including after shrinking a custom palette.\n for (let index = 0; index < 8; index++)\n inputs[`--atbl-input-chart-${index + 1}`] =\n chartColors[index % chartColors.length]!;\n\n const previousAttributes = Object.keys(attributes).map(\n name => [name, root.getAttribute(name)] as const\n );\n const previousInputs = Object.keys(inputs).map(\n name =>\n [\n name,\n root.style.getPropertyValue(name),\n root.style.getPropertyPriority(name),\n ] as const\n );\n for (const [name, token] of Object.entries(inputs)) {\n if (token) root.style.setProperty(name, token);\n else root.style.removeProperty(name);\n }\n for (const [name, attribute] of Object.entries(attributes))\n root.setAttribute(name, attribute);\n\n function applyTheme(): void {\n const dark =\n settings.theme === 'dark' ||\n (settings.theme === 'system' && preference.matches);\n root.setAttribute('data-atbl-theme', dark ? 'dark' : 'light');\n root.style.setProperty(\n '--atbl-input-on-accent',\n accentForeground(settings, dark)\n );\n }\n applyTheme();\n if (settings.theme === 'system')\n preference.addEventListener('change', applyTheme);\n\n return () => {\n preference.removeEventListener('change', applyTheme);\n for (const [name, attribute] of previousAttributes) {\n if (attribute === null) root.removeAttribute(name);\n else root.setAttribute(name, attribute);\n }\n for (const [name, token, priority] of previousInputs) {\n if (token) root.style.setProperty(name, token, priority);\n else root.style.removeProperty(name);\n }\n };\n}\n\n/** Persist a viewer theme preference. Applying appearance belongs to the UI owner. */\nexport function createThemeController(\n initialTheme: ThemePreference = 'light'\n): ThemeController {\n const storageKey = 'altertable.data-app.theme';\n let theme = initialTheme;\n try {\n const saved = window.localStorage.getItem(storageKey);\n if (oneOf(saved, ['light', 'dark', 'system'])) theme = saved;\n } catch {\n // Storage can be unavailable in private browsing or embedded contexts.\n }\n const listeners = new Set<() => void>();\n\n return {\n getTheme() {\n return theme;\n },\n setTheme(nextTheme) {\n if (nextTheme === theme) return;\n theme = nextTheme;\n try {\n window.localStorage.setItem(storageKey, theme);\n } catch {\n // The selection still applies to this page.\n }\n listeners.forEach(listener => listener());\n },\n subscribe(listener) {\n listeners.add(listener);\n\n return () => listeners.delete(listener);\n },\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "312AAB5702AE519564756E2164756E21",
9
+ "names": []
10
+ }
@@ -0,0 +1,28 @@
1
+ import {
2
+ defineOperation2
3
+ } from "./index-ag0cgnvq.js";
4
+ import {
5
+ snapshotQueries
6
+ } from "./index-qd5xgx6y.js";
7
+
8
+ // src/core/config.ts
9
+ function defineDataApp2(config) {
10
+ const queries = snapshotQueries(config.queries);
11
+ return Object.freeze({
12
+ ...config,
13
+ queries,
14
+ defineOperation(operation) {
15
+ return defineOperation2({
16
+ ...operation,
17
+ queries
18
+ });
19
+ }
20
+ });
21
+ }
22
+ function dataAppTitle2(config) {
23
+ return `${config.title} • ${config.scope.organization}/${config.scope.environment} • Altertable app`;
24
+ }
25
+
26
+ export { defineDataApp2, dataAppTitle2 };
27
+
28
+ //# debugId=BF0300C757D4413D64756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/config.ts"],
4
+ "sourcesContent": [
5
+ "/**\n * App configuration shared by browser and server.\n * @module @altertable/data-app\n */\nimport { defineOperation } from '@/src/core/contract';\nimport type { AppearanceOptions } from '@/src/core/appearance';\nimport { snapshotQueries, type QueryDefinitions } from '@/src/core/queries';\nexport type { QueryDefinitions, QueryParameterValue } from '@/src/core/queries';\n\nexport type DataAppConfig<Queries extends QueryDefinitions = QueryDefinitions> =\n {\n title: string;\n /** Display labels; scope does not grant data access. */\n scope: { organization: string; environment: string };\n /** Explain what the app helps readers explore. */\n description: string;\n /** Omit to use the standard appearance. */\n appearance?: AppearanceOptions;\n /** Named SQL statements and parameter defaults used by app operations. */\n queries: Queries;\n };\n\ntype ImmutableQueries<Queries extends QueryDefinitions> = {\n readonly [Name in keyof Queries]: {\n readonly statement: Queries[Name]['statement'];\n readonly params: {\n readonly [Param in keyof Queries[Name]['params']]: Readonly<\n Queries[Name]['params'][Param]\n >;\n };\n };\n};\n\n/** An app declaration with operations bound to its query registry. */\nexport type DataAppDefinition<\n Queries extends QueryDefinitions = QueryDefinitions,\n> = Readonly<Omit<DataAppConfig<Queries>, 'queries'>> & {\n readonly queries: ImmutableQueries<Queries>;\n defineOperation<Input, Output>(\n operation: Omit<\n Parameters<typeof defineOperation<Input, Output, Queries>>[0],\n 'queries'\n >\n ): ReturnType<typeof defineOperation<Input, Output, Queries>>;\n};\n\n/**\n * Define the app's query source of truth while preserving exact query and parameter names.\n * Use `app.defineOperation()` to bind operations to these queries. Pass the app once\n * to `mountDataApp({ app, component })` or `<DataAppProvider app={app}>`.\n * The app owns an immutable snapshot of its registry; later input mutations do not change it.\n * This declaration does not execute queries or mount UI. Static apps use `queries: {}`.\n *\n * Declare exactly one module-level const initialized with `defineDataApp({ ... })` in the app's\n * declaration source. For the future backend extractor, the argument is read before bundling\n * by resolving the named `defineDataApp` import from `@altertable/data-app`, including aliases.\n * Variable name is arbitrary;\n * export only for imports by other modules. The argument must be a direct object literal\n * containing schema-valid objects, arrays, strings (including templates without interpolation),\n * finite signed numbers, booleans, and null. No spreads, computed keys, references, calls,\n * or callbacks inside it. Extraction must validate data without evaluating app code.\n * TypeScript checks the shape, not AST syntax. Keep executable composition outside the call.\n *\n * SQL passes unchanged to the backend, which interprets placeholders such as `$orgId`.\n * Declare every parameter with `{ defaultValue: value }` or `{}` for a required value.\n * Values are finite numbers, strings, booleans, or null, never SQL fragments or identifiers.\n * Caller values override defaults; trusted server `queryParams` cannot be overridden.\n */\nexport function defineDataApp<const Queries extends QueryDefinitions>(\n config: DataAppConfig<Queries>\n): DataAppDefinition<Queries> {\n const queries = snapshotQueries(config.queries) as Queries &\n ImmutableQueries<Queries>;\n return Object.freeze({\n ...config,\n queries,\n defineOperation<Input, Output>(\n operation: Omit<\n Parameters<typeof defineOperation<Input, Output, Queries>>[0],\n 'queries'\n >\n ) {\n return defineOperation<Input, Output, Queries>({\n ...operation,\n queries,\n });\n },\n });\n}\n\nexport function dataAppTitle(\n config: Pick<DataAppConfig, 'title' | 'scope'>\n): string {\n return `${config.title} • ${config.scope.organization}/${config.scope.environment} • Altertable app`;\n}\n"
6
+ ],
7
+ "mappings": ";;;;;;;;AAoEO,SAAS,cAAqD,CACnE,QAC4B;AAAA,EAC5B,MAAM,UAAU,gBAAgB,OAAO,OAAO;AAAA,EAE9C,OAAO,OAAO,OAAO;AAAA,OAChB;AAAA,IACH;AAAA,IACA,eAA8B,CAC5B,WAIA;AAAA,MACA,OAAO,iBAAwC;AAAA,WAC1C;AAAA,QACH;AAAA,MACF,CAAC;AAAA;AAAA,EAEL,CAAC;AAAA;AAGI,SAAS,aAAY,CAC1B,QACQ;AAAA,EACR,OAAO,GAAG,OAAO,WAAW,OAAO,MAAM,gBAAgB,OAAO,MAAM;AAAA;",
8
+ "debugId": "BF0300C757D4413D64756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,3 +1,40 @@
1
+ // src/core/invariant.ts
2
+ function invariant(condition, message) {
3
+ if (!condition)
4
+ throw new Error(`Invariant failed: ${message}`);
5
+ }
6
+
7
+ // src/core/queries.ts
8
+ function isQueryParameterValue(value) {
9
+ return value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number" && Number.isFinite(value);
10
+ }
11
+ function isQueryParameters(value) {
12
+ return !!value && typeof value === "object" && !Array.isArray(value) && Object.values(value).every(isQueryParameterValue);
13
+ }
14
+ function snapshotQueries(definitions) {
15
+ return Object.freeze(Object.fromEntries(Object.entries(definitions).map(([name, query]) => {
16
+ invariant(!!name.trim() && !!query.statement.trim(), "Queries need a name and SQL statement.");
17
+ const params = Object.freeze(Object.fromEntries(Object.entries(query.params).map(([key, declaration]) => {
18
+ invariant(!Object.hasOwn(declaration, "defaultValue") || isQueryParameterValue(declaration.defaultValue), `Invalid default for parameter ${key} in query ${name}.`);
19
+ return [key, Object.freeze({ ...declaration })];
20
+ })));
21
+ return [name, Object.freeze({ statement: query.statement, params })];
22
+ })));
23
+ }
24
+ function resolveQueryParameters(declarations, values, context) {
25
+ invariant(values && typeof values === "object" && !Array.isArray(values), "Supply query parameter values as an object.");
26
+ for (const key of Object.keys(values)) {
27
+ invariant(Object.hasOwn(declarations, key), `Unknown parameter ${key}.`);
28
+ invariant(!Object.hasOwn(context, key), `Cannot override context parameter ${key}.`);
29
+ }
30
+ return Object.fromEntries(Object.entries(declarations).map(([key, declaration]) => {
31
+ const value = Object.hasOwn(context, key) ? context[key] : Object.hasOwn(values, key) ? values[key] : declaration.defaultValue;
32
+ invariant(value !== undefined, `Missing parameter ${key}.`);
33
+ invariant(isQueryParameterValue(value), `Parameter ${key} must be a scalar value.`);
34
+ return [key, value];
35
+ }));
36
+ }
37
+
1
38
  // src/core/navigation.ts
2
39
  function validLocation(value) {
3
40
  if (!value || typeof value !== "object")
@@ -98,7 +135,7 @@ function defineDataQueryRoute2(operations) {
98
135
  }
99
136
  if (!("data" in body) || typeof body.requestId !== "string" || typeof body.queriedAt !== "string" || !Array.isArray(body.queryIds) || !body.queryIds.every((id) => typeof id === "string"))
100
137
  throw new Error("Invalid data envelope.");
101
- if (body.queries !== undefined && (!Array.isArray(body.queries) || !body.queries.every((query) => query && typeof query === "object" && typeof query.name === "string" && typeof query.statement === "string" && (query.queryId === undefined || typeof query.queryId === "string"))))
138
+ if (body.queries !== undefined && (!Array.isArray(body.queries) || !body.queries.every((query) => query && typeof query === "object" && typeof query.name === "string" && typeof query.statement === "string" && (query.params === undefined || isQueryParameters(query.params)) && (query.queryId === undefined || typeof query.queryId === "string"))))
102
139
  throw new Error("Invalid query evidence.");
103
140
  const operation = operations?.[input.operation];
104
141
  return {
@@ -136,9 +173,13 @@ var sqlQueryRoute2 = defineMessageRoute2({
136
173
  if (!value || typeof value !== "object")
137
174
  throw new Error("Invalid SQL query.");
138
175
  const query = value;
139
- if (typeof query.statement !== "string" || !query.statement.trim() || typeof query.limit !== "number" || !Number.isSafeInteger(query.limit) || query.limit < 1)
176
+ if (typeof query.statement !== "string" || !query.statement.trim() || typeof query.limit !== "number" || !Number.isSafeInteger(query.limit) || query.limit < 1 || query.params !== undefined && !isQueryParameters(query.params))
140
177
  throw new Error("Invalid SQL query.");
141
- return { statement: query.statement, limit: query.limit };
178
+ return {
179
+ statement: query.statement,
180
+ limit: query.limit,
181
+ ...query.params === undefined ? {} : { params: query.params }
182
+ };
142
183
  },
143
184
  output(value, input) {
144
185
  if (!value || typeof value !== "object")
@@ -158,6 +199,6 @@ var dataAppRoutes2 = {
158
199
  "navigation:update": navigationUpdateRoute2
159
200
  };
160
201
 
161
- export { validLocation, MessageRoutingError2, defineMessageRoute2, createMessageRouter2, defineDataQueryRoute2, navigationUpdateRoute2, sqlQueryRoute2, dataAppRoutes2 };
202
+ export { invariant, snapshotQueries, resolveQueryParameters, validLocation, MessageRoutingError2, defineMessageRoute2, createMessageRouter2, defineDataQueryRoute2, navigationUpdateRoute2, sqlQueryRoute2, dataAppRoutes2 };
162
203
 
163
- //# debugId=7AD0B2977AA9174364756E2164756E21
204
+ //# debugId=6D70F2841935946464756E2164756E21
@@ -0,0 +1,13 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/invariant.ts", "../src/core/queries.ts", "../src/core/navigation.ts", "../src/core/messages.ts"],
4
+ "sourcesContent": [
5
+ "/** Assert an author or data contract while preserving a useful failure message. */\nexport function invariant(\n condition: unknown,\n message: string\n): asserts condition {\n if (!condition) throw new Error(`Invariant failed: ${message}`);\n}\n",
6
+ "import { invariant } from '@/src/core/invariant';\n\nexport type QueryParameterValue = string | number | boolean | null;\ntype QueryDefinition = {\n statement: string;\n params: Readonly<Record<string, { defaultValue?: QueryParameterValue }>>;\n};\nexport type QueryDefinitions = Readonly<Record<string, QueryDefinition>>;\n\n/** Parameters are scalar SQL values, never identifiers or SQL fragments. */\nexport type QueryParameters = Readonly<Record<string, QueryParameterValue>>;\n\nfunction isQueryParameterValue(value: unknown): value is QueryParameterValue {\n return (\n value === null ||\n typeof value === 'string' ||\n typeof value === 'boolean' ||\n (typeof value === 'number' && Number.isFinite(value))\n );\n}\n\nexport function isQueryParameters(value: unknown): value is QueryParameters {\n return (\n !!value &&\n typeof value === 'object' &&\n !Array.isArray(value) &&\n Object.values(value).every(isQueryParameterValue)\n );\n}\n\n/** Retain authored statements and defaults, rejecting empty SQL and invalid scalar defaults. */\nexport function snapshotQueries(\n definitions: QueryDefinitions\n): QueryDefinitions {\n return Object.freeze(\n Object.fromEntries(\n Object.entries(definitions).map(([name, query]) => {\n invariant(\n !!name.trim() && !!query.statement.trim(),\n 'Queries need a name and SQL statement.'\n );\n const params = Object.freeze(\n Object.fromEntries(\n Object.entries(query.params).map(([key, declaration]) => {\n invariant(\n !Object.hasOwn(declaration, 'defaultValue') ||\n isQueryParameterValue(declaration.defaultValue),\n `Invalid default for parameter ${key} in query ${name}.`\n );\n return [key, Object.freeze({ ...declaration })];\n })\n )\n );\n return [name, Object.freeze({ statement: query.statement, params })];\n })\n )\n );\n}\n\n/** Context owns protected values; callers supply filters; defaults fill remaining declarations. */\nexport function resolveQueryParameters(\n declarations: QueryDefinition['params'],\n values: Partial<QueryParameters>,\n context: QueryParameters\n): QueryParameters {\n invariant(\n values && typeof values === 'object' && !Array.isArray(values),\n 'Supply query parameter values as an object.'\n );\n for (const key of Object.keys(values)) {\n invariant(Object.hasOwn(declarations, key), `Unknown parameter ${key}.`);\n invariant(\n !Object.hasOwn(context, key),\n `Cannot override context parameter ${key}.`\n );\n }\n return Object.fromEntries(\n Object.entries(declarations).map(([key, declaration]) => {\n const value = Object.hasOwn(context, key)\n ? context[key]\n : Object.hasOwn(values, key)\n ? values[key]\n : declaration.defaultValue;\n invariant(value !== undefined, `Missing parameter ${key}.`);\n invariant(\n isQueryParameterValue(value),\n `Parameter ${key} must be a scalar value.`\n );\n return [key, value];\n })\n );\n}\n",
7
+ "/** App-owned URL state shared by controls, frame adapters, and host navigation. */\nexport type AppLocation = { search: string; hash: string };\nexport type HistoryMode = 'push' | 'replace';\nexport type NavigationUpdate = AppLocation & {\n mode: HistoryMode;\n title?: string;\n};\n\nexport function validLocation(value: unknown): value is AppLocation {\n if (!value || typeof value !== 'object') return false;\n const message = value as { search?: unknown; hash?: unknown };\n return (\n typeof message.search === 'string' &&\n message.search.length <= 16_384 &&\n (message.search === '' || message.search.startsWith('?')) &&\n typeof message.hash === 'string' &&\n message.hash.length <= 4096 &&\n (message.hash === '' || message.hash.startsWith('#'))\n );\n}\n",
8
+ "import { isQueryParameters, type QueryParameters } from '@/src/core/queries';\nimport type {\n TransportResponse,\n QueryResult,\n OperationContracts,\n DataQueryInput,\n DataQueryBody,\n OutputOf,\n} from '@/src/core/operation-types';\nexport type {\n OperationContracts,\n DataQueryInput,\n DataQueryBody,\n} from '@/src/core/operation-types';\nimport { validLocation, type NavigationUpdate } from '@/src/core/navigation';\nexport type { NavigationUpdate } from '@/src/core/navigation';\n\nexport type MessageContext = { signal: AbortSignal };\nexport type RoutedMessage = { route: string; payload: unknown };\nexport type MessageDispatcher = (\n message: unknown,\n context: MessageContext\n) => Promise<unknown>;\nexport type MessageTransport = (\n message: RoutedMessage,\n signal?: AbortSignal\n) => Promise<unknown>;\nexport type MessageRoute<Input, Output> = {\n input: (value: unknown) => Input;\n output: (value: unknown, input: Input) => Output;\n};\nexport type MessageRoutes = Record<\n string,\n {\n input: (value: unknown) => unknown;\n output: (value: unknown, input: never) => unknown;\n }\n>;\nexport type MessageInput<Route extends MessageRoutes[string]> = ReturnType<\n Route['input']\n>;\nexport type MessageHandlers<Routes extends MessageRoutes> = {\n [Name in keyof Routes]: (\n payload: MessageInput<Routes[Name]>,\n context: MessageContext\n ) =>\n | ReturnType<Routes[Name]['output']>\n | Promise<ReturnType<Routes[Name]['output']>>;\n};\n\n// A bootstrap and its app may bundle independent copies in the same window.\nconst errorBrand = Symbol.for('@altertable/data-app/MessageRoutingError');\n\n/** Only these deliberate, public failures cross the message boundary. Other errors stay private. */\nexport class MessageRoutingError 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 public readonly code: string,\n message: string,\n public readonly requestId?: string\n ) {\n super(message);\n this.name = 'MessageRoutingError';\n }\n}\n\nexport function defineMessageRoute<Input, Output>(\n route: MessageRoute<Input, Output>\n): MessageRoute<Input, Output> {\n return route;\n}\n\n/** Contracts are shared; handlers are supplied by the host and never belong in the app bundle. */\nexport function createMessageRouter<const Routes extends MessageRoutes>(\n routes: Routes,\n handlers: MessageHandlers<NoInfer<Routes>>\n) {\n const registered = new Map(\n Object.entries(routes).map(([name, contract]) => {\n const handler = handlers[name];\n if (!name || name.length > 256 || typeof handler !== 'function')\n throw new Error(\n 'Each message route requires a handler and a bounded name.'\n );\n\n return [name, { contract, handler }] as const;\n })\n );\n\n async function dispatch(\n value: unknown,\n context: MessageContext\n ): Promise<unknown> {\n if (\n !value ||\n typeof value !== 'object' ||\n typeof (value as RoutedMessage).route !== 'string'\n )\n throw new MessageRoutingError(\n 'invalid_message',\n 'Invalid routed message.'\n );\n const message = value as RoutedMessage;\n const entry = registered.get(message.route);\n if (!entry)\n throw new MessageRoutingError('unknown_route', 'Unknown message route.');\n let payload: unknown;\n try {\n payload = entry.contract.input(message.payload);\n } catch {\n throw new MessageRoutingError(\n 'invalid_payload',\n 'Invalid message payload.'\n );\n }\n context.signal.throwIfAborted();\n let result: unknown;\n try {\n result = await entry.handler(payload as never, context);\n } catch (error) {\n if (context.signal.aborted) throw context.signal.reason;\n if (error instanceof MessageRoutingError) throw error;\n throw new MessageRoutingError(\n 'request_failed',\n 'The message request failed. Retry the request.'\n );\n }\n context.signal.throwIfAborted();\n try {\n return entry.contract.output(result, payload as never);\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 return { dispatch };\n}\n\nexport type DataQueryRoute<Operations extends OperationContracts> =\n MessageRoute<DataQueryInput<Operations>, TransportResponse> & {\n operations: Operations | undefined;\n };\nexport type MessageOutput<Route extends MessageRoutes[string], Input> =\n Route extends DataQueryRoute<infer Operations>\n ? Input extends { operation: infer Name extends keyof Operations }\n ? TransportResponse<DataQueryBody<OutputOf<Operations[Name]>>>\n : never\n : ReturnType<Route['output']>;\n\n/** Omit contracts only in generic hosts such as the CLI shell, where Bun validates operations. */\nexport function defineDataQueryRoute<\n Operations extends OperationContracts = OperationContracts,\n>(operations?: Operations): DataQueryRoute<Operations> {\n return {\n operations,\n input(value) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid query.');\n const request = value as { operation?: unknown; input?: unknown };\n if (\n typeof request.operation !== 'string' ||\n !request.operation ||\n request.operation.length > 256 ||\n request.operation.includes('/')\n )\n throw new Error('Invalid operation.');\n const operation =\n operations && Object.hasOwn(operations, request.operation)\n ? operations[request.operation]\n : undefined;\n if (operations && !operation) throw new Error('Unknown operation.');\n\n return {\n operation: request.operation,\n input: operation ? operation.input(request.input) : request.input,\n } as DataQueryInput<Operations>;\n },\n output(value, input) {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid data response.');\n const response = value as TransportResponse;\n if (\n !Number.isInteger(response.status) ||\n response.status < 100 ||\n response.status > 599 ||\n !response.body ||\n typeof response.body !== 'object' ||\n Array.isArray(response.body)\n )\n throw new Error('Invalid data response.');\n const body = response.body as DataQueryBody<unknown> & {\n error?: { code?: unknown; message?: unknown; requestId?: unknown };\n };\n if (response.status < 200 || response.status >= 300) {\n const failure = body.error;\n throw new MessageRoutingError(\n typeof failure?.code === 'string' ? failure.code : 'request_failed',\n typeof failure?.message === 'string'\n ? failure.message\n : 'Could not load data.',\n typeof failure?.requestId === 'string' ? failure.requestId : undefined\n );\n }\n if (\n !('data' in body) ||\n typeof body.requestId !== 'string' ||\n typeof body.queriedAt !== 'string' ||\n !Array.isArray(body.queryIds) ||\n !body.queryIds.every(id => typeof id === 'string')\n )\n throw new Error('Invalid data envelope.');\n if (\n body.queries !== undefined &&\n (!Array.isArray(body.queries) ||\n !body.queries.every(\n query =>\n query &&\n typeof query === 'object' &&\n typeof query.name === 'string' &&\n typeof query.statement === 'string' &&\n (query.params === undefined || isQueryParameters(query.params)) &&\n (query.queryId === undefined || typeof query.queryId === 'string')\n ))\n )\n throw new Error('Invalid query evidence.');\n const operation = operations?.[input.operation];\n\n return {\n status: response.status,\n body: {\n ...body,\n data: operation ? operation.output(body.data) : body.data,\n },\n };\n },\n };\n}\n\nexport const navigationUpdateRoute = /* @__PURE__ */ defineMessageRoute({\n input(value: unknown): NavigationUpdate {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid navigation.');\n const input = value as NavigationUpdate;\n if (\n !validLocation(input) ||\n (input.mode !== 'push' && input.mode !== 'replace') ||\n (input.title !== undefined &&\n (typeof input.title !== 'string' || input.title.length > 512))\n )\n throw new Error('Invalid navigation.');\n\n return {\n search: input.search,\n hash: input.hash,\n mode: input.mode,\n ...(input.title === undefined ? {} : { title: input.title }),\n };\n },\n output(value: unknown): null {\n if (value !== null) throw new Error('Invalid navigation response.');\n\n return null;\n },\n});\nexport type SqlQueryInput = {\n statement: string;\n limit: number;\n params?: QueryParameters;\n};\n\n/** SQL delivery for browser-owned operations. Hosts must enforce backend access and resource limits. */\nexport const sqlQueryRoute = defineMessageRoute({\n input(value: unknown): SqlQueryInput {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid SQL query.');\n const query = value as {\n statement?: unknown;\n limit?: unknown;\n params?: unknown;\n };\n if (\n typeof query.statement !== 'string' ||\n !query.statement.trim() ||\n typeof query.limit !== 'number' ||\n !Number.isSafeInteger(query.limit) ||\n query.limit < 1 ||\n (query.params !== undefined && !isQueryParameters(query.params))\n )\n throw new Error('Invalid SQL query.');\n\n return {\n statement: query.statement,\n limit: query.limit,\n ...(query.params === undefined\n ? {}\n : { params: query.params as QueryParameters }),\n };\n },\n output(value: unknown, input: SqlQueryInput): QueryResult {\n if (!value || typeof value !== 'object')\n throw new Error('Invalid query result.');\n const result = value as QueryResult;\n if (\n !Array.isArray(result.columns) ||\n !result.columns.every(\n column =>\n column &&\n typeof column.name === 'string' &&\n (column.type === undefined || typeof column.type === 'string')\n ) ||\n !Array.isArray(result.rows) ||\n result.rows.length > input.limit ||\n !result.rows.every(\n row => Array.isArray(row) && row.length === result.columns.length\n ) ||\n (result.queryId !== undefined && typeof result.queryId !== 'string')\n )\n throw new Error('Invalid query result.');\n\n return {\n columns: result.columns,\n rows: result.rows,\n ...(result.queryId === undefined ? {} : { queryId: result.queryId }),\n };\n },\n});\n\nexport const dataAppRoutes = {\n 'data:query': /* @__PURE__ */ defineDataQueryRoute(),\n 'navigation:update': navigationUpdateRoute,\n};\n"
9
+ ],
10
+ "mappings": ";AACO,SAAS,SAAS,CACvB,WACA,SACmB;AAAA,EACnB,IAAI,CAAC;AAAA,IAAW,MAAM,IAAI,MAAM,qBAAqB,SAAS;AAAA;;;ACOhE,SAAS,qBAAqB,CAAC,OAA8C;AAAA,EAC3E,OACE,UAAU,QACV,OAAO,UAAU,YACjB,OAAO,UAAU,aAChB,OAAO,UAAU,YAAY,OAAO,SAAS,KAAK;AAAA;AAIhD,SAAS,iBAAiB,CAAC,OAA0C;AAAA,EAC1E,OACE,CAAC,CAAC,SACF,OAAO,UAAU,YACjB,CAAC,MAAM,QAAQ,KAAK,KACpB,OAAO,OAAO,KAAK,EAAE,MAAM,qBAAqB;AAAA;AAK7C,SAAS,eAAe,CAC7B,aACkB;AAAA,EAClB,OAAO,OAAO,OACZ,OAAO,YACL,OAAO,QAAQ,WAAW,EAAE,IAAI,EAAE,MAAM,WAAW;AAAA,IACjD,UACE,CAAC,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,MAAM,UAAU,KAAK,GACxC,wCACF;AAAA,IACA,MAAM,SAAS,OAAO,OACpB,OAAO,YACL,OAAO,QAAQ,MAAM,MAAM,EAAE,IAAI,EAAE,KAAK,iBAAiB;AAAA,MACvD,UACE,CAAC,OAAO,OAAO,aAAa,cAAc,KACxC,sBAAsB,YAAY,YAAY,GAChD,iCAAiC,gBAAgB,OACnD;AAAA,MACA,OAAO,CAAC,KAAK,OAAO,OAAO,KAAK,YAAY,CAAC,CAAC;AAAA,KAC/C,CACH,CACF;AAAA,IACA,OAAO,CAAC,MAAM,OAAO,OAAO,EAAE,WAAW,MAAM,WAAW,OAAO,CAAC,CAAC;AAAA,GACpE,CACH,CACF;AAAA;AAIK,SAAS,sBAAsB,CACpC,cACA,QACA,SACiB;AAAA,EACjB,UACE,UAAU,OAAO,WAAW,YAAY,CAAC,MAAM,QAAQ,MAAM,GAC7D,6CACF;AAAA,EACA,WAAW,OAAO,OAAO,KAAK,MAAM,GAAG;AAAA,IACrC,UAAU,OAAO,OAAO,cAAc,GAAG,GAAG,qBAAqB,MAAM;AAAA,IACvE,UACE,CAAC,OAAO,OAAO,SAAS,GAAG,GAC3B,qCAAqC,MACvC;AAAA,EACF;AAAA,EACA,OAAO,OAAO,YACZ,OAAO,QAAQ,YAAY,EAAE,IAAI,EAAE,KAAK,iBAAiB;AAAA,IACvD,MAAM,QAAQ,OAAO,OAAO,SAAS,GAAG,IACpC,QAAQ,OACR,OAAO,OAAO,QAAQ,GAAG,IACvB,OAAO,OACP,YAAY;AAAA,IAClB,UAAU,UAAU,WAAW,qBAAqB,MAAM;AAAA,IAC1D,UACE,sBAAsB,KAAK,GAC3B,aAAa,6BACf;AAAA,IACA,OAAO,CAAC,KAAK,KAAK;AAAA,GACnB,CACH;AAAA;;;AClFK,SAAS,aAAa,CAAC,OAAsC;AAAA,EAClE,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,IAAU,OAAO;AAAA,EAChD,MAAM,UAAU;AAAA,EAChB,OACE,OAAO,QAAQ,WAAW,YAC1B,QAAQ,OAAO,UAAU,UACxB,QAAQ,WAAW,MAAM,QAAQ,OAAO,WAAW,GAAG,MACvD,OAAO,QAAQ,SAAS,YACxB,QAAQ,KAAK,UAAU,SACtB,QAAQ,SAAS,MAAM,QAAQ,KAAK,WAAW,GAAG;AAAA;;;ACkCvD,IAAM,aAAa,OAAO,IAAI,0CAA0C;AAAA;AAGjE,MAAM,6BAA4B,MAAM;AAAA,EAW3B;AAAA,EAEA;AAAA,GAZR,cAAc;AAAA,UAEhB,OAAO,YAAY,CAAC,OAAyB;AAAA,IACnD,OACE,iBAAiB,SAChB,MAAqC,gBAAgB;AAAA;AAAA,EAI1D,WAAW,CACO,MAChB,SACgB,WAChB;AAAA,IACA,MAAM,OAAO;AAAA,IAJG;AAAA,IAEA;AAAA,IAGhB,KAAK,OAAO;AAAA;AAEhB;AAEO,SAAS,mBAAiC,CAC/C,OAC6B;AAAA,EAC7B,OAAO;AAAA;AAIF,SAAS,oBAAuD,CACrE,QACA,UACA;AAAA,EACA,MAAM,aAAa,IAAI,IACrB,OAAO,QAAQ,MAAM,EAAE,IAAI,EAAE,MAAM,cAAc;AAAA,IAC/C,MAAM,UAAU,SAAS;AAAA,IACzB,IAAI,CAAC,QAAQ,KAAK,SAAS,OAAO,OAAO,YAAY;AAAA,MACnD,MAAM,IAAI,MACR,2DACF;AAAA,IAEF,OAAO,CAAC,MAAM,EAAE,UAAU,QAAQ,CAAC;AAAA,GACpC,CACH;AAAA,EAEA,eAAe,QAAQ,CACrB,OACA,SACkB;AAAA,IAClB,IACE,CAAC,SACD,OAAO,UAAU,YACjB,OAAQ,MAAwB,UAAU;AAAA,MAE1C,MAAM,IAAI,qBACR,mBACA,yBACF;AAAA,IACF,MAAM,UAAU;AAAA,IAChB,MAAM,QAAQ,WAAW,IAAI,QAAQ,KAAK;AAAA,IAC1C,IAAI,CAAC;AAAA,MACH,MAAM,IAAI,qBAAoB,iBAAiB,wBAAwB;AAAA,IACzE,IAAI;AAAA,IACJ,IAAI;AAAA,MACF,UAAU,MAAM,SAAS,MAAM,QAAQ,OAAO;AAAA,MAC9C,MAAM;AAAA,MACN,MAAM,IAAI,qBACR,mBACA,0BACF;AAAA;AAAA,IAEF,QAAQ,OAAO,eAAe;AAAA,IAC9B,IAAI;AAAA,IACJ,IAAI;AAAA,MACF,SAAS,MAAM,MAAM,QAAQ,SAAkB,OAAO;AAAA,MACtD,OAAO,OAAO;AAAA,MACd,IAAI,QAAQ,OAAO;AAAA,QAAS,MAAM,QAAQ,OAAO;AAAA,MACjD,IAAI,iBAAiB;AAAA,QAAqB,MAAM;AAAA,MAChD,MAAM,IAAI,qBACR,kBACA,gDACF;AAAA;AAAA,IAEF,QAAQ,OAAO,eAAe;AAAA,IAC9B,IAAI;AAAA,MACF,OAAO,MAAM,SAAS,OAAO,QAAQ,OAAgB;AAAA,MACrD,OAAO,OAAO;AAAA,MACd,IAAI,iBAAiB;AAAA,QAAqB,MAAM;AAAA,MAChD,MAAM,IAAI,qBACR,oBACA,2BACF;AAAA;AAAA;AAAA,EAIJ,OAAO,EAAE,SAAS;AAAA;AAeb,SAAS,qBAEf,CAAC,YAAqD;AAAA,EACrD,OAAO;AAAA,IACL;AAAA,IACA,KAAK,CAAC,OAAO;AAAA,MACX,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,QAC7B,MAAM,IAAI,MAAM,gBAAgB;AAAA,MAClC,MAAM,UAAU;AAAA,MAChB,IACE,OAAO,QAAQ,cAAc,YAC7B,CAAC,QAAQ,aACT,QAAQ,UAAU,SAAS,OAC3B,QAAQ,UAAU,SAAS,GAAG;AAAA,QAE9B,MAAM,IAAI,MAAM,oBAAoB;AAAA,MACtC,MAAM,YACJ,cAAc,OAAO,OAAO,YAAY,QAAQ,SAAS,IACrD,WAAW,QAAQ,aACnB;AAAA,MACN,IAAI,cAAc,CAAC;AAAA,QAAW,MAAM,IAAI,MAAM,oBAAoB;AAAA,MAElE,OAAO;AAAA,QACL,WAAW,QAAQ;AAAA,QACnB,OAAO,YAAY,UAAU,MAAM,QAAQ,KAAK,IAAI,QAAQ;AAAA,MAC9D;AAAA;AAAA,IAEF,MAAM,CAAC,OAAO,OAAO;AAAA,MACnB,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,QAC7B,MAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C,MAAM,WAAW;AAAA,MACjB,IACE,CAAC,OAAO,UAAU,SAAS,MAAM,KACjC,SAAS,SAAS,OAClB,SAAS,SAAS,OAClB,CAAC,SAAS,QACV,OAAO,SAAS,SAAS,YACzB,MAAM,QAAQ,SAAS,IAAI;AAAA,QAE3B,MAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C,MAAM,OAAO,SAAS;AAAA,MAGtB,IAAI,SAAS,SAAS,OAAO,SAAS,UAAU,KAAK;AAAA,QACnD,MAAM,UAAU,KAAK;AAAA,QACrB,MAAM,IAAI,qBACR,OAAO,SAAS,SAAS,WAAW,QAAQ,OAAO,kBACnD,OAAO,SAAS,YAAY,WACxB,QAAQ,UACR,wBACJ,OAAO,SAAS,cAAc,WAAW,QAAQ,YAAY,SAC/D;AAAA,MACF;AAAA,MACA,IACE,EAAE,UAAU,SACZ,OAAO,KAAK,cAAc,YAC1B,OAAO,KAAK,cAAc,YAC1B,CAAC,MAAM,QAAQ,KAAK,QAAQ,KAC5B,CAAC,KAAK,SAAS,MAAM,QAAM,OAAO,OAAO,QAAQ;AAAA,QAEjD,MAAM,IAAI,MAAM,wBAAwB;AAAA,MAC1C,IACE,KAAK,YAAY,cAChB,CAAC,MAAM,QAAQ,KAAK,OAAO,KAC1B,CAAC,KAAK,QAAQ,MACZ,WACE,SACA,OAAO,UAAU,YACjB,OAAO,MAAM,SAAS,YACtB,OAAO,MAAM,cAAc,aAC1B,MAAM,WAAW,aAAa,kBAAkB,MAAM,MAAM,OAC5D,MAAM,YAAY,aAAa,OAAO,MAAM,YAAY,SAC7D;AAAA,QAEF,MAAM,IAAI,MAAM,yBAAyB;AAAA,MAC3C,MAAM,YAAY,aAAa,MAAM;AAAA,MAErC,OAAO;AAAA,QACL,QAAQ,SAAS;AAAA,QACjB,MAAM;AAAA,aACD;AAAA,UACH,MAAM,YAAY,UAAU,OAAO,KAAK,IAAI,IAAI,KAAK;AAAA,QACvD;AAAA,MACF;AAAA;AAAA,EAEJ;AAAA;AAGK,IAAM,yCAAwC,oBAAmB;AAAA,EACtE,KAAK,CAAC,OAAkC;AAAA,IACtC,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,MAC7B,MAAM,IAAI,MAAM,qBAAqB;AAAA,IACvC,MAAM,QAAQ;AAAA,IACd,IACE,CAAC,cAAc,KAAK,KACnB,MAAM,SAAS,UAAU,MAAM,SAAS,aACxC,MAAM,UAAU,cACd,OAAO,MAAM,UAAU,YAAY,MAAM,MAAM,SAAS;AAAA,MAE3D,MAAM,IAAI,MAAM,qBAAqB;AAAA,IAEvC,OAAO;AAAA,MACL,QAAQ,MAAM;AAAA,MACd,MAAM,MAAM;AAAA,MACZ,MAAM,MAAM;AAAA,SACR,MAAM,UAAU,YAAY,CAAC,IAAI,EAAE,OAAO,MAAM,MAAM;AAAA,IAC5D;AAAA;AAAA,EAEF,MAAM,CAAC,OAAsB;AAAA,IAC3B,IAAI,UAAU;AAAA,MAAM,MAAM,IAAI,MAAM,8BAA8B;AAAA,IAElE,OAAO;AAAA;AAEX,CAAC;AAQM,IAAM,iBAAgB,oBAAmB;AAAA,EAC9C,KAAK,CAAC,OAA+B;AAAA,IACnC,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,MAC7B,MAAM,IAAI,MAAM,oBAAoB;AAAA,IACtC,MAAM,QAAQ;AAAA,IAKd,IACE,OAAO,MAAM,cAAc,YAC3B,CAAC,MAAM,UAAU,KAAK,KACtB,OAAO,MAAM,UAAU,YACvB,CAAC,OAAO,cAAc,MAAM,KAAK,KACjC,MAAM,QAAQ,KACb,MAAM,WAAW,aAAa,CAAC,kBAAkB,MAAM,MAAM;AAAA,MAE9D,MAAM,IAAI,MAAM,oBAAoB;AAAA,IAEtC,OAAO;AAAA,MACL,WAAW,MAAM;AAAA,MACjB,OAAO,MAAM;AAAA,SACT,MAAM,WAAW,YACjB,CAAC,IACD,EAAE,QAAQ,MAAM,OAA0B;AAAA,IAChD;AAAA;AAAA,EAEF,MAAM,CAAC,OAAgB,OAAmC;AAAA,IACxD,IAAI,CAAC,SAAS,OAAO,UAAU;AAAA,MAC7B,MAAM,IAAI,MAAM,uBAAuB;AAAA,IACzC,MAAM,SAAS;AAAA,IACf,IACE,CAAC,MAAM,QAAQ,OAAO,OAAO,KAC7B,CAAC,OAAO,QAAQ,MACd,YACE,UACA,OAAO,OAAO,SAAS,aACtB,OAAO,SAAS,aAAa,OAAO,OAAO,SAAS,SACzD,KACA,CAAC,MAAM,QAAQ,OAAO,IAAI,KAC1B,OAAO,KAAK,SAAS,MAAM,SAC3B,CAAC,OAAO,KAAK,MACX,SAAO,MAAM,QAAQ,GAAG,KAAK,IAAI,WAAW,OAAO,QAAQ,MAC7D,KACC,OAAO,YAAY,aAAa,OAAO,OAAO,YAAY;AAAA,MAE3D,MAAM,IAAI,MAAM,uBAAuB;AAAA,IAEzC,OAAO;AAAA,MACL,SAAS,OAAO;AAAA,MAChB,MAAM,OAAO;AAAA,SACT,OAAO,YAAY,YAAY,CAAC,IAAI,EAAE,SAAS,OAAO,QAAQ;AAAA,IACpE;AAAA;AAEJ,CAAC;AAEM,IAAM,iBAAgB;AAAA,EAC3B,8BAA8B,sBAAqB;AAAA,EACnD,qBAAqB;AACvB;",
11
+ "debugId": "6D70F2841935946464756E2164756E21",
12
+ "names": []
13
+ }
@@ -0,0 +1,149 @@
1
+ import {
2
+ DataSourceError2
3
+ } from "./index-ag0cgnvq.js";
4
+
5
+ // src/core/operation.ts
6
+ async function executeDataOperation(operation, value, {
7
+ operationName,
8
+ lakehouse,
9
+ signal: requestSignal,
10
+ requestId,
11
+ queryParams
12
+ }) {
13
+ requestSignal.throwIfAborted();
14
+ let input;
15
+ try {
16
+ input = operation.input(value);
17
+ } catch {
18
+ throw new OperationInputError;
19
+ }
20
+ const signal = AbortSignal.any([
21
+ requestSignal,
22
+ AbortSignal.timeout(operation.policy.maxDurationMs)
23
+ ]);
24
+ const execution = createOperationLakehouse(operation, lakehouse, signal, operationName);
25
+ try {
26
+ const output = await runOperation(operation, input, {
27
+ lakehouse: execution.lakehouse,
28
+ signal,
29
+ queryParams
30
+ });
31
+ const body = {
32
+ data: operation.output(output),
33
+ requestId,
34
+ queriedAt: new Date().toISOString(),
35
+ queryIds: execution.queryIds,
36
+ queries: execution.queries
37
+ };
38
+ const serializedBody = JSON.stringify(body);
39
+ const responseBytes = new TextEncoder().encode(serializedBody).byteLength;
40
+ if (responseBytes > (operation.policy.maxResponseBytes ?? 1e6))
41
+ throw new Error("Response exceeds byte limit.");
42
+ return { body, serializedBody };
43
+ } catch (error) {
44
+ if (signal.aborted && !(error instanceof DataSourceError2))
45
+ throw new OperationTimeoutError;
46
+ throw error;
47
+ }
48
+ }
49
+ function createOperationLakehouse(operation, source, signal, operationName) {
50
+ const queryIds = [];
51
+ const queries = [];
52
+ const lakehouse = {
53
+ async queryAll(statement, options) {
54
+ if (!Number.isInteger(options.limit) || options.limit < 1)
55
+ throw new Error("Query needs a positive row limit.");
56
+ if (operation.queryNames && !Object.values(operation.queryNames).includes(options.name ?? ""))
57
+ throw new Error(`Query name is not registered for operation ${operationName}.`);
58
+ const query = {
59
+ name: options.name ?? `Query ${queries.length + 1}`,
60
+ statement,
61
+ ...options.params === undefined ? {} : { params: options.params }
62
+ };
63
+ queries.push(query);
64
+ const limit = Math.min(options.limit, operation.policy.maxQueryRows);
65
+ let result;
66
+ try {
67
+ result = await source.queryAll(statement, {
68
+ limit,
69
+ ...options.params === undefined ? {} : { params: options.params },
70
+ signal: AbortSignal.any([signal, options.signal])
71
+ });
72
+ } catch (error) {
73
+ if (error instanceof DataSourceError2)
74
+ error.queryName = query.name;
75
+ throw error;
76
+ }
77
+ if (result.rows.length > limit)
78
+ throw new Error("Result exceeds row limit.");
79
+ if (result.queryId) {
80
+ query.queryId = result.queryId;
81
+ queryIds.push(result.queryId);
82
+ }
83
+ return result;
84
+ }
85
+ };
86
+ return { lakehouse, queries, queryIds };
87
+ }
88
+ async function runOperation(operation, input, { lakehouse, signal, queryParams }) {
89
+ let abort;
90
+ try {
91
+ signal.throwIfAborted();
92
+ const cancelled = new Promise((_, reject) => {
93
+ function rejectAborted() {
94
+ reject(new Error("Request aborted."));
95
+ }
96
+ abort = rejectAborted;
97
+ signal.addEventListener("abort", rejectAborted, { once: true });
98
+ if (signal.aborted)
99
+ rejectAborted();
100
+ });
101
+ return await Promise.race([
102
+ cancelled,
103
+ Promise.resolve().then(() => {
104
+ signal.throwIfAborted();
105
+ return operation.run({ lakehouse, signal, queryParams }, input);
106
+ })
107
+ ]);
108
+ } finally {
109
+ if (abort)
110
+ signal.removeEventListener("abort", abort);
111
+ }
112
+ }
113
+
114
+ class OperationTimeoutError extends Error {
115
+ }
116
+
117
+ class OperationInputError extends Error {
118
+ }
119
+ var sourceErrorMessages = {
120
+ unauthorized: "This app could not authenticate its data connection. Contact the app owner.",
121
+ forbidden: "This app cannot access the requested data. Contact the app owner.",
122
+ rate_limited: "The lakehouse is busy. Wait a moment and retry.",
123
+ query_rejected: "A lakehouse query was rejected. Check the app's data operation.",
124
+ unavailable: "The lakehouse is unavailable. Check the connection and retry."
125
+ };
126
+ function toDataOperationFailure(error, aborted = false) {
127
+ if (error instanceof OperationInputError)
128
+ return {
129
+ status: 400,
130
+ code: "invalid_input",
131
+ message: "Check this operation's inputs."
132
+ };
133
+ if (error instanceof DataSourceError2)
134
+ return {
135
+ status: error.reason === "rate_limited" ? 429 : 502,
136
+ code: `source_${error.reason}`,
137
+ message: sourceErrorMessages[error.reason]
138
+ };
139
+ const timedOut = aborted || error instanceof OperationTimeoutError;
140
+ return {
141
+ status: timedOut ? 504 : 502,
142
+ code: timedOut ? "timeout" : "query_failed",
143
+ message: timedOut ? "The data request timed out." : "The data request failed."
144
+ };
145
+ }
146
+
147
+ export { executeDataOperation, toDataOperationFailure };
148
+
149
+ //# debugId=9709B0C78964A4A864756E2164756E21
@@ -0,0 +1,10 @@
1
+ {
2
+ "version": 3,
3
+ "sources": ["../src/core/operation.ts"],
4
+ "sourcesContent": [
5
+ "import { DataSourceError } from '@/src/core/contract';\nimport type {\n DataOperations,\n DisclosedQuery,\n Lakehouse,\n OperationContext,\n DataQueryBody,\n} from '@/src/core/operation-types';\n\ntype Operation = DataOperations[string];\ntype OperationExecutionOptions = {\n operationName: string;\n lakehouse: Lakehouse;\n signal: AbortSignal;\n requestId: string;\n queryParams?: OperationContext['queryParams'];\n};\n\n/** Shared operation execution. Adapters own authorization, delivery, and public errors. */\nexport async function executeDataOperation(\n operation: Operation,\n value: unknown,\n {\n operationName,\n lakehouse,\n signal: requestSignal,\n requestId,\n queryParams,\n }: OperationExecutionOptions\n) {\n requestSignal.throwIfAborted();\n let input: unknown;\n try {\n input = operation.input(value);\n } catch {\n throw new OperationInputError();\n }\n\n const signal = AbortSignal.any([\n requestSignal,\n AbortSignal.timeout(operation.policy.maxDurationMs),\n ]);\n const execution = createOperationLakehouse(\n operation,\n lakehouse,\n signal,\n operationName\n );\n try {\n const output = await runOperation(operation, input, {\n lakehouse: execution.lakehouse,\n signal,\n queryParams,\n });\n const body: DataQueryBody<unknown> = {\n data: operation.output(output),\n requestId,\n queriedAt: new Date().toISOString(),\n queryIds: execution.queryIds,\n queries: execution.queries,\n };\n const serializedBody = JSON.stringify(body);\n const responseBytes = new TextEncoder().encode(serializedBody).byteLength;\n if (responseBytes > (operation.policy.maxResponseBytes ?? 1_000_000))\n throw new Error('Response exceeds byte limit.');\n\n return { body, serializedBody };\n } catch (error) {\n if (signal.aborted && !(error instanceof DataSourceError))\n throw new OperationTimeoutError();\n throw error;\n }\n}\n\n/** Query evidence follows statement invocation order; query IDs retain completion order. */\nfunction createOperationLakehouse(\n operation: Operation,\n source: Lakehouse,\n signal: AbortSignal,\n operationName: string\n) {\n const queryIds: string[] = [];\n const queries: DisclosedQuery[] = [];\n const lakehouse: Lakehouse = {\n async queryAll(statement, options) {\n if (!Number.isInteger(options.limit) || options.limit < 1)\n throw new Error('Query needs a positive row limit.');\n if (\n operation.queryNames &&\n !Object.values(operation.queryNames).includes(options.name ?? '')\n )\n throw new Error(\n `Query name is not registered for operation ${operationName}.`\n );\n const query: DisclosedQuery = {\n name: options.name ?? `Query ${queries.length + 1}`,\n statement,\n ...(options.params === undefined ? {} : { params: options.params }),\n };\n queries.push(query);\n const limit = Math.min(options.limit, operation.policy.maxQueryRows);\n let result;\n try {\n result = await source.queryAll(statement, {\n limit,\n ...(options.params === undefined ? {} : { params: options.params }),\n signal: AbortSignal.any([signal, options.signal]),\n });\n } catch (error) {\n if (error instanceof DataSourceError) error.queryName = query.name;\n throw error;\n }\n if (result.rows.length > limit)\n throw new Error('Result exceeds row limit.');\n if (result.queryId) {\n query.queryId = result.queryId;\n queryIds.push(result.queryId);\n }\n\n return result;\n },\n };\n\n return { lakehouse, queries, queryIds };\n}\n\n/** Settle cancellation even when operation code or its lakehouse ignores the signal. */\nasync function runOperation(\n operation: Operation,\n input: unknown,\n { lakehouse, signal, queryParams }: OperationContext\n) {\n let abort: (() => void) | undefined;\n try {\n signal.throwIfAborted();\n const cancelled = new Promise<never>((_, reject) => {\n function rejectAborted() {\n reject(new Error('Request aborted.'));\n }\n abort = rejectAborted;\n signal.addEventListener('abort', rejectAborted, { once: true });\n if (signal.aborted) rejectAborted();\n });\n\n return await Promise.race([\n cancelled,\n Promise.resolve().then(() => {\n signal.throwIfAborted();\n\n return operation.run(\n { lakehouse, signal, queryParams },\n input as never\n );\n }),\n ]);\n } finally {\n if (abort) signal.removeEventListener('abort', abort);\n }\n}\n\nclass OperationTimeoutError extends Error {}\n\nclass OperationInputError extends Error {}\n\nconst sourceErrorMessages = {\n unauthorized:\n 'This app could not authenticate its data connection. Contact the app owner.',\n forbidden:\n 'This app cannot access the requested data. Contact the app owner.',\n rate_limited: 'The lakehouse is busy. Wait a moment and retry.',\n query_rejected:\n \"A lakehouse query was rejected. Check the app's data operation.\",\n unavailable: 'The lakehouse is unavailable. Check the connection and retry.',\n};\n\nexport function toDataOperationFailure(error: unknown, aborted = false) {\n if (error instanceof OperationInputError)\n return {\n status: 400,\n code: 'invalid_input',\n message: \"Check this operation's inputs.\",\n };\n if (error instanceof DataSourceError)\n return {\n status: error.reason === 'rate_limited' ? 429 : 502,\n code: `source_${error.reason}`,\n message: sourceErrorMessages[error.reason],\n };\n const timedOut = aborted || error instanceof OperationTimeoutError;\n return {\n status: timedOut ? 504 : 502,\n code: timedOut ? 'timeout' : 'query_failed',\n message: timedOut\n ? 'The data request timed out.'\n : 'The data request failed.',\n };\n}\n"
6
+ ],
7
+ "mappings": "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",
8
+ "debugId": "9709B0C78964A4A864756E2164756E21",
9
+ "names": []
10
+ }
@@ -1,10 +1,14 @@
1
- import"../chunks/contract-mev09s5v.js";
2
- import"../chunks/contract-yxbjea23.js";
1
+ import"../chunks/index-mev09s5v.js";
2
+ import"../chunks/index-ag0cgnvq.js";
3
+ import {
4
+ createDataClient2
5
+ } from "../chunks/index-23dktynd.js";
6
+ import"../chunks/index-x69p7cv7.js";
3
7
  import {
4
- createDataClient2,
5
8
  createDataAppNavigation2,
6
- getDataAppNavigation2
7
- } from "../chunks/contract-a061yj6r.js";
9
+ getDataAppNavigation2,
10
+ createAnnotationClient2
11
+ } from "../chunks/index-ev2b5aaf.js";
8
12
  import {
9
13
  DataAppError2,
10
14
  createHttpTransport2,
@@ -12,9 +16,10 @@ import {
12
16
  createIframeTransport2,
13
17
  installDataAppTransport2,
14
18
  getDataAppTransport2
15
- } from "../chunks/contract-sm7j7k95.js";
19
+ } from "../chunks/index-ktmvs916.js";
16
20
  export {
17
21
  DataAppError2 as DataAppError,
22
+ createAnnotationClient2 as createAnnotationClient,
18
23
  createDataAppNavigation2 as createDataAppNavigation,
19
24
  createDataClient2 as createDataClient,
20
25
  createHttpTransport2 as createHttpTransport,
@@ -25,4 +30,4 @@ export {
25
30
  installDataAppTransport2 as installDataAppTransport
26
31
  };
27
32
 
28
- //# debugId=88DF02CCA4F0E63864756E2164756E21
33
+ //# debugId=51C8B2874175323464756E2164756E21
@@ -4,6 +4,6 @@
4
4
  "sourcesContent": [
5
5
  ],
6
6
  "mappings": "",
7
- "debugId": "88DF02CCA4F0E63864756E2164756E21",
7
+ "debugId": "51C8B2874175323464756E2164756E21",
8
8
  "names": []
9
9
  }
@@ -3,7 +3,7 @@ import {
3
3
  normalizeAppearance2,
4
4
  applyAppearance2,
5
5
  createThemeController2
6
- } from "../chunks/contract-txjy0en2.js";
6
+ } from "../chunks/index-m6n8ctfc.js";
7
7
  export {
8
8
  applyAppearance2 as applyAppearance,
9
9
  createThemeController2 as createThemeController,