@datalayer/core 1.0.3 → 1.0.11

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (111) hide show
  1. package/lib/api/constants.d.ts +3 -0
  2. package/lib/api/constants.js +3 -0
  3. package/lib/api/runtimes/checkpoints.d.ts +122 -0
  4. package/lib/api/runtimes/checkpoints.js +118 -0
  5. package/lib/api/runtimes/index.d.ts +1 -0
  6. package/lib/api/runtimes/index.js +1 -0
  7. package/lib/api/runtimes/runtimes.d.ts +84 -0
  8. package/lib/api/runtimes/runtimes.js +50 -0
  9. package/lib/components/auth/Login.js +1 -1
  10. package/lib/components/display/BusyDots.d.ts +9 -0
  11. package/lib/components/display/BusyDots.js +31 -0
  12. package/lib/components/display/LiveRelativeTime.d.ts +10 -0
  13. package/lib/components/display/LiveRelativeTime.js +21 -0
  14. package/lib/components/display/index.d.ts +2 -0
  15. package/lib/components/display/index.js +2 -0
  16. package/lib/components/flashes/FlashSurveys.js +1 -1
  17. package/lib/components/index.d.ts +1 -0
  18. package/lib/components/index.js +1 -0
  19. package/lib/components/navbar/SubdomainNavBar.js +1 -1
  20. package/lib/components/progress/ConsumptionBar.js +6 -7
  21. package/lib/components/progress/CreditsIndicator.js +2 -2
  22. package/lib/components/progress/consumption.d.ts +12 -0
  23. package/lib/components/progress/consumption.js +31 -0
  24. package/lib/components/progress/index.d.ts +1 -0
  25. package/lib/components/progress/index.js +1 -0
  26. package/lib/components/sparklines/Sparklines.d.ts +16 -0
  27. package/lib/components/sparklines/Sparklines.js +65 -0
  28. package/lib/components/sparklines/SparklinesLine.d.ts +8 -0
  29. package/lib/components/sparklines/SparklinesLine.js +37 -0
  30. package/lib/components/sparklines/dataProcessing.d.ts +25 -0
  31. package/lib/components/sparklines/dataProcessing.js +35 -0
  32. package/lib/components/sparklines/index.d.ts +4 -0
  33. package/lib/components/sparklines/index.js +7 -0
  34. package/lib/components/sparklines/types.d.ts +36 -0
  35. package/lib/components/sparklines/types.js +5 -0
  36. package/lib/components/storage/ContentsBrowser.js +17 -1
  37. package/lib/components/subnav/SubNav.js +1 -1
  38. package/lib/hooks/useCache.d.ts +5 -67
  39. package/lib/hooks/useCache.js +15 -213
  40. package/lib/hooks/useProjects.d.ts +1 -1
  41. package/lib/models/ItemDTO.js +1 -1
  42. package/lib/models/RolesPlatform.js +2 -2
  43. package/lib/models/User.d.ts +2 -0
  44. package/lib/models/User.js +4 -1
  45. package/lib/otel/client/OtelClient.d.ts +93 -0
  46. package/lib/otel/client/OtelClient.js +232 -0
  47. package/lib/otel/client/index.d.ts +2 -0
  48. package/lib/otel/client/index.js +5 -0
  49. package/lib/otel/{hooks.d.ts → hooks/index.d.ts} +15 -1
  50. package/lib/otel/{hooks.js → hooks/index.js} +58 -16
  51. package/lib/otel/index.d.ts +29 -20
  52. package/lib/otel/index.js +19 -15
  53. package/lib/otel/{OtelLive.d.ts → views/OtelLive.d.ts} +1 -1
  54. package/lib/otel/{OtelLive.js → views/OtelLive.js} +22 -4
  55. package/lib/otel/{OtelLogsList.d.ts → views/OtelLogsList.d.ts} +1 -1
  56. package/lib/otel/{OtelLogsList.js → views/OtelLogsList.js} +1 -1
  57. package/lib/otel/{OtelMetricsChart.d.ts → views/OtelMetricsChart.d.ts} +1 -1
  58. package/lib/otel/{OtelMetricsList.d.ts → views/OtelMetricsList.d.ts} +1 -1
  59. package/lib/otel/{OtelMetricsList.js → views/OtelMetricsList.js} +1 -1
  60. package/lib/otel/{OtelSearchBar.d.ts → views/OtelSearchBar.d.ts} +1 -1
  61. package/lib/otel/{OtelSpanDetail.d.ts → views/OtelSpanDetail.d.ts} +1 -1
  62. package/lib/otel/{OtelSpanDetail.js → views/OtelSpanDetail.js} +1 -1
  63. package/lib/otel/{OtelSpanTree.d.ts → views/OtelSpanTree.d.ts} +1 -1
  64. package/lib/otel/{OtelSpanTree.js → views/OtelSpanTree.js} +1 -1
  65. package/lib/otel/{OtelSqlView.js → views/OtelSqlView.js} +1 -1
  66. package/lib/otel/{OtelSystemView.js → views/OtelSystemView.js} +1 -1
  67. package/lib/otel/{OtelTimeline.d.ts → views/OtelTimeline.d.ts} +1 -1
  68. package/lib/otel/{OtelTimeline.js → views/OtelTimeline.js} +1 -1
  69. package/lib/otel/{OtelTimelineRangeSlider.d.ts → views/OtelTimelineRangeSlider.d.ts} +1 -1
  70. package/lib/otel/{OtelTracesList.d.ts → views/OtelTracesList.d.ts} +1 -1
  71. package/lib/otel/{OtelTracesList.js → views/OtelTracesList.js} +1 -1
  72. package/lib/otel/views/index.d.ts +20 -0
  73. package/lib/otel/views/index.js +21 -0
  74. package/lib/state/substates/CoreState.js +6 -6
  75. package/lib/utils/Date.d.ts +6 -0
  76. package/lib/utils/Date.js +37 -0
  77. package/lib/views/iam/SignInSimple.d.ts +5 -0
  78. package/lib/views/iam/SignInSimple.js +39 -6
  79. package/lib/views/iam-tokens/IAMTokenEdit.d.ts +5 -1
  80. package/lib/views/iam-tokens/IAMTokenEdit.js +3 -3
  81. package/lib/views/iam-tokens/IAMTokenNew.js +2 -2
  82. package/lib/views/iam-tokens/IAMTokens.d.ts +4 -2
  83. package/lib/views/iam-tokens/IAMTokens.js +4 -4
  84. package/lib/views/index.d.ts +1 -0
  85. package/lib/views/index.js +1 -0
  86. package/lib/views/otel/DashboardView.d.ts +16 -0
  87. package/lib/views/otel/DashboardView.js +4 -0
  88. package/lib/views/otel/LogsView.d.ts +12 -0
  89. package/lib/views/otel/LogsView.js +4 -0
  90. package/lib/views/otel/MetricsView.d.ts +12 -0
  91. package/lib/views/otel/MetricsView.js +4 -0
  92. package/lib/views/otel/OtelHeader.d.ts +33 -0
  93. package/lib/views/otel/OtelHeader.js +105 -0
  94. package/lib/views/otel/SqlView.d.ts +9 -0
  95. package/lib/views/otel/SqlView.js +4 -0
  96. package/lib/views/otel/SystemView.d.ts +9 -0
  97. package/lib/views/otel/SystemView.js +4 -0
  98. package/lib/views/otel/TracesView.d.ts +12 -0
  99. package/lib/views/otel/TracesView.js +4 -0
  100. package/lib/views/otel/index.d.ts +16 -0
  101. package/lib/views/otel/index.js +12 -0
  102. package/lib/views/otel/simpleAuthStore.d.ts +21 -0
  103. package/lib/views/otel/simpleAuthStore.js +22 -0
  104. package/lib/views/profile/UserBadge.d.ts +2 -0
  105. package/lib/views/profile/UserBadge.js +3 -3
  106. package/package.json +1 -26
  107. /package/lib/otel/{OtelMetricsChart.js → views/OtelMetricsChart.js} +0 -0
  108. /package/lib/otel/{OtelSearchBar.js → views/OtelSearchBar.js} +0 -0
  109. /package/lib/otel/{OtelSqlView.d.ts → views/OtelSqlView.d.ts} +0 -0
  110. /package/lib/otel/{OtelSystemView.d.ts → views/OtelSystemView.d.ts} +0 -0
  111. /package/lib/otel/{OtelTimelineRangeSlider.js → views/OtelTimelineRangeSlider.js} +0 -0
