@datalayer/core 1.1.60 → 1.1.66
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 +2 -2
- package/lib/api/DatalayerApi.d.ts +42 -1
- package/lib/api/DatalayerApi.js +90 -3
- package/lib/api/constants.d.ts +18 -0
- package/lib/api/constants.js +18 -0
- package/lib/api/contents/attachments.d.ts +9 -0
- package/lib/api/contents/attachments.js +43 -0
- package/lib/api/contents/bridges.d.ts +22 -0
- package/lib/api/contents/bridges.js +79 -0
- package/lib/api/contents/capabilities.d.ts +11 -0
- package/lib/api/contents/capabilities.js +21 -0
- package/lib/api/contents/cloudStorage.d.ts +31 -0
- package/lib/api/contents/cloudStorage.js +89 -0
- package/lib/api/contents/dataservers.d.ts +37 -0
- package/lib/api/contents/dataservers.js +121 -0
- package/lib/api/contents/datasets.d.ts +15 -0
- package/lib/api/contents/datasets.js +45 -0
- package/lib/api/contents/datasources.d.ts +70 -0
- package/lib/api/contents/datasources.js +149 -0
- package/lib/api/contents/generated.d.ts +1070 -0
- package/lib/api/contents/index.d.ts +16 -0
- package/lib/api/contents/index.js +20 -0
- package/lib/api/contents/mcp.d.ts +46 -0
- package/lib/api/contents/mcp.js +157 -0
- package/lib/api/contents/objects.d.ts +31 -0
- package/lib/api/contents/objects.js +88 -0
- package/lib/api/contents/operations.d.ts +3 -0
- package/lib/api/contents/operations.js +19 -0
- package/lib/api/contents/runtimeMounts.d.ts +40 -0
- package/lib/api/contents/runtimeMounts.js +59 -0
- package/lib/api/contents/sandboxUid.d.ts +53 -0
- package/lib/api/contents/sandboxUid.js +78 -0
- package/lib/api/contents/sources.d.ts +19 -0
- package/lib/api/contents/sources.js +119 -0
- package/lib/api/contents/sync.d.ts +18 -0
- package/lib/api/contents/sync.js +69 -0
- package/lib/api/contents/transfers.d.ts +38 -0
- package/lib/api/contents/transfers.js +123 -0
- package/lib/api/iam/connectedAgents.d.ts +39 -0
- package/lib/api/iam/connectedAgents.js +52 -0
- package/lib/api/iam/index.d.ts +2 -1
- package/lib/api/iam/index.js +2 -1
- package/lib/api/iam/mcpAlertRules.d.ts +51 -0
- package/lib/api/iam/mcpAlertRules.js +198 -0
- package/lib/api/iam/mcpAuditSettings.d.ts +46 -0
- package/lib/api/iam/mcpAuditSettings.js +120 -0
- package/lib/api/iam/mcpPolicy.d.ts +80 -0
- package/lib/api/iam/mcpPolicy.js +132 -0
- package/lib/api/iam/organizationTeams.d.ts +13 -0
- package/lib/api/iam/organizationTeams.js +43 -0
- package/lib/api/iam/serviceAgents.d.ts +68 -0
- package/lib/api/iam/serviceAgents.js +119 -0
- package/lib/api/index.d.ts +4 -1
- package/lib/api/index.js +3 -1
- package/lib/api/mcp/activity.d.ts +37 -0
- package/lib/api/mcp/activity.js +26 -0
- package/lib/api/mcp/alerts.d.ts +25 -0
- package/lib/api/mcp/alerts.js +51 -0
- package/lib/api/mcp/audit.d.ts +29 -0
- package/lib/api/mcp/audit.js +55 -0
- package/lib/api/mcp/bindings.d.ts +18 -0
- package/lib/api/mcp/bindings.js +42 -0
- package/lib/api/mcp/forwarding.d.ts +25 -0
- package/lib/api/mcp/forwarding.js +46 -0
- package/lib/api/mcp/gateway.d.ts +16 -0
- package/lib/api/mcp/gateway.js +70 -0
- package/lib/api/mcp/generated.d.ts +22 -0
- package/lib/api/mcp/generated.js +213 -0
- package/lib/api/mcp/index.d.ts +17 -0
- package/lib/api/mcp/index.js +25 -0
- package/lib/api/mcp/observability.d.ts +125 -0
- package/lib/api/mcp/observability.js +254 -0
- package/lib/api/mcp/operations.d.ts +83 -0
- package/lib/api/mcp/operations.js +50 -0
- package/lib/api/mcp/organizations.d.ts +102 -0
- package/lib/api/mcp/organizations.js +46 -0
- package/lib/api/mcp/policy.d.ts +9 -0
- package/lib/api/mcp/policy.js +23 -0
- package/lib/api/mcp/tasks.d.ts +49 -0
- package/lib/api/mcp/tasks.js +147 -0
- package/lib/api/utils/validation.d.ts +1 -1
- package/lib/api/utils/validation.js +1 -1
- package/lib/client/auth/index.js +0 -5
- package/lib/client/auth/storage.js +0 -5
- package/lib/client/auth/strategies.js +0 -5
- package/lib/client/base.d.ts +6 -0
- package/lib/client/base.js +8 -0
- package/lib/client/index.d.ts +0 -10
- package/lib/client/index.js +2 -2
- package/lib/client/mixins/ContentsMixin.d.ts +71 -0
- package/lib/client/mixins/ContentsMixin.js +157 -0
- package/lib/client/mixins/IAMMixin.d.ts +0 -31
- package/lib/client/mixins/IAMMixin.js +0 -58
- package/lib/components/animation/AnimatedText.d.ts +1 -0
- package/lib/components/animation/AnimatedText.js +0 -4
- package/lib/components/auth/SigInAPIKey.d.ts +1 -0
- package/lib/components/auth/SigInAPIKey.js +0 -6
- package/lib/components/auth/SignIn.d.ts +1 -0
- package/lib/components/auth/SignIn.js +0 -4
- package/lib/components/auth/SignIn.stories.d.ts +2 -2
- package/lib/components/avatars/BoringAvatar.d.ts +1 -1
- package/lib/components/avatars/BoringAvatar.stories.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.d.ts +1 -1
- package/lib/components/avatars/DLAvatar.js +0 -4
- package/lib/components/avatars/UserAvatar.d.ts +9 -0
- package/lib/components/avatars/UserAvatar.js +0 -12
- package/lib/components/avatars/UserProfileAvatar.d.ts +1 -1
- package/lib/components/banners/NoAutomationBanner.d.ts +1 -1
- package/lib/components/billing/BillingEntitySelect.d.ts +10 -0
- package/lib/components/billing/BillingEntitySelect.js +0 -17
- package/lib/components/billing/index.js +0 -4
- package/lib/components/buttons/DownloadCSVButton.d.ts +1 -1
- package/lib/components/buttons/DownloadJsonButton.d.ts +1 -1
- package/lib/components/buttons/LongActionButton.d.ts +1 -0
- package/lib/components/buttons/LongActionButton.js +0 -4
- package/lib/components/buttons/UploadButton.d.ts +1 -0
- package/lib/components/buttons/UploadButton.js +0 -4
- package/lib/components/checkout/StripeCheckout.d.ts +1 -1
- package/lib/components/collaboration/LiveEditorCollaborators.d.ts +31 -0
- package/lib/components/collaboration/LiveEditorCollaborators.js +86 -53
- package/lib/components/collaboration/index.js +0 -4
- package/lib/components/confetti/ConfettiSuccess.d.ts +1 -1
- package/lib/components/contents/ContentSourceCard.d.ts +8 -0
- package/lib/components/contents/ContentSourceCard.js +23 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.d.ts +10 -0
- package/lib/components/contents/HomeFolderObjectsBrowser.js +148 -0
- package/lib/components/contents/index.d.ts +2 -0
- package/lib/components/contents/index.js +6 -0
- package/lib/components/context/OrganizationSelect.d.ts +1 -1
- package/lib/components/display/AvatarSkeleton.d.ts +1 -1
- package/lib/components/display/BusyDots.d.ts +1 -1
- package/lib/components/display/CenteredSpinner.d.ts +1 -1
- package/lib/components/display/CodePreview.d.ts +1 -1
- package/lib/components/display/DatalayerBox.d.ts +7 -2
- package/lib/components/display/DatalayerBox.js +6 -6
- package/lib/components/display/HorizontalCenter.d.ts +1 -1
- package/lib/components/display/JupyterDialog.d.ts +1 -0
- package/lib/components/display/JupyterDialog.js +1 -7
- package/lib/components/display/Markdown.d.ts +1 -0
- package/lib/components/display/NotebookSkeleton.d.ts +1 -1
- package/lib/components/display/Placeholder.d.ts +1 -1
- package/lib/components/display/ToTopBranded.d.ts +1 -1
- package/lib/components/echarts/EChartsReact.d.ts +1 -1
- package/lib/components/flashes/FlashClosable.d.ts +1 -0
- package/lib/components/flashes/FlashClosable.js +0 -4
- package/lib/components/flashes/FlashGuest.d.ts +1 -1
- package/lib/components/flashes/FlashSurveys.d.ts +1 -1
- package/lib/components/flashes/FlashUnauthorized.d.ts +1 -0
- package/lib/components/flashes/FlashUnauthorized.js +0 -6
- package/lib/components/flashes/surveys/Survey2025_1.d.ts +1 -1
- package/lib/components/iam/ExternalTokenSilentLogin.d.ts +1 -1
- package/lib/components/index.d.ts +2 -0
- package/lib/components/index.js +2 -0
- package/lib/components/labels/StatusLabels.d.ts +1 -0
- package/lib/components/labels/VisibilityLabel.d.ts +1 -1
- package/lib/components/landings/StepBlock.d.ts +1 -1
- package/lib/components/mcp/ClientBadge.d.ts +41 -0
- package/lib/components/mcp/ClientBadge.js +33 -0
- package/lib/components/mcp/McpErrorBlankslate.d.ts +21 -0
- package/lib/components/mcp/McpErrorBlankslate.js +17 -0
- package/lib/components/mcp/ScopeList.d.ts +28 -0
- package/lib/components/mcp/ScopeList.js +14 -0
- package/lib/components/mcp/index.d.ts +10 -0
- package/lib/components/mcp/index.js +18 -0
- package/lib/components/navbar/NavigationVisbilityObserver.d.ts +2 -1
- package/lib/components/navbar/SubdomainNavBar.d.ts +10 -5
- package/lib/components/navbar/SubdomainNavBar.js +2 -1
- package/lib/components/notebooks/JupyterNotebook.d.ts +1 -1
- package/lib/components/notebooks/JupyterNotebookToolbar.d.ts +1 -1
- package/lib/components/principal/PrincipalAppearance.d.ts +1 -0
- package/lib/components/principal/PrincipalAppearance.js +0 -8
- package/lib/components/principal/PrincipalAvatar.d.ts +1 -0
- package/lib/components/principal/PrincipalAvatar.js +17 -9
- package/lib/components/principal/PrincipalBadge.d.ts +1 -1
- package/lib/components/principal/PrincipalBanner.d.ts +1 -1
- package/lib/components/principal/PrincipalDetailsOverlay.d.ts +31 -1
- package/lib/components/principal/PrincipalDetailsOverlay.js +64 -33
- package/lib/components/principal/PrincipalHoverCard.d.ts +31 -0
- package/lib/components/principal/PrincipalHoverCard.js +52 -0
- package/lib/components/principal/PrincipalSwitcherMenu.d.ts +1 -0
- package/lib/components/principal/PrincipalSwitcherMenu.js +5 -14
- package/lib/components/principal/index.d.ts +2 -1
- package/lib/components/principal/index.js +2 -1
- package/lib/components/progress/ConsumptionBar.d.ts +1 -0
- package/lib/components/progress/ConsumptionBar.js +0 -4
- package/lib/components/progress/ProgressRing.d.ts +1 -0
- package/lib/components/progress/SpinnerBar.d.ts +1 -1
- package/lib/components/progress/Timer.d.ts +1 -0
- package/lib/components/progress/Timer.js +0 -4
- package/lib/components/screencapture/ScreencaptureButton.d.ts +1 -1
- package/lib/components/sharing/ShareAccessComponent.d.ts +15 -1
- package/lib/components/sharing/ShareAccessComponent.js +36 -23
- package/lib/components/sharing/SharingEditor.d.ts +17 -0
- package/lib/components/sharing/SharingEditor.js +0 -24
- package/lib/components/sparklines/Sparklines.js +3 -4
- package/lib/components/sparklines/index.js +0 -4
- package/lib/components/storage/ContentsBrowser.d.ts +25 -1
- package/lib/components/storage/ContentsBrowser.js +145 -52
- package/lib/components/storage/ContentsBrowserMock.d.ts +3 -0
- package/lib/components/storage/ContentsBrowserMock.js +75 -0
- package/lib/components/storage/ContentsItems.d.ts +2 -1
- package/lib/components/storage/ContentsItems.js +0 -4
- package/lib/components/storage/ContentsTable.d.ts +50 -0
- package/lib/components/storage/ContentsTable.js +134 -0
- package/lib/components/storage/HomeFolderDrive.d.ts +71 -0
- package/lib/components/storage/HomeFolderDrive.js +248 -0
- package/lib/components/storage/index.d.ts +2 -0
- package/lib/components/storage/index.js +2 -0
- package/lib/components/students/StudentItemStatus.d.ts +1 -1
- package/lib/components/students/StudentResultCircle.d.ts +1 -1
- package/lib/components/subnav/SubNav.d.ts +5 -5
- package/lib/components/subnav/SubNav.js +11 -9
- package/lib/components/tables/DataTable.d.ts +1 -1
- package/lib/components/text-reveal/TextRevealAnimation.d.ts +2 -2
- package/lib/components/text-reveal/useTextRevealAnimationLines.d.ts +1 -1
- package/lib/components/time/LiveRelativeTime.d.ts +1 -0
- package/lib/components/time/LiveRelativeTime.js +0 -8
- package/lib/components/time/index.js +0 -4
- package/lib/components/timeline/Timeline.d.ts +1 -1
- package/lib/components/timeline/index.js +0 -4
- package/lib/components/users/PeerIndicator.d.ts +1 -0
- package/lib/components/users/PeerIndicator.js +0 -4
- package/lib/config/Configuration.d.ts +15 -17
- package/lib/config/Configuration.js +7 -0
- package/lib/hooks/index.d.ts +2 -0
- package/lib/hooks/index.js +2 -0
- package/lib/hooks/layouts/LayoutBackdrop.d.ts +1 -1
- package/lib/hooks/layouts/LayoutScreencapture.d.ts +1 -1
- package/lib/hooks/useBackdrop.d.ts +1 -1
- package/lib/hooks/useBackdropJupyterLab.d.ts +3 -2
- package/lib/hooks/useBackdropJupyterLab.js +0 -4
- package/lib/hooks/useCache.d.ts +310 -105
- package/lib/hooks/useCache.js +142 -355
- package/lib/hooks/useContainsFocus.d.ts +1 -1
- package/lib/hooks/useContents.d.ts +313 -0
- package/lib/hooks/useContents.js +964 -0
- package/lib/hooks/useFocusTrap.d.ts +4 -4
- package/lib/hooks/useFocusTrap.js +1 -1
- package/lib/hooks/useMcp.d.ts +229 -0
- package/lib/hooks/useMcp.js +656 -0
- package/lib/hooks/useMobile.js +0 -5
- package/lib/hooks/useProjectStore.d.ts +3 -3
- package/lib/hooks/useProjectStore.js +4 -4
- package/lib/hooks/useRef.d.ts +1 -1
- package/lib/hooks/useRef.js +3 -0
- package/lib/hooks/useScreencapture.d.ts +2 -1
- package/lib/hooks/useScreencapture.js +0 -4
- package/lib/hooks/useToast.js +0 -4
- package/lib/hooks/useVisibilityObserver.d.ts +1 -1
- package/lib/index.d.ts +4 -1
- package/lib/index.js +3 -1
- package/lib/mocks/components/FlashMock.d.ts +1 -1
- package/lib/mocks/views/ActionMenuMock.d.ts +1 -1
- package/lib/mocks/views/ChartMock.d.ts +1 -1
- package/lib/mocks/views/DashboardMock.d.ts +1 -1
- package/lib/mocks/views/FormMock.d.ts +1 -1
- package/lib/mocks/views/TableMock.d.ts +1 -1
- package/lib/mocks/views/WipMock.d.ts +1 -1
- package/lib/models/Credits.d.ts +16 -0
- package/lib/models/Credits.js +22 -0
- package/lib/models/McpAuditEvent.d.ts +52 -0
- package/lib/models/McpAuditEvent.js +5 -0
- package/lib/models/McpBinding.d.ts +51 -0
- package/lib/models/McpBinding.js +5 -0
- package/lib/models/McpPolicy.d.ts +77 -0
- package/lib/models/McpPolicy.js +5 -0
- package/lib/models/McpTask.d.ts +94 -0
- package/lib/models/McpTask.js +7 -0
- package/lib/models/StartedBy.d.ts +57 -0
- package/lib/models/StartedBy.js +81 -0
- package/lib/models/UserDTO.js +4 -2
- package/lib/models/contents/__fixtures__/solr-codec.json +57 -0
- package/lib/models/contents/__fixtures__/v1-contracts.json +66 -0
- package/lib/models/contents/fieldCase.d.ts +8 -0
- package/lib/models/contents/fieldCase.js +37 -0
- package/lib/models/contents/index.d.ts +2 -0
- package/lib/models/contents/index.js +6 -0
- package/lib/models/contents/permissions.d.ts +16 -0
- package/lib/models/contents/permissions.js +34 -0
- package/lib/models/index.d.ts +5 -1
- package/lib/models/index.js +5 -1
- package/lib/state/substates/CoreState.d.ts +15 -7
- package/lib/state/substates/CoreState.js +18 -14
- package/lib/state/substates/IAMState.d.ts +1 -1
- package/lib/state/substates/IAMState.js +5 -5
- package/lib/state/substates/ProfileState.js +0 -4
- package/lib/state/substates/index.d.ts +0 -1
- package/lib/state/substates/index.js +0 -1
- package/lib/utils/Jwt.d.ts +26 -0
- package/lib/utils/Jwt.js +37 -0
- package/lib/utils/WithSuspense.d.ts +1 -1
- package/lib/views/api-keys/APIKeyEdit.d.ts +1 -1
- package/lib/views/api-keys/APIKeyNew.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.d.ts +1 -1
- package/lib/views/api-keys/APIKeys.js +30 -4
- package/lib/views/api-keys/APIKeysStandalone.d.ts +5 -1
- package/lib/views/api-keys/APIKeysStandalone.js +2 -2
- package/lib/views/datasources/DatasourceDetail.d.ts +12 -5
- package/lib/views/datasources/DatasourceDetail.js +80 -110
- package/lib/views/datasources/DatasourceNew.d.ts +14 -8
- package/lib/views/datasources/DatasourceNew.js +129 -118
- package/lib/views/datasources/Datasources.d.ts +39 -7
- package/lib/views/datasources/Datasources.js +95 -40
- package/lib/views/datasources/DatasourcesMock.d.ts +3 -0
- package/lib/views/datasources/DatasourcesMock.js +57 -0
- package/lib/views/iam/SignInSimple.d.ts +12 -0
- package/lib/views/iam/SignInSimple.js +4 -4
- package/lib/views/index.d.ts +1 -0
- package/lib/views/index.js +1 -0
- package/lib/views/mcp/AlertDestinations.d.ts +34 -0
- package/lib/views/mcp/AlertDestinations.js +75 -0
- package/lib/views/mcp/AlertRules.d.ts +32 -0
- package/lib/views/mcp/AlertRules.js +245 -0
- package/lib/views/mcp/AuditLog.d.ts +42 -0
- package/lib/views/mcp/AuditLog.js +144 -0
- package/lib/views/mcp/ConnectedAgents.d.ts +34 -0
- package/lib/views/mcp/ConnectedAgents.js +100 -0
- package/lib/views/mcp/EnterpriseConsole.d.ts +74 -0
- package/lib/views/mcp/EnterpriseConsole.js +173 -0
- package/lib/views/mcp/McpDashboard.d.ts +50 -0
- package/lib/views/mcp/McpDashboard.js +347 -0
- package/lib/views/mcp/McpHome.d.ts +92 -0
- package/lib/views/mcp/McpHome.js +153 -0
- package/lib/views/mcp/McpObservability.d.ts +50 -0
- package/lib/views/mcp/McpObservability.js +150 -0
- package/lib/views/mcp/OrganizationPolicy.d.ts +45 -0
- package/lib/views/mcp/OrganizationPolicy.js +107 -0
- package/lib/views/mcp/OrganizationUsage.d.ts +69 -0
- package/lib/views/mcp/OrganizationUsage.js +113 -0
- package/lib/views/mcp/PersonalPolicy.d.ts +54 -0
- package/lib/views/mcp/PersonalPolicy.js +125 -0
- package/lib/views/mcp/Policies.d.ts +53 -0
- package/lib/views/mcp/Policies.js +210 -0
- package/lib/views/mcp/PolicyForm.d.ts +67 -0
- package/lib/views/mcp/PolicyForm.js +91 -0
- package/lib/views/mcp/PolicyHistory.d.ts +45 -0
- package/lib/views/mcp/PolicyHistory.js +62 -0
- package/lib/views/mcp/ServiceAgents.d.ts +46 -0
- package/lib/views/mcp/ServiceAgents.js +194 -0
- package/lib/views/mcp/TeamPolicies.d.ts +33 -0
- package/lib/views/mcp/TeamPolicies.js +98 -0
- package/lib/views/mcp/format.d.ts +25 -0
- package/lib/views/mcp/format.js +77 -0
- package/lib/views/mcp/index.d.ts +29 -0
- package/lib/views/mcp/index.js +37 -0
- package/lib/views/mcp/types.d.ts +66 -0
- package/lib/views/mcp/types.js +5 -0
- package/lib/views/secrets/SecretEdit.d.ts +5 -1
- package/lib/views/secrets/SecretEdit.js +2 -2
- package/lib/views/secrets/SecretNew.d.ts +11 -1
- package/lib/views/secrets/SecretNew.js +2 -2
- package/lib/views/secrets/Secrets.d.ts +12 -1
- package/lib/views/secrets/Secrets.js +2 -2
- package/package.json +28 -24
- package/scripts/generate-contents-types.py +169 -0
- package/scripts/generate-mcp-types.py +233 -0
- package/lib/api/iam/datasources.d.ts +0 -86
- package/lib/api/iam/datasources.js +0 -185
- package/lib/components/toolbars/index.d.ts +0 -1
- package/lib/models/Datasource.d.ts +0 -181
- package/lib/models/Datasource.js +0 -154
- package/lib/state/substates/DatasourceState.d.ts +0 -11
- package/lib/state/substates/DatasourceState.js +0 -16
- /package/lib/{components/toolbars/index.js → api/contents/generated.js} +0 -0
package/README.md
CHANGED
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
|
|
19
19
|
## Overview
|
|
20
20
|
|
|
21
|
-
Datalayer Core is the foundational package that powers the [Datalayer AI Platform](https://datalayer.ai). It provides
|
|
21
|
+
Datalayer Core is the foundational package that powers the [Datalayer AI Platform](https://datalayer.ai). It provides TypeScript and Python packages as a Command Line Interface (CLI) for AI engineers, data scientists, and researchers to seamlessly integrate scalable compute runtimes into their workflows.
|
|
22
22
|
|
|
23
23
|
This package serves as the base foundation used by many other Datalayer packages, containing core application classes, configuration, and unified APIs for authentication, runtime management, and code execution in cloud-based environments.
|
|
24
24
|
|
|
@@ -99,7 +99,7 @@ Datalayer Core serves as the foundation for the entire Datalayer ecosystem:
|
|
|
99
99
|
|
|
100
100
|
## Examples
|
|
101
101
|
|
|
102
|
-
- [OTEL example README](
|
|
102
|
+
- [OTEL example README](https://github.com/datalayer/core/blob/main/examples/otel/README.md)
|
|
103
103
|
|
|
104
104
|
## Documentation
|
|
105
105
|
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AxiosRequestConfig } from 'axios';
|
|
1
2
|
/**
|
|
2
3
|
* Error wrapper for failed HTTP responses.
|
|
3
4
|
* Includes response details, warnings, errors, and tracebacks.
|
|
@@ -53,6 +54,37 @@ export declare class NetworkError extends TypeError {
|
|
|
53
54
|
*/
|
|
54
55
|
constructor(original: TypeError);
|
|
55
56
|
}
|
|
57
|
+
/**
|
|
58
|
+
* Thrown when a request is made with a JWT that has already expired.
|
|
59
|
+
*
|
|
60
|
+
* Raised in place of the `RunResponseError` a 401 would otherwise produce,
|
|
61
|
+
* and only when the token we sent says it has expired. That distinction is
|
|
62
|
+
* the point of the class: a 401 can mean a dozen things — a revoked token, a
|
|
63
|
+
* wrong audience, a permission the account never had — and none of them are
|
|
64
|
+
* fixed by the same action. An expired token has exactly one remedy, and a
|
|
65
|
+
* caller that can recognise it can offer that remedy instead of an error.
|
|
66
|
+
*
|
|
67
|
+
* Callers are expected to catch this by name:
|
|
68
|
+
*
|
|
69
|
+
* ```typescript
|
|
70
|
+
* try {
|
|
71
|
+
* await requestDatalayerAPI({ url, token });
|
|
72
|
+
* } catch (error) {
|
|
73
|
+
* if (error instanceof TokenExpiredError) {
|
|
74
|
+
* showSignIn();
|
|
75
|
+
* return;
|
|
76
|
+
* }
|
|
77
|
+
* throw error;
|
|
78
|
+
* }
|
|
79
|
+
* ```
|
|
80
|
+
*/
|
|
81
|
+
export declare class TokenExpiredError extends Error {
|
|
82
|
+
/** When the token expired, in milliseconds since the epoch. */
|
|
83
|
+
readonly expiredAt: number;
|
|
84
|
+
/** The URL the request was going to, for context in logs. */
|
|
85
|
+
readonly url: string;
|
|
86
|
+
constructor(url: string, expiredAt: number);
|
|
87
|
+
}
|
|
56
88
|
/**
|
|
57
89
|
* Options for Datalayer API requests.
|
|
58
90
|
*/
|
|
@@ -69,6 +101,14 @@ export interface IRequestDatalayerAPIOptions {
|
|
|
69
101
|
token?: string;
|
|
70
102
|
/** AbortSignal for request cancellation */
|
|
71
103
|
signal?: AbortSignal;
|
|
104
|
+
/** Axios response representation for binary or streaming transports. */
|
|
105
|
+
responseType?: AxiosRequestConfig['responseType'];
|
|
106
|
+
}
|
|
107
|
+
export interface IDatalayerAPIResponse<T> {
|
|
108
|
+
data: T;
|
|
109
|
+
status: number;
|
|
110
|
+
statusText: string;
|
|
111
|
+
headers: Record<string, string>;
|
|
72
112
|
}
|
|
73
113
|
/**
|
|
74
114
|
* Makes authenticated HTTP requests to Datalayer APIs.
|
|
@@ -88,4 +128,5 @@ export interface IRequestDatalayerAPIOptions {
|
|
|
88
128
|
* });
|
|
89
129
|
* ```
|
|
90
130
|
*/
|
|
91
|
-
export declare function
|
|
131
|
+
export declare function requestDatalayerAPIWithResponse<T = any>({ url, method, body, token, signal, responseType, headers, }: IRequestDatalayerAPIOptions): Promise<IDatalayerAPIResponse<T>>;
|
|
132
|
+
export declare function requestDatalayerAPI<T = any>(options: IRequestDatalayerAPIOptions): Promise<T>;
|
package/lib/api/DatalayerApi.js
CHANGED
|
@@ -11,6 +11,7 @@
|
|
|
11
11
|
import { URLExt } from '@jupyterlab/coreutils';
|
|
12
12
|
import axios from 'axios';
|
|
13
13
|
import { sleep } from '../utils/Sleep.js';
|
|
14
|
+
import { getJwtExpiryMs, isJwtExpired } from '../utils/Jwt.js';
|
|
14
15
|
function isFormDataBody(body) {
|
|
15
16
|
if (!body || typeof body !== 'object') {
|
|
16
17
|
return false;
|
|
@@ -119,6 +120,75 @@ export class NetworkError extends TypeError {
|
|
|
119
120
|
this.stack = original.stack;
|
|
120
121
|
}
|
|
121
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* Thrown when a request is made with a JWT that has already expired.
|
|
125
|
+
*
|
|
126
|
+
* Raised in place of the `RunResponseError` a 401 would otherwise produce,
|
|
127
|
+
* and only when the token we sent says it has expired. That distinction is
|
|
128
|
+
* the point of the class: a 401 can mean a dozen things — a revoked token, a
|
|
129
|
+
* wrong audience, a permission the account never had — and none of them are
|
|
130
|
+
* fixed by the same action. An expired token has exactly one remedy, and a
|
|
131
|
+
* caller that can recognise it can offer that remedy instead of an error.
|
|
132
|
+
*
|
|
133
|
+
* Callers are expected to catch this by name:
|
|
134
|
+
*
|
|
135
|
+
* ```typescript
|
|
136
|
+
* try {
|
|
137
|
+
* await requestDatalayerAPI({ url, token });
|
|
138
|
+
* } catch (error) {
|
|
139
|
+
* if (error instanceof TokenExpiredError) {
|
|
140
|
+
* showSignIn();
|
|
141
|
+
* return;
|
|
142
|
+
* }
|
|
143
|
+
* throw error;
|
|
144
|
+
* }
|
|
145
|
+
* ```
|
|
146
|
+
*/
|
|
147
|
+
export class TokenExpiredError extends Error {
|
|
148
|
+
/** When the token expired, in milliseconds since the epoch. */
|
|
149
|
+
expiredAt;
|
|
150
|
+
/** The URL the request was going to, for context in logs. */
|
|
151
|
+
url;
|
|
152
|
+
constructor(url, expiredAt) {
|
|
153
|
+
super(`The Datalayer token expired at ${new Date(expiredAt).toISOString()}; ` +
|
|
154
|
+
`not sending the request to ${url}.`);
|
|
155
|
+
// `name` rather than only the prototype, because a bundler that downlevels
|
|
156
|
+
// this class can break `instanceof` across package boundaries and a name
|
|
157
|
+
// check is the fallback every caller can still make.
|
|
158
|
+
this.name = 'TokenExpiredError';
|
|
159
|
+
this.expiredAt = expiredAt;
|
|
160
|
+
this.url = url;
|
|
161
|
+
// Restores the prototype chain when compiled down to ES5, without which
|
|
162
|
+
// `instanceof TokenExpiredError` is false — see TypeScript #13965.
|
|
163
|
+
Object.setPrototypeOf(this, TokenExpiredError.prototype);
|
|
164
|
+
}
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Turn a 401 into a `TokenExpiredError` when the token is the reason for it.
|
|
168
|
+
*
|
|
169
|
+
* After the fact rather than before it. Checking the token up front would
|
|
170
|
+
* have meant deciding, at the door, which endpoints require one — and plenty
|
|
171
|
+
* here accept anonymous callers, so a pre-flight refusal would reject
|
|
172
|
+
* requests that were going to succeed. The server is the only thing that
|
|
173
|
+
* knows whether a given endpoint wanted credentials, and a 401 is it saying
|
|
174
|
+
* so.
|
|
175
|
+
*
|
|
176
|
+
* Asked only on a 401, and only when we actually hold a token that says it
|
|
177
|
+
* has expired. Every other 401 — a revoked token, a wrong audience, a
|
|
178
|
+
* permission the account never had, an anonymous call to a protected route —
|
|
179
|
+
* stays a `RunResponseError`, because those are not fixed by signing in
|
|
180
|
+
* again and should not be dressed up as though they were.
|
|
181
|
+
*
|
|
182
|
+
* Reading `exp` after the response has come back is also the more reliable
|
|
183
|
+
* moment: time has only moved forward, so a token the server judged expired
|
|
184
|
+
* reads as expired here too, with no clock-skew allowance to tune.
|
|
185
|
+
*/
|
|
186
|
+
function throwIfTokenExpired(status, token, url) {
|
|
187
|
+
if (status !== 401 || !token || !isJwtExpired(token)) {
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
throw new TokenExpiredError(url, getJwtExpiryMs(token) ?? Date.now());
|
|
191
|
+
}
|
|
122
192
|
/**
|
|
123
193
|
* Makes authenticated HTTP requests to Datalayer APIs.
|
|
124
194
|
* Handles JSON and FormData, includes auth headers, and manages redirects.
|
|
@@ -137,7 +207,7 @@ export class NetworkError extends TypeError {
|
|
|
137
207
|
* });
|
|
138
208
|
* ```
|
|
139
209
|
*/
|
|
140
|
-
export async function
|
|
210
|
+
export async function requestDatalayerAPIWithResponse({ url, method, body, token, signal, responseType, headers = {}, }) {
|
|
141
211
|
// Handle FormData differently from JSON
|
|
142
212
|
const isFormData = isFormDataBody(body);
|
|
143
213
|
// Prepare axios config
|
|
@@ -147,6 +217,7 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
|
|
|
147
217
|
headers: { ...headers },
|
|
148
218
|
withCredentials: true, // equivalent to credentials: 'include'
|
|
149
219
|
signal,
|
|
220
|
+
responseType,
|
|
150
221
|
// CORS mode is handled automatically by axios
|
|
151
222
|
// Cache control headers
|
|
152
223
|
};
|
|
@@ -191,10 +262,17 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
|
|
|
191
262
|
if (response.status < 300) {
|
|
192
263
|
// Handle redirections if needed.
|
|
193
264
|
if (response.status === 202 && response.headers.location) {
|
|
194
|
-
|
|
265
|
+
const data = await handleAxiosRedirection(response, axiosConfig);
|
|
266
|
+
return {
|
|
267
|
+
data: data,
|
|
268
|
+
status: response.status,
|
|
269
|
+
statusText: response.statusText,
|
|
270
|
+
headers: { ...response.headers },
|
|
271
|
+
};
|
|
195
272
|
}
|
|
196
273
|
}
|
|
197
274
|
else {
|
|
275
|
+
throwIfTokenExpired(response.status, token, url);
|
|
198
276
|
const adaptedResponse = {
|
|
199
277
|
ok: false,
|
|
200
278
|
status: response.status,
|
|
@@ -204,11 +282,17 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
|
|
|
204
282
|
};
|
|
205
283
|
throw await RunResponseError.create(adaptedResponse);
|
|
206
284
|
}
|
|
207
|
-
return
|
|
285
|
+
return {
|
|
286
|
+
data: response.data,
|
|
287
|
+
status: response.status,
|
|
288
|
+
statusText: response.statusText,
|
|
289
|
+
headers: { ...response.headers },
|
|
290
|
+
};
|
|
208
291
|
}
|
|
209
292
|
catch (error) {
|
|
210
293
|
if (axios.isAxiosError(error)) {
|
|
211
294
|
if (error.response) {
|
|
295
|
+
throwIfTokenExpired(error.response.status, token, url);
|
|
212
296
|
// Convert axios error to our RunResponseError format
|
|
213
297
|
const adaptedResponse = {
|
|
214
298
|
ok: false,
|
|
@@ -224,6 +308,9 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
|
|
|
224
308
|
throw error;
|
|
225
309
|
}
|
|
226
310
|
}
|
|
311
|
+
export async function requestDatalayerAPI(options) {
|
|
312
|
+
return (await requestDatalayerAPIWithResponse(options)).data;
|
|
313
|
+
}
|
|
227
314
|
async function handleAxiosRedirection(response, originalConfig) {
|
|
228
315
|
let redirect = response.headers.location;
|
|
229
316
|
if (redirect) {
|
package/lib/api/constants.d.ts
CHANGED
|
@@ -3,7 +3,9 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export declare const API_BASE_PATHS: {
|
|
5
5
|
readonly AI_AGENTS: "/api/ai-agents/v1";
|
|
6
|
+
readonly CONTENTS: "/api/contents/v1";
|
|
6
7
|
readonly IAM: "/api/iam/v1";
|
|
8
|
+
readonly MCP: "/api/mcp/v1";
|
|
7
9
|
readonly OTEL: "/api/otel/v1";
|
|
8
10
|
readonly RUNTIMES: "/api/runtimes/v1";
|
|
9
11
|
readonly SCHEDULER: "/api/scheduler/v1";
|
|
@@ -15,8 +17,24 @@ export declare const API_BASE_PATHS: {
|
|
|
15
17
|
export declare const DEFAULT_SERVICE_URLS: {
|
|
16
18
|
/** Default URL for AI Agents (durable agent management) service */
|
|
17
19
|
readonly AI_AGENTS: "https://prod1.datalayer.run";
|
|
20
|
+
/**
|
|
21
|
+
* Default URL for the Contents service.
|
|
22
|
+
*
|
|
23
|
+
* The same host as RUNTIMES: Contents runs on the runtimes plane, where the NFS that backs the Home Folder and Volumes lives,
|
|
24
|
+
* so the service sits beside the storage it serves rather than a network
|
|
25
|
+
* away from it.
|
|
26
|
+
*/
|
|
27
|
+
readonly CONTENTS: "https://r1.datalayer.run";
|
|
18
28
|
/** Default URL for IAM (Identity and Access Management) service */
|
|
19
29
|
readonly IAM: "https://prod1.datalayer.run";
|
|
30
|
+
/**
|
|
31
|
+
* Default URL of the Jupyter MCP Server, the hosted MCP endpoint.
|
|
32
|
+
*
|
|
33
|
+
* This is the MCP resource itself — the URL an agent connects to and the
|
|
34
|
+
* audience a token names — so it ends in `/mcp`. The gateway's REST
|
|
35
|
+
* routes (`/api/mcp/v1/...`) live on the same host, one path segment up.
|
|
36
|
+
*/
|
|
37
|
+
readonly JUPYTER_MCP_SERVER: "https://mcp.datalayer.run/mcp";
|
|
20
38
|
/** Default URL for OTEL (OpenTelemetry observability) service */
|
|
21
39
|
readonly OTEL: "https://prod1.datalayer.run";
|
|
22
40
|
/** Default URL for Runtimes service */
|
package/lib/api/constants.js
CHANGED
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
*/
|
|
8
8
|
export const API_BASE_PATHS = {
|
|
9
9
|
AI_AGENTS: '/api/ai-agents/v1',
|
|
10
|
+
CONTENTS: '/api/contents/v1',
|
|
10
11
|
IAM: '/api/iam/v1',
|
|
12
|
+
MCP: '/api/mcp/v1',
|
|
11
13
|
OTEL: '/api/otel/v1',
|
|
12
14
|
RUNTIMES: '/api/runtimes/v1',
|
|
13
15
|
SCHEDULER: '/api/scheduler/v1',
|
|
@@ -19,8 +21,24 @@ export const API_BASE_PATHS = {
|
|
|
19
21
|
export const DEFAULT_SERVICE_URLS = {
|
|
20
22
|
/** Default URL for AI Agents (durable agent management) service */
|
|
21
23
|
AI_AGENTS: 'https://prod1.datalayer.run',
|
|
24
|
+
/**
|
|
25
|
+
* Default URL for the Contents service.
|
|
26
|
+
*
|
|
27
|
+
* The same host as RUNTIMES: Contents runs on the runtimes plane, where the NFS that backs the Home Folder and Volumes lives,
|
|
28
|
+
* so the service sits beside the storage it serves rather than a network
|
|
29
|
+
* away from it.
|
|
30
|
+
*/
|
|
31
|
+
CONTENTS: 'https://r1.datalayer.run',
|
|
22
32
|
/** Default URL for IAM (Identity and Access Management) service */
|
|
23
33
|
IAM: 'https://prod1.datalayer.run',
|
|
34
|
+
/**
|
|
35
|
+
* Default URL of the Jupyter MCP Server, the hosted MCP endpoint.
|
|
36
|
+
*
|
|
37
|
+
* This is the MCP resource itself — the URL an agent connects to and the
|
|
38
|
+
* audience a token names — so it ends in `/mcp`. The gateway's REST
|
|
39
|
+
* routes (`/api/mcp/v1/...`) live on the same host, one path segment up.
|
|
40
|
+
*/
|
|
41
|
+
JUPYTER_MCP_SERVER: 'https://mcp.datalayer.run/mcp',
|
|
24
42
|
/** Default URL for OTEL (OpenTelemetry observability) service */
|
|
25
43
|
OTEL: 'https://prod1.datalayer.run',
|
|
26
44
|
/** Default URL for Runtimes service */
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import type { AttachmentCreate, AttachmentList, ContentAttachment, ContentAttachmentManifest } from './generated';
|
|
2
|
+
export declare const createAttachment: (token: string, request: AttachmentCreate, idempotencyKey: string, baseUrl?: string) => Promise<ContentAttachment>;
|
|
3
|
+
export declare const listAttachments: (token: string, options?: {
|
|
4
|
+
sandboxUid?: string;
|
|
5
|
+
sourceUid?: string;
|
|
6
|
+
active?: boolean;
|
|
7
|
+
}, baseUrl?: string) => Promise<AttachmentList>;
|
|
8
|
+
export declare const getAttachmentManifest: (token: string, sandboxUid: string, baseUrl?: string) => Promise<ContentAttachmentManifest>;
|
|
9
|
+
export declare const revokeAttachment: (token: string, attachmentUid: string, baseUrl?: string) => Promise<ContentAttachment>;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
6
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
7
|
+
import { contentsToCamelCase, contentsToSnakeCase } from '../../models/contents/index.js';
|
|
8
|
+
import { assertSandboxUid } from './sandboxUid.js';
|
|
9
|
+
const convert = (value) => contentsToCamelCase(value);
|
|
10
|
+
const url = (baseUrl, suffix = '') => `${baseUrl}${API_BASE_PATHS.CONTENTS}/attachments${suffix}`;
|
|
11
|
+
export const createAttachment = async (token, request, idempotencyKey, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
12
|
+
url: url(baseUrl),
|
|
13
|
+
method: 'POST',
|
|
14
|
+
token,
|
|
15
|
+
headers: { 'Idempotency-Key': idempotencyKey },
|
|
16
|
+
body: contentsToSnakeCase(request),
|
|
17
|
+
}));
|
|
18
|
+
export const listAttachments = async (token, options = {}, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
19
|
+
const parameters = new URLSearchParams();
|
|
20
|
+
if (options.sandboxUid)
|
|
21
|
+
parameters.set('sandbox_uid', assertSandboxUid(options.sandboxUid));
|
|
22
|
+
if (options.sourceUid)
|
|
23
|
+
parameters.set('source_uid', options.sourceUid);
|
|
24
|
+
parameters.set('active', String(options.active ?? false));
|
|
25
|
+
return convert(await requestDatalayerAPI({
|
|
26
|
+
url: `${url(baseUrl)}?${parameters.toString()}`,
|
|
27
|
+
method: 'GET',
|
|
28
|
+
token,
|
|
29
|
+
}));
|
|
30
|
+
};
|
|
31
|
+
export const getAttachmentManifest = async (token, sandboxUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
32
|
+
// Throws on a Pod name. Contents validates this while building its
|
|
33
|
+
// reply, so sending the wrong spelling produced a 500 the caller could
|
|
34
|
+
// not read; this fails where the caller can be seen.
|
|
35
|
+
url: url(baseUrl, `/manifest/${encodeURIComponent(assertSandboxUid(sandboxUid))}`),
|
|
36
|
+
method: 'GET',
|
|
37
|
+
token,
|
|
38
|
+
}));
|
|
39
|
+
export const revokeAttachment = async (token, attachmentUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
40
|
+
url: url(baseUrl, `/${encodeURIComponent(attachmentUid)}`),
|
|
41
|
+
method: 'DELETE',
|
|
42
|
+
token,
|
|
43
|
+
}));
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { BridgeCreate, BridgeHeartbeat, BridgeList, BridgeOpened, BridgeSession } from './generated';
|
|
2
|
+
export type BridgeState = BridgeSession['state'];
|
|
3
|
+
/** The states a bridge does not leave on its own; polling stops on them. */
|
|
4
|
+
export declare const ENDED_BRIDGE_STATES: ReadonlySet<BridgeState>;
|
|
5
|
+
export declare const isBridgeEnded: (bridge: Pick<BridgeSession, "state">) => boolean;
|
|
6
|
+
/** Open the session of a `local-bridge` attachment, or find it open. */
|
|
7
|
+
export declare const openBridge: (token: string, attachmentUid: string, request: BridgeCreate, baseUrl?: string) => Promise<BridgeOpened>;
|
|
8
|
+
/**
|
|
9
|
+
* The live session of one attachment, or `null` when none has been opened:
|
|
10
|
+
* an attachment asked for and not yet dialled has no session, which is an
|
|
11
|
+
* answer rather than a failure.
|
|
12
|
+
*/
|
|
13
|
+
export declare const getBridgeSession: (token: string, attachmentUid: string, baseUrl?: string) => Promise<BridgeSession | null>;
|
|
14
|
+
/** The caller's sessions, newest first; `active` leaves out the ended ones. */
|
|
15
|
+
export declare const listBridges: (token: string, options?: {
|
|
16
|
+
active?: boolean;
|
|
17
|
+
}, baseUrl?: string) => Promise<BridgeList>;
|
|
18
|
+
export declare const getBridge: (token: string, bridgeUid: string, baseUrl?: string) => Promise<BridgeSession>;
|
|
19
|
+
/** Still here: the session stays alive and the answer carries a fresh client token. */
|
|
20
|
+
export declare const heartbeatBridge: (token: string, bridgeUid: string, baseUrl?: string) => Promise<BridgeHeartbeat>;
|
|
21
|
+
/** End a session: its tokens stop working before the sandbox side unmounts. */
|
|
22
|
+
export declare const revokeBridge: (token: string, bridgeUid: string, baseUrl?: string) => Promise<BridgeSession>;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/**
|
|
6
|
+
* The bridge session behind a `local-bridge` attachment.
|
|
7
|
+
*
|
|
8
|
+
* A session is what the attachment holds while a person's computer serves a
|
|
9
|
+
* folder to the sandbox through the relay. A browser never serves one — the
|
|
10
|
+
* CLI does — so what it does here is look: the session of an attachment,
|
|
11
|
+
* the caller's sessions, and the one thing it may do to them, revoke.
|
|
12
|
+
* Opening and heartbeating are here for completeness and for a desktop
|
|
13
|
+
* client that embeds this library; a page has no folder to bind.
|
|
14
|
+
*/
|
|
15
|
+
import { RunResponseError, requestDatalayerAPI } from '../DatalayerApi.js';
|
|
16
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
17
|
+
import { contentsToCamelCase, contentsToSnakeCase } from '../../models/contents/index.js';
|
|
18
|
+
/** The states a bridge does not leave on its own; polling stops on them. */
|
|
19
|
+
export const ENDED_BRIDGE_STATES = new Set([
|
|
20
|
+
'revoked',
|
|
21
|
+
'expired',
|
|
22
|
+
]);
|
|
23
|
+
export const isBridgeEnded = (bridge) => ENDED_BRIDGE_STATES.has(bridge.state);
|
|
24
|
+
const convert = (value) => contentsToCamelCase(value);
|
|
25
|
+
const contentsUrl = (baseUrl, suffix) => `${baseUrl}${API_BASE_PATHS.CONTENTS}${suffix}`;
|
|
26
|
+
/** Open the session of a `local-bridge` attachment, or find it open. */
|
|
27
|
+
export const openBridge = async (token, attachmentUid, request, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
28
|
+
url: contentsUrl(baseUrl, `/attachments/${encodeURIComponent(attachmentUid)}/bridge`),
|
|
29
|
+
method: 'POST',
|
|
30
|
+
token,
|
|
31
|
+
body: contentsToSnakeCase(request),
|
|
32
|
+
}));
|
|
33
|
+
/**
|
|
34
|
+
* The live session of one attachment, or `null` when none has been opened:
|
|
35
|
+
* an attachment asked for and not yet dialled has no session, which is an
|
|
36
|
+
* answer rather than a failure.
|
|
37
|
+
*/
|
|
38
|
+
export const getBridgeSession = async (token, attachmentUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
39
|
+
try {
|
|
40
|
+
return convert(await requestDatalayerAPI({
|
|
41
|
+
url: contentsUrl(baseUrl, `/attachments/${encodeURIComponent(attachmentUid)}/bridge`),
|
|
42
|
+
method: 'GET',
|
|
43
|
+
token,
|
|
44
|
+
}));
|
|
45
|
+
}
|
|
46
|
+
catch (error) {
|
|
47
|
+
if (error instanceof RunResponseError && error.response.status === 404) {
|
|
48
|
+
return null;
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
/** The caller's sessions, newest first; `active` leaves out the ended ones. */
|
|
54
|
+
export const listBridges = async (token, options = {}, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
55
|
+
const parameters = new URLSearchParams();
|
|
56
|
+
parameters.set('active', String(options.active ?? false));
|
|
57
|
+
return convert(await requestDatalayerAPI({
|
|
58
|
+
url: `${contentsUrl(baseUrl, '/bridges')}?${parameters.toString()}`,
|
|
59
|
+
method: 'GET',
|
|
60
|
+
token,
|
|
61
|
+
}));
|
|
62
|
+
};
|
|
63
|
+
export const getBridge = async (token, bridgeUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
64
|
+
url: contentsUrl(baseUrl, `/bridges/${encodeURIComponent(bridgeUid)}`),
|
|
65
|
+
method: 'GET',
|
|
66
|
+
token,
|
|
67
|
+
}));
|
|
68
|
+
/** Still here: the session stays alive and the answer carries a fresh client token. */
|
|
69
|
+
export const heartbeatBridge = async (token, bridgeUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
70
|
+
url: contentsUrl(baseUrl, `/bridges/${encodeURIComponent(bridgeUid)}/heartbeat`),
|
|
71
|
+
method: 'POST',
|
|
72
|
+
token,
|
|
73
|
+
}));
|
|
74
|
+
/** End a session: its tokens stop working before the sandbox side unmounts. */
|
|
75
|
+
export const revokeBridge = async (token, bridgeUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convert(await requestDatalayerAPI({
|
|
76
|
+
url: contentsUrl(baseUrl, `/bridges/${encodeURIComponent(bridgeUid)}`),
|
|
77
|
+
method: 'DELETE',
|
|
78
|
+
token,
|
|
79
|
+
}));
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { ContentsCapabilities, OperationCapability, SourceKindCapability } from './generated';
|
|
2
|
+
export type ContentsSourceKindCapability = SourceKindCapability;
|
|
3
|
+
export type ContentsOperationCapability = OperationCapability;
|
|
4
|
+
export type { ContentsCapabilities };
|
|
5
|
+
/**
|
|
6
|
+
* Ask the service what this caller can reach, create and count.
|
|
7
|
+
*
|
|
8
|
+
* A client cannot answer either question on its own: it does not know which
|
|
9
|
+
* parts of Contents are deployed here, nor what this principal may use.
|
|
10
|
+
*/
|
|
11
|
+
export declare const getCapabilities: (token: string, baseUrl?: string) => Promise<ContentsCapabilities>;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
import { requestDatalayerAPI } from '../DatalayerApi.js';
|
|
6
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
7
|
+
import { contentsToCamelCase } from '../../models/contents/index.js';
|
|
8
|
+
/**
|
|
9
|
+
* Ask the service what this caller can reach, create and count.
|
|
10
|
+
*
|
|
11
|
+
* A client cannot answer either question on its own: it does not know which
|
|
12
|
+
* parts of Contents are deployed here, nor what this principal may use.
|
|
13
|
+
*/
|
|
14
|
+
export const getCapabilities = async (token, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
15
|
+
const value = await requestDatalayerAPI({
|
|
16
|
+
url: `${baseUrl}${API_BASE_PATHS.CONTENTS}/capabilities`,
|
|
17
|
+
method: 'GET',
|
|
18
|
+
token,
|
|
19
|
+
});
|
|
20
|
+
return contentsToCamelCase(value);
|
|
21
|
+
};
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { CloudObjectList, CloudObjectView, ConnectionTest, CredentialDiagnostics, CatalogSource } from './generated';
|
|
2
|
+
export interface PresignedObjectUrl {
|
|
3
|
+
url: string;
|
|
4
|
+
operation: 'get' | 'put';
|
|
5
|
+
expiresIn: number;
|
|
6
|
+
}
|
|
7
|
+
/** One page of a bucket under a prefix; `nextCursor` continues it. */
|
|
8
|
+
export declare const listCloudObjects: (token: string, sourceUid: string, options?: {
|
|
9
|
+
prefix?: string;
|
|
10
|
+
cursor?: string;
|
|
11
|
+
}, baseUrl?: string) => Promise<CloudObjectList>;
|
|
12
|
+
export declare const statCloudObject: (token: string, sourceUid: string, path: string, baseUrl?: string) => Promise<CloudObjectView>;
|
|
13
|
+
/** The bytes of one object, or a range of them. */
|
|
14
|
+
export declare const downloadCloudObject: (token: string, sourceUid: string, path: string, options?: {
|
|
15
|
+
range?: string;
|
|
16
|
+
}, baseUrl?: string) => Promise<{
|
|
17
|
+
body: ArrayBuffer;
|
|
18
|
+
status: number;
|
|
19
|
+
headers: Record<string, string>;
|
|
20
|
+
}>;
|
|
21
|
+
/** Can the bucket be reached with the credential attached: a verdict, not a stack trace. */
|
|
22
|
+
export declare const testCloudConnection: (token: string, sourceUid: string, baseUrl?: string) => Promise<ConnectionTest>;
|
|
23
|
+
/** A URL good for one path, one operation, a bounded time. A `put` needs the right to update. */
|
|
24
|
+
export declare const presignCloudObject: (token: string, sourceUid: string, path: string, options?: {
|
|
25
|
+
operation?: "get" | "put";
|
|
26
|
+
expiresIn?: number;
|
|
27
|
+
}, baseUrl?: string) => Promise<PresignedObjectUrl>;
|
|
28
|
+
/** Whether the source's credential is referenced and resolvable — never its value. */
|
|
29
|
+
export declare const getCredentialDiagnostics: (token: string, sourceUid: string, baseUrl?: string) => Promise<CredentialDiagnostics>;
|
|
30
|
+
/** Point the source at another credential. Owner only, conditional on the ETag. */
|
|
31
|
+
export declare const rotateSourceCredential: (token: string, sourceUid: string, credentialUid: string, etag: string, baseUrl?: string) => Promise<CatalogSource>;
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (c) 2023-2025 Datalayer, Inc.
|
|
3
|
+
* Distributed under the terms of the Modified BSD License.
|
|
4
|
+
*/
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (c) 2023-2026 Datalayer, Inc.
|
|
7
|
+
* Distributed under the terms of the Modified BSD License.
|
|
8
|
+
*/
|
|
9
|
+
/**
|
|
10
|
+
* A bucket through the service: listed, stat'ed, read, tested and signed.
|
|
11
|
+
*
|
|
12
|
+
* The credential never comes this way. The service resolves it for each
|
|
13
|
+
* request and hands it to a provider adapter; what a browser gets back is
|
|
14
|
+
* objects, bytes, a verdict, or a URL good for one path, one operation and a
|
|
15
|
+
* bounded time.
|
|
16
|
+
*/
|
|
17
|
+
import { requestDatalayerAPI, requestDatalayerAPIWithResponse, } from '../DatalayerApi.js';
|
|
18
|
+
import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
|
|
19
|
+
import { contentsToCamelCase } from '../../models/contents/index.js';
|
|
20
|
+
const convertResponse = (value) => contentsToCamelCase(value);
|
|
21
|
+
const cloudUrl = (baseUrl, sourceUid, suffix = '') => `${baseUrl}${API_BASE_PATHS.CONTENTS}/sources/${encodeURIComponent(sourceUid)}/cloud${suffix}`;
|
|
22
|
+
/** One page of a bucket under a prefix; `nextCursor` continues it. */
|
|
23
|
+
export const listCloudObjects = async (token, sourceUid, options = {}, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
24
|
+
const parameters = new URLSearchParams();
|
|
25
|
+
if (options.prefix) {
|
|
26
|
+
parameters.set('prefix', options.prefix);
|
|
27
|
+
}
|
|
28
|
+
if (options.cursor) {
|
|
29
|
+
parameters.set('cursor', options.cursor);
|
|
30
|
+
}
|
|
31
|
+
const query = parameters.toString();
|
|
32
|
+
return convertResponse(await requestDatalayerAPI({
|
|
33
|
+
url: `${cloudUrl(baseUrl, sourceUid, '/objects')}${query ? `?${query}` : ''}`,
|
|
34
|
+
method: 'GET',
|
|
35
|
+
token,
|
|
36
|
+
}));
|
|
37
|
+
};
|
|
38
|
+
export const statCloudObject = async (token, sourceUid, path, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convertResponse(await requestDatalayerAPI({
|
|
39
|
+
url: `${cloudUrl(baseUrl, sourceUid, '/objects/stat')}?path=${encodeURIComponent(path)}`,
|
|
40
|
+
method: 'GET',
|
|
41
|
+
token,
|
|
42
|
+
}));
|
|
43
|
+
/** The bytes of one object, or a range of them. */
|
|
44
|
+
export const downloadCloudObject = async (token, sourceUid, path, options = {}, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
45
|
+
const response = await requestDatalayerAPIWithResponse({
|
|
46
|
+
url: `${cloudUrl(baseUrl, sourceUid, '/objects/content')}?path=${encodeURIComponent(path)}`,
|
|
47
|
+
method: 'GET',
|
|
48
|
+
token,
|
|
49
|
+
headers: options.range ? { Range: options.range } : undefined,
|
|
50
|
+
responseType: 'arraybuffer',
|
|
51
|
+
});
|
|
52
|
+
return {
|
|
53
|
+
body: response.data,
|
|
54
|
+
status: response.status,
|
|
55
|
+
headers: response.headers,
|
|
56
|
+
};
|
|
57
|
+
};
|
|
58
|
+
/** Can the bucket be reached with the credential attached: a verdict, not a stack trace. */
|
|
59
|
+
export const testCloudConnection = async (token, sourceUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convertResponse(await requestDatalayerAPI({
|
|
60
|
+
url: cloudUrl(baseUrl, sourceUid, '/test'),
|
|
61
|
+
method: 'POST',
|
|
62
|
+
token,
|
|
63
|
+
}));
|
|
64
|
+
/** A URL good for one path, one operation, a bounded time. A `put` needs the right to update. */
|
|
65
|
+
export const presignCloudObject = async (token, sourceUid, path, options = {}, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => {
|
|
66
|
+
const parameters = new URLSearchParams({ path, operation: options.operation ?? 'get' });
|
|
67
|
+
if (options.expiresIn) {
|
|
68
|
+
parameters.set('expires_in', String(options.expiresIn));
|
|
69
|
+
}
|
|
70
|
+
return convertResponse(await requestDatalayerAPI({
|
|
71
|
+
url: `${cloudUrl(baseUrl, sourceUid, '/objects/presign')}?${parameters.toString()}`,
|
|
72
|
+
method: 'POST',
|
|
73
|
+
token,
|
|
74
|
+
}));
|
|
75
|
+
};
|
|
76
|
+
/** Whether the source's credential is referenced and resolvable — never its value. */
|
|
77
|
+
export const getCredentialDiagnostics = async (token, sourceUid, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convertResponse(await requestDatalayerAPI({
|
|
78
|
+
url: `${baseUrl}${API_BASE_PATHS.CONTENTS}/sources/${encodeURIComponent(sourceUid)}/diagnostics`,
|
|
79
|
+
method: 'GET',
|
|
80
|
+
token,
|
|
81
|
+
}));
|
|
82
|
+
/** Point the source at another credential. Owner only, conditional on the ETag. */
|
|
83
|
+
export const rotateSourceCredential = async (token, sourceUid, credentialUid, etag, baseUrl = DEFAULT_SERVICE_URLS.CONTENTS) => convertResponse(await requestDatalayerAPI({
|
|
84
|
+
url: `${baseUrl}${API_BASE_PATHS.CONTENTS}/sources/${encodeURIComponent(sourceUid)}/credential`,
|
|
85
|
+
method: 'POST',
|
|
86
|
+
token,
|
|
87
|
+
headers: { 'If-Match': etag },
|
|
88
|
+
body: { credential_uid: credentialUid },
|
|
89
|
+
}));
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { CertificateSigningRequest, DataServerConnectivity, DataServerStatus, EffectivePermissions, IssuedIdentity } from './generated';
|
|
2
|
+
/** The states the service keeps a registration in. */
|
|
3
|
+
export type DataserverState = DataServerStatus['state'];
|
|
4
|
+
export declare const DATASERVER_STATES: ReadonlyArray<DataserverState>;
|
|
5
|
+
/** The state as a person reads it. */
|
|
6
|
+
export declare const DATASERVER_STATE_LABELS: Record<DataserverState, string>;
|
|
7
|
+
export type DataserverAction = 'test' | 'rotateIdentity' | 'drain' | 'resume' | 'revoke' | 'archive' | 'delete';
|
|
8
|
+
export interface DataserverActionAvailability {
|
|
9
|
+
enabled: boolean;
|
|
10
|
+
/** Why not, when not: the state or the permission that stands in the way. */
|
|
11
|
+
reason?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Which actions a reader may take on a gateway in this state, and why not.
|
|
15
|
+
*
|
|
16
|
+
* `view` inspects; `execute` tests; owner or update-holder registers,
|
|
17
|
+
* rotates, drains, resumes, revokes, archives and deletes. A gateway that is
|
|
18
|
+
* revoked, or one that has gone quiet, keeps its record — the disabled
|
|
19
|
+
* actions name the state as the reason rather than disappearing.
|
|
20
|
+
*/
|
|
21
|
+
export declare const dataserverActionAvailability: (state: DataserverState | null | undefined, permissions: Pick<EffectivePermissions, "isOwner" | "update" | "execute">, options?: {
|
|
22
|
+
archived?: boolean;
|
|
23
|
+
}) => Record<DataserverAction, DataserverActionAvailability>;
|
|
24
|
+
/** The gateway as last heard: its lease, its connectors, its queue. */
|
|
25
|
+
export declare const getDataserverStatus: (token: string, sourceUid: string, baseUrl?: string) => Promise<DataServerStatus>;
|
|
26
|
+
/** Try the gateway on Flight and on the HTTPS fallback; the answer is a verdict per path. */
|
|
27
|
+
export declare const testDataserver: (token: string, sourceUid: string, baseUrl?: string) => Promise<DataServerConnectivity>;
|
|
28
|
+
/** Stop routing new queries; the ones running finish. */
|
|
29
|
+
export declare const drainDataserver: (token: string, sourceUid: string, baseUrl?: string) => Promise<DataServerStatus>;
|
|
30
|
+
/** Route to the gateway again. */
|
|
31
|
+
export declare const resumeDataserver: (token: string, sourceUid: string, baseUrl?: string) => Promise<DataServerStatus>;
|
|
32
|
+
/** Refuse the gateway's identity from now on. Nothing in its network changes. */
|
|
33
|
+
export declare const revokeDataserver: (token: string, sourceUid: string, baseUrl?: string) => Promise<DataServerStatus>;
|
|
34
|
+
/** A first certificate for the identity the CSR names. */
|
|
35
|
+
export declare const issueDataserverIdentity: (token: string, sourceUid: string, request: CertificateSigningRequest, baseUrl?: string) => Promise<IssuedIdentity>;
|
|
36
|
+
/** A new certificate that overlaps the current one, so nothing stops. */
|
|
37
|
+
export declare const rotateDataserverIdentity: (token: string, sourceUid: string, request: CertificateSigningRequest, baseUrl?: string) => Promise<IssuedIdentity>;
|