@tetrascience-npm/tetrascience-react-ui 0.7.0 → 1.0.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.
- package/README.md +58 -4
- package/dist/ai/attachments.cjs +2 -0
- package/dist/ai/attachments.cjs.map +1 -0
- package/dist/ai/attachments.js +224 -0
- package/dist/ai/attachments.js.map +1 -0
- package/dist/ai/chain-of-thought.cjs +2 -0
- package/dist/ai/chain-of-thought.cjs.map +1 -0
- package/dist/ai/chain-of-thought.js +145 -0
- package/dist/ai/chain-of-thought.js.map +1 -0
- package/dist/ai/confirmation.cjs +2 -0
- package/dist/ai/confirmation.cjs.map +1 -0
- package/dist/ai/confirmation.js +109 -0
- package/dist/ai/confirmation.js.map +1 -0
- package/dist/ai/context.cjs +2 -0
- package/dist/ai/context.cjs.map +1 -0
- package/dist/ai/context.js +267 -0
- package/dist/ai/context.js.map +1 -0
- package/dist/ai/conversation.cjs +4 -0
- package/dist/ai/conversation.cjs.map +1 -0
- package/dist/ai/conversation.js +108 -0
- package/dist/ai/conversation.js.map +1 -0
- package/dist/ai/inline-citation.cjs +2 -0
- package/dist/ai/inline-citation.cjs.map +1 -0
- package/dist/ai/inline-citation.js +182 -0
- package/dist/ai/inline-citation.js.map +1 -0
- package/dist/ai/message.cjs +2 -0
- package/dist/ai/message.cjs.map +1 -0
- package/dist/ai/message.js +237 -0
- package/dist/ai/message.js.map +1 -0
- package/dist/ai/model-selector.cjs +2 -0
- package/dist/ai/model-selector.cjs.map +1 -0
- package/dist/ai/model-selector.js +77 -0
- package/dist/ai/model-selector.js.map +1 -0
- package/dist/ai/prompt-input.cjs +2 -0
- package/dist/ai/prompt-input.cjs.map +1 -0
- package/dist/ai/prompt-input.js +776 -0
- package/dist/ai/prompt-input.js.map +1 -0
- package/dist/ai/queue.cjs +2 -0
- package/dist/ai/queue.cjs.map +1 -0
- package/dist/ai/queue.js +209 -0
- package/dist/ai/queue.js.map +1 -0
- package/dist/ai/reasoning.cjs +2 -0
- package/dist/ai/reasoning.cjs.map +1 -0
- package/dist/ai/reasoning.js +129 -0
- package/dist/ai/reasoning.js.map +1 -0
- package/dist/ai/shimmer.cjs +2 -0
- package/dist/ai/shimmer.cjs.map +1 -0
- package/dist/ai/shimmer.js +49 -0
- package/dist/ai/shimmer.js.map +1 -0
- package/dist/ai/sources.cjs +2 -0
- package/dist/ai/sources.cjs.map +1 -0
- package/dist/ai/sources.js +54 -0
- package/dist/ai/sources.js.map +1 -0
- package/dist/ai/speech-input.cjs +2 -0
- package/dist/ai/speech-input.cjs.map +1 -0
- package/dist/ai/speech-input.js +123 -0
- package/dist/ai/speech-input.js.map +1 -0
- package/dist/ai/stream-status.cjs +2 -0
- package/dist/ai/stream-status.cjs.map +1 -0
- package/dist/ai/stream-status.js +108 -0
- package/dist/ai/stream-status.js.map +1 -0
- package/dist/ai/suggestion.cjs +2 -0
- package/dist/ai/suggestion.cjs.map +1 -0
- package/dist/ai/suggestion.js +38 -0
- package/dist/ai/suggestion.js.map +1 -0
- package/dist/ai/task.cjs +2 -0
- package/dist/ai/task.cjs.map +1 -0
- package/dist/ai/task.js +101 -0
- package/dist/ai/task.js.map +1 -0
- package/dist/ai/tool.cjs +2 -0
- package/dist/ai/tool.cjs.map +1 -0
- package/dist/ai/tool.js +139 -0
- package/dist/ai/tool.js.map +1 -0
- package/dist/charts/AreaPlot.cjs +2 -0
- package/dist/charts/AreaPlot.cjs.map +1 -0
- package/dist/charts/AreaPlot.js +5 -0
- package/dist/charts/AreaPlot.js.map +1 -0
- package/dist/charts/BarChart.cjs +2 -0
- package/dist/charts/BarChart.cjs.map +1 -0
- package/dist/charts/BarChart.js +5 -0
- package/dist/charts/BarChart.js.map +1 -0
- package/dist/charts/BoxPlot.cjs +2 -0
- package/dist/charts/BoxPlot.cjs.map +1 -0
- package/dist/charts/BoxPlot.js +5 -0
- package/dist/charts/BoxPlot.js.map +1 -0
- package/dist/charts/ChartTooltip.cjs +2 -0
- package/dist/charts/ChartTooltip.cjs.map +1 -0
- package/dist/charts/ChartTooltip.js +8 -0
- package/dist/charts/ChartTooltip.js.map +1 -0
- package/dist/charts/Chromatogram.cjs +2 -0
- package/dist/charts/Chromatogram.cjs.map +1 -0
- package/dist/charts/Chromatogram.js +5 -0
- package/dist/charts/Chromatogram.js.map +1 -0
- package/dist/charts/Electropherogram.cjs +2 -0
- package/dist/charts/Electropherogram.cjs.map +1 -0
- package/dist/charts/Electropherogram.js +5 -0
- package/dist/charts/Electropherogram.js.map +1 -0
- package/dist/charts/Histogram.cjs +2 -0
- package/dist/charts/Histogram.cjs.map +1 -0
- package/dist/charts/Histogram.js +5 -0
- package/dist/charts/Histogram.js.map +1 -0
- package/dist/charts/LinePlot.cjs +2 -0
- package/dist/charts/LinePlot.cjs.map +1 -0
- package/dist/charts/LinePlot.js +5 -0
- package/dist/charts/LinePlot.js.map +1 -0
- package/dist/charts/PieChart.cjs +2 -0
- package/dist/charts/PieChart.cjs.map +1 -0
- package/dist/charts/PieChart.js +5 -0
- package/dist/charts/PieChart.js.map +1 -0
- package/dist/charts/PlateMap.cjs +2 -0
- package/dist/charts/PlateMap.cjs.map +1 -0
- package/dist/charts/PlateMap.js +5 -0
- package/dist/charts/PlateMap.js.map +1 -0
- package/dist/charts/ScatterPlot.cjs +2 -0
- package/dist/charts/ScatterPlot.cjs.map +1 -0
- package/dist/charts/ScatterPlot.js +5 -0
- package/dist/charts/ScatterPlot.js.map +1 -0
- package/dist/charts/ScatterPlotInteractive.cjs +2 -0
- package/dist/charts/ScatterPlotInteractive.cjs.map +1 -0
- package/dist/charts/ScatterPlotInteractive.js +14 -0
- package/dist/charts/ScatterPlotInteractive.js.map +1 -0
- package/dist/charts/StackedChromatogram.cjs +2 -0
- package/dist/charts/StackedChromatogram.cjs.map +1 -0
- package/dist/charts/StackedChromatogram.js +7 -0
- package/dist/charts/StackedChromatogram.js.map +1 -0
- package/dist/components/ai/attachments.d.ts +54 -0
- package/dist/components/ai/chain-of-thought.d.ts +56 -0
- package/dist/components/ai/confirmation.d.ts +47 -0
- package/dist/components/ai/context.d.ts +40 -0
- package/dist/components/ai/conversation.d.ts +23 -0
- package/dist/components/ai/inline-citation.d.ts +38 -0
- package/dist/components/ai/message.d.ts +37 -0
- package/dist/components/ai/model-selector.d.ts +36 -0
- package/dist/components/ai/prompt-input.d.ts +158 -0
- package/dist/components/ai/queue.d.ts +72 -0
- package/dist/components/ai/reasoning.d.ts +26 -0
- package/dist/components/ai/shimmer.d.ts +17 -0
- package/dist/components/ai/sources.d.ts +12 -0
- package/dist/components/ai/speech-input.d.ts +54 -0
- package/dist/components/ai/stream-status.d.ts +66 -0
- package/dist/components/ai/streamdown-code-plugin.cjs +2 -0
- package/dist/components/ai/streamdown-code-plugin.cjs.map +1 -0
- package/dist/components/ai/streamdown-code-plugin.d.ts +2 -0
- package/dist/components/ai/streamdown-code-plugin.js +42 -0
- package/dist/components/ai/streamdown-code-plugin.js.map +1 -0
- package/dist/components/ai/streamdown-plugins.cjs +2 -0
- package/dist/components/ai/streamdown-plugins.cjs.map +1 -0
- package/dist/components/ai/streamdown-plugins.d.ts +2 -0
- package/dist/components/ai/streamdown-plugins.js +14 -0
- package/dist/components/ai/streamdown-plugins.js.map +1 -0
- package/dist/components/ai/suggestion.d.ts +9 -0
- package/dist/components/ai/task.d.ts +16 -0
- package/dist/components/ai/tool.d.ts +33 -0
- package/dist/components/ai/use-streamdown-plugins.cjs +2 -0
- package/dist/components/ai/use-streamdown-plugins.cjs.map +1 -0
- package/dist/components/ai/use-streamdown-plugins.d.ts +8 -0
- package/dist/components/ai/use-streamdown-plugins.js +25 -0
- package/dist/components/ai/use-streamdown-plugins.js.map +1 -0
- package/dist/components/charts/AreaPlot/AreaPlot.cjs +2 -0
- package/dist/components/charts/AreaPlot/AreaPlot.cjs.map +1 -0
- package/dist/components/charts/AreaPlot/AreaPlot.d.ts +39 -0
- package/dist/components/charts/AreaPlot/AreaPlot.js +270 -0
- package/dist/components/charts/AreaPlot/AreaPlot.js.map +1 -0
- package/dist/components/charts/AreaPlot/index.d.ts +2 -0
- package/dist/components/charts/BarChart/BarChart.cjs +2 -0
- package/dist/components/charts/BarChart/BarChart.cjs.map +1 -0
- package/dist/components/charts/BarChart/BarChart.d.ts +44 -0
- package/dist/components/charts/BarChart/BarChart.js +219 -0
- package/dist/components/charts/BarChart/BarChart.js.map +1 -0
- package/dist/components/charts/BarChart/index.d.ts +2 -0
- package/dist/components/charts/BoxPlot/BoxPlot.cjs +2 -0
- package/dist/components/charts/BoxPlot/BoxPlot.cjs.map +1 -0
- package/dist/components/charts/BoxPlot/BoxPlot.d.ts +33 -0
- package/dist/components/charts/BoxPlot/BoxPlot.js +208 -0
- package/dist/components/charts/BoxPlot/BoxPlot.js.map +1 -0
- package/dist/components/charts/BoxPlot/index.d.ts +2 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs +1 -1
- package/dist/components/charts/ChartTooltip/ChartTooltip.cjs.map +1 -1
- package/dist/components/charts/ChartTooltip/ChartTooltip.d.ts +71 -0
- package/dist/components/charts/ChartTooltip/ChartTooltip.js +22 -22
- package/dist/components/charts/ChartTooltip/ChartTooltip.js.map +1 -1
- package/dist/components/charts/ChartTooltip/index.d.ts +2 -0
- package/dist/components/charts/ChartTooltip/lines.d.ts +54 -0
- package/dist/components/charts/Chromatogram/Chromatogram.cjs +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.cjs.map +1 -1
- package/dist/components/charts/Chromatogram/Chromatogram.d.ts +5 -0
- package/dist/components/charts/Chromatogram/Chromatogram.js +232 -170
- package/dist/components/charts/Chromatogram/Chromatogram.js.map +1 -1
- package/dist/components/charts/Chromatogram/annotations.cjs +2 -0
- package/dist/components/charts/Chromatogram/annotations.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/annotations.d.ts +50 -0
- package/dist/components/charts/Chromatogram/annotations.js +137 -0
- package/dist/components/charts/Chromatogram/annotations.js.map +1 -0
- package/dist/components/charts/Chromatogram/boundaryMarkers.cjs +2 -0
- package/dist/components/charts/Chromatogram/boundaryMarkers.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/boundaryMarkers.d.ts +14 -0
- package/dist/components/charts/Chromatogram/boundaryMarkers.js +34 -0
- package/dist/components/charts/Chromatogram/boundaryMarkers.js.map +1 -0
- package/dist/components/charts/Chromatogram/constants.cjs +2 -0
- package/dist/components/charts/Chromatogram/constants.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/constants.d.ts +46 -0
- package/dist/components/charts/Chromatogram/constants.js +36 -0
- package/dist/components/charts/Chromatogram/constants.js.map +1 -0
- package/dist/components/charts/Chromatogram/dataProcessing.cjs +2 -0
- package/dist/components/charts/Chromatogram/dataProcessing.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/dataProcessing.d.ts +49 -0
- package/dist/components/charts/Chromatogram/dataProcessing.js +90 -0
- package/dist/components/charts/Chromatogram/dataProcessing.js.map +1 -0
- package/dist/components/charts/Chromatogram/index.d.ts +2 -0
- package/dist/components/charts/Chromatogram/peakDetection.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/peakDetection.d.ts +33 -0
- package/dist/components/charts/Chromatogram/peakDetection.js.map +1 -0
- package/dist/components/charts/Chromatogram/plotBuilder.cjs +2 -0
- package/dist/components/charts/Chromatogram/plotBuilder.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/plotBuilder.d.ts +58 -0
- package/dist/components/charts/Chromatogram/plotBuilder.js +216 -0
- package/dist/components/charts/Chromatogram/plotBuilder.js.map +1 -0
- package/dist/components/charts/Chromatogram/regionOverlays.cjs +2 -0
- package/dist/components/charts/Chromatogram/regionOverlays.cjs.map +1 -0
- package/dist/components/charts/Chromatogram/regionOverlays.d.ts +9 -0
- package/dist/components/charts/Chromatogram/regionOverlays.js +26 -0
- package/dist/components/charts/Chromatogram/regionOverlays.js.map +1 -0
- package/dist/components/charts/Chromatogram/types.d.ts +258 -0
- package/dist/components/charts/Electropherogram/Electropherogram.cjs +2 -0
- package/dist/components/charts/Electropherogram/Electropherogram.cjs.map +1 -0
- package/dist/components/charts/Electropherogram/Electropherogram.d.ts +22 -0
- package/dist/components/charts/Electropherogram/Electropherogram.js +180 -0
- package/dist/components/charts/Electropherogram/Electropherogram.js.map +1 -0
- package/dist/components/charts/Electropherogram/index.d.ts +2 -0
- package/dist/components/charts/Histogram/Histogram.cjs +1 -1
- package/dist/components/charts/Histogram/Histogram.cjs.map +1 -1
- package/dist/components/charts/Histogram/Histogram.d.ts +36 -0
- package/dist/components/charts/Histogram/Histogram.js +107 -108
- package/dist/components/charts/Histogram/Histogram.js.map +1 -1
- package/dist/components/charts/Histogram/index.d.ts +2 -0
- package/dist/components/charts/LinePlot/LinePlot.cjs +2 -0
- package/dist/components/charts/LinePlot/LinePlot.cjs.map +1 -0
- package/dist/components/charts/LinePlot/LinePlot.d.ts +45 -0
- package/dist/components/charts/LinePlot/LinePlot.js +224 -0
- package/dist/components/charts/LinePlot/LinePlot.js.map +1 -0
- package/dist/components/charts/LinePlot/index.d.ts +2 -0
- package/dist/components/charts/PieChart/PieChart.cjs +1 -1
- package/dist/components/charts/PieChart/PieChart.cjs.map +1 -1
- package/dist/components/charts/PieChart/PieChart.d.ts +20 -0
- package/dist/components/charts/PieChart/PieChart.js +62 -61
- package/dist/components/charts/PieChart/PieChart.js.map +1 -1
- package/dist/components/charts/PieChart/index.d.ts +2 -0
- package/dist/components/charts/PlateMap/PlateMap.cjs +1 -1
- package/dist/components/charts/PlateMap/PlateMap.cjs.map +1 -1
- package/dist/components/charts/PlateMap/PlateMap.d.ts +29 -0
- package/dist/components/charts/PlateMap/PlateMap.js +246 -242
- package/dist/components/charts/PlateMap/PlateMap.js.map +1 -1
- package/dist/components/charts/PlateMap/constants.d.ts +75 -0
- package/dist/components/charts/PlateMap/index.d.ts +2 -0
- package/dist/components/charts/PlateMap/types.d.ts +322 -0
- package/dist/components/charts/PlateMap/utils.d.ts +133 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.cjs +2 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.cjs.map +1 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.d.ts +43 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.js +252 -0
- package/dist/components/charts/ScatterPlot/ScatterPlot.js.map +1 -0
- package/dist/components/charts/ScatterPlot/index.d.ts +2 -0
- package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.cjs +2 -0
- package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.cjs.map +1 -0
- package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.d.ts +25 -0
- package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.js +215 -0
- package/dist/components/charts/ScatterPlotInteractive/ScatterPlotInteractive.js.map +1 -0
- package/dist/components/charts/ScatterPlotInteractive/constants.cjs +2 -0
- package/dist/components/charts/ScatterPlotInteractive/constants.cjs.map +1 -0
- package/dist/components/charts/ScatterPlotInteractive/constants.d.ts +50 -0
- package/dist/components/charts/ScatterPlotInteractive/constants.js +38 -0
- package/dist/components/charts/ScatterPlotInteractive/constants.js.map +1 -0
- package/dist/components/charts/ScatterPlotInteractive/index.d.ts +3 -0
- package/dist/components/charts/ScatterPlotInteractive/types.d.ts +226 -0
- package/dist/components/charts/ScatterPlotInteractive/utils.cjs +2 -0
- package/dist/components/charts/ScatterPlotInteractive/utils.cjs.map +1 -0
- package/dist/components/charts/ScatterPlotInteractive/utils.d.ts +72 -0
- package/dist/components/charts/ScatterPlotInteractive/utils.js +261 -0
- package/dist/components/charts/ScatterPlotInteractive/utils.js.map +1 -0
- package/dist/components/charts/StackedChromatogram/StackedChromatogram.cjs +2 -0
- package/dist/components/charts/StackedChromatogram/StackedChromatogram.cjs.map +1 -0
- package/dist/components/charts/StackedChromatogram/StackedChromatogram.d.ts +3 -0
- package/dist/components/charts/StackedChromatogram/StackedChromatogram.js +40 -0
- package/dist/components/charts/StackedChromatogram/StackedChromatogram.js.map +1 -0
- package/dist/components/charts/StackedChromatogram/index.d.ts +3 -0
- package/dist/components/charts/StackedChromatogram/transforms.cjs +2 -0
- package/dist/components/charts/StackedChromatogram/transforms.cjs.map +1 -0
- package/dist/components/charts/StackedChromatogram/transforms.d.ts +9 -0
- package/dist/components/charts/StackedChromatogram/transforms.js +31 -0
- package/dist/components/charts/StackedChromatogram/transforms.js.map +1 -0
- package/dist/components/charts/StackedChromatogram/types.d.ts +26 -0
- package/dist/components/charts/plotly-loader.cjs +2 -0
- package/dist/components/charts/plotly-loader.cjs.map +1 -0
- package/dist/components/charts/plotly-loader.d.ts +29 -0
- package/dist/components/charts/plotly-loader.js +22 -0
- package/dist/components/charts/plotly-loader.js.map +1 -0
- package/dist/components/composed/AssistantLayout/AssistantLayout.cjs +2 -0
- package/dist/components/composed/AssistantLayout/AssistantLayout.cjs.map +1 -0
- package/dist/components/composed/AssistantLayout/AssistantLayout.d.ts +63 -0
- package/dist/components/composed/AssistantLayout/AssistantLayout.js +142 -0
- package/dist/components/composed/AssistantLayout/AssistantLayout.js.map +1 -0
- package/dist/components/composed/AssistantLayout/dockLayout.cjs +2 -0
- package/dist/components/composed/AssistantLayout/dockLayout.cjs.map +1 -0
- package/dist/components/composed/AssistantLayout/dockLayout.d.ts +15 -0
- package/dist/components/composed/AssistantLayout/dockLayout.js +10 -0
- package/dist/components/composed/AssistantLayout/dockLayout.js.map +1 -0
- package/dist/components/composed/AssistantLayout/index.d.ts +3 -0
- package/dist/components/composed/Chat/Chat.cjs +1 -1
- package/dist/components/composed/Chat/Chat.cjs.map +1 -1
- package/dist/components/composed/Chat/Chat.d.ts +35 -0
- package/dist/components/composed/Chat/Chat.js +28 -28
- package/dist/components/composed/Chat/Chat.js.map +1 -1
- package/dist/components/composed/Chat/index.d.ts +2 -0
- package/dist/components/composed/ConfirmDialog/ConfirmDialog.cjs +1 -1
- package/dist/components/composed/ConfirmDialog/ConfirmDialog.cjs.map +1 -1
- package/dist/components/composed/ConfirmDialog/ConfirmDialog.d.ts +23 -0
- package/dist/components/composed/ConfirmDialog/ConfirmDialog.js +33 -29
- package/dist/components/composed/ConfirmDialog/ConfirmDialog.js.map +1 -1
- package/dist/components/composed/ConfirmDialog/index.d.ts +1 -0
- package/dist/components/composed/DataAppShell/CollapseButton.cjs +2 -0
- package/dist/components/composed/DataAppShell/CollapseButton.cjs.map +1 -0
- package/dist/components/composed/DataAppShell/CollapseButton.d.ts +23 -0
- package/dist/components/composed/DataAppShell/CollapseButton.js +42 -0
- package/dist/components/composed/DataAppShell/CollapseButton.js.map +1 -0
- package/dist/components/composed/DataAppShell/DataAppShell.cjs +1 -1
- package/dist/components/composed/DataAppShell/DataAppShell.cjs.map +1 -1
- package/dist/components/composed/DataAppShell/DataAppShell.d.ts +88 -0
- package/dist/components/composed/DataAppShell/DataAppShell.js +350 -328
- package/dist/components/composed/DataAppShell/DataAppShell.js.map +1 -1
- package/dist/components/composed/DataAppShell/PrimaryNav.cjs +2 -0
- package/dist/components/composed/DataAppShell/PrimaryNav.cjs.map +1 -0
- package/dist/components/composed/DataAppShell/PrimaryNav.d.ts +64 -0
- package/dist/components/composed/DataAppShell/PrimaryNav.js +268 -0
- package/dist/components/composed/DataAppShell/PrimaryNav.js.map +1 -0
- package/dist/components/composed/DataAppShell/RightPanel.cjs +2 -0
- package/dist/components/composed/DataAppShell/RightPanel.cjs.map +1 -0
- package/dist/components/composed/DataAppShell/RightPanel.d.ts +95 -0
- package/dist/components/composed/DataAppShell/RightPanel.js +282 -0
- package/dist/components/composed/DataAppShell/RightPanel.js.map +1 -0
- package/dist/components/composed/DataAppShell/SecondaryNav.cjs +2 -0
- package/dist/components/composed/DataAppShell/SecondaryNav.cjs.map +1 -0
- package/dist/components/composed/DataAppShell/SecondaryNav.d.ts +63 -0
- package/dist/components/composed/DataAppShell/SecondaryNav.js +364 -0
- package/dist/components/composed/DataAppShell/SecondaryNav.js.map +1 -0
- package/dist/components/composed/DataAppShell/ShellContext.cjs +2 -0
- package/dist/components/composed/DataAppShell/ShellContext.cjs.map +1 -0
- package/dist/components/composed/DataAppShell/ShellContext.d.ts +20 -0
- package/dist/components/composed/DataAppShell/ShellContext.js +23 -0
- package/dist/components/composed/DataAppShell/ShellContext.js.map +1 -0
- package/dist/components/composed/DataAppShell/index.d.ts +12 -0
- package/dist/components/composed/EmptyState/EmptyState.d.ts +12 -0
- package/dist/components/composed/EmptyState/index.d.ts +2 -0
- package/dist/components/composed/FormPatterns/FormSection.cjs +1 -1
- package/dist/components/composed/FormPatterns/FormSection.cjs.map +1 -1
- package/dist/components/composed/FormPatterns/FormSection.d.ts +7 -0
- package/dist/components/composed/FormPatterns/FormSection.js +2 -2
- package/dist/components/composed/FormPatterns/index.d.ts +1 -0
- package/dist/components/composed/MoleculeStructure/MoleculeStructure.cjs +2 -0
- package/dist/components/composed/MoleculeStructure/MoleculeStructure.cjs.map +1 -0
- package/dist/components/composed/MoleculeStructure/MoleculeStructure.d.ts +43 -0
- package/dist/components/composed/MoleculeStructure/MoleculeStructure.js +87 -0
- package/dist/components/composed/MoleculeStructure/MoleculeStructure.js.map +1 -0
- package/dist/components/composed/MoleculeStructure/index.d.ts +3 -0
- package/dist/components/composed/MoleculeStructure/rdkit-loader.cjs +2 -0
- package/dist/components/composed/MoleculeStructure/rdkit-loader.cjs.map +1 -0
- package/dist/components/composed/MoleculeStructure/rdkit-loader.d.ts +104 -0
- package/dist/components/composed/MoleculeStructure/rdkit-loader.js +89 -0
- package/dist/components/composed/MoleculeStructure/rdkit-loader.js.map +1 -0
- package/dist/components/composed/MoleculeStructure/use-rdkit.cjs +2 -0
- package/dist/components/composed/MoleculeStructure/use-rdkit.cjs.map +1 -0
- package/dist/components/composed/MoleculeStructure/use-rdkit.d.ts +29 -0
- package/dist/components/composed/MoleculeStructure/use-rdkit.js +19 -0
- package/dist/components/composed/MoleculeStructure/use-rdkit.js.map +1 -0
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.d.ts +12 -0
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js +21 -21
- package/dist/components/composed/PlateMapEditor/ManifestFilterPopover.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.d.ts +22 -0
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js +34 -34
- package/dist/components/composed/PlateMapEditor/PlateMapActionsMenu.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.d.ts +106 -0
- package/dist/components/composed/PlateMapEditor/PlateMapEditor.js +2 -2
- package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapForm.d.ts +30 -0
- package/dist/components/composed/PlateMapEditor/PlateMapForm.js +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.d.ts +64 -0
- package/dist/components/composed/PlateMapEditor/PlateMapGrid.js +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapManifest.d.ts +29 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.d.ts +19 -0
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js +11 -11
- package/dist/components/composed/PlateMapEditor/PlateMapPlateSelector.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.d.ts +73 -0
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js +1 -1
- package/dist/components/composed/PlateMapEditor/PlatePaintGrid.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.d.ts +12 -0
- package/dist/components/composed/PlateMapEditor/PlateZoomControl.js +2 -2
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.d.ts +13 -0
- package/dist/components/composed/PlateMapEditor/TemplateIOPanel.js +4 -4
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellLegend.d.ts +21 -0
- package/dist/components/composed/PlateMapEditor/WellLegend.js +24 -12
- package/dist/components/composed/PlateMapEditor/WellLegend.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellManifestTable.d.ts +46 -0
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js +10 -10
- package/dist/components/composed/PlateMapEditor/WellManifestTable.js.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.cjs.map +1 -1
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.d.ts +17 -0
- package/dist/components/composed/PlateMapEditor/WellMetadataForm.js +7 -7
- package/dist/components/composed/PlateMapEditor/autoFill.d.ts +26 -0
- package/dist/components/composed/PlateMapEditor/csvPlateTriage.d.ts +4 -0
- package/dist/components/composed/PlateMapEditor/helpers.d.ts +2 -0
- package/dist/components/composed/PlateMapEditor/index.d.ts +31 -0
- package/dist/components/composed/PlateMapEditor/types.d.ts +137 -0
- package/dist/components/composed/PlateMapEditor/wellGrid.d.ts +12 -0
- package/dist/components/composed/ProcessFlow/ProcessFlow.d.ts +32 -0
- package/dist/components/composed/ProcessFlow/ProcessFlow.utils.d.ts +86 -0
- package/dist/components/composed/ProcessFlow/index.d.ts +1 -0
- package/dist/components/composed/RichListItem/RichListItem.cjs +1 -1
- package/dist/components/composed/RichListItem/RichListItem.cjs.map +1 -1
- package/dist/components/composed/RichListItem/RichListItem.d.ts +22 -0
- package/dist/components/composed/RichListItem/RichListItem.js +2 -2
- package/dist/components/composed/RichListItem/index.d.ts +2 -0
- package/dist/components/composed/StatCard/StatCard.cjs +1 -1
- package/dist/components/composed/StatCard/StatCard.cjs.map +1 -1
- package/dist/components/composed/StatCard/StatCard.d.ts +11 -0
- package/dist/components/composed/StatCard/StatCard.js +1 -1
- package/dist/components/composed/StatCard/index.d.ts +1 -0
- package/dist/components/composed/TdpSearch/TdpSearch.cjs +1 -1
- package/dist/components/composed/TdpSearch/TdpSearch.cjs.map +1 -1
- package/dist/components/composed/TdpSearch/TdpSearch.d.ts +21 -0
- package/dist/components/composed/TdpSearch/TdpSearch.js +14 -13
- package/dist/components/composed/TdpSearch/TdpSearch.mocks.d.ts +5 -0
- package/dist/components/composed/TdpSearch/components/DefaultFilters.cjs +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultFilters.cjs.map +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultFilters.d.ts +3 -0
- package/dist/components/composed/TdpSearch/components/DefaultFilters.js +4 -4
- package/dist/components/composed/TdpSearch/components/DefaultFilters.js.map +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultResults.cjs +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultResults.cjs.map +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultResults.d.ts +3 -0
- package/dist/components/composed/TdpSearch/components/DefaultResults.js +2 -2
- package/dist/components/composed/TdpSearch/components/DefaultSearchBar.cjs +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultSearchBar.cjs.map +1 -1
- package/dist/components/composed/TdpSearch/components/DefaultSearchBar.d.ts +3 -0
- package/dist/components/composed/TdpSearch/components/DefaultSearchBar.js +2 -2
- package/dist/components/composed/TdpSearch/constants.d.ts +3 -0
- package/dist/components/composed/TdpSearch/hooks/useSearch.d.ts +2 -0
- package/dist/components/composed/TdpSearch/hooks/useTdpCredentials.d.ts +14 -0
- package/dist/components/composed/TdpSearch/index.d.ts +3 -0
- package/dist/components/composed/TdpSearch/types.d.ts +128 -0
- package/dist/components/composed/TdpSearch/utils.d.ts +3 -0
- package/dist/components/composed/TopBar/TopBar.cjs +2 -0
- package/dist/components/composed/TopBar/TopBar.cjs.map +1 -0
- package/dist/components/composed/TopBar/TopBar.d.ts +25 -0
- package/dist/components/composed/TopBar/TopBar.js +56 -0
- package/dist/components/composed/TopBar/TopBar.js.map +1 -0
- package/dist/components/composed/TopBar/index.d.ts +2 -0
- package/dist/components/composed/UserMenu/UserMenu.cjs +2 -0
- package/dist/components/composed/UserMenu/UserMenu.cjs.map +1 -0
- package/dist/components/composed/UserMenu/UserMenu.d.ts +53 -0
- package/dist/components/composed/UserMenu/UserMenu.js +99 -0
- package/dist/components/composed/UserMenu/UserMenu.js.map +1 -0
- package/dist/components/composed/UserMenu/index.d.ts +2 -0
- package/dist/components/composed/tdp-link.d.ts +110 -0
- package/dist/components/composed/tdp-url.d.ts +68 -0
- package/dist/components/ui/accordion.d.ts +7 -0
- package/dist/components/ui/alert-dialog.d.ts +18 -0
- package/dist/components/ui/alert.d.ts +10 -0
- package/dist/components/ui/aspect-ratio.d.ts +3 -0
- package/dist/components/ui/avatar.d.ts +11 -0
- package/dist/components/ui/badge.d.ts +9 -0
- package/dist/components/ui/banner.d.ts +19 -0
- package/dist/components/ui/breadcrumb.d.ts +11 -0
- package/dist/components/ui/button-group.d.ts +11 -0
- package/dist/components/ui/button.d.ts +10 -0
- package/dist/components/ui/calendar.d.ts +10 -0
- package/dist/components/ui/card.d.ts +11 -0
- package/dist/components/ui/carousel.d.ts +28 -0
- package/dist/components/ui/checkbox.d.ts +4 -0
- package/dist/components/ui/code-block.d.ts +45 -0
- package/dist/components/ui/code-editor.d.ts +18 -0
- package/dist/components/ui/collapsible.d.ts +5 -0
- package/dist/components/ui/combobox.d.ts +24 -0
- package/dist/components/ui/command.d.ts +18 -0
- package/dist/components/ui/context-menu.d.ts +31 -0
- package/dist/components/ui/data-table/data-table-column-toggle.cjs +1 -1
- package/dist/components/ui/data-table/data-table-column-toggle.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-column-toggle.d.ts +6 -0
- package/dist/components/ui/data-table/data-table-column-toggle.js +71 -63
- package/dist/components/ui/data-table/data-table-column-toggle.js.map +1 -1
- package/dist/components/ui/data-table/data-table-filter.cjs +1 -1
- package/dist/components/ui/data-table/data-table-filter.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-filter.d.ts +9 -0
- package/dist/components/ui/data-table/data-table-filter.js +26 -25
- package/dist/components/ui/data-table/data-table-filter.js.map +1 -1
- package/dist/components/ui/data-table/data-table-group.cjs +1 -1
- package/dist/components/ui/data-table/data-table-group.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-group.d.ts +9 -0
- package/dist/components/ui/data-table/data-table-group.js +18 -17
- package/dist/components/ui/data-table/data-table-group.js.map +1 -1
- package/dist/components/ui/data-table/data-table-pagination.cjs +1 -1
- package/dist/components/ui/data-table/data-table-pagination.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table-pagination.d.ts +7 -0
- package/dist/components/ui/data-table/data-table-pagination.js +16 -16
- package/dist/components/ui/data-table/data-table-pagination.js.map +1 -1
- package/dist/components/ui/data-table/data-table.cjs +1 -1
- package/dist/components/ui/data-table/data-table.cjs.map +1 -1
- package/dist/components/ui/data-table/data-table.d.ts +82 -0
- package/dist/components/ui/data-table/data-table.js +191 -190
- package/dist/components/ui/data-table/data-table.js.map +1 -1
- package/dist/components/ui/data-table/index.d.ts +5 -0
- package/dist/components/ui/dialog.d.ts +18 -0
- package/dist/components/ui/dropdown-menu.d.ts +29 -0
- package/dist/components/ui/field.d.ts +24 -0
- package/dist/components/ui/hover-card.d.ts +6 -0
- package/dist/components/ui/input-group.d.ts +16 -0
- package/dist/components/ui/input.d.ts +3 -0
- package/dist/components/ui/item.d.ts +23 -0
- package/dist/components/ui/kbd.d.ts +3 -0
- package/dist/components/ui/label.d.ts +4 -0
- package/dist/components/ui/menubar.d.ts +30 -0
- package/dist/components/ui/navigation-menu.d.ts +14 -0
- package/dist/components/ui/popover.d.ts +7 -0
- package/dist/components/ui/progress.d.ts +4 -0
- package/dist/components/ui/radio-group.d.ts +5 -0
- package/dist/components/ui/resizable.d.ts +25 -0
- package/dist/components/ui/scroll-area.d.ts +5 -0
- package/dist/components/ui/select.d.ts +15 -0
- package/dist/components/ui/separator.d.ts +4 -0
- package/dist/components/ui/sheet.d.ts +14 -0
- package/dist/components/ui/sidebar.d.ts +69 -0
- package/dist/components/ui/skeleton.d.ts +2 -0
- package/dist/components/ui/slider.d.ts +4 -0
- package/dist/components/ui/snippet.d.ts +18 -0
- package/dist/components/ui/sonner.d.ts +3 -0
- package/dist/components/ui/spinner.d.ts +6 -0
- package/dist/components/ui/switch.d.ts +6 -0
- package/dist/components/ui/table.d.ts +22 -0
- package/dist/components/ui/tabs.d.ts +11 -0
- package/dist/components/ui/tetra-molecule-icon.d.ts +11 -0
- package/dist/components/ui/tetrascience-icon.d.ts +7 -0
- package/dist/components/ui/textarea.d.ts +3 -0
- package/dist/components/ui/toggle-group.d.ts +10 -0
- package/dist/components/ui/toggle.d.ts +9 -0
- package/dist/components/ui/tooltip.d.ts +7 -0
- package/dist/composed/AssistantLayout.cjs +2 -0
- package/dist/composed/AssistantLayout.cjs.map +1 -0
- package/dist/composed/AssistantLayout.js +10 -0
- package/dist/composed/AssistantLayout.js.map +1 -0
- package/dist/composed/Chat.cjs +2 -0
- package/dist/composed/Chat.cjs.map +1 -0
- package/dist/composed/Chat.js +5 -0
- package/dist/composed/Chat.js.map +1 -0
- package/dist/composed/ConfirmDialog.cjs +2 -0
- package/dist/composed/ConfirmDialog.cjs.map +1 -0
- package/dist/composed/ConfirmDialog.js +5 -0
- package/dist/composed/ConfirmDialog.js.map +1 -0
- package/dist/composed/DataAppShell.cjs +2 -0
- package/dist/composed/DataAppShell.cjs.map +1 -0
- package/dist/composed/DataAppShell.js +22 -0
- package/dist/composed/DataAppShell.js.map +1 -0
- package/dist/composed/EmptyState.cjs +2 -0
- package/dist/composed/EmptyState.cjs.map +1 -0
- package/dist/composed/EmptyState.js +5 -0
- package/dist/composed/EmptyState.js.map +1 -0
- package/dist/composed/FormPatterns.cjs +2 -0
- package/dist/composed/FormPatterns.cjs.map +1 -0
- package/dist/composed/FormPatterns.js +5 -0
- package/dist/composed/FormPatterns.js.map +1 -0
- package/dist/composed/MoleculeStructure.cjs +2 -0
- package/dist/composed/MoleculeStructure.cjs.map +1 -0
- package/dist/composed/MoleculeStructure.js +11 -0
- package/dist/composed/MoleculeStructure.js.map +1 -0
- package/dist/composed/PlateMapEditor.cjs +2 -0
- package/dist/composed/PlateMapEditor.cjs.map +1 -0
- package/dist/composed/PlateMapEditor.js +45 -0
- package/dist/composed/PlateMapEditor.js.map +1 -0
- package/dist/composed/ProcessFlow.cjs +2 -0
- package/dist/composed/ProcessFlow.cjs.map +1 -0
- package/dist/composed/ProcessFlow.js +7 -0
- package/dist/composed/ProcessFlow.js.map +1 -0
- package/dist/composed/RichListItem.cjs +2 -0
- package/dist/composed/RichListItem.cjs.map +1 -0
- package/dist/composed/RichListItem.js +6 -0
- package/dist/composed/RichListItem.js.map +1 -0
- package/dist/composed/StatCard.cjs +2 -0
- package/dist/composed/StatCard.cjs.map +1 -0
- package/dist/composed/StatCard.js +5 -0
- package/dist/composed/StatCard.js.map +1 -0
- package/dist/composed/TdpSearch.cjs +2 -0
- package/dist/composed/TdpSearch.cjs.map +1 -0
- package/dist/composed/TdpSearch.js +8 -0
- package/dist/composed/TdpSearch.js.map +1 -0
- package/dist/composed/TopBar.cjs +2 -0
- package/dist/composed/TopBar.cjs.map +1 -0
- package/dist/composed/TopBar.js +6 -0
- package/dist/composed/TopBar.js.map +1 -0
- package/dist/composed/UserMenu.cjs +2 -0
- package/dist/composed/UserMenu.cjs.map +1 -0
- package/dist/composed/UserMenu.js +7 -0
- package/dist/composed/UserMenu.js.map +1 -0
- package/dist/composed/tdp-link.cjs +2 -0
- package/dist/composed/tdp-link.cjs.map +1 -0
- package/dist/composed/tdp-link.js +84 -0
- package/dist/composed/tdp-link.js.map +1 -0
- package/dist/composed/tdp-url.cjs.map +1 -0
- package/dist/composed/tdp-url.js.map +1 -0
- package/dist/hooks/use-code-editor-theme.d.ts +34 -0
- package/dist/hooks/use-element-size.d.ts +25 -0
- package/dist/hooks/use-is-dark.d.ts +12 -0
- package/dist/hooks/use-mobile.d.ts +1 -0
- package/dist/hooks/use-plotly-theme.cjs +1 -1
- package/dist/hooks/use-plotly-theme.cjs.map +1 -1
- package/dist/hooks/use-plotly-theme.d.ts +49 -0
- package/dist/hooks/use-plotly-theme.js +4 -3
- package/dist/hooks/use-plotly-theme.js.map +1 -1
- package/dist/index.cjs +1 -1
- package/dist/index.css +1 -1
- package/dist/index.d.ts +102 -4404
- package/dist/index.js +698 -659
- package/dist/index.js.map +1 -1
- package/dist/index.tailwind.css +1 -1
- package/dist/jest-setup.cjs +4 -0
- package/dist/jest-setup.cjs.map +1 -0
- package/dist/jest-setup.d.ts +106 -0
- package/dist/jest-setup.js +218 -0
- package/dist/jest-setup.js.map +1 -0
- package/dist/lib/shiki.cjs +2 -0
- package/dist/lib/shiki.cjs.map +1 -0
- package/dist/lib/shiki.d.ts +32 -0
- package/dist/lib/shiki.js +72 -0
- package/dist/lib/shiki.js.map +1 -0
- package/dist/lib/utils.d.ts +2 -0
- package/dist/server/auth/JwtTokenManager.cjs +1 -1
- package/dist/server/auth/JwtTokenManager.cjs.map +1 -1
- package/dist/server/auth/JwtTokenManager.d.ts +113 -0
- package/dist/server/auth/JwtTokenManager.js +44 -21
- package/dist/server/auth/JwtTokenManager.js.map +1 -1
- package/dist/server/auth/index.d.ts +5 -0
- package/dist/server/index.d.ts +8 -0
- package/dist/server/providers/AthenaProvider.cjs +1 -1
- package/dist/server/providers/AthenaProvider.cjs.map +1 -1
- package/dist/server/providers/AthenaProvider.d.ts +75 -0
- package/dist/server/providers/DatabricksProvider.cjs +1 -1
- package/dist/server/providers/DatabricksProvider.cjs.map +1 -1
- package/dist/server/providers/DatabricksProvider.d.ts +38 -0
- package/dist/server/providers/SnowflakeProvider.cjs +1 -1
- package/dist/server/providers/SnowflakeProvider.cjs.map +1 -1
- package/dist/server/providers/SnowflakeProvider.d.ts +36 -0
- package/dist/server/providers/buildProvider.d.ts +39 -0
- package/dist/server/providers/entries/athena.d.ts +24 -0
- package/dist/server/providers/entries/databricks.d.ts +25 -0
- package/dist/server/providers/entries/snowflake.d.ts +25 -0
- package/dist/server/providers/exceptions.d.ts +36 -0
- package/dist/server/providers/getProviderConfigurations.d.ts +45 -0
- package/dist/server/providers/index.d.ts +31 -0
- package/dist/server/providers/providerDiscovery.d.ts +81 -0
- package/dist/server/providers/types.d.ts +145 -0
- package/dist/server/search/TdpSearchManager.d.ts +40 -0
- package/dist/server/search/index.d.ts +5 -0
- package/dist/server.d.ts +17 -540
- package/dist/ui/accordion.cjs +2 -0
- package/dist/ui/accordion.cjs.map +1 -0
- package/dist/ui/accordion.js +83 -0
- package/dist/ui/accordion.js.map +1 -0
- package/dist/ui/alert-dialog.cjs +2 -0
- package/dist/ui/alert-dialog.cjs.map +1 -0
- package/dist/ui/alert-dialog.js +181 -0
- package/dist/ui/alert-dialog.js.map +1 -0
- package/dist/ui/alert.cjs +2 -0
- package/dist/ui/alert.cjs.map +1 -0
- package/dist/ui/alert.js +81 -0
- package/dist/ui/alert.js.map +1 -0
- package/dist/ui/aspect-ratio.cjs.map +1 -0
- package/dist/ui/aspect-ratio.js.map +1 -0
- package/dist/ui/avatar.cjs +2 -0
- package/dist/ui/avatar.cjs.map +1 -0
- package/dist/ui/avatar.js +107 -0
- package/dist/ui/avatar.js.map +1 -0
- package/dist/ui/badge.cjs +2 -0
- package/dist/ui/badge.cjs.map +1 -0
- package/dist/ui/badge.js +47 -0
- package/dist/ui/badge.js.map +1 -0
- package/dist/ui/banner.cjs +2 -0
- package/dist/ui/banner.cjs.map +1 -0
- package/dist/ui/banner.js +80 -0
- package/dist/ui/banner.js.map +1 -0
- package/dist/ui/breadcrumb.cjs +2 -0
- package/dist/ui/breadcrumb.cjs.map +1 -0
- package/dist/ui/breadcrumb.js +118 -0
- package/dist/ui/breadcrumb.js.map +1 -0
- package/dist/ui/button-group.cjs +2 -0
- package/dist/ui/button-group.cjs.map +1 -0
- package/dist/ui/button-group.js +77 -0
- package/dist/ui/button-group.js.map +1 -0
- package/dist/ui/button.cjs +2 -0
- package/dist/ui/button.cjs.map +1 -0
- package/dist/ui/button.js +57 -0
- package/dist/ui/button.js.map +1 -0
- package/dist/ui/calendar.cjs +2 -0
- package/dist/ui/calendar.cjs.map +1 -0
- package/dist/ui/calendar.js +174 -0
- package/dist/ui/calendar.js.map +1 -0
- package/dist/ui/card.cjs +2 -0
- package/dist/ui/card.cjs.map +1 -0
- package/dist/ui/card.js +102 -0
- package/dist/ui/card.js.map +1 -0
- package/dist/ui/carousel.cjs +2 -0
- package/dist/ui/carousel.cjs.map +1 -0
- package/dist/ui/carousel.js +179 -0
- package/dist/ui/carousel.js.map +1 -0
- package/dist/ui/checkbox.cjs +2 -0
- package/dist/ui/checkbox.cjs.map +1 -0
- package/dist/ui/checkbox.js +35 -0
- package/dist/ui/checkbox.js.map +1 -0
- package/dist/ui/code-block.cjs +4 -0
- package/dist/ui/code-block.cjs.map +1 -0
- package/dist/ui/code-block.js +324 -0
- package/dist/ui/code-block.js.map +1 -0
- package/dist/ui/code-editor.cjs +2 -0
- package/dist/ui/code-editor.cjs.map +1 -0
- package/dist/ui/code-editor.js +106 -0
- package/dist/ui/code-editor.js.map +1 -0
- package/dist/ui/collapsible.cjs.map +1 -0
- package/dist/ui/collapsible.js.map +1 -0
- package/dist/ui/combobox.cjs +2 -0
- package/dist/ui/combobox.cjs.map +1 -0
- package/dist/ui/combobox.js +285 -0
- package/dist/ui/combobox.js.map +1 -0
- package/dist/ui/command.cjs +2 -0
- package/dist/ui/command.cjs.map +1 -0
- package/dist/ui/command.js +178 -0
- package/dist/ui/command.js.map +1 -0
- package/dist/ui/context-menu.cjs +2 -0
- package/dist/ui/context-menu.cjs.map +1 -0
- package/dist/ui/context-menu.js +236 -0
- package/dist/ui/context-menu.js.map +1 -0
- package/dist/ui/data-table.cjs +2 -0
- package/dist/ui/data-table.cjs.map +1 -0
- package/dist/ui/data-table.js +16 -0
- package/dist/ui/data-table.js.map +1 -0
- package/dist/ui/dialog.cjs +2 -0
- package/dist/ui/dialog.cjs.map +1 -0
- package/dist/ui/dialog.js +165 -0
- package/dist/ui/dialog.js.map +1 -0
- package/dist/ui/dropdown-menu.cjs +2 -0
- package/dist/ui/dropdown-menu.cjs.map +1 -0
- package/dist/ui/dropdown-menu.js +260 -0
- package/dist/ui/dropdown-menu.js.map +1 -0
- package/dist/ui/field.cjs +2 -0
- package/dist/ui/field.cjs.map +1 -0
- package/dist/ui/field.js +210 -0
- package/dist/ui/field.js.map +1 -0
- package/dist/ui/hover-card.cjs +2 -0
- package/dist/ui/hover-card.cjs.map +1 -0
- package/dist/ui/hover-card.js +39 -0
- package/dist/ui/hover-card.js.map +1 -0
- package/dist/ui/input-group.cjs +2 -0
- package/dist/ui/input-group.cjs.map +1 -0
- package/dist/ui/input-group.js +145 -0
- package/dist/ui/input-group.js.map +1 -0
- package/dist/ui/input.cjs +2 -0
- package/dist/ui/input.cjs.map +1 -0
- package/dist/ui/input.js +20 -0
- package/dist/ui/input.js.map +1 -0
- package/dist/ui/item.cjs +2 -0
- package/dist/ui/item.cjs.map +1 -0
- package/dist/ui/item.js +199 -0
- package/dist/ui/item.js.map +1 -0
- package/dist/ui/kbd.cjs +2 -0
- package/dist/ui/kbd.cjs.map +1 -0
- package/dist/ui/kbd.js +30 -0
- package/dist/ui/kbd.js.map +1 -0
- package/dist/ui/label.cjs +2 -0
- package/dist/ui/label.cjs.map +1 -0
- package/dist/ui/label.js +23 -0
- package/dist/ui/label.js.map +1 -0
- package/dist/ui/menubar.cjs +2 -0
- package/dist/ui/menubar.cjs.map +1 -0
- package/dist/ui/menubar.js +256 -0
- package/dist/ui/menubar.js.map +1 -0
- package/dist/ui/navigation-menu.cjs +2 -0
- package/dist/ui/navigation-menu.cjs.map +1 -0
- package/dist/ui/navigation-menu.js +164 -0
- package/dist/ui/navigation-menu.js.map +1 -0
- package/dist/ui/popover.cjs +2 -0
- package/dist/ui/popover.cjs.map +1 -0
- package/dist/ui/popover.js +45 -0
- package/dist/ui/popover.js.map +1 -0
- package/dist/ui/radio-group.cjs +2 -0
- package/dist/ui/radio-group.cjs.map +1 -0
- package/dist/ui/radio-group.js +45 -0
- package/dist/ui/radio-group.js.map +1 -0
- package/dist/ui/resizable.cjs +2 -0
- package/dist/ui/resizable.cjs.map +1 -0
- package/dist/ui/resizable.js +58 -0
- package/dist/ui/resizable.js.map +1 -0
- package/dist/ui/scroll-area.cjs +2 -0
- package/dist/ui/scroll-area.cjs.map +1 -0
- package/dist/ui/scroll-area.js +61 -0
- package/dist/ui/scroll-area.js.map +1 -0
- package/dist/ui/select.cjs +2 -0
- package/dist/ui/select.cjs.map +1 -0
- package/dist/ui/select.js +184 -0
- package/dist/ui/select.js.map +1 -0
- package/dist/ui/separator.cjs +2 -0
- package/dist/ui/separator.cjs.map +1 -0
- package/dist/ui/separator.js +27 -0
- package/dist/ui/separator.js.map +1 -0
- package/dist/ui/sheet.cjs +2 -0
- package/dist/ui/sheet.cjs.map +1 -0
- package/dist/ui/sheet.js +137 -0
- package/dist/ui/sheet.js.map +1 -0
- package/dist/ui/sidebar.cjs +2 -0
- package/dist/ui/sidebar.cjs.map +1 -0
- package/dist/ui/sidebar.js +579 -0
- package/dist/ui/sidebar.js.map +1 -0
- package/dist/ui/skeleton.cjs +2 -0
- package/dist/ui/skeleton.cjs.map +1 -0
- package/dist/ui/skeleton.js +24 -0
- package/dist/ui/skeleton.js.map +1 -0
- package/dist/ui/slider.cjs +2 -0
- package/dist/ui/slider.cjs.map +1 -0
- package/dist/ui/slider.js +61 -0
- package/dist/ui/slider.js.map +1 -0
- package/dist/ui/sonner.cjs +2 -0
- package/dist/ui/sonner.cjs.map +1 -0
- package/dist/ui/sonner.js +52 -0
- package/dist/ui/sonner.js.map +1 -0
- package/dist/ui/spinner.cjs +2 -0
- package/dist/ui/spinner.cjs.map +1 -0
- package/dist/ui/spinner.js +39 -0
- package/dist/ui/spinner.js.map +1 -0
- package/dist/ui/switch.cjs +2 -0
- package/dist/ui/switch.cjs.map +1 -0
- package/dist/ui/switch.js +32 -0
- package/dist/ui/switch.js.map +1 -0
- package/dist/ui/table.cjs +2 -0
- package/dist/ui/table.cjs.map +1 -0
- package/dist/ui/table.js +153 -0
- package/dist/ui/table.js.map +1 -0
- package/dist/ui/tabs.cjs +2 -0
- package/dist/ui/tabs.cjs.map +1 -0
- package/dist/ui/tabs.js +92 -0
- package/dist/ui/tabs.js.map +1 -0
- package/dist/ui/tetra-molecule-icon.cjs +2 -0
- package/dist/ui/tetra-molecule-icon.cjs.map +1 -0
- package/dist/ui/tetra-molecule-icon.js +50 -0
- package/dist/ui/tetra-molecule-icon.js.map +1 -0
- package/dist/ui/tetrascience-icon.cjs +2 -0
- package/dist/ui/tetrascience-icon.cjs.map +1 -0
- package/dist/ui/tetrascience-icon.js +47 -0
- package/dist/ui/tetrascience-icon.js.map +1 -0
- package/dist/ui/textarea.cjs +2 -0
- package/dist/ui/textarea.cjs.map +1 -0
- package/dist/ui/textarea.js +19 -0
- package/dist/ui/textarea.js.map +1 -0
- package/dist/ui/toggle-group.cjs +2 -0
- package/dist/ui/toggle-group.cjs.map +1 -0
- package/dist/ui/toggle-group.js +81 -0
- package/dist/ui/toggle-group.js.map +1 -0
- package/dist/ui/toggle.cjs +2 -0
- package/dist/ui/toggle.cjs.map +1 -0
- package/dist/ui/toggle.js +44 -0
- package/dist/ui/toggle.js.map +1 -0
- package/dist/ui/tooltip.cjs +2 -0
- package/dist/ui/tooltip.cjs.map +1 -0
- package/dist/ui/tooltip.js +56 -0
- package/dist/ui/tooltip.js.map +1 -0
- package/dist/utils/colors.d.ts +50 -0
- package/package.json +137 -24
- package/dist/athena.d.ts +0 -167
- package/dist/components/ai/attachments.cjs +0 -2
- package/dist/components/ai/attachments.cjs.map +0 -1
- package/dist/components/ai/attachments.js +0 -224
- package/dist/components/ai/attachments.js.map +0 -1
- package/dist/components/ai/chain-of-thought.cjs +0 -2
- package/dist/components/ai/chain-of-thought.cjs.map +0 -1
- package/dist/components/ai/chain-of-thought.js +0 -145
- package/dist/components/ai/chain-of-thought.js.map +0 -1
- package/dist/components/ai/confirmation.cjs +0 -2
- package/dist/components/ai/confirmation.cjs.map +0 -1
- package/dist/components/ai/confirmation.js +0 -109
- package/dist/components/ai/confirmation.js.map +0 -1
- package/dist/components/ai/context.cjs +0 -2
- package/dist/components/ai/context.cjs.map +0 -1
- package/dist/components/ai/context.js +0 -266
- package/dist/components/ai/context.js.map +0 -1
- package/dist/components/ai/conversation.cjs +0 -4
- package/dist/components/ai/conversation.cjs.map +0 -1
- package/dist/components/ai/conversation.js +0 -108
- package/dist/components/ai/conversation.js.map +0 -1
- package/dist/components/ai/inline-citation.cjs +0 -2
- package/dist/components/ai/inline-citation.cjs.map +0 -1
- package/dist/components/ai/inline-citation.js +0 -182
- package/dist/components/ai/inline-citation.js.map +0 -1
- package/dist/components/ai/message.cjs +0 -2
- package/dist/components/ai/message.cjs.map +0 -1
- package/dist/components/ai/message.js +0 -237
- package/dist/components/ai/message.js.map +0 -1
- package/dist/components/ai/model-selector.cjs +0 -2
- package/dist/components/ai/model-selector.cjs.map +0 -1
- package/dist/components/ai/model-selector.js +0 -77
- package/dist/components/ai/model-selector.js.map +0 -1
- package/dist/components/ai/prompt-input.cjs +0 -2
- package/dist/components/ai/prompt-input.cjs.map +0 -1
- package/dist/components/ai/prompt-input.js +0 -774
- package/dist/components/ai/prompt-input.js.map +0 -1
- package/dist/components/ai/queue.cjs +0 -2
- package/dist/components/ai/queue.cjs.map +0 -1
- package/dist/components/ai/queue.js +0 -209
- package/dist/components/ai/queue.js.map +0 -1
- package/dist/components/ai/reasoning.cjs +0 -2
- package/dist/components/ai/reasoning.cjs.map +0 -1
- package/dist/components/ai/reasoning.js +0 -129
- package/dist/components/ai/reasoning.js.map +0 -1
- package/dist/components/ai/shimmer.cjs +0 -2
- package/dist/components/ai/shimmer.cjs.map +0 -1
- package/dist/components/ai/shimmer.js +0 -49
- package/dist/components/ai/shimmer.js.map +0 -1
- package/dist/components/ai/sources.cjs +0 -2
- package/dist/components/ai/sources.cjs.map +0 -1
- package/dist/components/ai/sources.js +0 -54
- package/dist/components/ai/sources.js.map +0 -1
- package/dist/components/ai/speech-input.cjs +0 -2
- package/dist/components/ai/speech-input.cjs.map +0 -1
- package/dist/components/ai/speech-input.js +0 -123
- package/dist/components/ai/speech-input.js.map +0 -1
- package/dist/components/ai/stream-status.cjs +0 -2
- package/dist/components/ai/stream-status.cjs.map +0 -1
- package/dist/components/ai/stream-status.js +0 -106
- package/dist/components/ai/stream-status.js.map +0 -1
- package/dist/components/ai/suggestion.cjs +0 -2
- package/dist/components/ai/suggestion.cjs.map +0 -1
- package/dist/components/ai/suggestion.js +0 -38
- package/dist/components/ai/suggestion.js.map +0 -1
- package/dist/components/ai/task.cjs +0 -2
- package/dist/components/ai/task.cjs.map +0 -1
- package/dist/components/ai/task.js +0 -94
- package/dist/components/ai/task.js.map +0 -1
- package/dist/components/ai/tool.cjs +0 -2
- package/dist/components/ai/tool.cjs.map +0 -1
- package/dist/components/ai/tool.js +0 -143
- package/dist/components/ai/tool.js.map +0 -1
- package/dist/components/charts/AreaGraph/AreaGraph.cjs +0 -2
- package/dist/components/charts/AreaGraph/AreaGraph.cjs.map +0 -1
- package/dist/components/charts/AreaGraph/AreaGraph.js +0 -271
- package/dist/components/charts/AreaGraph/AreaGraph.js.map +0 -1
- package/dist/components/charts/BarGraph/BarGraph.cjs +0 -2
- package/dist/components/charts/BarGraph/BarGraph.cjs.map +0 -1
- package/dist/components/charts/BarGraph/BarGraph.js +0 -220
- package/dist/components/charts/BarGraph/BarGraph.js.map +0 -1
- package/dist/components/charts/Boxplot/Boxplot.cjs +0 -2
- package/dist/components/charts/Boxplot/Boxplot.cjs.map +0 -1
- package/dist/components/charts/Boxplot/Boxplot.js +0 -209
- package/dist/components/charts/Boxplot/Boxplot.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs +0 -2
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js +0 -227
- package/dist/components/charts/ChromatogramChart/ChromatogramChart.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/annotations.cjs +0 -2
- package/dist/components/charts/ChromatogramChart/annotations.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/annotations.js +0 -73
- package/dist/components/charts/ChromatogramChart/annotations.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs +0 -2
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js +0 -34
- package/dist/components/charts/ChromatogramChart/boundaryMarkers.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/constants.cjs +0 -2
- package/dist/components/charts/ChromatogramChart/constants.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/constants.js +0 -30
- package/dist/components/charts/ChromatogramChart/constants.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs +0 -2
- package/dist/components/charts/ChromatogramChart/dataProcessing.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/dataProcessing.js +0 -79
- package/dist/components/charts/ChromatogramChart/dataProcessing.js.map +0 -1
- package/dist/components/charts/ChromatogramChart/peakDetection.cjs.map +0 -1
- package/dist/components/charts/ChromatogramChart/peakDetection.js.map +0 -1
- package/dist/components/charts/DotPlot/DotPlot.cjs +0 -2
- package/dist/components/charts/DotPlot/DotPlot.cjs.map +0 -1
- package/dist/components/charts/DotPlot/DotPlot.js +0 -208
- package/dist/components/charts/DotPlot/DotPlot.js.map +0 -1
- package/dist/components/charts/Heatmap/Heatmap.cjs +0 -2
- package/dist/components/charts/Heatmap/Heatmap.cjs.map +0 -1
- package/dist/components/charts/Heatmap/Heatmap.js +0 -67
- package/dist/components/charts/Heatmap/Heatmap.js.map +0 -1
- package/dist/components/charts/LineGraph/LineGraph.cjs +0 -2
- package/dist/components/charts/LineGraph/LineGraph.cjs.map +0 -1
- package/dist/components/charts/LineGraph/LineGraph.js +0 -225
- package/dist/components/charts/LineGraph/LineGraph.js.map +0 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs +0 -2
- package/dist/components/charts/ScatterGraph/ScatterGraph.cjs.map +0 -1
- package/dist/components/charts/ScatterGraph/ScatterGraph.js +0 -234
- package/dist/components/charts/ScatterGraph/ScatterGraph.js.map +0 -1
- package/dist/components/composed/tdp-link.cjs +0 -2
- package/dist/components/composed/tdp-link.cjs.map +0 -1
- package/dist/components/composed/tdp-link.js +0 -84
- package/dist/components/composed/tdp-link.js.map +0 -1
- package/dist/components/composed/tdp-url.cjs.map +0 -1
- package/dist/components/composed/tdp-url.js.map +0 -1
- package/dist/components/ui/accordion.cjs +0 -2
- package/dist/components/ui/accordion.cjs.map +0 -1
- package/dist/components/ui/accordion.js +0 -83
- package/dist/components/ui/accordion.js.map +0 -1
- package/dist/components/ui/alert-dialog.cjs +0 -2
- package/dist/components/ui/alert-dialog.cjs.map +0 -1
- package/dist/components/ui/alert-dialog.js +0 -181
- package/dist/components/ui/alert-dialog.js.map +0 -1
- package/dist/components/ui/alert.cjs +0 -2
- package/dist/components/ui/alert.cjs.map +0 -1
- package/dist/components/ui/alert.js +0 -81
- package/dist/components/ui/alert.js.map +0 -1
- package/dist/components/ui/aspect-ratio.cjs.map +0 -1
- package/dist/components/ui/aspect-ratio.js.map +0 -1
- package/dist/components/ui/avatar.cjs +0 -2
- package/dist/components/ui/avatar.cjs.map +0 -1
- package/dist/components/ui/avatar.js +0 -107
- package/dist/components/ui/avatar.js.map +0 -1
- package/dist/components/ui/badge.cjs +0 -2
- package/dist/components/ui/badge.cjs.map +0 -1
- package/dist/components/ui/badge.js +0 -47
- package/dist/components/ui/badge.js.map +0 -1
- package/dist/components/ui/banner.cjs +0 -2
- package/dist/components/ui/banner.cjs.map +0 -1
- package/dist/components/ui/banner.js +0 -80
- package/dist/components/ui/banner.js.map +0 -1
- package/dist/components/ui/breadcrumb.cjs +0 -2
- package/dist/components/ui/breadcrumb.cjs.map +0 -1
- package/dist/components/ui/breadcrumb.js +0 -118
- package/dist/components/ui/breadcrumb.js.map +0 -1
- package/dist/components/ui/button-group.cjs +0 -2
- package/dist/components/ui/button-group.cjs.map +0 -1
- package/dist/components/ui/button-group.js +0 -77
- package/dist/components/ui/button-group.js.map +0 -1
- package/dist/components/ui/button.cjs +0 -2
- package/dist/components/ui/button.cjs.map +0 -1
- package/dist/components/ui/button.js +0 -57
- package/dist/components/ui/button.js.map +0 -1
- package/dist/components/ui/calendar.cjs +0 -2
- package/dist/components/ui/calendar.cjs.map +0 -1
- package/dist/components/ui/calendar.js +0 -174
- package/dist/components/ui/calendar.js.map +0 -1
- package/dist/components/ui/card.cjs +0 -2
- package/dist/components/ui/card.cjs.map +0 -1
- package/dist/components/ui/card.js +0 -102
- package/dist/components/ui/card.js.map +0 -1
- package/dist/components/ui/carousel.cjs +0 -2
- package/dist/components/ui/carousel.cjs.map +0 -1
- package/dist/components/ui/carousel.js +0 -179
- package/dist/components/ui/carousel.js.map +0 -1
- package/dist/components/ui/checkbox.cjs +0 -2
- package/dist/components/ui/checkbox.cjs.map +0 -1
- package/dist/components/ui/checkbox.js +0 -35
- package/dist/components/ui/checkbox.js.map +0 -1
- package/dist/components/ui/code-block.cjs +0 -4
- package/dist/components/ui/code-block.cjs.map +0 -1
- package/dist/components/ui/code-block.js +0 -306
- package/dist/components/ui/code-block.js.map +0 -1
- package/dist/components/ui/code-editor.cjs +0 -2
- package/dist/components/ui/code-editor.cjs.map +0 -1
- package/dist/components/ui/code-editor.js +0 -103
- package/dist/components/ui/code-editor.js.map +0 -1
- package/dist/components/ui/collapsible.cjs.map +0 -1
- package/dist/components/ui/collapsible.js.map +0 -1
- package/dist/components/ui/combobox.cjs +0 -2
- package/dist/components/ui/combobox.cjs.map +0 -1
- package/dist/components/ui/combobox.js +0 -281
- package/dist/components/ui/combobox.js.map +0 -1
- package/dist/components/ui/command.cjs +0 -2
- package/dist/components/ui/command.cjs.map +0 -1
- package/dist/components/ui/command.js +0 -174
- package/dist/components/ui/command.js.map +0 -1
- package/dist/components/ui/context-menu.cjs +0 -2
- package/dist/components/ui/context-menu.cjs.map +0 -1
- package/dist/components/ui/context-menu.js +0 -236
- package/dist/components/ui/context-menu.js.map +0 -1
- package/dist/components/ui/dialog.cjs +0 -2
- package/dist/components/ui/dialog.cjs.map +0 -1
- package/dist/components/ui/dialog.js +0 -165
- package/dist/components/ui/dialog.js.map +0 -1
- package/dist/components/ui/drawer.cjs +0 -2
- package/dist/components/ui/drawer.cjs.map +0 -1
- package/dist/components/ui/drawer.js +0 -125
- package/dist/components/ui/drawer.js.map +0 -1
- package/dist/components/ui/dropdown-menu.cjs +0 -2
- package/dist/components/ui/dropdown-menu.cjs.map +0 -1
- package/dist/components/ui/dropdown-menu.js +0 -252
- package/dist/components/ui/dropdown-menu.js.map +0 -1
- package/dist/components/ui/field.cjs +0 -2
- package/dist/components/ui/field.cjs.map +0 -1
- package/dist/components/ui/field.js +0 -210
- package/dist/components/ui/field.js.map +0 -1
- package/dist/components/ui/hover-card.cjs +0 -2
- package/dist/components/ui/hover-card.cjs.map +0 -1
- package/dist/components/ui/hover-card.js +0 -39
- package/dist/components/ui/hover-card.js.map +0 -1
- package/dist/components/ui/input-group.cjs +0 -2
- package/dist/components/ui/input-group.cjs.map +0 -1
- package/dist/components/ui/input-group.js +0 -145
- package/dist/components/ui/input-group.js.map +0 -1
- package/dist/components/ui/input-otp.cjs +0 -2
- package/dist/components/ui/input-otp.cjs.map +0 -1
- package/dist/components/ui/input-otp.js +0 -82
- package/dist/components/ui/input-otp.js.map +0 -1
- package/dist/components/ui/input.cjs +0 -2
- package/dist/components/ui/input.cjs.map +0 -1
- package/dist/components/ui/input.js +0 -20
- package/dist/components/ui/input.js.map +0 -1
- package/dist/components/ui/item.cjs +0 -2
- package/dist/components/ui/item.cjs.map +0 -1
- package/dist/components/ui/item.js +0 -191
- package/dist/components/ui/item.js.map +0 -1
- package/dist/components/ui/kbd.cjs +0 -2
- package/dist/components/ui/kbd.cjs.map +0 -1
- package/dist/components/ui/kbd.js +0 -30
- package/dist/components/ui/kbd.js.map +0 -1
- package/dist/components/ui/label.cjs +0 -2
- package/dist/components/ui/label.cjs.map +0 -1
- package/dist/components/ui/label.js +0 -23
- package/dist/components/ui/label.js.map +0 -1
- package/dist/components/ui/menubar.cjs +0 -2
- package/dist/components/ui/menubar.cjs.map +0 -1
- package/dist/components/ui/menubar.js +0 -256
- package/dist/components/ui/menubar.js.map +0 -1
- package/dist/components/ui/navigation-menu.cjs +0 -2
- package/dist/components/ui/navigation-menu.cjs.map +0 -1
- package/dist/components/ui/navigation-menu.js +0 -164
- package/dist/components/ui/navigation-menu.js.map +0 -1
- package/dist/components/ui/popover.cjs +0 -2
- package/dist/components/ui/popover.cjs.map +0 -1
- package/dist/components/ui/popover.js +0 -45
- package/dist/components/ui/popover.js.map +0 -1
- package/dist/components/ui/radio-group.cjs +0 -2
- package/dist/components/ui/radio-group.cjs.map +0 -1
- package/dist/components/ui/radio-group.js +0 -45
- package/dist/components/ui/radio-group.js.map +0 -1
- package/dist/components/ui/resizable.cjs +0 -2
- package/dist/components/ui/resizable.cjs.map +0 -1
- package/dist/components/ui/resizable.js +0 -58
- package/dist/components/ui/resizable.js.map +0 -1
- package/dist/components/ui/scroll-area.cjs +0 -2
- package/dist/components/ui/scroll-area.cjs.map +0 -1
- package/dist/components/ui/scroll-area.js +0 -60
- package/dist/components/ui/scroll-area.js.map +0 -1
- package/dist/components/ui/select.cjs +0 -2
- package/dist/components/ui/select.cjs.map +0 -1
- package/dist/components/ui/select.js +0 -184
- package/dist/components/ui/select.js.map +0 -1
- package/dist/components/ui/separator.cjs +0 -2
- package/dist/components/ui/separator.cjs.map +0 -1
- package/dist/components/ui/separator.js +0 -27
- package/dist/components/ui/separator.js.map +0 -1
- package/dist/components/ui/sheet.cjs +0 -2
- package/dist/components/ui/sheet.cjs.map +0 -1
- package/dist/components/ui/sheet.js +0 -137
- package/dist/components/ui/sheet.js.map +0 -1
- package/dist/components/ui/sidebar.cjs +0 -2
- package/dist/components/ui/sidebar.cjs.map +0 -1
- package/dist/components/ui/sidebar.js +0 -579
- package/dist/components/ui/sidebar.js.map +0 -1
- package/dist/components/ui/skeleton.cjs +0 -2
- package/dist/components/ui/skeleton.cjs.map +0 -1
- package/dist/components/ui/skeleton.js +0 -24
- package/dist/components/ui/skeleton.js.map +0 -1
- package/dist/components/ui/slider.cjs +0 -2
- package/dist/components/ui/slider.cjs.map +0 -1
- package/dist/components/ui/slider.js +0 -60
- package/dist/components/ui/slider.js.map +0 -1
- package/dist/components/ui/sonner.cjs +0 -2
- package/dist/components/ui/sonner.cjs.map +0 -1
- package/dist/components/ui/sonner.js +0 -37
- package/dist/components/ui/sonner.js.map +0 -1
- package/dist/components/ui/spinner.cjs +0 -2
- package/dist/components/ui/spinner.cjs.map +0 -1
- package/dist/components/ui/spinner.js +0 -39
- package/dist/components/ui/spinner.js.map +0 -1
- package/dist/components/ui/switch.cjs +0 -2
- package/dist/components/ui/switch.cjs.map +0 -1
- package/dist/components/ui/switch.js +0 -32
- package/dist/components/ui/switch.js.map +0 -1
- package/dist/components/ui/table.cjs +0 -2
- package/dist/components/ui/table.cjs.map +0 -1
- package/dist/components/ui/table.js +0 -152
- package/dist/components/ui/table.js.map +0 -1
- package/dist/components/ui/tabs.cjs +0 -2
- package/dist/components/ui/tabs.cjs.map +0 -1
- package/dist/components/ui/tabs.js +0 -92
- package/dist/components/ui/tabs.js.map +0 -1
- package/dist/components/ui/tetrascience-icon.cjs +0 -2
- package/dist/components/ui/tetrascience-icon.cjs.map +0 -1
- package/dist/components/ui/tetrascience-icon.js +0 -46
- package/dist/components/ui/tetrascience-icon.js.map +0 -1
- package/dist/components/ui/textarea.cjs +0 -2
- package/dist/components/ui/textarea.cjs.map +0 -1
- package/dist/components/ui/textarea.js +0 -19
- package/dist/components/ui/textarea.js.map +0 -1
- package/dist/components/ui/toggle-group.cjs +0 -2
- package/dist/components/ui/toggle-group.cjs.map +0 -1
- package/dist/components/ui/toggle-group.js +0 -77
- package/dist/components/ui/toggle-group.js.map +0 -1
- package/dist/components/ui/toggle.cjs +0 -2
- package/dist/components/ui/toggle.cjs.map +0 -1
- package/dist/components/ui/toggle.js +0 -44
- package/dist/components/ui/toggle.js.map +0 -1
- package/dist/components/ui/tooltip.cjs +0 -2
- package/dist/components/ui/tooltip.cjs.map +0 -1
- package/dist/components/ui/tooltip.js +0 -56
- package/dist/components/ui/tooltip.js.map +0 -1
- package/dist/databricks.d.ts +0 -129
- package/dist/providers/athena.d.ts +0 -9
- package/dist/providers/databricks.d.ts +0 -9
- package/dist/providers/snowflake.d.ts +0 -9
- package/dist/snowflake.d.ts +0 -125
- /package/dist/components/charts/{ChromatogramChart → Chromatogram}/peakDetection.cjs +0 -0
- /package/dist/components/charts/{ChromatogramChart → Chromatogram}/peakDetection.js +0 -0
- /package/dist/{components/composed → composed}/tdp-url.cjs +0 -0
- /package/dist/{components/composed → composed}/tdp-url.js +0 -0
- /package/dist/{components/ui → ui}/aspect-ratio.cjs +0 -0
- /package/dist/{components/ui → ui}/aspect-ratio.js +0 -0
- /package/dist/{components/ui → ui}/collapsible.cjs +0 -0
- /package/dist/{components/ui → ui}/collapsible.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JwtTokenManager.cjs","sources":["../../../src/server/auth/JwtTokenManager.ts"],"sourcesContent":["/**\n * JWT Token Manager for TetraScience Data Apps\n *\n * Handles authentication token retrieval from Express request cookies,\n * supporting both direct JWT tokens (ts-auth-token) and token references\n * (ts-token-ref) that are resolved via the connector K/V store.\n *\n * Note: This manager does not perform cryptographic verification of JWT signatures.\n * Signature verification is the responsibility of the consuming application or\n * the upstream authentication layer. The JWT payload is decoded only to read\n * expiration times for cache invalidation.\n */\n\nimport { TDPClient } from \"@tetrascience-npm/ts-connectors-sdk\";\n\n/** Configuration options for JwtTokenManager */\nexport interface JwtTokenManagerConfig {\n baseUrl?: string;\n tokenRefreshThresholdMs?: number;\n}\n\n/** Cookie dictionary type - matches Express req.cookies */\nexport interface CookieDict {\n [key: string]: string;\n}\n\n/** Express-like request interface (works with Express, Koa, etc.) */\nexport interface ExpressRequestLike {\n cookies?: CookieDict;\n}\n\n/** JWT payload structure */\ninterface JwtPayload {\n exp?: number;\n iat?: number;\n [key: string]: unknown;\n}\n\n/** Cached token entry storing both raw token and parsed payload */\ninterface CachedTokenEntry {\n token: string;\n payload: JwtPayload;\n}\n\n/** Number of seconds in a minute */\nconst SECONDS_PER_MINUTE = 60;\n/** Milliseconds per second */\nconst MS_PER_SECOND = 1000;\nconst DEFAULT_TOKEN_REFRESH_THRESHOLD_MS = 5 * SECONDS_PER_MINUTE * MS_PER_SECOND; // 5 minutes\n\n/**\n * Manages JWT token retrieval from request cookies.\n * Supports both ts-auth-token (direct JWT) and ts-token-ref (resolved via connector store).\n */\nexport class JwtTokenManager {\n private baseUrlOverride: string | undefined;\n private connectorId: string | undefined;\n private orgSlug: string | undefined;\n private tokenCache: Map<string, CachedTokenEntry>;\n private tokenRefreshThresholdMs: number;\n private tdpClient: TDPClient | null;\n\n constructor(config: JwtTokenManagerConfig = {}) {\n this.baseUrlOverride = config.baseUrl;\n this.connectorId = process.env.CONNECTOR_ID;\n this.orgSlug = process.env.ORG_SLUG;\n this.tokenCache = new Map();\n this.tokenRefreshThresholdMs = config.tokenRefreshThresholdMs || DEFAULT_TOKEN_REFRESH_THRESHOLD_MS;\n this.tdpClient = null;\n }\n\n /**\n * Get the base URL for TDP API calls.\n * Throws an error if not configured (either via config.baseUrl or TDP_ENDPOINT env var).\n */\n private getBaseUrl(): string {\n const baseUrl = this.baseUrlOverride || process.env.TDP_ENDPOINT;\n if (!baseUrl) {\n throw new Error(\"TDP base URL not configured. Set TDP_ENDPOINT environment variable or pass baseUrl in config.\");\n }\n return baseUrl;\n }\n\n /**\n * Decode JWT payload without verifying signature.\n * Used only for reading expiration times for cache invalidation.\n * Signature verification is NOT performed here.\n */\n private decodeJwtPayload(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n console.warn(\"Invalid JWT token format\");\n return null;\n }\n\n const payload = parts[1];\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const paddedBase64 = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n\n // Use Buffer.from for Node.js compatibility (atob not available in all runtimes)\n return JSON.parse(Buffer.from(paddedBase64, \"base64\").toString(\"utf-8\"));\n } catch (error) {\n console.warn(\"Error decoding JWT token:\", error);\n return null;\n }\n }\n\n /** Check if payload is expiring within the refresh threshold */\n private isPayloadExpiringSoon(payload: JwtPayload): boolean {\n if (!payload.exp) {\n console.warn(\"JWT token has no expiration claim\");\n return true;\n }\n\n const expiryTimeMs = payload.exp * MS_PER_SECOND;\n const refreshTimeMs = Date.now() + this.tokenRefreshThresholdMs;\n return expiryTimeMs <= refreshTimeMs;\n }\n\n /** Get valid cached token if not expiring */\n private getValidUserJwt(tokenRef: string): string | null {\n const cached = this.tokenCache.get(tokenRef);\n if (cached && !this.isPayloadExpiringSoon(cached.payload)) {\n return cached.token;\n }\n // Clean up expired entry to prevent unbounded cache growth\n if (cached) {\n // TODO: If data apps become high-traffic, consider enhancing with\n // an LRU cache (e.g., lru-cache package) to purge stale entries automatically\n this.tokenCache.delete(tokenRef);\n }\n return null;\n }\n\n /** Initialize or get TDP client */\n private async getTdpClient(): Promise<TDPClient> {\n if (this.tdpClient !== null) {\n return this.tdpClient;\n }\n\n if (!this.connectorId || !this.orgSlug) {\n throw new Error(\"Missing required configuration: CONNECTOR_ID or ORG_SLUG\");\n }\n\n // getBaseUrl() throws if TDP_ENDPOINT not configured - let it propagate\n const baseUrl = this.getBaseUrl();\n\n try {\n const client = new TDPClient({\n tdpEndpoint: baseUrl,\n connectorId: this.connectorId,\n orgSlug: this.orgSlug,\n artifactType: \"data-app\",\n });\n\n await client.init();\n // Only assign after successful initialization to allow retry on failure\n this.tdpClient = client;\n return this.tdpClient;\n } catch (error) {\n // Log init errors but rethrow so callers know something went wrong\n console.error(\"Failed to initialize TDP client:\", error);\n throw error;\n }\n }\n\n /** Retrieve JWT from connector K/V store using getValues (calls getConnectorData internally) */\n private async getJwtFromTokenRefInternal(tokenRef: string): Promise<string | null> {\n // getTdpClient() throws on config errors - let those propagate\n const tdpClient = await this.getTdpClient();\n\n try {\n // getValues returns array of values for the given keys\n // Each value is expected to have a jwt property: { jwt: \"...\" }\n const values = await tdpClient.getValues([tokenRef]);\n\n if (values && values.length > 0 && values[0]?.jwt) {\n const jwtToken = values[0].jwt;\n // Parse and cache both the raw token and its payload to avoid repeated decoding\n const payload = this.decodeJwtPayload(jwtToken);\n if (payload) {\n this.tokenCache.set(tokenRef, { token: jwtToken, payload });\n }\n return jwtToken;\n }\n\n console.error(`No JWT found for key '${tokenRef}' in connector store`);\n } catch (error) {\n console.error(\"Error retrieving JWT token:\", error);\n }\n\n return null;\n }\n\n /** Resolve ts-token-ref to full JWT token (with caching) */\n async getJwtFromTokenRef(tokenRef: string): Promise<string | null> {\n if (!tokenRef || !this.orgSlug) {\n console.warn(\"Missing required parameters for JWT token retrieval\");\n return null;\n }\n\n const cachedUserToken = this.getValidUserJwt(tokenRef);\n if (cachedUserToken) {\n return cachedUserToken;\n }\n\n return this.getJwtFromTokenRefInternal(tokenRef);\n }\n\n /** Get token from cookies (ts-auth-token or resolved ts-token-ref) */\n async getUserToken(cookies: CookieDict): Promise<string | null> {\n // Prefer ts-auth-token or TS_AUTH_TOKEN env var (latter is for local dev testing)\n const authToken = cookies[\"ts-auth-token\"] || process.env.TS_AUTH_TOKEN;\n if (authToken) {\n return authToken;\n }\n\n // Try to resolve ts-token-ref\n const tokenRef = cookies[\"ts-token-ref\"];\n if (tokenRef && this.connectorId) {\n const jwtToken = await this.getJwtFromTokenRef(tokenRef);\n if (jwtToken) {\n return jwtToken;\n }\n console.warn(\"Failed to resolve ts-token-ref to JWT token\");\n } else if (tokenRef) {\n console.error(\"Connector ID not configured\");\n }\n\n console.warn(\"No valid authentication token found\");\n return null;\n }\n\n /**\n * Get user token from an Express request object.\n * This is the primary method for Express middleware integration.\n *\n * @example\n * ```typescript\n * import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';\n *\n * app.use(async (req, res, next) => {\n * const token = await jwtManager.getTokenFromExpressRequest(req);\n * req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };\n * next();\n * });\n * ```\n */\n async getTokenFromExpressRequest(req: ExpressRequestLike): Promise<string | null> {\n // Handle missing cookies gracefully (e.g., if cookie-parser middleware not installed)\n return this.getUserToken(req.cookies || {});\n }\n\n /** Clear the token cache */\n clearCache(): void {\n this.tokenCache.clear();\n }\n}\n\n/**\n * Global singleton instance.\n *\n * Note: This instance is created when the module is imported. Configuration\n * that depends on environment variables (CONNECTOR_ID, ORG_SLUG, TDP_ENDPOINT)\n * is read at module load time. Ensure these environment\n * variables are set before importing this module.\n *\n * If you need different configuration at runtime, create a new JwtTokenManager\n * instance instead of using this singleton.\n */\nexport const jwtManager = new JwtTokenManager();\n"],"names":["SECONDS_PER_MINUTE","MS_PER_SECOND","DEFAULT_TOKEN_REFRESH_THRESHOLD_MS","JwtTokenManager","config","baseUrl","token","parts","base64","paddedBase64","error","payload","expiryTimeMs","refreshTimeMs","tokenRef","cached","client","TDPClient","tdpClient","values","jwtToken","cachedUserToken","cookies","authToken","req","jwtManager"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"JwtTokenManager.cjs","sources":["../../../src/server/auth/JwtTokenManager.ts"],"sourcesContent":["/**\n * JWT Token Manager for TetraScience Data Apps\n *\n * Handles authentication token retrieval from Express request cookies,\n * supporting both direct JWT tokens (ts-auth-token) and token references\n * (ts-token-ref) that are resolved via the connector K/V store.\n *\n * Note: This manager does not perform cryptographic verification of JWT signatures.\n * Signature verification is the responsibility of the consuming application or\n * the upstream authentication layer. The JWT payload is decoded only to read\n * expiration times for cache invalidation.\n */\n\nimport { TDPClient } from \"@tetrascience-npm/ts-connectors-sdk\";\n\n/** Configuration options for JwtTokenManager */\nexport interface JwtTokenManagerConfig {\n baseUrl?: string;\n tokenRefreshThresholdMs?: number;\n}\n\n/** Cookie dictionary type - matches Express req.cookies */\nexport interface CookieDict {\n [key: string]: string;\n}\n\n/** Header dictionary type - matches Express req.headers (keys are lowercased) */\nexport interface HeaderDict {\n [key: string]: string | string[] | undefined;\n}\n\n/** Express-like request interface (works with Express, Koa, etc.) */\nexport interface ExpressRequestLike {\n cookies?: CookieDict;\n headers?: HeaderDict;\n}\n\n/** Request header carrying the resolved JWT injected by the data-apps proxy. */\nconst AUTH_TOKEN_HEADER = \"ts-auth-token\";\n\n/** JWT payload structure */\ninterface JwtPayload {\n exp?: number;\n iat?: number;\n [key: string]: unknown;\n}\n\n/** Cached token entry storing both raw token and parsed payload */\ninterface CachedTokenEntry {\n token: string;\n payload: JwtPayload;\n}\n\n/** Number of seconds in a minute */\nconst SECONDS_PER_MINUTE = 60;\n/** Milliseconds per second */\nconst MS_PER_SECOND = 1000;\nconst DEFAULT_TOKEN_REFRESH_THRESHOLD_MS = 5 * SECONDS_PER_MINUTE * MS_PER_SECOND; // 5 minutes\n\n/**\n * Manages JWT token retrieval from request cookies.\n * Supports both ts-auth-token (direct JWT) and ts-token-ref (resolved via connector store).\n */\nexport class JwtTokenManager {\n private baseUrlOverride: string | undefined;\n private connectorId: string | undefined;\n private orgSlug: string | undefined;\n private tokenCache: Map<string, CachedTokenEntry>;\n private tokenRefreshThresholdMs: number;\n private tdpClient: TDPClient | null;\n\n constructor(config: JwtTokenManagerConfig = {}) {\n this.baseUrlOverride = config.baseUrl;\n this.connectorId = process.env.CONNECTOR_ID;\n this.orgSlug = process.env.ORG_SLUG;\n this.tokenCache = new Map();\n this.tokenRefreshThresholdMs = config.tokenRefreshThresholdMs || DEFAULT_TOKEN_REFRESH_THRESHOLD_MS;\n this.tdpClient = null;\n }\n\n /**\n * Get the base URL for TDP API calls.\n * Throws an error if not configured (either via config.baseUrl or TDP_ENDPOINT env var).\n */\n private getBaseUrl(): string {\n const baseUrl = this.baseUrlOverride || process.env.TDP_ENDPOINT;\n if (!baseUrl) {\n throw new Error(\"TDP base URL not configured. Set TDP_ENDPOINT environment variable or pass baseUrl in config.\");\n }\n return baseUrl;\n }\n\n /**\n * Decode JWT payload without verifying signature.\n * Used only for reading expiration times for cache invalidation.\n * Signature verification is NOT performed here.\n */\n private decodeJwtPayload(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n console.warn(\"Invalid JWT token format\");\n return null;\n }\n\n const payload = parts[1];\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const paddedBase64 = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n\n // Use Buffer.from for Node.js compatibility (atob not available in all runtimes)\n return JSON.parse(Buffer.from(paddedBase64, \"base64\").toString(\"utf-8\"));\n } catch (error) {\n console.warn(\"Error decoding JWT token:\", error);\n return null;\n }\n }\n\n /** Check if payload is expiring within the refresh threshold */\n private isPayloadExpiringSoon(payload: JwtPayload): boolean {\n if (!payload.exp) {\n console.warn(\"JWT token has no expiration claim\");\n return true;\n }\n\n const expiryTimeMs = payload.exp * MS_PER_SECOND;\n const refreshTimeMs = Date.now() + this.tokenRefreshThresholdMs;\n return expiryTimeMs <= refreshTimeMs;\n }\n\n /** Get valid cached token if not expiring */\n private getValidUserJwt(tokenRef: string): string | null {\n const cached = this.tokenCache.get(tokenRef);\n if (cached && !this.isPayloadExpiringSoon(cached.payload)) {\n return cached.token;\n }\n // Clean up expired entry to prevent unbounded cache growth\n if (cached) {\n // TODO: If data apps become high-traffic, consider enhancing with\n // an LRU cache (e.g., lru-cache package) to purge stale entries automatically\n this.tokenCache.delete(tokenRef);\n }\n return null;\n }\n\n /** Initialize or get TDP client */\n private async getTdpClient(): Promise<TDPClient> {\n if (this.tdpClient !== null) {\n return this.tdpClient;\n }\n\n if (!this.connectorId || !this.orgSlug) {\n throw new Error(\"Missing required configuration: CONNECTOR_ID or ORG_SLUG\");\n }\n\n // getBaseUrl() throws if TDP_ENDPOINT not configured - let it propagate\n const baseUrl = this.getBaseUrl();\n\n try {\n const client = new TDPClient({\n tdpEndpoint: baseUrl,\n connectorId: this.connectorId,\n orgSlug: this.orgSlug,\n artifactType: \"data-app\",\n });\n\n await client.init();\n // Only assign after successful initialization to allow retry on failure\n this.tdpClient = client;\n return this.tdpClient;\n } catch (error) {\n // Log init errors but rethrow so callers know something went wrong\n console.error(\"Failed to initialize TDP client:\", error);\n throw error;\n }\n }\n\n /** Retrieve JWT from connector K/V store using getValues (calls getConnectorData internally) */\n private async getJwtFromTokenRefInternal(tokenRef: string): Promise<string | null> {\n // getTdpClient() throws on config errors - let those propagate\n const tdpClient = await this.getTdpClient();\n\n try {\n // getValues returns array of values for the given keys\n // Each value is expected to have a jwt property: { jwt: \"...\" }\n const values = await tdpClient.getValues([tokenRef]);\n\n if (values && values.length > 0 && values[0]?.jwt) {\n const jwtToken = values[0].jwt;\n // Parse and cache both the raw token and its payload to avoid repeated decoding\n const payload = this.decodeJwtPayload(jwtToken);\n if (payload) {\n this.tokenCache.set(tokenRef, { token: jwtToken, payload });\n }\n return jwtToken;\n }\n\n console.error(`No JWT found for key '${tokenRef}' in connector store`);\n } catch (error) {\n console.error(\"Error retrieving JWT token:\", error);\n }\n\n return null;\n }\n\n /** Resolve ts-token-ref to full JWT token (with caching) */\n async getJwtFromTokenRef(tokenRef: string): Promise<string | null> {\n if (!tokenRef || !this.orgSlug) {\n console.warn(\"Missing required parameters for JWT token retrieval\");\n return null;\n }\n\n const cachedUserToken = this.getValidUserJwt(tokenRef);\n if (cachedUserToken) {\n return cachedUserToken;\n }\n\n return this.getJwtFromTokenRefInternal(tokenRef);\n }\n\n /**\n * Read the ts-auth-token request header, normalizing the array form that\n * Node/Express may produce for a repeated header.\n */\n private getHeaderAuthToken(headers?: HeaderDict): string | null {\n const raw = headers?.[AUTH_TOKEN_HEADER];\n const value = Array.isArray(raw) ? raw[0] : raw;\n return value || null;\n }\n\n /**\n * Get token from a request (proxy-injected header, then cookie, then token ref).\n *\n * Precedence (SW-2352):\n * 1. `ts-auth-token` request header — for large-JWT sessions the data-apps\n * proxy resolves the token reference server-side and injects the real JWT\n * here; the `ts-token-ref` cookie is no longer forwarded to the container.\n * Checking the header first is also what keeps SSO users authenticated.\n * 2. `ts-auth-token` cookie / `TS_AUTH_TOKEN` env var (small-JWT + local dev).\n * 3. `ts-token-ref` cookie → connector K/V resolution (legacy fallback; goes\n * dead in prod once the proxy stops forwarding the cookie, retained for\n * local dev and defense in depth).\n */\n async getUserToken(cookies: CookieDict, headers?: HeaderDict): Promise<string | null> {\n // Prefer the proxy-injected ts-auth-token request header.\n const headerAuthToken = this.getHeaderAuthToken(headers);\n if (headerAuthToken) {\n return headerAuthToken;\n }\n\n // Then ts-auth-token cookie or TS_AUTH_TOKEN env var (latter is for local dev testing)\n const authToken = cookies[\"ts-auth-token\"] || process.env.TS_AUTH_TOKEN;\n if (authToken) {\n return authToken;\n }\n\n // Try to resolve ts-token-ref (legacy fallback).\n // TODO(next major): drop the ts-token-ref → connector-KV resolution entirely.\n // As of SW-2352 the data-apps proxy resolves the reference server-side and\n // injects the JWT via the ts-auth-token header (preferred above), and no\n // longer forwards the ts-token-ref cookie to the container — so this path is\n // dead in production and kept only for local dev / older proxies.\n const tokenRef = cookies[\"ts-token-ref\"];\n if (tokenRef && this.connectorId) {\n const jwtToken = await this.getJwtFromTokenRef(tokenRef);\n if (jwtToken) {\n return jwtToken;\n }\n console.warn(\"Failed to resolve ts-token-ref to JWT token\");\n } else if (tokenRef) {\n console.error(\"Connector ID not configured\");\n }\n\n console.warn(\"No valid authentication token found\");\n return null;\n }\n\n /**\n * Get user token from an Express request object.\n * This is the primary method for Express middleware integration.\n *\n * @example\n * ```typescript\n * import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';\n *\n * app.use(async (req, res, next) => {\n * const token = await jwtManager.getTokenFromExpressRequest(req);\n * req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };\n * next();\n * });\n * ```\n */\n async getTokenFromExpressRequest(req: ExpressRequestLike): Promise<string | null> {\n // Handle missing cookies gracefully (e.g., if cookie-parser middleware not installed).\n // Headers are checked first (proxy-injected ts-auth-token) — see getUserToken.\n return this.getUserToken(req.cookies || {}, req.headers);\n }\n\n /** Clear the token cache */\n clearCache(): void {\n this.tokenCache.clear();\n }\n}\n\n/**\n * Global singleton instance.\n *\n * Note: This instance is created when the module is imported. Configuration\n * that depends on environment variables (CONNECTOR_ID, ORG_SLUG, TDP_ENDPOINT)\n * is read at module load time. Ensure these environment\n * variables are set before importing this module.\n *\n * If you need different configuration at runtime, create a new JwtTokenManager\n * instance instead of using this singleton.\n */\nexport const jwtManager = new JwtTokenManager();\n"],"names":["AUTH_TOKEN_HEADER","SECONDS_PER_MINUTE","MS_PER_SECOND","DEFAULT_TOKEN_REFRESH_THRESHOLD_MS","JwtTokenManager","config","baseUrl","token","parts","base64","paddedBase64","error","payload","expiryTimeMs","refreshTimeMs","tokenRef","cached","client","TDPClient","tdpClient","values","jwtToken","cachedUserToken","headers","raw","cookies","headerAuthToken","authToken","req","jwtManager"],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT Token Manager for TetraScience Data Apps
|
|
3
|
+
*
|
|
4
|
+
* Handles authentication token retrieval from Express request cookies,
|
|
5
|
+
* supporting both direct JWT tokens (ts-auth-token) and token references
|
|
6
|
+
* (ts-token-ref) that are resolved via the connector K/V store.
|
|
7
|
+
*
|
|
8
|
+
* Note: This manager does not perform cryptographic verification of JWT signatures.
|
|
9
|
+
* Signature verification is the responsibility of the consuming application or
|
|
10
|
+
* the upstream authentication layer. The JWT payload is decoded only to read
|
|
11
|
+
* expiration times for cache invalidation.
|
|
12
|
+
*/
|
|
13
|
+
/** Configuration options for JwtTokenManager */
|
|
14
|
+
export interface JwtTokenManagerConfig {
|
|
15
|
+
baseUrl?: string;
|
|
16
|
+
tokenRefreshThresholdMs?: number;
|
|
17
|
+
}
|
|
18
|
+
/** Cookie dictionary type - matches Express req.cookies */
|
|
19
|
+
export interface CookieDict {
|
|
20
|
+
[key: string]: string;
|
|
21
|
+
}
|
|
22
|
+
/** Header dictionary type - matches Express req.headers (keys are lowercased) */
|
|
23
|
+
export interface HeaderDict {
|
|
24
|
+
[key: string]: string | string[] | undefined;
|
|
25
|
+
}
|
|
26
|
+
/** Express-like request interface (works with Express, Koa, etc.) */
|
|
27
|
+
export interface ExpressRequestLike {
|
|
28
|
+
cookies?: CookieDict;
|
|
29
|
+
headers?: HeaderDict;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Manages JWT token retrieval from request cookies.
|
|
33
|
+
* Supports both ts-auth-token (direct JWT) and ts-token-ref (resolved via connector store).
|
|
34
|
+
*/
|
|
35
|
+
export declare class JwtTokenManager {
|
|
36
|
+
private baseUrlOverride;
|
|
37
|
+
private connectorId;
|
|
38
|
+
private orgSlug;
|
|
39
|
+
private tokenCache;
|
|
40
|
+
private tokenRefreshThresholdMs;
|
|
41
|
+
private tdpClient;
|
|
42
|
+
constructor(config?: JwtTokenManagerConfig);
|
|
43
|
+
/**
|
|
44
|
+
* Get the base URL for TDP API calls.
|
|
45
|
+
* Throws an error if not configured (either via config.baseUrl or TDP_ENDPOINT env var).
|
|
46
|
+
*/
|
|
47
|
+
private getBaseUrl;
|
|
48
|
+
/**
|
|
49
|
+
* Decode JWT payload without verifying signature.
|
|
50
|
+
* Used only for reading expiration times for cache invalidation.
|
|
51
|
+
* Signature verification is NOT performed here.
|
|
52
|
+
*/
|
|
53
|
+
private decodeJwtPayload;
|
|
54
|
+
/** Check if payload is expiring within the refresh threshold */
|
|
55
|
+
private isPayloadExpiringSoon;
|
|
56
|
+
/** Get valid cached token if not expiring */
|
|
57
|
+
private getValidUserJwt;
|
|
58
|
+
/** Initialize or get TDP client */
|
|
59
|
+
private getTdpClient;
|
|
60
|
+
/** Retrieve JWT from connector K/V store using getValues (calls getConnectorData internally) */
|
|
61
|
+
private getJwtFromTokenRefInternal;
|
|
62
|
+
/** Resolve ts-token-ref to full JWT token (with caching) */
|
|
63
|
+
getJwtFromTokenRef(tokenRef: string): Promise<string | null>;
|
|
64
|
+
/**
|
|
65
|
+
* Read the ts-auth-token request header, normalizing the array form that
|
|
66
|
+
* Node/Express may produce for a repeated header.
|
|
67
|
+
*/
|
|
68
|
+
private getHeaderAuthToken;
|
|
69
|
+
/**
|
|
70
|
+
* Get token from a request (proxy-injected header, then cookie, then token ref).
|
|
71
|
+
*
|
|
72
|
+
* Precedence (SW-2352):
|
|
73
|
+
* 1. `ts-auth-token` request header — for large-JWT sessions the data-apps
|
|
74
|
+
* proxy resolves the token reference server-side and injects the real JWT
|
|
75
|
+
* here; the `ts-token-ref` cookie is no longer forwarded to the container.
|
|
76
|
+
* Checking the header first is also what keeps SSO users authenticated.
|
|
77
|
+
* 2. `ts-auth-token` cookie / `TS_AUTH_TOKEN` env var (small-JWT + local dev).
|
|
78
|
+
* 3. `ts-token-ref` cookie → connector K/V resolution (legacy fallback; goes
|
|
79
|
+
* dead in prod once the proxy stops forwarding the cookie, retained for
|
|
80
|
+
* local dev and defense in depth).
|
|
81
|
+
*/
|
|
82
|
+
getUserToken(cookies: CookieDict, headers?: HeaderDict): Promise<string | null>;
|
|
83
|
+
/**
|
|
84
|
+
* Get user token from an Express request object.
|
|
85
|
+
* This is the primary method for Express middleware integration.
|
|
86
|
+
*
|
|
87
|
+
* @example
|
|
88
|
+
* ```typescript
|
|
89
|
+
* import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';
|
|
90
|
+
*
|
|
91
|
+
* app.use(async (req, res, next) => {
|
|
92
|
+
* const token = await jwtManager.getTokenFromExpressRequest(req);
|
|
93
|
+
* req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };
|
|
94
|
+
* next();
|
|
95
|
+
* });
|
|
96
|
+
* ```
|
|
97
|
+
*/
|
|
98
|
+
getTokenFromExpressRequest(req: ExpressRequestLike): Promise<string | null>;
|
|
99
|
+
/** Clear the token cache */
|
|
100
|
+
clearCache(): void;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Global singleton instance.
|
|
104
|
+
*
|
|
105
|
+
* Note: This instance is created when the module is imported. Configuration
|
|
106
|
+
* that depends on environment variables (CONNECTOR_ID, ORG_SLUG, TDP_ENDPOINT)
|
|
107
|
+
* is read at module load time. Ensure these environment
|
|
108
|
+
* variables are set before importing this module.
|
|
109
|
+
*
|
|
110
|
+
* If you need different configuration at runtime, create a new JwtTokenManager
|
|
111
|
+
* instance instead of using this singleton.
|
|
112
|
+
*/
|
|
113
|
+
export declare const jwtManager: JwtTokenManager;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { TDPClient as
|
|
2
|
-
const
|
|
3
|
-
class
|
|
1
|
+
import { TDPClient as a } from "@tetrascience-npm/ts-connectors-sdk";
|
|
2
|
+
const c = "ts-auth-token", l = 60, i = 1e3, h = 5 * l * i;
|
|
3
|
+
class d {
|
|
4
4
|
baseUrlOverride;
|
|
5
5
|
connectorId;
|
|
6
6
|
orgSlug;
|
|
@@ -8,7 +8,7 @@ class l {
|
|
|
8
8
|
tokenRefreshThresholdMs;
|
|
9
9
|
tdpClient;
|
|
10
10
|
constructor(e = {}) {
|
|
11
|
-
this.baseUrlOverride = e.baseUrl, this.connectorId = process.env.CONNECTOR_ID, this.orgSlug = process.env.ORG_SLUG, this.tokenCache = /* @__PURE__ */ new Map(), this.tokenRefreshThresholdMs = e.tokenRefreshThresholdMs ||
|
|
11
|
+
this.baseUrlOverride = e.baseUrl, this.connectorId = process.env.CONNECTOR_ID, this.orgSlug = process.env.ORG_SLUG, this.tokenCache = /* @__PURE__ */ new Map(), this.tokenRefreshThresholdMs = e.tokenRefreshThresholdMs || h, this.tdpClient = null;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
14
|
* Get the base URL for TDP API calls.
|
|
@@ -40,7 +40,7 @@ class l {
|
|
|
40
40
|
isPayloadExpiringSoon(e) {
|
|
41
41
|
if (!e.exp)
|
|
42
42
|
return console.warn("JWT token has no expiration claim"), !0;
|
|
43
|
-
const t = e.exp *
|
|
43
|
+
const t = e.exp * i, r = Date.now() + this.tokenRefreshThresholdMs;
|
|
44
44
|
return t <= r;
|
|
45
45
|
}
|
|
46
46
|
/** Get valid cached token if not expiring */
|
|
@@ -56,7 +56,7 @@ class l {
|
|
|
56
56
|
throw new Error("Missing required configuration: CONNECTOR_ID or ORG_SLUG");
|
|
57
57
|
const e = this.getBaseUrl();
|
|
58
58
|
try {
|
|
59
|
-
const t = new
|
|
59
|
+
const t = new a({
|
|
60
60
|
tdpEndpoint: e,
|
|
61
61
|
connectorId: this.connectorId,
|
|
62
62
|
orgSlug: this.orgSlug,
|
|
@@ -89,18 +89,41 @@ class l {
|
|
|
89
89
|
const t = this.getValidUserJwt(e);
|
|
90
90
|
return t || this.getJwtFromTokenRefInternal(e);
|
|
91
91
|
}
|
|
92
|
-
/**
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
92
|
+
/**
|
|
93
|
+
* Read the ts-auth-token request header, normalizing the array form that
|
|
94
|
+
* Node/Express may produce for a repeated header.
|
|
95
|
+
*/
|
|
96
|
+
getHeaderAuthToken(e) {
|
|
97
|
+
const t = e?.[c];
|
|
98
|
+
return (Array.isArray(t) ? t[0] : t) || null;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Get token from a request (proxy-injected header, then cookie, then token ref).
|
|
102
|
+
*
|
|
103
|
+
* Precedence (SW-2352):
|
|
104
|
+
* 1. `ts-auth-token` request header — for large-JWT sessions the data-apps
|
|
105
|
+
* proxy resolves the token reference server-side and injects the real JWT
|
|
106
|
+
* here; the `ts-token-ref` cookie is no longer forwarded to the container.
|
|
107
|
+
* Checking the header first is also what keeps SSO users authenticated.
|
|
108
|
+
* 2. `ts-auth-token` cookie / `TS_AUTH_TOKEN` env var (small-JWT + local dev).
|
|
109
|
+
* 3. `ts-token-ref` cookie → connector K/V resolution (legacy fallback; goes
|
|
110
|
+
* dead in prod once the proxy stops forwarding the cookie, retained for
|
|
111
|
+
* local dev and defense in depth).
|
|
112
|
+
*/
|
|
113
|
+
async getUserToken(e, t) {
|
|
114
|
+
const r = this.getHeaderAuthToken(t);
|
|
115
|
+
if (r)
|
|
116
|
+
return r;
|
|
117
|
+
const n = e["ts-auth-token"] || process.env.TS_AUTH_TOKEN;
|
|
118
|
+
if (n)
|
|
119
|
+
return n;
|
|
120
|
+
const o = e["ts-token-ref"];
|
|
121
|
+
if (o && this.connectorId) {
|
|
122
|
+
const s = await this.getJwtFromTokenRef(o);
|
|
123
|
+
if (s)
|
|
124
|
+
return s;
|
|
102
125
|
console.warn("Failed to resolve ts-token-ref to JWT token");
|
|
103
|
-
} else
|
|
126
|
+
} else o && console.error("Connector ID not configured");
|
|
104
127
|
return console.warn("No valid authentication token found"), null;
|
|
105
128
|
}
|
|
106
129
|
/**
|
|
@@ -119,16 +142,16 @@ class l {
|
|
|
119
142
|
* ```
|
|
120
143
|
*/
|
|
121
144
|
async getTokenFromExpressRequest(e) {
|
|
122
|
-
return this.getUserToken(e.cookies || {});
|
|
145
|
+
return this.getUserToken(e.cookies || {}, e.headers);
|
|
123
146
|
}
|
|
124
147
|
/** Clear the token cache */
|
|
125
148
|
clearCache() {
|
|
126
149
|
this.tokenCache.clear();
|
|
127
150
|
}
|
|
128
151
|
}
|
|
129
|
-
const
|
|
152
|
+
const g = new d();
|
|
130
153
|
export {
|
|
131
|
-
|
|
132
|
-
|
|
154
|
+
d as JwtTokenManager,
|
|
155
|
+
g as jwtManager
|
|
133
156
|
};
|
|
134
157
|
//# sourceMappingURL=JwtTokenManager.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"JwtTokenManager.js","sources":["../../../src/server/auth/JwtTokenManager.ts"],"sourcesContent":["/**\n * JWT Token Manager for TetraScience Data Apps\n *\n * Handles authentication token retrieval from Express request cookies,\n * supporting both direct JWT tokens (ts-auth-token) and token references\n * (ts-token-ref) that are resolved via the connector K/V store.\n *\n * Note: This manager does not perform cryptographic verification of JWT signatures.\n * Signature verification is the responsibility of the consuming application or\n * the upstream authentication layer. The JWT payload is decoded only to read\n * expiration times for cache invalidation.\n */\n\nimport { TDPClient } from \"@tetrascience-npm/ts-connectors-sdk\";\n\n/** Configuration options for JwtTokenManager */\nexport interface JwtTokenManagerConfig {\n baseUrl?: string;\n tokenRefreshThresholdMs?: number;\n}\n\n/** Cookie dictionary type - matches Express req.cookies */\nexport interface CookieDict {\n [key: string]: string;\n}\n\n/** Express-like request interface (works with Express, Koa, etc.) */\nexport interface ExpressRequestLike {\n cookies?: CookieDict;\n}\n\n/** JWT payload structure */\ninterface JwtPayload {\n exp?: number;\n iat?: number;\n [key: string]: unknown;\n}\n\n/** Cached token entry storing both raw token and parsed payload */\ninterface CachedTokenEntry {\n token: string;\n payload: JwtPayload;\n}\n\n/** Number of seconds in a minute */\nconst SECONDS_PER_MINUTE = 60;\n/** Milliseconds per second */\nconst MS_PER_SECOND = 1000;\nconst DEFAULT_TOKEN_REFRESH_THRESHOLD_MS = 5 * SECONDS_PER_MINUTE * MS_PER_SECOND; // 5 minutes\n\n/**\n * Manages JWT token retrieval from request cookies.\n * Supports both ts-auth-token (direct JWT) and ts-token-ref (resolved via connector store).\n */\nexport class JwtTokenManager {\n private baseUrlOverride: string | undefined;\n private connectorId: string | undefined;\n private orgSlug: string | undefined;\n private tokenCache: Map<string, CachedTokenEntry>;\n private tokenRefreshThresholdMs: number;\n private tdpClient: TDPClient | null;\n\n constructor(config: JwtTokenManagerConfig = {}) {\n this.baseUrlOverride = config.baseUrl;\n this.connectorId = process.env.CONNECTOR_ID;\n this.orgSlug = process.env.ORG_SLUG;\n this.tokenCache = new Map();\n this.tokenRefreshThresholdMs = config.tokenRefreshThresholdMs || DEFAULT_TOKEN_REFRESH_THRESHOLD_MS;\n this.tdpClient = null;\n }\n\n /**\n * Get the base URL for TDP API calls.\n * Throws an error if not configured (either via config.baseUrl or TDP_ENDPOINT env var).\n */\n private getBaseUrl(): string {\n const baseUrl = this.baseUrlOverride || process.env.TDP_ENDPOINT;\n if (!baseUrl) {\n throw new Error(\"TDP base URL not configured. Set TDP_ENDPOINT environment variable or pass baseUrl in config.\");\n }\n return baseUrl;\n }\n\n /**\n * Decode JWT payload without verifying signature.\n * Used only for reading expiration times for cache invalidation.\n * Signature verification is NOT performed here.\n */\n private decodeJwtPayload(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n console.warn(\"Invalid JWT token format\");\n return null;\n }\n\n const payload = parts[1];\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const paddedBase64 = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n\n // Use Buffer.from for Node.js compatibility (atob not available in all runtimes)\n return JSON.parse(Buffer.from(paddedBase64, \"base64\").toString(\"utf-8\"));\n } catch (error) {\n console.warn(\"Error decoding JWT token:\", error);\n return null;\n }\n }\n\n /** Check if payload is expiring within the refresh threshold */\n private isPayloadExpiringSoon(payload: JwtPayload): boolean {\n if (!payload.exp) {\n console.warn(\"JWT token has no expiration claim\");\n return true;\n }\n\n const expiryTimeMs = payload.exp * MS_PER_SECOND;\n const refreshTimeMs = Date.now() + this.tokenRefreshThresholdMs;\n return expiryTimeMs <= refreshTimeMs;\n }\n\n /** Get valid cached token if not expiring */\n private getValidUserJwt(tokenRef: string): string | null {\n const cached = this.tokenCache.get(tokenRef);\n if (cached && !this.isPayloadExpiringSoon(cached.payload)) {\n return cached.token;\n }\n // Clean up expired entry to prevent unbounded cache growth\n if (cached) {\n // TODO: If data apps become high-traffic, consider enhancing with\n // an LRU cache (e.g., lru-cache package) to purge stale entries automatically\n this.tokenCache.delete(tokenRef);\n }\n return null;\n }\n\n /** Initialize or get TDP client */\n private async getTdpClient(): Promise<TDPClient> {\n if (this.tdpClient !== null) {\n return this.tdpClient;\n }\n\n if (!this.connectorId || !this.orgSlug) {\n throw new Error(\"Missing required configuration: CONNECTOR_ID or ORG_SLUG\");\n }\n\n // getBaseUrl() throws if TDP_ENDPOINT not configured - let it propagate\n const baseUrl = this.getBaseUrl();\n\n try {\n const client = new TDPClient({\n tdpEndpoint: baseUrl,\n connectorId: this.connectorId,\n orgSlug: this.orgSlug,\n artifactType: \"data-app\",\n });\n\n await client.init();\n // Only assign after successful initialization to allow retry on failure\n this.tdpClient = client;\n return this.tdpClient;\n } catch (error) {\n // Log init errors but rethrow so callers know something went wrong\n console.error(\"Failed to initialize TDP client:\", error);\n throw error;\n }\n }\n\n /** Retrieve JWT from connector K/V store using getValues (calls getConnectorData internally) */\n private async getJwtFromTokenRefInternal(tokenRef: string): Promise<string | null> {\n // getTdpClient() throws on config errors - let those propagate\n const tdpClient = await this.getTdpClient();\n\n try {\n // getValues returns array of values for the given keys\n // Each value is expected to have a jwt property: { jwt: \"...\" }\n const values = await tdpClient.getValues([tokenRef]);\n\n if (values && values.length > 0 && values[0]?.jwt) {\n const jwtToken = values[0].jwt;\n // Parse and cache both the raw token and its payload to avoid repeated decoding\n const payload = this.decodeJwtPayload(jwtToken);\n if (payload) {\n this.tokenCache.set(tokenRef, { token: jwtToken, payload });\n }\n return jwtToken;\n }\n\n console.error(`No JWT found for key '${tokenRef}' in connector store`);\n } catch (error) {\n console.error(\"Error retrieving JWT token:\", error);\n }\n\n return null;\n }\n\n /** Resolve ts-token-ref to full JWT token (with caching) */\n async getJwtFromTokenRef(tokenRef: string): Promise<string | null> {\n if (!tokenRef || !this.orgSlug) {\n console.warn(\"Missing required parameters for JWT token retrieval\");\n return null;\n }\n\n const cachedUserToken = this.getValidUserJwt(tokenRef);\n if (cachedUserToken) {\n return cachedUserToken;\n }\n\n return this.getJwtFromTokenRefInternal(tokenRef);\n }\n\n /** Get token from cookies (ts-auth-token or resolved ts-token-ref) */\n async getUserToken(cookies: CookieDict): Promise<string | null> {\n // Prefer ts-auth-token or TS_AUTH_TOKEN env var (latter is for local dev testing)\n const authToken = cookies[\"ts-auth-token\"] || process.env.TS_AUTH_TOKEN;\n if (authToken) {\n return authToken;\n }\n\n // Try to resolve ts-token-ref\n const tokenRef = cookies[\"ts-token-ref\"];\n if (tokenRef && this.connectorId) {\n const jwtToken = await this.getJwtFromTokenRef(tokenRef);\n if (jwtToken) {\n return jwtToken;\n }\n console.warn(\"Failed to resolve ts-token-ref to JWT token\");\n } else if (tokenRef) {\n console.error(\"Connector ID not configured\");\n }\n\n console.warn(\"No valid authentication token found\");\n return null;\n }\n\n /**\n * Get user token from an Express request object.\n * This is the primary method for Express middleware integration.\n *\n * @example\n * ```typescript\n * import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';\n *\n * app.use(async (req, res, next) => {\n * const token = await jwtManager.getTokenFromExpressRequest(req);\n * req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };\n * next();\n * });\n * ```\n */\n async getTokenFromExpressRequest(req: ExpressRequestLike): Promise<string | null> {\n // Handle missing cookies gracefully (e.g., if cookie-parser middleware not installed)\n return this.getUserToken(req.cookies || {});\n }\n\n /** Clear the token cache */\n clearCache(): void {\n this.tokenCache.clear();\n }\n}\n\n/**\n * Global singleton instance.\n *\n * Note: This instance is created when the module is imported. Configuration\n * that depends on environment variables (CONNECTOR_ID, ORG_SLUG, TDP_ENDPOINT)\n * is read at module load time. Ensure these environment\n * variables are set before importing this module.\n *\n * If you need different configuration at runtime, create a new JwtTokenManager\n * instance instead of using this singleton.\n */\nexport const jwtManager = new JwtTokenManager();\n"],"names":["SECONDS_PER_MINUTE","MS_PER_SECOND","DEFAULT_TOKEN_REFRESH_THRESHOLD_MS","JwtTokenManager","config","baseUrl","token","parts","base64","paddedBase64","error","payload","expiryTimeMs","refreshTimeMs","tokenRef","cached","client","TDPClient","tdpClient","values","jwtToken","cachedUserToken","cookies","authToken","req","jwtManager"],"mappings":";AA6CA,MAAMA,IAAqB,IAErBC,IAAgB,KAChBC,IAAqC,IAAIF,IAAqBC;AAM7D,MAAME,EAAgB;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAER,YAAYC,IAAgC,IAAI;AAC9C,SAAK,kBAAkBA,EAAO,SAC9B,KAAK,cAAc,QAAQ,IAAI,cAC/B,KAAK,UAAU,QAAQ,IAAI,UAC3B,KAAK,iCAAiB,IAAA,GACtB,KAAK,0BAA0BA,EAAO,2BAA2BF,GACjE,KAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMQ,aAAqB;AAC3B,UAAMG,IAAU,KAAK,mBAAmB,QAAQ,IAAI;AACpD,QAAI,CAACA;AACH,YAAM,IAAI,MAAM,+FAA+F;AAEjH,WAAOA;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,iBAAiBC,GAAkC;AACzD,QAAI;AACF,YAAMC,IAAQD,EAAM,MAAM,GAAG;AAC7B,UAAIC,EAAM,WAAW;AACnB,uBAAQ,KAAK,0BAA0B,GAChC;AAIT,YAAMC,IADUD,EAAM,CAAC,EACA,QAAQ,MAAM,GAAG,EAAE,QAAQ,MAAM,GAAG,GACrDE,IAAeD,EAAO,OAAOA,EAAO,UAAW,IAAKA,EAAO,SAAS,KAAM,GAAI,GAAG;AAGvF,aAAO,KAAK,MAAM,OAAO,KAAKC,GAAc,QAAQ,EAAE,SAAS,OAAO,CAAC;AAAA,IACzE,SAASC,GAAO;AACd,qBAAQ,KAAK,6BAA6BA,CAAK,GACxC;AAAA,IACT;AAAA,EACF;AAAA;AAAA,EAGQ,sBAAsBC,GAA8B;AAC1D,QAAI,CAACA,EAAQ;AACX,qBAAQ,KAAK,mCAAmC,GACzC;AAGT,UAAMC,IAAeD,EAAQ,MAAMV,GAC7BY,IAAgB,KAAK,IAAA,IAAQ,KAAK;AACxC,WAAOD,KAAgBC;AAAA,EACzB;AAAA;AAAA,EAGQ,gBAAgBC,GAAiC;AACvD,UAAMC,IAAS,KAAK,WAAW,IAAID,CAAQ;AAC3C,WAAIC,KAAU,CAAC,KAAK,sBAAsBA,EAAO,OAAO,IAC/CA,EAAO,SAGZA,KAGF,KAAK,WAAW,OAAOD,CAAQ,GAE1B;AAAA,EACT;AAAA;AAAA,EAGA,MAAc,eAAmC;AAC/C,QAAI,KAAK,cAAc;AACrB,aAAO,KAAK;AAGd,QAAI,CAAC,KAAK,eAAe,CAAC,KAAK;AAC7B,YAAM,IAAI,MAAM,0DAA0D;AAI5E,UAAMT,IAAU,KAAK,WAAA;AAErB,QAAI;AACF,YAAMW,IAAS,IAAIC,EAAU;AAAA,QAC3B,aAAaZ;AAAA,QACb,aAAa,KAAK;AAAA,QAClB,SAAS,KAAK;AAAA,QACd,cAAc;AAAA,MAAA,CACf;AAED,mBAAMW,EAAO,KAAA,GAEb,KAAK,YAAYA,GACV,KAAK;AAAA,IACd,SAASN,GAAO;AAEd,oBAAQ,MAAM,oCAAoCA,CAAK,GACjDA;AAAA,IACR;AAAA,EACF;AAAA;AAAA,EAGA,MAAc,2BAA2BI,GAA0C;AAEjF,UAAMI,IAAY,MAAM,KAAK,aAAA;AAE7B,QAAI;AAGF,YAAMC,IAAS,MAAMD,EAAU,UAAU,CAACJ,CAAQ,CAAC;AAEnD,UAAIK,KAAUA,EAAO,SAAS,KAAKA,EAAO,CAAC,GAAG,KAAK;AACjD,cAAMC,IAAWD,EAAO,CAAC,EAAE,KAErBR,IAAU,KAAK,iBAAiBS,CAAQ;AAC9C,eAAIT,KACF,KAAK,WAAW,IAAIG,GAAU,EAAE,OAAOM,GAAU,SAAAT,GAAS,GAErDS;AAAA,MACT;AAEA,cAAQ,MAAM,yBAAyBN,CAAQ,sBAAsB;AAAA,IACvE,SAASJ,GAAO;AACd,cAAQ,MAAM,+BAA+BA,CAAK;AAAA,IACpD;AAEA,WAAO;AAAA,EACT;AAAA;AAAA,EAGA,MAAM,mBAAmBI,GAA0C;AACjE,QAAI,CAACA,KAAY,CAAC,KAAK;AACrB,qBAAQ,KAAK,qDAAqD,GAC3D;AAGT,UAAMO,IAAkB,KAAK,gBAAgBP,CAAQ;AACrD,WAAIO,KAIG,KAAK,2BAA2BP,CAAQ;AAAA,EACjD;AAAA;AAAA,EAGA,MAAM,aAAaQ,GAA6C;AAE9D,UAAMC,IAAYD,EAAQ,eAAe,KAAK,QAAQ,IAAI;AAC1D,QAAIC;AACF,aAAOA;AAIT,UAAMT,IAAWQ,EAAQ,cAAc;AACvC,QAAIR,KAAY,KAAK,aAAa;AAChC,YAAMM,IAAW,MAAM,KAAK,mBAAmBN,CAAQ;AACvD,UAAIM;AACF,eAAOA;AAET,cAAQ,KAAK,6CAA6C;AAAA,IAC5D,OAAWN,KACT,QAAQ,MAAM,6BAA6B;AAG7C,mBAAQ,KAAK,qCAAqC,GAC3C;AAAA,EACT;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAiBA,MAAM,2BAA2BU,GAAiD;AAEhF,WAAO,KAAK,aAAaA,EAAI,WAAW,CAAA,CAAE;AAAA,EAC5C;AAAA;AAAA,EAGA,aAAmB;AACjB,SAAK,WAAW,MAAA;AAAA,EAClB;AACF;AAaO,MAAMC,IAAa,IAAItB,EAAA;"}
|
|
1
|
+
{"version":3,"file":"JwtTokenManager.js","sources":["../../../src/server/auth/JwtTokenManager.ts"],"sourcesContent":["/**\n * JWT Token Manager for TetraScience Data Apps\n *\n * Handles authentication token retrieval from Express request cookies,\n * supporting both direct JWT tokens (ts-auth-token) and token references\n * (ts-token-ref) that are resolved via the connector K/V store.\n *\n * Note: This manager does not perform cryptographic verification of JWT signatures.\n * Signature verification is the responsibility of the consuming application or\n * the upstream authentication layer. The JWT payload is decoded only to read\n * expiration times for cache invalidation.\n */\n\nimport { TDPClient } from \"@tetrascience-npm/ts-connectors-sdk\";\n\n/** Configuration options for JwtTokenManager */\nexport interface JwtTokenManagerConfig {\n baseUrl?: string;\n tokenRefreshThresholdMs?: number;\n}\n\n/** Cookie dictionary type - matches Express req.cookies */\nexport interface CookieDict {\n [key: string]: string;\n}\n\n/** Header dictionary type - matches Express req.headers (keys are lowercased) */\nexport interface HeaderDict {\n [key: string]: string | string[] | undefined;\n}\n\n/** Express-like request interface (works with Express, Koa, etc.) */\nexport interface ExpressRequestLike {\n cookies?: CookieDict;\n headers?: HeaderDict;\n}\n\n/** Request header carrying the resolved JWT injected by the data-apps proxy. */\nconst AUTH_TOKEN_HEADER = \"ts-auth-token\";\n\n/** JWT payload structure */\ninterface JwtPayload {\n exp?: number;\n iat?: number;\n [key: string]: unknown;\n}\n\n/** Cached token entry storing both raw token and parsed payload */\ninterface CachedTokenEntry {\n token: string;\n payload: JwtPayload;\n}\n\n/** Number of seconds in a minute */\nconst SECONDS_PER_MINUTE = 60;\n/** Milliseconds per second */\nconst MS_PER_SECOND = 1000;\nconst DEFAULT_TOKEN_REFRESH_THRESHOLD_MS = 5 * SECONDS_PER_MINUTE * MS_PER_SECOND; // 5 minutes\n\n/**\n * Manages JWT token retrieval from request cookies.\n * Supports both ts-auth-token (direct JWT) and ts-token-ref (resolved via connector store).\n */\nexport class JwtTokenManager {\n private baseUrlOverride: string | undefined;\n private connectorId: string | undefined;\n private orgSlug: string | undefined;\n private tokenCache: Map<string, CachedTokenEntry>;\n private tokenRefreshThresholdMs: number;\n private tdpClient: TDPClient | null;\n\n constructor(config: JwtTokenManagerConfig = {}) {\n this.baseUrlOverride = config.baseUrl;\n this.connectorId = process.env.CONNECTOR_ID;\n this.orgSlug = process.env.ORG_SLUG;\n this.tokenCache = new Map();\n this.tokenRefreshThresholdMs = config.tokenRefreshThresholdMs || DEFAULT_TOKEN_REFRESH_THRESHOLD_MS;\n this.tdpClient = null;\n }\n\n /**\n * Get the base URL for TDP API calls.\n * Throws an error if not configured (either via config.baseUrl or TDP_ENDPOINT env var).\n */\n private getBaseUrl(): string {\n const baseUrl = this.baseUrlOverride || process.env.TDP_ENDPOINT;\n if (!baseUrl) {\n throw new Error(\"TDP base URL not configured. Set TDP_ENDPOINT environment variable or pass baseUrl in config.\");\n }\n return baseUrl;\n }\n\n /**\n * Decode JWT payload without verifying signature.\n * Used only for reading expiration times for cache invalidation.\n * Signature verification is NOT performed here.\n */\n private decodeJwtPayload(token: string): JwtPayload | null {\n try {\n const parts = token.split(\".\");\n if (parts.length !== 3) {\n console.warn(\"Invalid JWT token format\");\n return null;\n }\n\n const payload = parts[1];\n const base64 = payload.replace(/-/g, \"+\").replace(/_/g, \"/\");\n const paddedBase64 = base64.padEnd(base64.length + ((4 - (base64.length % 4)) % 4), \"=\");\n\n // Use Buffer.from for Node.js compatibility (atob not available in all runtimes)\n return JSON.parse(Buffer.from(paddedBase64, \"base64\").toString(\"utf-8\"));\n } catch (error) {\n console.warn(\"Error decoding JWT token:\", error);\n return null;\n }\n }\n\n /** Check if payload is expiring within the refresh threshold */\n private isPayloadExpiringSoon(payload: JwtPayload): boolean {\n if (!payload.exp) {\n console.warn(\"JWT token has no expiration claim\");\n return true;\n }\n\n const expiryTimeMs = payload.exp * MS_PER_SECOND;\n const refreshTimeMs = Date.now() + this.tokenRefreshThresholdMs;\n return expiryTimeMs <= refreshTimeMs;\n }\n\n /** Get valid cached token if not expiring */\n private getValidUserJwt(tokenRef: string): string | null {\n const cached = this.tokenCache.get(tokenRef);\n if (cached && !this.isPayloadExpiringSoon(cached.payload)) {\n return cached.token;\n }\n // Clean up expired entry to prevent unbounded cache growth\n if (cached) {\n // TODO: If data apps become high-traffic, consider enhancing with\n // an LRU cache (e.g., lru-cache package) to purge stale entries automatically\n this.tokenCache.delete(tokenRef);\n }\n return null;\n }\n\n /** Initialize or get TDP client */\n private async getTdpClient(): Promise<TDPClient> {\n if (this.tdpClient !== null) {\n return this.tdpClient;\n }\n\n if (!this.connectorId || !this.orgSlug) {\n throw new Error(\"Missing required configuration: CONNECTOR_ID or ORG_SLUG\");\n }\n\n // getBaseUrl() throws if TDP_ENDPOINT not configured - let it propagate\n const baseUrl = this.getBaseUrl();\n\n try {\n const client = new TDPClient({\n tdpEndpoint: baseUrl,\n connectorId: this.connectorId,\n orgSlug: this.orgSlug,\n artifactType: \"data-app\",\n });\n\n await client.init();\n // Only assign after successful initialization to allow retry on failure\n this.tdpClient = client;\n return this.tdpClient;\n } catch (error) {\n // Log init errors but rethrow so callers know something went wrong\n console.error(\"Failed to initialize TDP client:\", error);\n throw error;\n }\n }\n\n /** Retrieve JWT from connector K/V store using getValues (calls getConnectorData internally) */\n private async getJwtFromTokenRefInternal(tokenRef: string): Promise<string | null> {\n // getTdpClient() throws on config errors - let those propagate\n const tdpClient = await this.getTdpClient();\n\n try {\n // getValues returns array of values for the given keys\n // Each value is expected to have a jwt property: { jwt: \"...\" }\n const values = await tdpClient.getValues([tokenRef]);\n\n if (values && values.length > 0 && values[0]?.jwt) {\n const jwtToken = values[0].jwt;\n // Parse and cache both the raw token and its payload to avoid repeated decoding\n const payload = this.decodeJwtPayload(jwtToken);\n if (payload) {\n this.tokenCache.set(tokenRef, { token: jwtToken, payload });\n }\n return jwtToken;\n }\n\n console.error(`No JWT found for key '${tokenRef}' in connector store`);\n } catch (error) {\n console.error(\"Error retrieving JWT token:\", error);\n }\n\n return null;\n }\n\n /** Resolve ts-token-ref to full JWT token (with caching) */\n async getJwtFromTokenRef(tokenRef: string): Promise<string | null> {\n if (!tokenRef || !this.orgSlug) {\n console.warn(\"Missing required parameters for JWT token retrieval\");\n return null;\n }\n\n const cachedUserToken = this.getValidUserJwt(tokenRef);\n if (cachedUserToken) {\n return cachedUserToken;\n }\n\n return this.getJwtFromTokenRefInternal(tokenRef);\n }\n\n /**\n * Read the ts-auth-token request header, normalizing the array form that\n * Node/Express may produce for a repeated header.\n */\n private getHeaderAuthToken(headers?: HeaderDict): string | null {\n const raw = headers?.[AUTH_TOKEN_HEADER];\n const value = Array.isArray(raw) ? raw[0] : raw;\n return value || null;\n }\n\n /**\n * Get token from a request (proxy-injected header, then cookie, then token ref).\n *\n * Precedence (SW-2352):\n * 1. `ts-auth-token` request header — for large-JWT sessions the data-apps\n * proxy resolves the token reference server-side and injects the real JWT\n * here; the `ts-token-ref` cookie is no longer forwarded to the container.\n * Checking the header first is also what keeps SSO users authenticated.\n * 2. `ts-auth-token` cookie / `TS_AUTH_TOKEN` env var (small-JWT + local dev).\n * 3. `ts-token-ref` cookie → connector K/V resolution (legacy fallback; goes\n * dead in prod once the proxy stops forwarding the cookie, retained for\n * local dev and defense in depth).\n */\n async getUserToken(cookies: CookieDict, headers?: HeaderDict): Promise<string | null> {\n // Prefer the proxy-injected ts-auth-token request header.\n const headerAuthToken = this.getHeaderAuthToken(headers);\n if (headerAuthToken) {\n return headerAuthToken;\n }\n\n // Then ts-auth-token cookie or TS_AUTH_TOKEN env var (latter is for local dev testing)\n const authToken = cookies[\"ts-auth-token\"] || process.env.TS_AUTH_TOKEN;\n if (authToken) {\n return authToken;\n }\n\n // Try to resolve ts-token-ref (legacy fallback).\n // TODO(next major): drop the ts-token-ref → connector-KV resolution entirely.\n // As of SW-2352 the data-apps proxy resolves the reference server-side and\n // injects the JWT via the ts-auth-token header (preferred above), and no\n // longer forwards the ts-token-ref cookie to the container — so this path is\n // dead in production and kept only for local dev / older proxies.\n const tokenRef = cookies[\"ts-token-ref\"];\n if (tokenRef && this.connectorId) {\n const jwtToken = await this.getJwtFromTokenRef(tokenRef);\n if (jwtToken) {\n return jwtToken;\n }\n console.warn(\"Failed to resolve ts-token-ref to JWT token\");\n } else if (tokenRef) {\n console.error(\"Connector ID not configured\");\n }\n\n console.warn(\"No valid authentication token found\");\n return null;\n }\n\n /**\n * Get user token from an Express request object.\n * This is the primary method for Express middleware integration.\n *\n * @example\n * ```typescript\n * import { jwtManager } from '@tetrascience-npm/tetrascience-react-ui/server';\n *\n * app.use(async (req, res, next) => {\n * const token = await jwtManager.getTokenFromExpressRequest(req);\n * req.tdpAuth = { token, orgSlug: process.env.ORG_SLUG };\n * next();\n * });\n * ```\n */\n async getTokenFromExpressRequest(req: ExpressRequestLike): Promise<string | null> {\n // Handle missing cookies gracefully (e.g., if cookie-parser middleware not installed).\n // Headers are checked first (proxy-injected ts-auth-token) — see getUserToken.\n return this.getUserToken(req.cookies || {}, req.headers);\n }\n\n /** Clear the token cache */\n clearCache(): void {\n this.tokenCache.clear();\n }\n}\n\n/**\n * Global singleton instance.\n *\n * Note: This instance is created when the module is imported. Configuration\n * that depends on environment variables (CONNECTOR_ID, ORG_SLUG, TDP_ENDPOINT)\n * is read at module load time. Ensure these environment\n * variables are set before importing this module.\n *\n * If you need different configuration at runtime, create a new JwtTokenManager\n * instance instead of using this singleton.\n */\nexport const jwtManager = new JwtTokenManager();\n"],"names":["AUTH_TOKEN_HEADER","SECONDS_PER_MINUTE","MS_PER_SECOND","DEFAULT_TOKEN_REFRESH_THRESHOLD_MS","JwtTokenManager","config","baseUrl","token","parts","base64","paddedBase64","error","payload","expiryTimeMs","refreshTimeMs","tokenRef","cached","client","TDPClient","tdpClient","values","jwtToken","cachedUserToken","headers","raw","cookies","headerAuthToken","authToken","req","jwtManager"],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TetraScience Server Utilities
|
|
3
|
+
*
|
|
4
|
+
* Backend utilities and helper functions for TetraScience applications.
|
|
5
|
+
* This module contains server-side code that does not depend on React or browser APIs.
|
|
6
|
+
*/
|
|
7
|
+
export * from './auth';
|
|
8
|
+
export * from './providers';
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const d=require("./exceptions.cjs");function f(r){const t=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(r){for(const e in r)if(e!=="default"){const n=Object.getOwnPropertyDescriptor(r,e);Object.defineProperty(t,e,n.get?n:{enumerable:!0,get:()=>r[e]})}}return t.default=r,Object.freeze(t)}const E=1e3;async function g(){try{return await Promise.resolve().then(()=>f(require("@aws-sdk/client-athena")))}catch{throw new d.InvalidProviderConfigurationError("The '@aws-sdk/client-athena' package is required to use the Athena provider. Please install it: npm install @aws-sdk/client-athena")}}const S=262144;class w{client;sdk;workgroup;database;outputLocation;constructor(t,e,n,s,o){this.client=t,this.sdk=e,this.workgroup=n,this.database=s,this.outputLocation=o}async query(t,e={}){if(t.length>S)throw new Error("Query length exceeds the maximum allowed limit.");const n=new this.sdk.StartQueryExecutionCommand({QueryString:t,WorkGroup:this.workgroup,QueryExecutionContext:{Database:this.database},ResultConfiguration:this.outputLocation?{OutputLocation:this.outputLocation}:void 0}),o=(await this.client.send(n)).QueryExecutionId;if(!o)throw new d.QueryError("Failed to start query execution");return await this.waitForQueryCompletion(o,t),this.fetchAllResults(o)}async waitForQueryCompletion(t,e){const o=Date.now();for(;Date.now()-o<3e5;){const c=new this.sdk.GetQueryExecutionCommand({QueryExecutionId:t}),a=await this.client.send(c),i=a.QueryExecution?.Status?.State;if(i===this.sdk.QueryExecutionState.SUCCEEDED)return;if(i===this.sdk.QueryExecutionState.FAILED||i===this.sdk.QueryExecutionState.CANCELLED){const u=a.QueryExecution?.Status?.StateChangeReason??"Unknown error";if(u.includes("TABLE_NOT_FOUND")){const l=u.split(":").pop()?.trim()??"";throw new d.MissingTableError("Athena is unable to find the table. If the table is created by a tetraflow, make sure that the tetraflow has run successfully. "+l+".")}throw new d.QueryError(`Query failed: ${e}. Reason: ${u}`)}await new Promise(u=>setTimeout(u,1e3))}throw new d.QueryError(`Query timed out after ${3e5/E} seconds`)}async fetchAllResults(t){const e=[];let n,s=[],o=!0;do{const c=new this.sdk.GetQueryResultsCommand({QueryExecutionId:t,NextToken:n}),a=await this.client.send(c);o&&a.ResultSet?.ResultSetMetadata?.ColumnInfo&&(s=a.ResultSet.ResultSetMetadata.ColumnInfo.map((l,m)=>{const h=l.Name;return h&&h.trim()!==""?h:`column_${m}`}));const i=a.ResultSet?.Rows??[],u=o?i.slice(1):i;for(const l of u){const m={};l.Data?.forEach((h,p)=>{const y=s[p]??`column_${p}`;m[y]=h.VarCharValue??null}),e.push(m)}n=a.NextToken,o=!1}while(n);return e}async close(){this.client.destroy()}}async function k(){const r=await g(),t=process.env.ORG_SLUG??"",e=t.replace(/-/g,"_"),n=process.env.ATHENA_S3_OUTPUT_LOCATION,s=process.env.AWS_REGION,o=`${e}__tss__default`,c=t,a=new r.AthenaClient({region:s});try{return await a.send(new r.GetWorkGroupCommand({WorkGroup:c})),new w(a,r,c,o)}catch{if(!n)throw new Error("ATHENA_S3_OUTPUT_LOCATION environment variable is required when using the 'primary' workgroup. Either set this variable or ensure the org-specific workgroup exists.");const i=`s3://${n}/${e}/`;return new w(a,r,"primary",o,i)}}exports.AthenaProvider=w;exports.getTdpAthenaProvider=k;
|
|
2
2
|
//# sourceMappingURL=AthenaProvider.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AthenaProvider.cjs","sources":["../../../src/server/providers/AthenaProvider.ts"],"sourcesContent":["/**\n * Athena Data Provider\n *\n * TypeScript equivalent of AthenaProvider from\n * ts-lib-ui-kit-streamlit/tetrascience/data_app_providers/provider.py\n *\n * @remarks\n * This provider requires the `@aws-sdk/client-athena` package to be installed.\n * It is an optional peer dependency - install it only if you need Athena support:\n * ```bash\n * npm install @aws-sdk/client-athena\n * # or\n * yarn add @aws-sdk/client-athena\n * ```\n */\n\nimport {\n QueryError,\n MissingTableError,\n InvalidProviderConfigurationError,\n} from \"./exceptions\";\n\n/** Milliseconds per second */\nconst MILLISECONDS_PER_SECOND = 1000;\n\n// Type imports for @aws-sdk/client-athena (these don't require the package at runtime)\ntype AthenaClient = import(\"@aws-sdk/client-athena\").AthenaClient;\ntype AthenaSDK = typeof import(\"@aws-sdk/client-athena\");\n\n/**\n * Dynamically import @aws-sdk/client-athena\n * @throws {InvalidProviderConfigurationError} If @aws-sdk/client-athena is not installed\n */\nasync function getAthenaSDK(): Promise<AthenaSDK> {\n try {\n return await import(\"@aws-sdk/client-athena\");\n } catch {\n throw new InvalidProviderConfigurationError(\n \"The '@aws-sdk/client-athena' package is required to use the Athena provider. \" +\n \"Please install it: npm install @aws-sdk/client-athena\",\n );\n }\n}\n\n/** Maximum query length allowed by Athena */\nconst MAX_QUERY_LENGTH = 262144;\n\n/**\n * Athena data provider\n */\nexport class AthenaProvider {\n private client: AthenaClient;\n private sdk: AthenaSDK;\n private workgroup: string;\n private database: string;\n private outputLocation?: string;\n\n /**\n * Initialize the Athena data provider\n *\n * @param client - AWS Athena client\n * @param sdk - AWS Athena SDK module (for accessing command classes)\n * @param workgroup - Athena workgroup to use\n * @param database - Default database/schema\n * @param outputLocation - Optional S3 output location\n */\n constructor(\n client: AthenaClient,\n sdk: AthenaSDK,\n workgroup: string,\n database: string,\n outputLocation?: string,\n ) {\n this.client = client;\n this.sdk = sdk;\n this.workgroup = workgroup;\n this.database = database;\n this.outputLocation = outputLocation;\n }\n\n /**\n * Query the Athena database\n *\n * @param sqlQuery - SQL query to execute\n * @param _params - Parameters to pass to the query (currently not used - Athena doesn't support parameterized queries)\n * @returns Promise resolving to array of row objects\n *\n * @remarks\n * **Security Note:** AWS Athena does not support parameterized queries.\n * Unlike traditional databases, there is no native way to use bind parameters\n * with Athena. Callers are responsible for properly sanitizing any user input\n * before constructing the SQL query string. This is a known limitation of the\n * Athena service, not a design flaw in this implementation.\n */\n async query(\n sqlQuery: string,\n _params: Record<string, unknown> = {},\n ): Promise<Array<Record<string, unknown>>> {\n if (sqlQuery.length > MAX_QUERY_LENGTH) {\n throw new Error(\"Query length exceeds the maximum allowed limit.\");\n }\n\n // Start query execution\n // Note: Athena does not support parameterized queries. The sqlQuery is passed\n // directly to Athena. Callers must sanitize user input before constructing queries.\n const startCommand = new this.sdk.StartQueryExecutionCommand({\n QueryString: sqlQuery,\n WorkGroup: this.workgroup,\n QueryExecutionContext: {\n Database: this.database,\n },\n ResultConfiguration: this.outputLocation\n ? { OutputLocation: this.outputLocation }\n : undefined,\n });\n\n const startResponse = await this.client.send(startCommand);\n const queryExecutionId = startResponse.QueryExecutionId;\n\n if (!queryExecutionId) {\n throw new QueryError(\"Failed to start query execution\");\n }\n\n // Wait for query to complete\n await this.waitForQueryCompletion(queryExecutionId, sqlQuery);\n\n // Fetch results\n return this.fetchAllResults(queryExecutionId);\n }\n\n /**\n * Wait for query to complete\n */\n private async waitForQueryCompletion(\n queryExecutionId: string,\n originalQuery: string,\n ): Promise<void> {\n const maxWaitTime = 300000; // 5 minutes\n const pollInterval = 1000; // 1 second\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitTime) {\n const command = new this.sdk.GetQueryExecutionCommand({\n QueryExecutionId: queryExecutionId,\n });\n const response = await this.client.send(command);\n const state = response.QueryExecution?.Status?.State;\n\n if (state === this.sdk.QueryExecutionState.SUCCEEDED) {\n return;\n }\n\n if (\n state === this.sdk.QueryExecutionState.FAILED ||\n state === this.sdk.QueryExecutionState.CANCELLED\n ) {\n const reason =\n response.QueryExecution?.Status?.StateChangeReason ?? \"Unknown error\";\n\n if (reason.includes(\"TABLE_NOT_FOUND\")) {\n const errorTail = reason.split(\":\").pop()?.trim() ?? \"\";\n throw new MissingTableError(\n \"Athena is unable to find the table. If the table is created by a \" +\n \"tetraflow, make sure that the tetraflow has run successfully. \" +\n errorTail +\n \".\",\n );\n }\n\n throw new QueryError(\n `Query failed: ${originalQuery}. Reason: ${reason}`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new QueryError(\n `Query timed out after ${maxWaitTime / MILLISECONDS_PER_SECOND} seconds`,\n );\n }\n\n /**\n * Fetch all results from a completed query\n */\n private async fetchAllResults(\n queryExecutionId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const results: Array<Record<string, unknown>> = [];\n let nextToken: string | undefined;\n let columnNames: string[] = [];\n let isFirstPage = true;\n\n do {\n const command = new this.sdk.GetQueryResultsCommand({\n QueryExecutionId: queryExecutionId,\n NextToken: nextToken,\n });\n\n const response = await this.client.send(command);\n\n if (isFirstPage && response.ResultSet?.ResultSetMetadata?.ColumnInfo) {\n columnNames = response.ResultSet.ResultSetMetadata.ColumnInfo.map(\n (col, idx) => {\n // Handle empty or missing column names by using a fallback\n const name = col.Name;\n return name && name.trim() !== \"\" ? name : `column_${idx}`;\n },\n );\n }\n\n const rows = response.ResultSet?.Rows ?? [];\n // Skip header row on first page\n const dataRows = isFirstPage ? rows.slice(1) : rows;\n\n for (const row of dataRows) {\n const rowData: Record<string, unknown> = {};\n row.Data?.forEach((cell, index) => {\n // columnNames already has fallback values, so we can use them directly\n const columnName = columnNames[index] ?? `column_${index}`;\n rowData[columnName] = cell.VarCharValue ?? null;\n });\n results.push(rowData);\n }\n\n nextToken = response.NextToken;\n isFirstPage = false;\n } while (nextToken);\n\n return results;\n }\n\n /**\n * Close the Athena client (no-op for AWS SDK clients)\n */\n async close(): Promise<void> {\n this.client.destroy();\n }\n}\n\n/**\n * Get the TDP Athena provider\n *\n * Creates an Athena provider using TDP environment configuration\n *\n * @returns Promise resolving to Athena data provider\n * @throws {InvalidProviderConfigurationError} If @aws-sdk/client-athena is not installed\n * @throws {Error} If ATHENA_S3_OUTPUT_LOCATION is not set when using the 'primary' workgroup\n */\nexport async function getTdpAthenaProvider(): Promise<AthenaProvider> {\n // Dynamically import @aws-sdk/client-athena\n const athenaSDK = await getAthenaSDK();\n\n const orgSlug = process.env.ORG_SLUG ?? \"\";\n const orgSlugDbFriendly = orgSlug.replace(/-/g, \"_\");\n const athenaQueryBucket = process.env.ATHENA_S3_OUTPUT_LOCATION;\n const athenaRegion = process.env.AWS_REGION;\n const athenaSchema = `${orgSlugDbFriendly}__tss__default`;\n const athenaWorkgroup = orgSlug;\n\n const client = new athenaSDK.AthenaClient({\n region: athenaRegion,\n });\n\n // Check if the org-specific workgroup exists\n try {\n await client.send(\n new athenaSDK.GetWorkGroupCommand({\n WorkGroup: athenaWorkgroup,\n }),\n );\n\n // Workgroup exists, use it\n return new AthenaProvider(client, athenaSDK, athenaWorkgroup, athenaSchema);\n } catch {\n // Workgroup doesn't exist or access denied, use 'primary' workgroup\n // The 'primary' workgroup requires an explicit output location\n if (!athenaQueryBucket) {\n throw new Error(\n \"ATHENA_S3_OUTPUT_LOCATION environment variable is required when using the 'primary' workgroup. \" +\n \"Either set this variable or ensure the org-specific workgroup exists.\",\n );\n }\n\n const athenaOutputLocation = `s3://${athenaQueryBucket}/${orgSlugDbFriendly}/`;\n return new AthenaProvider(\n client,\n athenaSDK,\n \"primary\",\n athenaSchema,\n athenaOutputLocation,\n );\n }\n}\n\n"],"names":["MILLISECONDS_PER_SECOND","getAthenaSDK","InvalidProviderConfigurationError","MAX_QUERY_LENGTH","AthenaProvider","client","sdk","workgroup","database","outputLocation","sqlQuery","_params","startCommand","queryExecutionId","QueryError","originalQuery","startTime","command","response","state","reason","errorTail","MissingTableError","resolve","results","nextToken","columnNames","isFirstPage","col","idx","name","rows","dataRows","row","rowData","cell","index","columnName","getTdpAthenaProvider","athenaSDK","orgSlug","orgSlugDbFriendly","athenaQueryBucket","athenaRegion","athenaSchema","athenaWorkgroup","athenaOutputLocation"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"AthenaProvider.cjs","sources":["../../../src/server/providers/AthenaProvider.ts"],"sourcesContent":["/**\n * Athena Data Provider\n *\n * TypeScript equivalent of AthenaProvider from\n * ts-lib-ui-kit-streamlit/tetrascience/data_app_providers/provider.py\n *\n * @remarks\n * This provider requires the `@aws-sdk/client-athena` package to be installed.\n * It is an optional peer dependency - install it only if you need Athena support:\n * ```bash\n * npm install @aws-sdk/client-athena\n * # or\n * yarn add @aws-sdk/client-athena\n * ```\n */\n\nimport {\n QueryError,\n MissingTableError,\n InvalidProviderConfigurationError,\n} from \"./exceptions\";\n\n/** Milliseconds per second */\nconst MILLISECONDS_PER_SECOND = 1000;\n\n// Type imports for @aws-sdk/client-athena (these don't require the package at runtime)\ntype AthenaClient = import(\"@aws-sdk/client-athena\").AthenaClient;\ntype AthenaSDK = typeof import(\"@aws-sdk/client-athena\");\n\n/**\n * Dynamically import @aws-sdk/client-athena\n * @throws {InvalidProviderConfigurationError} If @aws-sdk/client-athena is not installed\n */\nasync function getAthenaSDK(): Promise<AthenaSDK> {\n try {\n return await import(\"@aws-sdk/client-athena\");\n } catch {\n throw new InvalidProviderConfigurationError(\n \"The '@aws-sdk/client-athena' package is required to use the Athena provider. \" +\n \"Please install it: npm install @aws-sdk/client-athena\",\n );\n }\n}\n\n/** Maximum query length allowed by Athena */\nconst MAX_QUERY_LENGTH = 262144;\n\n/**\n * Athena data provider\n */\nexport class AthenaProvider {\n private client: AthenaClient;\n private sdk: AthenaSDK;\n private workgroup: string;\n private database: string;\n private outputLocation?: string;\n\n /**\n * Initialize the Athena data provider\n *\n * @param client - AWS Athena client\n * @param sdk - AWS Athena SDK module (for accessing command classes)\n * @param workgroup - Athena workgroup to use\n * @param database - Default database/schema\n * @param outputLocation - Optional S3 output location\n */\n constructor(\n client: AthenaClient,\n sdk: AthenaSDK,\n workgroup: string,\n database: string,\n outputLocation?: string,\n ) {\n this.client = client;\n this.sdk = sdk;\n this.workgroup = workgroup;\n this.database = database;\n this.outputLocation = outputLocation;\n }\n\n /**\n * Query the Athena database\n *\n * @param sqlQuery - SQL query to execute\n * @param _params - Parameters to pass to the query (currently not used - Athena doesn't support parameterized queries)\n * @returns Promise resolving to array of row objects\n *\n * @remarks\n * **Security Note:** AWS Athena does not support parameterized queries.\n * Unlike traditional databases, there is no native way to use bind parameters\n * with Athena. Callers are responsible for properly sanitizing any user input\n * before constructing the SQL query string. This is a known limitation of the\n * Athena service, not a design flaw in this implementation.\n */\n async query(\n sqlQuery: string,\n _params: Record<string, unknown> = {},\n ): Promise<Array<Record<string, unknown>>> {\n if (sqlQuery.length > MAX_QUERY_LENGTH) {\n throw new Error(\"Query length exceeds the maximum allowed limit.\");\n }\n\n // Start query execution\n // Note: Athena does not support parameterized queries. The sqlQuery is passed\n // directly to Athena. Callers must sanitize user input before constructing queries.\n const startCommand = new this.sdk.StartQueryExecutionCommand({\n QueryString: sqlQuery,\n WorkGroup: this.workgroup,\n QueryExecutionContext: {\n Database: this.database,\n },\n ResultConfiguration: this.outputLocation\n ? { OutputLocation: this.outputLocation }\n : undefined,\n });\n\n const startResponse = await this.client.send(startCommand);\n const queryExecutionId = startResponse.QueryExecutionId;\n\n if (!queryExecutionId) {\n throw new QueryError(\"Failed to start query execution\");\n }\n\n // Wait for query to complete\n await this.waitForQueryCompletion(queryExecutionId, sqlQuery);\n\n // Fetch results\n return this.fetchAllResults(queryExecutionId);\n }\n\n /**\n * Wait for query to complete\n */\n private async waitForQueryCompletion(\n queryExecutionId: string,\n originalQuery: string,\n ): Promise<void> {\n const maxWaitTime = 300000; // 5 minutes\n const pollInterval = 1000; // 1 second\n const startTime = Date.now();\n\n while (Date.now() - startTime < maxWaitTime) {\n const command = new this.sdk.GetQueryExecutionCommand({\n QueryExecutionId: queryExecutionId,\n });\n const response = await this.client.send(command);\n const state = response.QueryExecution?.Status?.State;\n\n if (state === this.sdk.QueryExecutionState.SUCCEEDED) {\n return;\n }\n\n if (\n state === this.sdk.QueryExecutionState.FAILED ||\n state === this.sdk.QueryExecutionState.CANCELLED\n ) {\n const reason =\n response.QueryExecution?.Status?.StateChangeReason ?? \"Unknown error\";\n\n if (reason.includes(\"TABLE_NOT_FOUND\")) {\n const errorTail = reason.split(\":\").pop()?.trim() ?? \"\";\n throw new MissingTableError(\n \"Athena is unable to find the table. If the table is created by a \" +\n \"tetraflow, make sure that the tetraflow has run successfully. \" +\n errorTail +\n \".\",\n );\n }\n\n throw new QueryError(\n `Query failed: ${originalQuery}. Reason: ${reason}`,\n );\n }\n\n await new Promise((resolve) => setTimeout(resolve, pollInterval));\n }\n\n throw new QueryError(\n `Query timed out after ${maxWaitTime / MILLISECONDS_PER_SECOND} seconds`,\n );\n }\n\n /**\n * Fetch all results from a completed query\n */\n private async fetchAllResults(\n queryExecutionId: string,\n ): Promise<Array<Record<string, unknown>>> {\n const results: Array<Record<string, unknown>> = [];\n let nextToken: string | undefined;\n let columnNames: string[] = [];\n let isFirstPage = true;\n\n do {\n const command = new this.sdk.GetQueryResultsCommand({\n QueryExecutionId: queryExecutionId,\n NextToken: nextToken,\n });\n\n const response = await this.client.send(command);\n\n if (isFirstPage && response.ResultSet?.ResultSetMetadata?.ColumnInfo) {\n columnNames = response.ResultSet.ResultSetMetadata.ColumnInfo.map(\n (col, idx) => {\n // Handle empty or missing column names by using a fallback\n const name = col.Name;\n return name && name.trim() !== \"\" ? name : `column_${idx}`;\n },\n );\n }\n\n const rows = response.ResultSet?.Rows ?? [];\n // Skip header row on first page\n const dataRows = isFirstPage ? rows.slice(1) : rows;\n\n for (const row of dataRows) {\n const rowData: Record<string, unknown> = {};\n row.Data?.forEach((cell, index) => {\n // columnNames already has fallback values, so we can use them directly\n const columnName = columnNames[index] ?? `column_${index}`;\n rowData[columnName] = cell.VarCharValue ?? null;\n });\n results.push(rowData);\n }\n\n nextToken = response.NextToken;\n isFirstPage = false;\n } while (nextToken);\n\n return results;\n }\n\n /**\n * Close the Athena client (no-op for AWS SDK clients)\n */\n async close(): Promise<void> {\n this.client.destroy();\n }\n}\n\n/**\n * Get the TDP Athena provider\n *\n * Creates an Athena provider using TDP environment configuration\n *\n * @returns Promise resolving to Athena data provider\n * @throws {InvalidProviderConfigurationError} If @aws-sdk/client-athena is not installed\n * @throws {Error} If ATHENA_S3_OUTPUT_LOCATION is not set when using the 'primary' workgroup\n */\nexport async function getTdpAthenaProvider(): Promise<AthenaProvider> {\n // Dynamically import @aws-sdk/client-athena\n const athenaSDK = await getAthenaSDK();\n\n const orgSlug = process.env.ORG_SLUG ?? \"\";\n const orgSlugDbFriendly = orgSlug.replace(/-/g, \"_\");\n const athenaQueryBucket = process.env.ATHENA_S3_OUTPUT_LOCATION;\n const athenaRegion = process.env.AWS_REGION;\n const athenaSchema = `${orgSlugDbFriendly}__tss__default`;\n const athenaWorkgroup = orgSlug;\n\n const client = new athenaSDK.AthenaClient({\n region: athenaRegion,\n });\n\n // Check if the org-specific workgroup exists\n try {\n await client.send(\n new athenaSDK.GetWorkGroupCommand({\n WorkGroup: athenaWorkgroup,\n }),\n );\n\n // Workgroup exists, use it\n return new AthenaProvider(client, athenaSDK, athenaWorkgroup, athenaSchema);\n } catch {\n // Workgroup doesn't exist or access denied, use 'primary' workgroup\n // The 'primary' workgroup requires an explicit output location\n if (!athenaQueryBucket) {\n throw new Error(\n \"ATHENA_S3_OUTPUT_LOCATION environment variable is required when using the 'primary' workgroup. \" +\n \"Either set this variable or ensure the org-specific workgroup exists.\",\n );\n }\n\n const athenaOutputLocation = `s3://${athenaQueryBucket}/${orgSlugDbFriendly}/`;\n return new AthenaProvider(\n client,\n athenaSDK,\n \"primary\",\n athenaSchema,\n athenaOutputLocation,\n );\n }\n}\n\n"],"names":["MILLISECONDS_PER_SECOND","getAthenaSDK","_interopNamespaceDefault","InvalidProviderConfigurationError","MAX_QUERY_LENGTH","AthenaProvider","client","sdk","workgroup","database","outputLocation","sqlQuery","_params","startCommand","queryExecutionId","QueryError","originalQuery","startTime","command","response","state","reason","errorTail","MissingTableError","resolve","results","nextToken","columnNames","isFirstPage","col","idx","name","rows","dataRows","row","rowData","cell","index","columnName","getTdpAthenaProvider","athenaSDK","orgSlug","orgSlugDbFriendly","athenaQueryBucket","athenaRegion","athenaSchema","athenaWorkgroup","athenaOutputLocation"],"mappings":"iYAuBA,MAAMA,EAA0B,IAUhC,eAAeC,GAAmC,CAChD,GAAI,CACF,OAAO,MAAM,QAAA,QAAA,EAAA,KAAA,IAAAC,EAAA,QAAO,wBAAwB,CAAA,CAAA,CAC9C,MAAQ,CACN,MAAM,IAAIC,EAAAA,kCACR,oIAAA,CAGJ,CACF,CAGA,MAAMC,EAAmB,OAKlB,MAAMC,CAAe,CAClB,OACA,IACA,UACA,SACA,eAWR,YACEC,EACAC,EACAC,EACAC,EACAC,EACA,CACA,KAAK,OAASJ,EACd,KAAK,IAAMC,EACX,KAAK,UAAYC,EACjB,KAAK,SAAWC,EAChB,KAAK,eAAiBC,CACxB,CAgBA,MAAM,MACJC,EACAC,EAAmC,GACM,CACzC,GAAID,EAAS,OAASP,EACpB,MAAM,IAAI,MAAM,iDAAiD,EAMnE,MAAMS,EAAe,IAAI,KAAK,IAAI,2BAA2B,CAC3D,YAAaF,EACb,UAAW,KAAK,UAChB,sBAAuB,CACrB,SAAU,KAAK,QAAA,EAEjB,oBAAqB,KAAK,eACtB,CAAE,eAAgB,KAAK,gBACvB,MAAA,CACL,EAGKG,GADgB,MAAM,KAAK,OAAO,KAAKD,CAAY,GAClB,iBAEvC,GAAI,CAACC,EACH,MAAM,IAAIC,EAAAA,WAAW,iCAAiC,EAIxD,aAAM,KAAK,uBAAuBD,EAAkBH,CAAQ,EAGrD,KAAK,gBAAgBG,CAAgB,CAC9C,CAKA,MAAc,uBACZA,EACAE,EACe,CAGf,MAAMC,EAAY,KAAK,IAAA,EAEvB,KAAO,KAAK,MAAQA,EAAY,KAAa,CAC3C,MAAMC,EAAU,IAAI,KAAK,IAAI,yBAAyB,CACpD,iBAAkBJ,CAAA,CACnB,EACKK,EAAW,MAAM,KAAK,OAAO,KAAKD,CAAO,EACzCE,EAAQD,EAAS,gBAAgB,QAAQ,MAE/C,GAAIC,IAAU,KAAK,IAAI,oBAAoB,UACzC,OAGF,GACEA,IAAU,KAAK,IAAI,oBAAoB,QACvCA,IAAU,KAAK,IAAI,oBAAoB,UACvC,CACA,MAAMC,EACJF,EAAS,gBAAgB,QAAQ,mBAAqB,gBAExD,GAAIE,EAAO,SAAS,iBAAiB,EAAG,CACtC,MAAMC,EAAYD,EAAO,MAAM,GAAG,EAAE,IAAA,GAAO,QAAU,GACrD,MAAM,IAAIE,EAAAA,kBACR,kIAEED,EACA,GAAA,CAEN,CAEA,MAAM,IAAIP,EAAAA,WACR,iBAAiBC,CAAa,aAAaK,CAAM,EAAA,CAErD,CAEA,MAAM,IAAI,QAASG,GAAY,WAAWA,EAAS,GAAY,CAAC,CAClE,CAEA,MAAM,IAAIT,EAAAA,WACR,yBAAyB,IAAcf,CAAuB,UAAA,CAElE,CAKA,MAAc,gBACZc,EACyC,CACzC,MAAMW,EAA0C,CAAA,EAChD,IAAIC,EACAC,EAAwB,CAAA,EACxBC,EAAc,GAElB,EAAG,CACD,MAAMV,EAAU,IAAI,KAAK,IAAI,uBAAuB,CAClD,iBAAkBJ,EAClB,UAAWY,CAAA,CACZ,EAEKP,EAAW,MAAM,KAAK,OAAO,KAAKD,CAAO,EAE3CU,GAAeT,EAAS,WAAW,mBAAmB,aACxDQ,EAAcR,EAAS,UAAU,kBAAkB,WAAW,IAC5D,CAACU,EAAKC,IAAQ,CAEZ,MAAMC,EAAOF,EAAI,KACjB,OAAOE,GAAQA,EAAK,KAAA,IAAW,GAAKA,EAAO,UAAUD,CAAG,EAC1D,CAAA,GAIJ,MAAME,EAAOb,EAAS,WAAW,MAAQ,CAAA,EAEnCc,EAAWL,EAAcI,EAAK,MAAM,CAAC,EAAIA,EAE/C,UAAWE,KAAOD,EAAU,CAC1B,MAAME,EAAmC,CAAA,EACzCD,EAAI,MAAM,QAAQ,CAACE,EAAMC,IAAU,CAEjC,MAAMC,EAAaX,EAAYU,CAAK,GAAK,UAAUA,CAAK,GACxDF,EAAQG,CAAU,EAAIF,EAAK,cAAgB,IAC7C,CAAC,EACDX,EAAQ,KAAKU,CAAO,CACtB,CAEAT,EAAYP,EAAS,UACrBS,EAAc,EAChB,OAASF,GAET,OAAOD,CACT,CAKA,MAAM,OAAuB,CAC3B,KAAK,OAAO,QAAA,CACd,CACF,CAWA,eAAsBc,GAAgD,CAEpE,MAAMC,EAAY,MAAMvC,EAAA,EAElBwC,EAAU,QAAQ,IAAI,UAAY,GAClCC,EAAoBD,EAAQ,QAAQ,KAAM,GAAG,EAC7CE,EAAoB,QAAQ,IAAI,0BAChCC,EAAe,QAAQ,IAAI,WAC3BC,EAAe,GAAGH,CAAiB,iBACnCI,EAAkBL,EAElBnC,EAAS,IAAIkC,EAAU,aAAa,CACxC,OAAQI,CAAA,CACT,EAGD,GAAI,CACF,aAAMtC,EAAO,KACX,IAAIkC,EAAU,oBAAoB,CAChC,UAAWM,CAAA,CACZ,CAAA,EAII,IAAIzC,EAAeC,EAAQkC,EAAWM,EAAiBD,CAAY,CAC5E,MAAQ,CAGN,GAAI,CAACF,EACH,MAAM,IAAI,MACR,sKAAA,EAKJ,MAAMI,EAAuB,QAAQJ,CAAiB,IAAID,CAAiB,IAC3E,OAAO,IAAIrC,EACTC,EACAkC,EACA,UACAK,EACAE,CAAA,CAEJ,CACF"}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Athena Data Provider
|
|
3
|
+
*
|
|
4
|
+
* TypeScript equivalent of AthenaProvider from
|
|
5
|
+
* ts-lib-ui-kit-streamlit/tetrascience/data_app_providers/provider.py
|
|
6
|
+
*
|
|
7
|
+
* @remarks
|
|
8
|
+
* This provider requires the `@aws-sdk/client-athena` package to be installed.
|
|
9
|
+
* It is an optional peer dependency - install it only if you need Athena support:
|
|
10
|
+
* ```bash
|
|
11
|
+
* npm install @aws-sdk/client-athena
|
|
12
|
+
* # or
|
|
13
|
+
* yarn add @aws-sdk/client-athena
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
type AthenaClient = import('@aws-sdk/client-athena').AthenaClient;
|
|
17
|
+
type AthenaSDK = typeof import("@aws-sdk/client-athena");
|
|
18
|
+
/**
|
|
19
|
+
* Athena data provider
|
|
20
|
+
*/
|
|
21
|
+
export declare class AthenaProvider {
|
|
22
|
+
private client;
|
|
23
|
+
private sdk;
|
|
24
|
+
private workgroup;
|
|
25
|
+
private database;
|
|
26
|
+
private outputLocation?;
|
|
27
|
+
/**
|
|
28
|
+
* Initialize the Athena data provider
|
|
29
|
+
*
|
|
30
|
+
* @param client - AWS Athena client
|
|
31
|
+
* @param sdk - AWS Athena SDK module (for accessing command classes)
|
|
32
|
+
* @param workgroup - Athena workgroup to use
|
|
33
|
+
* @param database - Default database/schema
|
|
34
|
+
* @param outputLocation - Optional S3 output location
|
|
35
|
+
*/
|
|
36
|
+
constructor(client: AthenaClient, sdk: AthenaSDK, workgroup: string, database: string, outputLocation?: string);
|
|
37
|
+
/**
|
|
38
|
+
* Query the Athena database
|
|
39
|
+
*
|
|
40
|
+
* @param sqlQuery - SQL query to execute
|
|
41
|
+
* @param _params - Parameters to pass to the query (currently not used - Athena doesn't support parameterized queries)
|
|
42
|
+
* @returns Promise resolving to array of row objects
|
|
43
|
+
*
|
|
44
|
+
* @remarks
|
|
45
|
+
* **Security Note:** AWS Athena does not support parameterized queries.
|
|
46
|
+
* Unlike traditional databases, there is no native way to use bind parameters
|
|
47
|
+
* with Athena. Callers are responsible for properly sanitizing any user input
|
|
48
|
+
* before constructing the SQL query string. This is a known limitation of the
|
|
49
|
+
* Athena service, not a design flaw in this implementation.
|
|
50
|
+
*/
|
|
51
|
+
query(sqlQuery: string, _params?: Record<string, unknown>): Promise<Array<Record<string, unknown>>>;
|
|
52
|
+
/**
|
|
53
|
+
* Wait for query to complete
|
|
54
|
+
*/
|
|
55
|
+
private waitForQueryCompletion;
|
|
56
|
+
/**
|
|
57
|
+
* Fetch all results from a completed query
|
|
58
|
+
*/
|
|
59
|
+
private fetchAllResults;
|
|
60
|
+
/**
|
|
61
|
+
* Close the Athena client (no-op for AWS SDK clients)
|
|
62
|
+
*/
|
|
63
|
+
close(): Promise<void>;
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Get the TDP Athena provider
|
|
67
|
+
*
|
|
68
|
+
* Creates an Athena provider using TDP environment configuration
|
|
69
|
+
*
|
|
70
|
+
* @returns Promise resolving to Athena data provider
|
|
71
|
+
* @throws {InvalidProviderConfigurationError} If @aws-sdk/client-athena is not installed
|
|
72
|
+
* @throws {Error} If ATHENA_S3_OUTPUT_LOCATION is not set when using the 'primary' workgroup
|
|
73
|
+
*/
|
|
74
|
+
export declare function getTdpAthenaProvider(): Promise<AthenaProvider>;
|
|
75
|
+
export {};
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";
|
|
1
|
+
"use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const o=require("./exceptions.cjs");function p(t){const e=Object.create(null,{[Symbol.toStringTag]:{value:"Module"}});if(t){for(const s in t)if(s!=="default"){const i=Object.getOwnPropertyDescriptor(t,s);Object.defineProperty(e,s,i.get?i:{enumerable:!0,get:()=>t[s]})}}return e.default=t,Object.freeze(e)}async function b(){try{return await Promise.resolve().then(()=>p(require("@databricks/sql")))}catch{throw new o.InvalidProviderConfigurationError("The '@databricks/sql' package is required to use the Databricks provider. Please install it: npm install @databricks/sql")}}class c{client;session;constructor(e,s){this.client=e,this.session=s}async query(e,s={}){const i=await this.session.executeStatement(e);try{return await i.fetchAll()}finally{await i.close()}}async close(){await this.session.close(),await this.client.close()}}function g(){return`${(process.env.ORG_SLUG??"").replace(/-/g,"_")}__tss__default`}async function v(t){const{DBSQLClient:e}=await b(),s=["server_hostname","http_path","client_id","client_secret","catalog"];for(const n of s)if(!t.fields[n])throw new o.InvalidProviderConfigurationError(`Missing field '${n}' in the provider '${t.name}' to connect to Databricks.`);const i=t.fields.server_hostname,a=t.fields.http_path,l=t.fields.client_id,u=t.fields.client_secret,d=t.fields.catalog,h=t.fields.schema??g(),r=new e;await r.connect({host:i,path:a,authType:"databricks-oauth",oauthClientId:l,oauthClientSecret:u});const f=await r.openSession({initialCatalog:d,initialSchema:h});return new c(r,f)}exports.DatabricksProvider=c;exports.buildDatabricksProvider=v;
|
|
2
2
|
//# sourceMappingURL=DatabricksProvider.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"DatabricksProvider.cjs","sources":["../../../src/server/providers/DatabricksProvider.ts"],"sourcesContent":["/**\n * Databricks Data Provider\n *\n * TypeScript equivalent of DatabricksProvider from\n * ts-lib-ui-kit-streamlit/tetrascience/data_app_providers/provider.py\n *\n * @remarks\n * This provider requires the `@databricks/sql` package to be installed.\n * It is an optional peer dependency - install it only if you need Databricks support:\n * ```bash\n * npm install @databricks/sql\n * # or\n * yarn add @databricks/sql\n * ```\n */\n\nimport { InvalidProviderConfigurationError } from \"./exceptions\";\n\nimport type { ProviderConfiguration } from \"./types\";\n\n// Type imports for @databricks/sql (these don't require the package at runtime)\ntype DBSQLClient = import(\"@databricks/sql\").DBSQLClient;\ntype IDBSQLSession = import(\"@databricks/sql/dist/contracts/IDBSQLSession\").default;\n\n/**\n * Dynamically import @databricks/sql\n * @throws {InvalidProviderConfigurationError} If @databricks/sql is not installed\n */\nasync function getDatabricksSQL(): Promise<typeof import(\"@databricks/sql\")> {\n try {\n return await import(\"@databricks/sql\");\n } catch {\n throw new InvalidProviderConfigurationError(\n \"The '@databricks/sql' package is required to use the Databricks provider. \" +\n \"Please install it: npm install @databricks/sql\",\n );\n }\n}\n\n/**\n * Databricks data provider\n */\nexport class DatabricksProvider {\n private client: DBSQLClient;\n private session: IDBSQLSession;\n\n /**\n * Initialize the Databricks data provider\n *\n * @param client - Databricks SQL client\n * @param session - Databricks SQL session\n */\n constructor(client: DBSQLClient, session: IDBSQLSession) {\n this.client = client;\n this.session = session;\n }\n\n /**\n * Query the Databricks database\n *\n * @param sqlQuery - SQL query to execute\n * @param _params - Parameters to pass to the query (currently not used)\n * @returns Promise resolving to array of row objects\n */\n async query(\n sqlQuery: string,\n _params: Record<string, unknown> = {},\n ): Promise<Array<Record<string, unknown>>> {\n const operation = await this.session.executeStatement(sqlQuery);\n try {\n const result = await operation.fetchAll();\n return result as Array<Record<string, unknown>>;\n } finally {\n // Always close the operation to avoid leaking server-side resources\n await operation.close();\n }\n }\n\n /**\n * Close the Databricks connection\n */\n async close(): Promise<void> {\n await this.session.close();\n await this.client.close();\n }\n}\n\n/**\n * Get the default Athena schema from environment\n */\nfunction getDefaultSchema(): string {\n const orgSlug = process.env.ORG_SLUG ?? \"\";\n const orgSlugDbFriendly = orgSlug.replace(/-/g, \"_\");\n return `${orgSlugDbFriendly}__tss__default`;\n}\n\n/**\n * Build a Databricks data provider from the configuration\n *\n * @param config - Provider configuration\n * @returns Promise resolving to Databricks data provider\n * @throws {InvalidProviderConfigurationError} If @databricks/sql is not installed or config is invalid\n */\nexport async function buildDatabricksProvider(\n config: ProviderConfiguration,\n): Promise<DatabricksProvider> {\n // Dynamically import @databricks/sql\n const { DBSQLClient } = await getDatabricksSQL();\n\n const requiredFields = [\n \"server_hostname\",\n \"http_path\",\n \"client_id\",\n \"client_secret\",\n \"catalog\",\n ] as const;\n\n for (const field of requiredFields) {\n if (!config.fields[field]) {\n throw new InvalidProviderConfigurationError(\n `Missing field '${field}' in the provider '${config.name}' to connect to Databricks.`,\n );\n }\n }\n\n const serverHostname = config.fields[\"server_hostname\"]!;\n const httpPath = config.fields[\"http_path\"]!;\n const clientId = config.fields[\"client_id\"]!;\n const clientSecret = config.fields[\"client_secret\"]!;\n const catalog = config.fields[\"catalog\"]!;\n const schema = config.fields[\"schema\"] ?? getDefaultSchema();\n\n const client = new DBSQLClient();\n\n await client.connect({\n host: serverHostname,\n path: httpPath,\n authType: \"databricks-oauth\",\n oauthClientId: clientId,\n oauthClientSecret: clientSecret,\n });\n\n const session = await client.openSession({\n initialCatalog: catalog,\n initialSchema: schema,\n });\n\n return new DatabricksProvider(client, session);\n}\n\n"],"names":["getDatabricksSQL","InvalidProviderConfigurationError","DatabricksProvider","client","session","sqlQuery","_params","operation","getDefaultSchema","buildDatabricksProvider","config","DBSQLClient","requiredFields","field","serverHostname","httpPath","clientId","clientSecret","catalog","schema"],"mappings":"
|
|
1
|
+
{"version":3,"file":"DatabricksProvider.cjs","sources":["../../../src/server/providers/DatabricksProvider.ts"],"sourcesContent":["/**\n * Databricks Data Provider\n *\n * TypeScript equivalent of DatabricksProvider from\n * ts-lib-ui-kit-streamlit/tetrascience/data_app_providers/provider.py\n *\n * @remarks\n * This provider requires the `@databricks/sql` package to be installed.\n * It is an optional peer dependency - install it only if you need Databricks support:\n * ```bash\n * npm install @databricks/sql\n * # or\n * yarn add @databricks/sql\n * ```\n */\n\nimport { InvalidProviderConfigurationError } from \"./exceptions\";\n\nimport type { ProviderConfiguration } from \"./types\";\n\n// Type imports for @databricks/sql (these don't require the package at runtime)\ntype DBSQLClient = import(\"@databricks/sql\").DBSQLClient;\ntype IDBSQLSession = import(\"@databricks/sql/dist/contracts/IDBSQLSession\").default;\n\n/**\n * Dynamically import @databricks/sql\n * @throws {InvalidProviderConfigurationError} If @databricks/sql is not installed\n */\nasync function getDatabricksSQL(): Promise<typeof import(\"@databricks/sql\")> {\n try {\n return await import(\"@databricks/sql\");\n } catch {\n throw new InvalidProviderConfigurationError(\n \"The '@databricks/sql' package is required to use the Databricks provider. \" +\n \"Please install it: npm install @databricks/sql\",\n );\n }\n}\n\n/**\n * Databricks data provider\n */\nexport class DatabricksProvider {\n private client: DBSQLClient;\n private session: IDBSQLSession;\n\n /**\n * Initialize the Databricks data provider\n *\n * @param client - Databricks SQL client\n * @param session - Databricks SQL session\n */\n constructor(client: DBSQLClient, session: IDBSQLSession) {\n this.client = client;\n this.session = session;\n }\n\n /**\n * Query the Databricks database\n *\n * @param sqlQuery - SQL query to execute\n * @param _params - Parameters to pass to the query (currently not used)\n * @returns Promise resolving to array of row objects\n */\n async query(\n sqlQuery: string,\n _params: Record<string, unknown> = {},\n ): Promise<Array<Record<string, unknown>>> {\n const operation = await this.session.executeStatement(sqlQuery);\n try {\n const result = await operation.fetchAll();\n return result as Array<Record<string, unknown>>;\n } finally {\n // Always close the operation to avoid leaking server-side resources\n await operation.close();\n }\n }\n\n /**\n * Close the Databricks connection\n */\n async close(): Promise<void> {\n await this.session.close();\n await this.client.close();\n }\n}\n\n/**\n * Get the default Athena schema from environment\n */\nfunction getDefaultSchema(): string {\n const orgSlug = process.env.ORG_SLUG ?? \"\";\n const orgSlugDbFriendly = orgSlug.replace(/-/g, \"_\");\n return `${orgSlugDbFriendly}__tss__default`;\n}\n\n/**\n * Build a Databricks data provider from the configuration\n *\n * @param config - Provider configuration\n * @returns Promise resolving to Databricks data provider\n * @throws {InvalidProviderConfigurationError} If @databricks/sql is not installed or config is invalid\n */\nexport async function buildDatabricksProvider(\n config: ProviderConfiguration,\n): Promise<DatabricksProvider> {\n // Dynamically import @databricks/sql\n const { DBSQLClient } = await getDatabricksSQL();\n\n const requiredFields = [\n \"server_hostname\",\n \"http_path\",\n \"client_id\",\n \"client_secret\",\n \"catalog\",\n ] as const;\n\n for (const field of requiredFields) {\n if (!config.fields[field]) {\n throw new InvalidProviderConfigurationError(\n `Missing field '${field}' in the provider '${config.name}' to connect to Databricks.`,\n );\n }\n }\n\n const serverHostname = config.fields[\"server_hostname\"]!;\n const httpPath = config.fields[\"http_path\"]!;\n const clientId = config.fields[\"client_id\"]!;\n const clientSecret = config.fields[\"client_secret\"]!;\n const catalog = config.fields[\"catalog\"]!;\n const schema = config.fields[\"schema\"] ?? getDefaultSchema();\n\n const client = new DBSQLClient();\n\n await client.connect({\n host: serverHostname,\n path: httpPath,\n authType: \"databricks-oauth\",\n oauthClientId: clientId,\n oauthClientSecret: clientSecret,\n });\n\n const session = await client.openSession({\n initialCatalog: catalog,\n initialSchema: schema,\n });\n\n return new DatabricksProvider(client, session);\n}\n\n"],"names":["getDatabricksSQL","_interopNamespaceDefault","InvalidProviderConfigurationError","DatabricksProvider","client","session","sqlQuery","_params","operation","getDefaultSchema","buildDatabricksProvider","config","DBSQLClient","requiredFields","field","serverHostname","httpPath","clientId","clientSecret","catalog","schema"],"mappings":"iYA4BA,eAAeA,GAA8D,CAC3E,GAAI,CACF,OAAO,MAAM,QAAA,QAAA,EAAA,KAAA,IAAAC,EAAA,QAAO,iBAAiB,CAAA,CAAA,CACvC,MAAQ,CACN,MAAM,IAAIC,EAAAA,kCACR,0HAAA,CAGJ,CACF,CAKO,MAAMC,CAAmB,CACtB,OACA,QAQR,YAAYC,EAAqBC,EAAwB,CACvD,KAAK,OAASD,EACd,KAAK,QAAUC,CACjB,CASA,MAAM,MACJC,EACAC,EAAmC,GACM,CACzC,MAAMC,EAAY,MAAM,KAAK,QAAQ,iBAAiBF,CAAQ,EAC9D,GAAI,CAEF,OADe,MAAME,EAAU,SAAA,CAEjC,QAAA,CAEE,MAAMA,EAAU,MAAA,CAClB,CACF,CAKA,MAAM,OAAuB,CAC3B,MAAM,KAAK,QAAQ,MAAA,EACnB,MAAM,KAAK,OAAO,MAAA,CACpB,CACF,CAKA,SAASC,GAA2B,CAGlC,MAAO,IAFS,QAAQ,IAAI,UAAY,IACN,QAAQ,KAAM,GAAG,CACxB,gBAC7B,CASA,eAAsBC,EACpBC,EAC6B,CAE7B,KAAM,CAAE,YAAAC,GAAgB,MAAMZ,EAAA,EAExBa,EAAiB,CACrB,kBACA,YACA,YACA,gBACA,SAAA,EAGF,UAAWC,KAASD,EAClB,GAAI,CAACF,EAAO,OAAOG,CAAK,EACtB,MAAM,IAAIZ,EAAAA,kCACR,kBAAkBY,CAAK,sBAAsBH,EAAO,IAAI,6BAAA,EAK9D,MAAMI,EAAiBJ,EAAO,OAAO,gBAC/BK,EAAWL,EAAO,OAAO,UACzBM,EAAWN,EAAO,OAAO,UACzBO,EAAeP,EAAO,OAAO,cAC7BQ,EAAUR,EAAO,OAAO,QACxBS,EAAST,EAAO,OAAO,QAAaF,EAAA,EAEpCL,EAAS,IAAIQ,EAEnB,MAAMR,EAAO,QAAQ,CACnB,KAAMW,EACN,KAAMC,EACN,SAAU,mBACV,cAAeC,EACf,kBAAmBC,CAAA,CACpB,EAED,MAAMb,EAAU,MAAMD,EAAO,YAAY,CACvC,eAAgBe,EAChB,cAAeC,CAAA,CAChB,EAED,OAAO,IAAIjB,EAAmBC,EAAQC,CAAO,CAC/C"}
|