@@ -1,4 +1,4 @@
1
- import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
2
  /*
3
3
  * Copyright (c) 2023-2025 Datalayer, Inc.
4
4
  * Distributed under the terms of the Modified BSD License.
@@ -12,16 +12,21 @@ import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
12
12
  *
13
13
  * @module views/signin
14
14
  */
15
- import { useState, useCallback } from 'react';
16
- import { Box, Button, FormControl, Heading, Text, TextInput, } from '@primer/react';
17
- import { EyeIcon, EyeClosedIcon, TelescopeIcon } from '@primer/octicons-react';
15
+ import { useState, useCallback, useRef } from 'react';
16
+ import { Box, Button, FormControl, Heading, Text, Textarea, TextInput, } from '@primer/react';
17
+ import { Dialog } from '@primer/react/experimental';
18
+ import { EyeIcon, EyeClosedIcon, KeyIcon, TelescopeIcon, } from '@primer/octicons-react';
18
19
  // ── Component ────────────────────────────────────────────────────────
19
- export const SignInSimple = ({ onSignIn, loginUrl = '/api/iam/v1/login', title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', leadingIcon = _jsx(TelescopeIcon, { size: 24 }), }) => {
20
+ export const SignInSimple = ({ onSignIn, onApiKeySignIn, loginUrl = '/api/iam/v1/login', title = 'Datalayer OTEL', description = 'Sign in to access the observability dashboard.', leadingIcon = _jsx(TelescopeIcon, { size: 24 }), }) => {
20
21
  const [handle, setHandle] = useState('');
21
22
  const [password, setPassword] = useState('');
22
23
  const [showPassword, setShowPassword] = useState(false);
23
24
  const [loading, setLoading] = useState(false);
24
25
  const [error, setError] = useState(null);
26
+ // API Key dialog state
27
+ const [showApiKeyDialog, setShowApiKeyDialog] = useState(false);
28
+ const [apiKey, setApiKey] = useState('');
29
+ const apiKeyRef = useRef(null);
25
30
  const submit = useCallback(async () => {
26
31
  if (!handle || !password || loading)
27
32
  return;
@@ -75,6 +80,34 @@ export const SignInSimple = ({ onSignIn, loginUrl = '/api/iam/v1/login', title =
75
80
  gap: 2,
76
81
  mb: 4,
77
82
  justifyContent: 'center',
78
- }, children: [leadingIcon, _jsx(Heading, { sx: { fontSize: 3 }, children: title })] }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', mb: 3, textAlign: 'center' }, children: description }), _jsxs(FormControl, { required: true, sx: { mb: 3 }, children: [_jsx(FormControl.Label, { children: "Username" }), _jsx(TextInput, { autoFocus: true, block: true, placeholder: "Your username", value: handle, onChange: e => setHandle(e.target.value), onKeyDown: handleKeyDown })] }), _jsxs(FormControl, { required: true, sx: { mb: 3 }, children: [_jsx(FormControl.Label, { children: "Password" }), _jsx(TextInput, { block: true, placeholder: "Your password", type: showPassword ? 'text' : 'password', value: password, onChange: e => setPassword(e.target.value), onKeyDown: handleKeyDown, trailingAction: _jsx(TextInput.Action, { onClick: () => setShowPassword(!showPassword), icon: showPassword ? EyeClosedIcon : EyeIcon, "aria-label": showPassword ? 'Hide password' : 'Show password', sx: { color: 'var(--fgColor-muted)' } }) })] }), error && (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1, mb: 3, display: 'block' }, children: error })), _jsx(Button, { variant: "primary", block: true, disabled: loading || !handle || !password, onClick: submit, children: loading ? 'Signing in…' : 'Sign in' })] }) }));
83
+ }, children: [leadingIcon, _jsx(Heading, { sx: { fontSize: 3 }, children: title })] }), _jsx(Text, { as: "p", sx: { fontSize: 1, color: 'fg.muted', mb: 3, textAlign: 'center' }, children: description }), _jsxs(FormControl, { required: true, sx: { mb: 3 }, children: [_jsx(FormControl.Label, { children: "Username" }), _jsx(TextInput, { autoFocus: true, block: true, placeholder: "Your username", value: handle, onChange: e => setHandle(e.target.value), onKeyDown: handleKeyDown })] }), _jsxs(FormControl, { required: true, sx: { mb: 3 }, children: [_jsx(FormControl.Label, { children: "Password" }), _jsx(TextInput, { block: true, placeholder: "Your password", type: showPassword ? 'text' : 'password', value: password, onChange: e => setPassword(e.target.value), onKeyDown: handleKeyDown, trailingAction: _jsx(TextInput.Action, { onClick: () => setShowPassword(!showPassword), icon: showPassword ? EyeClosedIcon : EyeIcon, "aria-label": showPassword ? 'Hide password' : 'Show password', sx: { color: 'var(--fgColor-muted)' } }) })] }), error && (_jsx(Text, { sx: { color: 'danger.fg', fontSize: 1, mb: 3, display: 'block' }, children: error })), _jsx(Button, { variant: "primary", block: true, disabled: loading || !handle || !password, onClick: submit, children: loading ? 'Signing in…' : 'Sign in' }), onApiKeySignIn && (_jsxs(_Fragment, { children: [_jsxs(Box, { sx: {
84
+ display: 'flex',
85
+ alignItems: 'center',
86
+ gap: 2,
87
+ my: 3,
88
+ }, children: [_jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } }), _jsx(Text, { sx: { fontSize: 0, color: 'fg.muted' }, children: "or" }), _jsx(Box, { sx: { flex: 1, height: '1px', bg: 'border.default' } })] }), _jsx(Button, { block: true, leadingVisual: KeyIcon, onClick: () => setShowApiKeyDialog(true), children: "Sign in with API Key" }), showApiKeyDialog && (_jsx(Dialog, { title: "Enter your API Key", onClose: () => {
89
+ setShowApiKeyDialog(false);
90
+ setApiKey('');
91
+ }, initialFocusRef: apiKeyRef, footerButtons: [
92
+ {
93
+ buttonType: 'default',
94
+ onClick: () => {
95
+ setShowApiKeyDialog(false);
96
+ setApiKey('');
97
+ },
98
+ content: 'Cancel',
99
+ },
100
+ {
101
+ buttonType: 'primary',
102
+ onClick: () => {
103
+ if (apiKey.trim()) {
104
+ onApiKeySignIn(apiKey.trim());
105
+ setShowApiKeyDialog(false);
106
+ setApiKey('');
107
+ }
108
+ },
109
+ content: 'Authenticate',
110
+ },
111
+ ], children: _jsx(Box, { as: "form", children: _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "API Key" }), _jsx(Textarea, { block: true, required: true, autoFocus: true, placeholder: "Paste your API key here", value: apiKey, onInput: (e) => setApiKey(e.target.value), ref: apiKeyRef })] }) }) }))] }))] }) }));
79
112
  };
80
113
  export default SignInSimple;
@@ -1,2 +1,6 @@
1
- export declare const IAMTokenEdit: () => import("react/jsx-runtime").JSX.Element;
1
+ export type IAMTokenEditProps = {
2
+ /** Route to navigate after delete. Defaults to '/settings/iam/tokens'. */
3
+ tokensListRoute?: string;
4
+ };
5
+ export declare const IAMTokenEdit: ({ tokensListRoute, }?: IAMTokenEditProps) => import("react/jsx-runtime").JSX.Element;
2
6
  export default IAMTokenEdit;
@@ -10,7 +10,7 @@ import { Box } from '@datalayer/primer-addons';
10
10
  import { BoringAvatar } from '../../components/avatars';
11
11
  import { useCache, useNavigate, useToast } from '../../hooks';
12
12
  import { useRunStore } from '../../state';
13
- export const IAMTokenEdit = () => {
13
+ export const IAMTokenEdit = ({ tokensListRoute = '/settings/iam/tokens', } = {}) => {
14
14
  const { tokenId } = useParams();
15
15
  const runStore = useRunStore();
16
16
  const navigate = useNavigate();
@@ -100,7 +100,7 @@ export const IAMTokenEdit = () => {
100
100
  enqueueToast('The token is successfully deleted.', {
101
101
  variant: 'success',
102
102
  });
103
- navigate('/settings/iam/tokens');
103
+ navigate(tokensListRoute);
104
104
  }
105
105
  else {
106
106
  enqueueToast(resp.message || 'Failed to delete token.', {
@@ -116,7 +116,7 @@ export const IAMTokenEdit = () => {
116
116
  },
117
117
  });
118
118
  };
119
- return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(Heading, { sx: { fontSize: 3 }, children: "IAM Token" }) }), _jsxs(Box, { display: "flex", children: [_jsxs(Box, { children: [_jsx(BoringAvatar, { displayName: token?.name, size: 100, style: { paddingRight: 10 } }), _jsx(Text, { as: "h2", sx: { paddingTop: 3 }, children: token?.name }), _jsx(Box, { mt: 3, children: _jsx(Label, { size: "large", children: token?.variant }) })] }), _jsxs(Box, { ml: 10, children: [_jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: nameNameChange }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: nameDescriptionChange, rows: 5 }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Expiration date" }), _jsx(TextInput, { block: true, value: token?.expirationDate.toLocaleDateString(), onChange: nameNameChange, disabled: true })] }), _jsx(Button, { variant: "primary", disabled: !validationResult.name || !validationResult.description, sx: { marginTop: 3 }, onClick: nameSubmit, children: "Update token" })] }), _jsxs(Box, { sx: { marginTop: 3 }, children: [_jsx(Heading, { as: "h2", sx: {
119
+ return (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(Heading, { sx: { fontSize: 3 }, children: "API Key" }) }), _jsxs(Box, { display: "flex", children: [_jsxs(Box, { children: [_jsx(BoringAvatar, { displayName: token?.name, size: 100, style: { paddingRight: 10 } }), _jsx(Text, { as: "h2", sx: { paddingTop: 3 }, children: token?.name }), _jsx(Box, { mt: 3, children: _jsx(Label, { size: "large", children: token?.variant }) })] }), _jsxs(Box, { ml: 10, children: [_jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: nameNameChange }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: nameDescriptionChange, rows: 5 }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsxs(FormControl, { children: [_jsx(FormControl.Label, { children: "Expiration date" }), _jsx(TextInput, { block: true, value: token?.expirationDate.toLocaleDateString(), onChange: nameNameChange, disabled: true })] }), _jsx(Button, { variant: "primary", disabled: !validationResult.name || !validationResult.description, sx: { marginTop: 3 }, onClick: nameSubmit, children: "Update token" })] }), _jsxs(Box, { sx: { marginTop: 3 }, children: [_jsx(Heading, { as: "h2", sx: {
120
120
  fontSize: 4,
121
121
  fontWeight: 'normal',
122
122
  color: 'danger.fg',
@@ -95,7 +95,7 @@ export const IAMTokenNew = ({ tokensListRoute = '/settings/iam/tokens', } = {})
95
95
  },
96
96
  });
97
97
  };
98
- return (_jsx(Box, { children: showToken ? (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "Your Token is created" }) }) }), _jsx(Box, { children: _jsx(Text, { children: "Take note of the Token value, you won't be able to see it after." }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Name: ", token?.name] }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Description: ", token?.description] }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Expiration date: ", token?.expirationDate.toISOString()] }) }), _jsxs(Box, { children: [_jsx(Text, { mb: 2, children: "Value: " }), _jsxs(Box, { display: "flex", sx: { alignItems: 'center', gap: 2 }, children: [_jsx(Text, { as: "code", sx: {
98
+ return (_jsx(Box, { children: showToken ? (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "Your API Key is created" }) }) }), _jsx(Box, { children: _jsx(Text, { children: "Take note of the API Key value, you will not be able to see it after." }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Name: ", token?.name] }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Description: ", token?.description] }) }), _jsx(Box, { children: _jsxs(Text, { children: ["Expiration date: ", token?.expirationDate.toISOString()] }) }), _jsxs(Box, { children: [_jsx(Text, { mb: 2, children: "Value: " }), _jsxs(Box, { display: "flex", sx: { alignItems: 'center', gap: 2 }, children: [_jsx(Text, { as: "code", sx: {
99
99
  color: 'fg.onEmphasis',
100
100
  bg: 'neutral.emphasis',
101
101
  p: 2,
@@ -108,7 +108,7 @@ export const IAMTokenNew = ({ tokensListRoute = '/settings/iam/tokens', } = {})
108
108
  variant: 'success',
109
109
  });
110
110
  }
111
- } })] })] }), _jsx(Box, { mt: 3, children: _jsx(Button, { onClick: e => navigate(tokensListRoute, e), children: "List my Tokens" }) })] })) : (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "New IAM Token" }) }) }), _jsx(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", sx: { gap: 3 }, children: _jsx(Box, { children: _jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Token type" }), _jsx(Select, { name: "type", value: formValues.variant, onChange: valueVariantChange, children: _jsx(Select.Option, { value: "user_token", children: "User Token" }) }), _jsx(FormControl.Caption, { children: "Pick the most appropriate token type." })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: valueNameChange, autoFocus: true }), _jsx(FormControl.Caption, { children: "Hint: The token name is a short name that identifies in a unique way your token." }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name length must be between 2 and 32 characters." }))] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Expiration day" }), _jsx(Calendar, { showGoToToday: true, onSelectDate: expirationDateChange, value: formValues.expirationDate, strings: defaultCalendarStrings }), validationResult.expirationDate !== true ? (_jsx(FormControl.Validation, { variant: "error", children: "Pick an expiration date in the future." })) : (_jsxs(FormControl.Validation, { variant: "success", children: ["Expiration date:", ' ', formValues.expirationDate?.toLocaleDateString(), "."] }))] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: valueDescriptionChange }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsx(Button, { variant: "primary", disabled: !validationResult.name ||
111
+ } })] })] }), _jsx(Box, { mt: 3, children: _jsx(Button, { onClick: e => navigate(tokensListRoute, e), children: "List my API Keys" }) })] })) : (_jsxs(_Fragment, { children: [_jsx(PageHeader, { children: _jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "New API Key" }) }) }), _jsx(Box, { display: "grid", gridTemplateColumns: "1fr 1fr", sx: { gap: 3 }, children: _jsx(Box, { children: _jsxs(Box, { sx: { label: { marginTop: 2 } }, children: [_jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Token type" }), _jsx(Select, { name: "type", value: formValues.variant, onChange: valueVariantChange, children: _jsx(Select.Option, { value: "user_token", children: "User Token" }) }), _jsx(FormControl.Caption, { children: "Pick the most appropriate token type." })] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Name" }), _jsx(TextInput, { block: true, value: formValues.name, onChange: valueNameChange, autoFocus: true }), _jsx(FormControl.Caption, { children: "Hint: The token name is a short name that identifies in a unique way your token." }), validationResult.name === false && (_jsx(FormControl.Validation, { variant: "error", children: "Name length must be between 2 and 32 characters." }))] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Expiration day" }), _jsx(Calendar, { showGoToToday: true, onSelectDate: expirationDateChange, value: formValues.expirationDate, strings: defaultCalendarStrings }), validationResult.expirationDate !== true ? (_jsx(FormControl.Validation, { variant: "error", children: "Pick an expiration date in the future." })) : (_jsxs(FormControl.Validation, { variant: "success", children: ["Expiration date:", ' ', formValues.expirationDate?.toLocaleDateString(), "."] }))] }), _jsxs(FormControl, { required: true, children: [_jsx(FormControl.Label, { children: "Description" }), _jsx(Textarea, { block: true, value: formValues.description, onChange: valueDescriptionChange }), validationResult.description === false && (_jsx(FormControl.Validation, { variant: "error", children: "Description must have more than 2 characters." }))] }), _jsx(Button, { variant: "primary", disabled: !validationResult.name ||
112
112
  !validationResult.description ||
113
113
  !validationResult.expirationDate, sx: { marginTop: 2 }, onClick: e => {
114
114
  e.preventDefault();
@@ -1,8 +1,10 @@
1
1
  export type IAMTokensProps = {
2
- /** Route to navigate when clicking "New IAM token" button. Defaults to '/new/token'. */
2
+ /** Route to navigate when clicking "New API Key" button. Defaults to '/new/token'. */
3
3
  newTokenRoute?: string;
4
4
  /** Base route for the tokens list (used for edit navigation). Defaults to current relative path. */
5
5
  tokensListRoute?: string;
6
+ /** Whether to display view titles/headings. Defaults to true. */
7
+ showTitle?: boolean;
6
8
  };
7
- export declare const IAMTokens: ({ newTokenRoute, tokensListRoute, }?: IAMTokensProps) => import("react/jsx-runtime").JSX.Element;
9
+ export declare const IAMTokens: ({ newTokenRoute, tokensListRoute, showTitle, }?: IAMTokensProps) => import("react/jsx-runtime").JSX.Element;
8
10
  export default IAMTokens;
@@ -10,7 +10,7 @@ import { Box } from '@datalayer/primer-addons';
10
10
  import { EditIcon } from '@datalayer/icons-react';
11
11
  import { TrashIcon } from '@primer/octicons-react';
12
12
  import { useCache, useNavigate, useToast } from '../../hooks';
13
- const TokensTable = ({ tokensListRoute }) => {
13
+ const TokensTable = ({ tokensListRoute, showTitle = true, }) => {
14
14
  const { useTokens, useDeleteToken } = useCache();
15
15
  const { enqueueToast } = useToast();
16
16
  const getTokensQuery = useTokens();
@@ -46,7 +46,7 @@ const TokensTable = ({ tokensListRoute }) => {
46
46
  onSettled: () => setDeletingToken(null),
47
47
  });
48
48
  };
49
- return tokens.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [_jsx(Blankslate.Heading, { children: "IAM Tokens" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "No IAM Tokens found." }) })] })) : (_jsxs(_Fragment, { children: [_jsxs(Table.Container, { children: [_jsx(Table.Title, { as: "h2", id: "tokens", children: "IAM Tokens" }), _jsx(Table.Subtitle, { as: "p", id: "tokens-subtitle", children: "Your tokens." }), _jsx(DataTable, { "aria-labelledby": "teams", "aria-describedby": "teams-subtitle", data: tokens, columns: [
49
+ return tokens.length === 0 ? (_jsxs(Blankslate, { border: true, spacious: true, children: [showTitle && _jsx(Blankslate.Heading, { children: "API Keys" }), _jsx(Blankslate.Description, { children: _jsx(Text, { sx: { textAlign: 'center' }, children: "No API Keys found." }) })] })) : (_jsxs(_Fragment, { children: [_jsxs(Table.Container, { children: [showTitle && (_jsxs(_Fragment, { children: [_jsx(Table.Title, { as: "h2", id: "tokens", children: "API Keys" }), _jsx(Table.Subtitle, { as: "p", id: "tokens-subtitle", children: "Your tokens." })] })), _jsx(DataTable, { "aria-labelledby": "teams", "aria-describedby": "teams-subtitle", data: tokens, columns: [
50
50
  {
51
51
  header: 'Type',
52
52
  field: 'variant',
@@ -80,8 +80,8 @@ const TokensTable = ({ tokensListRoute }) => {
80
80
  setDeletingToken(null);
81
81
  }, confirmButtonContent: "Delete", confirmButtonType: "danger", children: ["Are you sure you want to delete the token", ' ', _jsx("strong", { children: deletingToken.name }), "? This action cannot be undone."] }))] }));
82
82
  };
83
- export const IAMTokens = ({ newTokenRoute = '/new/token', tokensListRoute, } = {}) => {
83
+ export const IAMTokens = ({ newTokenRoute = '/new/token', tokensListRoute, showTitle = true, } = {}) => {
84
84
  const navigate = useNavigate();
85
- return (_jsxs(PageLayout, { containerWidth: "full", padding: "normal", style: { overflow: 'visible', minHeight: 'calc(100vh - 45px)' }, children: [_jsx(PageLayout.Header, { children: _jsxs(PageHeader, { children: [_jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "IAM Tokens" }) }), _jsx(PageHeader.Actions, { children: _jsx(Button, { size: "small", variant: "primary", onClick: e => navigate(newTokenRoute, e), children: "New IAM token" }) })] }) }), _jsx(PageLayout.Content, { children: _jsx(Box, { children: _jsx(TokensTable, { tokensListRoute: tokensListRoute }) }) })] }));
85
+ return (_jsxs(PageLayout, { containerWidth: "full", padding: "normal", style: { overflow: 'visible', minHeight: 'calc(100vh - 45px)' }, children: [_jsx(PageLayout.Header, { children: _jsxs(PageHeader, { children: [showTitle && (_jsx(PageHeader.TitleArea, { variant: "large", children: _jsx(PageHeader.Title, { children: "API Keys" }) })), _jsx(PageHeader.Actions, { children: _jsx(Button, { size: "small", variant: "primary", onClick: e => navigate(newTokenRoute, e), children: "New API Key" }) })] }) }), _jsx(PageLayout.Content, { children: _jsx(Box, { children: _jsx(TokensTable, { tokensListRoute: tokensListRoute, showTitle: showTitle }) }) })] }));
86
86
  };
87
87
  export default IAMTokens;
@@ -1,2 +1,3 @@
1
1
  export * from './iam';
2
2
  export * from './profile';
3
+ export * from './otel';
@@ -4,3 +4,4 @@
4
4
  */
5
5
  export * from './iam';
6
6
  export * from './profile';
7
+ export * from './otel';
@@ -0,0 +1,16 @@
1
+ /**
2
+ * DashboardView – Full observability dashboard wrapping OtelLive.
3
+ */
4
+ import React from 'react';
5
+ export interface DashboardViewProps {
6
+ baseUrl?: string;
7
+ /** WebSocket base URL – passed directly to OtelLive to bypass any Vite proxy. */
8
+ wsBaseUrl?: string;
9
+ token?: string;
10
+ autoRefreshMs?: number;
11
+ defaultSignal?: 'traces' | 'logs' | 'metrics';
12
+ limit?: number;
13
+ /** Callback to receive the signal setter from OtelLive. */
14
+ onSignalRef?: (setter: (s: 'traces' | 'logs' | 'metrics') => void) => void;
15
+ }
16
+ export declare const DashboardView: React.FC<DashboardViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelLive } from '../../otel';
4
+ export const DashboardView = ({ baseUrl = '', wsBaseUrl, token, autoRefreshMs = 5000, defaultSignal = 'traces', limit = 200, onSignalRef, }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelLive, { baseUrl: baseUrl, wsBaseUrl: wsBaseUrl, token: token, autoRefreshMs: autoRefreshMs, defaultSignal: defaultSignal, limit: limit, onSignalRef: onSignalRef }) }));
@@ -0,0 +1,12 @@
1
+ /**
2
+ * LogsView – Standalone logs-only view.
3
+ * Renders OtelLive defaulting to the logs signal.
4
+ */
5
+ import React from 'react';
6
+ export interface LogsViewProps {
7
+ baseUrl?: string;
8
+ token?: string;
9
+ autoRefreshMs?: number;
10
+ limit?: number;
11
+ }
12
+ export declare const LogsView: React.FC<LogsViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelLive } from '../../otel';
4
+ export const LogsView = ({ baseUrl = '', token, autoRefreshMs = 5000, limit = 200, }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelLive, { baseUrl: baseUrl, token: token, autoRefreshMs: autoRefreshMs, defaultSignal: "logs", limit: limit }) }));
@@ -0,0 +1,12 @@
1
+ /**
2
+ * MetricsView – Standalone metrics-only view.
3
+ * Renders OtelLive defaulting to the metrics signal.
4
+ */
5
+ import React from 'react';
6
+ export interface MetricsViewProps {
7
+ baseUrl?: string;
8
+ token?: string;
9
+ autoRefreshMs?: number;
10
+ limit?: number;
11
+ }
12
+ export declare const MetricsView: React.FC<MetricsViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelLive } from '../../otel';
4
+ export const MetricsView = ({ baseUrl = '', token, autoRefreshMs = 5000, limit = 200, }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelLive, { baseUrl: baseUrl, token: token, autoRefreshMs: autoRefreshMs, defaultSignal: "metrics", limit: limit }) }));
@@ -0,0 +1,33 @@
1
+ /**
2
+ * OtelHeader – Top-level header bar with branding, signal generator
3
+ * buttons, and a result dialog for OTEL observability applications.
4
+ *
5
+ * This is a generic, reusable header. Authentication state is decoupled:
6
+ * pass `onSignOut` to wire up your own logout action.
7
+ */
8
+ import React from 'react';
9
+ export interface OtelHeaderProps {
10
+ /** Base URL for the generate API (e.g. '/api' or 'https://…'). Defaults to ''. */
11
+ baseUrl?: string;
12
+ /** JWT bearer token for authenticated requests. */
13
+ token?: string;
14
+ /** Optional extra controls rendered to the right of the generate buttons. */
15
+ trailing?: React.ReactNode;
16
+ /**
17
+ * Called before a generate request fires so a parent can navigate to
18
+ * the relevant signal view (e.g. 'logs', 'metrics').
19
+ */
20
+ onNavigate?: (signal: 'traces' | 'logs' | 'metrics') => void;
21
+ /**
22
+ * Optional sign-out handler. When provided a "Sign out" button is shown.
23
+ * Wire this to your auth store's clearAuth / signOut action.
24
+ */
25
+ onSignOut?: () => void;
26
+ /**
27
+ * Whether to show the "+ Traces / + Logs / + Metrics" generate buttons.
28
+ * Defaults to `true`. Pass `false` to hide them (e.g. in agent-runtime views
29
+ * where data is generated by agents, not manually).
30
+ */
31
+ showGenerateButtons?: boolean;
32
+ }
33
+ export declare const OtelHeader: React.FC<OtelHeaderProps>;
@@ -0,0 +1,105 @@
1
+ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
2
+ /*
3
+ * Copyright (c) 2023-2025 Datalayer, Inc.
4
+ * Distributed under the terms of the Modified BSD License.
5
+ */
6
+ /**
7
+ * OtelHeader – Top-level header bar with branding, signal generator
8
+ * buttons, and a result dialog for OTEL observability applications.
9
+ *
10
+ * This is a generic, reusable header. Authentication state is decoupled:
11
+ * pass `onSignOut` to wire up your own logout action.
12
+ */
13
+ import { useState, useCallback, useRef } from 'react';
14
+ import { Box, Text, Button, Dialog } from '@primer/react';
15
+ import { TelescopeIcon, SignOutIcon } from '@primer/octicons-react';
16
+ import { UserBadge } from '../profile';
17
+ export const OtelHeader = ({ baseUrl = '', token, trailing, onNavigate, onSignOut, showGenerateButtons = true, }) => {
18
+ const [dialogOpen, setDialogOpen] = useState(false);
19
+ const [dialogTitle, setDialogTitle] = useState('');
20
+ const [dialogRequest, setDialogRequest] = useState('');
21
+ const [dialogBody, setDialogBody] = useState('');
22
+ const [dialogVariant, setDialogVariant] = useState('success');
23
+ const [generating, setGenerating] = useState(false);
24
+ const returnFocusRef = useRef(null);
25
+ const generate = useCallback(async (kind, count) => {
26
+ if (onNavigate) {
27
+ const signalMap = {
28
+ traces: 'traces',
29
+ 'ai-traces': 'traces',
30
+ logs: 'logs',
31
+ metrics: 'metrics',
32
+ };
33
+ onNavigate(signalMap[kind]);
34
+ }
35
+ setGenerating(true);
36
+ const url = `${baseUrl}/api/generate/${kind}?count=${count}`;
37
+ setDialogRequest(`POST ${url}`);
38
+ try {
39
+ const headers = {};
40
+ if (token) {
41
+ headers['Authorization'] = `Bearer ${token}`;
42
+ }
43
+ const resp = await fetch(url, { method: 'POST', headers });
44
+ if (!resp.ok)
45
+ throw new Error(`HTTP ${resp.status}`);
46
+ const data = await resp.json();
47
+ setDialogTitle(`Generated ${kind}`);
48
+ setDialogBody(JSON.stringify(data, null, 2));
49
+ setDialogVariant('success');
50
+ }
51
+ catch (err) {
52
+ setDialogTitle(`Error generating ${kind}`);
53
+ setDialogBody(err instanceof Error ? err.message : String(err));
54
+ setDialogVariant('error');
55
+ }
56
+ finally {
57
+ setGenerating(false);
58
+ setDialogOpen(true);
59
+ }
60
+ }, [baseUrl, token, onNavigate]);
61
+ return (_jsxs(_Fragment, { children: [_jsxs(Box, { as: "header", sx: {
62
+ display: 'flex',
63
+ alignItems: 'center',
64
+ gap: 3,
65
+ px: 3,
66
+ py: 2,
67
+ bg: 'canvas.inset',
68
+ borderBottom: '1px solid',
69
+ borderColor: 'border.default',
70
+ flexShrink: 0,
71
+ // Allow overflow visible so the JWT popover can extend below the header.
72
+ overflow: 'visible',
73
+ }, children: [_jsxs(Box, { sx: { display: 'flex', alignItems: 'center', gap: 2 }, children: [_jsx(TelescopeIcon, { size: 20 }), _jsx(Text, { sx: { fontWeight: 'bold', fontSize: 2 }, children: "Datalayer OTEL" })] }), _jsx(Box, { sx: { flex: 1 } }), showGenerateButtons && (_jsxs(_Fragment, { children: [_jsx(Button, { ref: returnFocusRef, size: "small", variant: "primary", disabled: generating, onClick: () => generate('traces', 3), children: "+ Traces" }), _jsx(Button, { size: "small", variant: "primary", disabled: generating, onClick: () => generate('ai-traces', 3), children: "+ AI Traces" }), _jsx(Button, { size: "small", variant: "primary", disabled: generating, onClick: () => generate('logs', 10), children: "+ Logs" }), _jsx(Button, { size: "small", variant: "primary", disabled: generating, onClick: () => generate('metrics', 5), children: "+ Metrics" })] })), trailing, token && _jsx(UserBadge, { token: token }), onSignOut && (_jsx(Button, { size: "small", variant: "invisible", onClick: onSignOut, sx: { color: 'fg.muted' }, leadingVisual: SignOutIcon, children: "Sign out" }))] }), dialogOpen && (_jsxs(Dialog, { title: dialogTitle, onClose: () => setDialogOpen(false), footerButtons: [
74
+ {
75
+ content: 'Close',
76
+ onClick: () => setDialogOpen(false),
77
+ buttonType: 'default',
78
+ },
79
+ ], children: [_jsxs(Box, { sx: { mb: 2 }, children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1, color: 'fg.muted' }, children: "Request" }), _jsx(Box, { as: "pre", sx: {
80
+ fontFamily: 'mono',
81
+ fontSize: 1,
82
+ p: 2,
83
+ mt: 1,
84
+ bg: 'canvas.inset',
85
+ borderRadius: 2,
86
+ overflow: 'auto',
87
+ color: 'fg.default',
88
+ whiteSpace: 'pre-wrap',
89
+ wordBreak: 'break-all',
90
+ border: '1px solid',
91
+ borderColor: 'border.default',
92
+ }, children: dialogRequest })] }), _jsxs(Box, { children: [_jsx(Text, { sx: { fontWeight: 'bold', fontSize: 1, color: 'fg.muted' }, children: "Response" }), _jsx(Box, { as: "pre", sx: {
93
+ fontFamily: 'mono',
94
+ fontSize: 1,
95
+ p: 2,
96
+ mt: 1,
97
+ bg: 'canvas.subtle',
98
+ borderRadius: 2,
99
+ overflow: 'auto',
100
+ maxHeight: 300,
101
+ color: dialogVariant === 'error' ? 'danger.fg' : 'fg.default',
102
+ whiteSpace: 'pre-wrap',
103
+ wordBreak: 'break-all',
104
+ }, children: dialogBody })] })] }))] }));
105
+ };
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SqlView – Standalone SQL query view for exploring OTEL data.
3
+ */
4
+ import React from 'react';
5
+ export interface SqlViewProps {
6
+ baseUrl?: string;
7
+ token?: string;
8
+ }
9
+ export declare const SqlView: React.FC<SqlViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelSqlView } from '../../otel';
4
+ export const SqlView = ({ baseUrl = '', token }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelSqlView, { baseUrl: baseUrl, token: token }) }));
@@ -0,0 +1,9 @@
1
+ /**
2
+ * SystemView – OTEL system/infrastructure view.
3
+ */
4
+ import React from 'react';
5
+ export interface SystemViewProps {
6
+ baseUrl?: string;
7
+ token?: string;
8
+ }
9
+ export declare const SystemView: React.FC<SystemViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelSystemView } from '../../otel';
4
+ export const SystemView = ({ baseUrl = '', token, }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelSystemView, { baseUrl: baseUrl, token: token }) }));
@@ -0,0 +1,12 @@
1
+ /**
2
+ * TracesView – Standalone traces-only view.
3
+ * Renders OtelLive defaulting to the traces signal.
4
+ */
5
+ import React from 'react';
6
+ export interface TracesViewProps {
7
+ baseUrl?: string;
8
+ token?: string;
9
+ autoRefreshMs?: number;
10
+ limit?: number;
11
+ }
12
+ export declare const TracesView: React.FC<TracesViewProps>;
@@ -0,0 +1,4 @@
1
+ import { jsx as _jsx } from "react/jsx-runtime";
2
+ import { Box } from '@primer/react';
3
+ import { OtelLive } from '../../otel';
4
+ export const TracesView = ({ baseUrl = '', token, autoRefreshMs = 5000, limit = 200, }) => (_jsx(Box, { sx: { display: 'flex', flex: 1, minHeight: 0, overflow: 'hidden' }, children: _jsx(OtelLive, { baseUrl: baseUrl, token: token, autoRefreshMs: autoRefreshMs, defaultSignal: "traces", limit: limit }) }));
@@ -0,0 +1,16 @@
1
+ export { DashboardView } from './DashboardView';
2
+ export type { DashboardViewProps } from './DashboardView';
3
+ export { TracesView } from './TracesView';
4
+ export type { TracesViewProps } from './TracesView';
5
+ export { LogsView } from './LogsView';
6
+ export type { LogsViewProps } from './LogsView';
7
+ export { MetricsView } from './MetricsView';
8
+ export type { MetricsViewProps } from './MetricsView';
9
+ export { SqlView } from './SqlView';
10
+ export type { SqlViewProps } from './SqlView';
11
+ export { SystemView } from './SystemView';
12
+ export type { SystemViewProps } from './SystemView';
13
+ export { OtelHeader } from './OtelHeader';
14
+ export type { OtelHeaderProps } from './OtelHeader';
15
+ export { useSimpleAuthStore } from './simpleAuthStore';
16
+ export type { SimpleAuthState } from './simpleAuthStore';
@@ -0,0 +1,12 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ export { DashboardView } from './DashboardView';
6
+ export { TracesView } from './TracesView';
7
+ export { LogsView } from './LogsView';
8
+ export { MetricsView } from './MetricsView';
9
+ export { SqlView } from './SqlView';
10
+ export { SystemView } from './SystemView';
11
+ export { OtelHeader } from './OtelHeader';
12
+ export { useSimpleAuthStore } from './simpleAuthStore';
@@ -0,0 +1,21 @@
1
+ export interface SimpleAuthState {
2
+ /** JWT bearer token (from IAM login). */
3
+ token: string | null;
4
+ /** Authenticated user's handle. */
5
+ handle: string | null;
6
+ /** Set credentials after successful login. */
7
+ setAuth: (token: string, handle: string) => void;
8
+ /** Clear credentials (logout). */
9
+ clearAuth: () => void;
10
+ }
11
+ export declare const useSimpleAuthStore: import("zustand").UseBoundStore<Omit<import("zustand").StoreApi<SimpleAuthState>, "persist"> & {
12
+ persist: {
13
+ setOptions: (options: Partial<import("zustand/middleware").PersistOptions<SimpleAuthState, SimpleAuthState>>) => void;
14
+ clearStorage: () => void;
15
+ rehydrate: () => Promise<void> | void;
16
+ hasHydrated: () => boolean;
17
+ onHydrate: (fn: (state: SimpleAuthState) => void) => () => void;
18
+ onFinishHydration: (fn: (state: SimpleAuthState) => void) => () => void;
19
+ getOptions: () => Partial<import("zustand/middleware").PersistOptions<SimpleAuthState, SimpleAuthState>>;
20
+ };
21
+ }>;
@@ -0,0 +1,22 @@
1
+ /*
2
+ * Copyright (c) 2023-2025 Datalayer, Inc.
3
+ * Distributed under the terms of the Modified BSD License.
4
+ */
5
+ /**
6
+ * Minimal token-based authentication store.
7
+ *
8
+ * Persists a JWT bearer token and a user handle to localStorage so the
9
+ * session survives page refreshes. Intended for demo / example apps that
10
+ * need a lightweight auth layer without a full IAM integration.
11
+ *
12
+ * Import via the `@datalayer/core/views/otel` subpath:
13
+ * import { useSimpleAuthStore } from '@datalayer/core/views/otel';
14
+ */
15
+ import { create } from 'zustand';
16
+ import { persist } from 'zustand/middleware';
17
+ export const useSimpleAuthStore = create()(persist((set) => ({
18
+ token: null,
19
+ handle: null,
20
+ setAuth: (token, handle) => set({ token, handle }),
21
+ clearAuth: () => set({ token: null, handle: null }),
22
+ }), { name: 'datalayer-simple-auth' }));
@@ -13,6 +13,8 @@ import React from 'react';
13
13
  export interface UserBadgeProps {
14
14
  /** Raw JWT bearer token. */
15
15
  token: string;
16
+ /** Display variant for the claims overlay. */
17
+ variant?: 'full' | 'small';
16
18
  }
17
19
  export declare const UserBadge: React.FC<UserBadgeProps>;
18
20
  export default UserBadge;
@@ -18,7 +18,7 @@ import { useState, useRef, useCallback } from 'react';
18
18
  import { Box, Text } from '@primer/react';
19
19
  import { parseJwtPayload, getDatalayerJwtUser, getDatalayerDisplayName, } from '../../utils/Jwt';
20
20
  // ── Component ─────────────────────────────────────────────────────
21
- export const UserBadge = ({ token }) => {
21
+ export const UserBadge = ({ token, variant = 'full', }) => {
22
22
  const [open, setOpen] = useState(false);
23
23
  const closeTimer = useRef(null);
24
24
  const handleEnter = useCallback(() => {
@@ -85,7 +85,7 @@ export const UserBadge = ({ token }) => {
85
85
  borderRadius: 1,
86
86
  border: '1px solid',
87
87
  borderColor: 'accent.muted',
88
- }, children: r }, r))) })] })), _jsx(Box, { as: "pre", sx: {
88
+ }, children: r }, r))) })] })), variant === 'full' && (_jsx(Box, { as: "pre", sx: {
89
89
  m: 0,
90
90
  px: 3,
91
91
  py: 2,
@@ -96,6 +96,6 @@ export const UserBadge = ({ token }) => {
96
96
  overflow: 'auto',
97
97
  maxHeight: '220px',
98
98
  whiteSpace: 'pre',
99
- }, children: JSON.stringify(claims, null, 2) })] }))] }));
99
+ }, children: JSON.stringify(claims, null, 2) }))] }))] }));
100
100
  };
101
101
  export default UserBadge;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@datalayer/core",
3
- "version": "1.0.3",
3
+ "version": "1.0.11",
4
4
  "type": "module",
5
5
  "workspaces": [
6
6
  ".",
@@ -28,30 +28,6 @@
28
28
  ],
29
29
  "main": "lib/index.js",
30
30
  "types": "lib/index.d.ts",
31
- "exports": {
32
- ".": {
33
- "types": "./lib/index.d.ts",
34
- "default": "./lib/index.js"
35
- },
36
- "./otel": {
37
- "types": "./lib/otel/index.d.ts",
38
- "default": "./lib/otel/index.js"
39
- },
40
- "./views/iam": {
41
- "types": "./lib/views/iam/index.d.ts",
42
- "default": "./lib/views/iam/index.js"
43
- },
44
- "./views/profile": {
45
- "types": "./lib/views/profile/index.d.ts",
46
- "default": "./lib/views/profile/index.js"
47
- },
48
- "./utils/jwt": {
49
- "types": "./lib/utils/Jwt.d.ts",
50
- "default": "./lib/utils/Jwt.js"
51
- },
52
- "./style/*": "./style/*",
53
- "./*": "./*"
54
- },
55
31
  "style": "style/index.css",
56
32
  "repository": {
57
33
  "type": "git",
@@ -220,7 +196,6 @@
220
196
  "@types/node": "^20.11.0",
221
197
  "@types/react": "18.3.20",
222
198
  "@types/react-dom": "18.3.6",
223
- "@types/react-syntax-highlighter": "^15.5.13",
224
199
  "@vitejs/plugin-react": "^4.5.2",
225
200
  "@vitest/browser": "^3.2.4",
226
201
  "@vitest/coverage-v8": "^3.2.4",