@datalayer/core 1.0.20 → 1.0.22

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 (138) hide show
  1. package/README.md +27 -0
  2. package/lib/api/DatalayerApi.d.ts +5 -1
  3. package/lib/api/DatalayerApi.js +55 -8
  4. package/lib/api/iam/oauth2.d.ts +3 -3
  5. package/lib/api/iam/oauth2.js +2 -2
  6. package/lib/api/iam/profile.d.ts +9 -1
  7. package/lib/api/iam/profile.js +15 -0
  8. package/lib/api/runtimes/checkpoints.js +1 -1
  9. package/lib/api/runtimes/snapshots.d.ts +7 -7
  10. package/lib/api/runtimes/snapshots.js +9 -9
  11. package/lib/client/auth/storage.js +103 -12
  12. package/lib/client/index.d.ts +7 -7
  13. package/lib/client/index.js +1 -1
  14. package/lib/client/mixins/RuntimesMixin.d.ts +6 -6
  15. package/lib/client/mixins/RuntimesMixin.js +5 -5
  16. package/lib/client/mixins/SpacerMixin.js +22 -1
  17. package/lib/collaboration/DatalayerCollaborationProvider.d.ts +4 -3
  18. package/lib/components/avatars/DLAvatar.d.ts +24 -0
  19. package/lib/components/avatars/DLAvatar.js +26 -0
  20. package/lib/components/avatars/UserProfileAvatar.js +4 -4
  21. package/lib/components/avatars/index.d.ts +1 -0
  22. package/lib/components/avatars/index.js +1 -0
  23. package/lib/components/billing/BillableAccountSelect.d.ts +35 -0
  24. package/lib/components/billing/BillableAccountSelect.js +340 -0
  25. package/lib/components/billing/index.d.ts +1 -0
  26. package/lib/components/billing/index.js +5 -0
  27. package/lib/components/checkout/StripeCheckout.d.ts +24 -3
  28. package/lib/components/checkout/StripeCheckout.js +1116 -55
  29. package/lib/components/display/DatalayerBox.js +6 -1
  30. package/lib/components/index.d.ts +2 -0
  31. package/lib/components/index.js +2 -0
  32. package/lib/components/principal/Principal.d.ts +37 -0
  33. package/lib/components/principal/Principal.js +54 -0
  34. package/lib/components/principal/PrincipalAvatar.d.ts +10 -0
  35. package/lib/components/principal/PrincipalAvatar.js +55 -0
  36. package/lib/components/principal/PrincipalBadge.d.ts +20 -0
  37. package/lib/components/principal/PrincipalBadge.js +208 -0
  38. package/lib/components/principal/PrincipalBanner.d.ts +7 -0
  39. package/lib/components/principal/PrincipalBanner.js +84 -0
  40. package/lib/components/principal/PrincipalDetailsOverlay.d.ts +23 -0
  41. package/lib/components/principal/PrincipalDetailsOverlay.js +86 -0
  42. package/lib/components/principal/PrincipalSwitcherMenu.d.ts +14 -0
  43. package/lib/components/principal/PrincipalSwitcherMenu.js +287 -0
  44. package/lib/components/principal/index.d.ts +7 -0
  45. package/lib/components/principal/index.js +10 -0
  46. package/lib/components/runtimes/RuntimeLauncherDialog.d.ts +2 -2
  47. package/lib/components/sharing/ShareAccessComponent.d.ts +18 -0
  48. package/lib/components/sharing/ShareAccessComponent.js +1368 -0
  49. package/lib/components/sharing/SharingEditor.d.ts +20 -0
  50. package/lib/components/sharing/SharingEditor.js +65 -0
  51. package/lib/components/sharing/index.d.ts +9 -0
  52. package/lib/components/sharing/index.js +12 -0
  53. package/lib/components/snapshots/{RuntimeSnapshotMenu.d.ts → SandboxSnapshotMenu.d.ts} +4 -4
  54. package/lib/components/snapshots/{RuntimeSnapshotMenu.js → SandboxSnapshotMenu.js} +33 -33
  55. package/lib/components/snapshots/index.d.ts +1 -1
  56. package/lib/components/snapshots/index.js +1 -1
  57. package/lib/components/storage/ContentsBrowser.js +2 -2
  58. package/lib/components/tokens/SpaceVariantToken.d.ts +1 -1
  59. package/lib/components/tokens/SpaceVariantToken.js +7 -4
  60. package/lib/components/users/PeerIndicator.js +5 -4
  61. package/lib/hooks/index.d.ts +5 -0
  62. package/lib/hooks/index.js +5 -0
  63. package/lib/hooks/useBillableAccountStore.d.ts +31 -0
  64. package/lib/hooks/useBillableAccountStore.js +53 -0
  65. package/lib/hooks/useCache.d.ts +125 -18
  66. package/lib/hooks/useCache.js +893 -120
  67. package/lib/hooks/useDatalayer.js +31 -3
  68. package/lib/hooks/useIAM.js +1 -8
  69. package/lib/hooks/usePrincipalStore.d.ts +41 -0
  70. package/lib/hooks/usePrincipalStore.js +101 -0
  71. package/lib/hooks/useProjects.d.ts +44 -0
  72. package/lib/hooks/useProjects.js +26 -2
  73. package/lib/hooks/useSelectedBillableAccount.d.ts +14 -0
  74. package/lib/hooks/useSelectedBillableAccount.js +36 -0
  75. package/lib/hooks/useSelectedPrincipal.d.ts +17 -0
  76. package/lib/hooks/useSelectedPrincipal.js +29 -0
  77. package/lib/hooks/useUsageRefreshStore.d.ts +8 -0
  78. package/lib/hooks/useUsageRefreshStore.js +16 -0
  79. package/lib/index.d.ts +2 -2
  80. package/lib/index.js +1 -1
  81. package/lib/mocks/components/FlashMock.js +8 -2
  82. package/lib/models/{RuntimeSnapshot.d.ts → CodeSandboxSnapshot.d.ts} +5 -5
  83. package/lib/models/{RuntimeSnapshot.js → CodeSandboxSnapshot.js} +1 -1
  84. package/lib/models/{RuntimeSnapshotDTO.d.ts → CodeSandboxSnapshotDTO.d.ts} +30 -30
  85. package/lib/models/{RuntimeSnapshotDTO.js → CodeSandboxSnapshotDTO.js} +6 -6
  86. package/lib/models/Environment.d.ts +4 -0
  87. package/lib/models/IAM.d.ts +66 -0
  88. package/lib/models/Organization.d.ts +1 -0
  89. package/lib/models/Organization.js +1 -0
  90. package/lib/models/Page.d.ts +2 -2
  91. package/lib/models/Page.js +2 -2
  92. package/lib/models/Profile.d.ts +1 -1
  93. package/lib/models/RuntimeDTO.d.ts +2 -2
  94. package/lib/models/Space.d.ts +1 -0
  95. package/lib/models/Space.js +29 -5
  96. package/lib/models/SpaceDTO.d.ts +4 -0
  97. package/lib/models/SpaceDTO.js +5 -0
  98. package/lib/models/Usage.d.ts +15 -0
  99. package/lib/models/Usage.js +9 -0
  100. package/lib/models/User.d.ts +21 -0
  101. package/lib/models/User.js +6 -2
  102. package/lib/models/index.d.ts +2 -2
  103. package/lib/models/index.js +2 -2
  104. package/lib/otel/auth.js +0 -4
  105. package/lib/services/index.d.ts +1 -1
  106. package/lib/services/index.js +1 -1
  107. package/lib/state/substates/IAMState.js +0 -7
  108. package/lib/state/substates/RuntimesState.d.ts +9 -9
  109. package/lib/state/substates/RuntimesState.js +3 -3
  110. package/lib/stateful/runtimes/actions.d.ts +17 -17
  111. package/lib/stateful/runtimes/actions.js +35 -55
  112. package/lib/stateful/runtimes/apis.d.ts +3 -3
  113. package/lib/stateful/runtimes/snapshots.d.ts +2 -2
  114. package/lib/stateful/runtimes/snapshots.js +7 -7
  115. package/lib/utils/Format.d.ts +6 -0
  116. package/lib/utils/Format.js +17 -0
  117. package/lib/utils/Handles.d.ts +3 -0
  118. package/lib/utils/Handles.js +53 -0
  119. package/lib/utils/Snapshot.d.ts +1 -1
  120. package/lib/utils/Snapshot.js +1 -1
  121. package/lib/utils/index.d.ts +1 -0
  122. package/lib/utils/index.js +1 -0
  123. package/lib/views/datasources/DatasourceDetail.d.ts +7 -1
  124. package/lib/views/datasources/DatasourceDetail.js +61 -23
  125. package/lib/views/datasources/DatasourceNew.d.ts +8 -1
  126. package/lib/views/datasources/DatasourceNew.js +23 -10
  127. package/lib/views/datasources/Datasources.d.ts +5 -1
  128. package/lib/views/datasources/Datasources.js +38 -30
  129. package/lib/views/iam-tokens/IAMTokenNew.d.ts +3 -1
  130. package/lib/views/iam-tokens/IAMTokenNew.js +2 -2
  131. package/lib/views/iam-tokens/IAMTokens.d.ts +3 -1
  132. package/lib/views/iam-tokens/IAMTokens.js +2 -2
  133. package/lib/views/otel/OtelHeader.d.ts +5 -0
  134. package/lib/views/otel/OtelHeader.js +3 -3
  135. package/lib/views/profile/UserBadge.d.ts +7 -2
  136. package/lib/views/profile/UserBadge.js +11 -2
  137. package/lib/views/secrets/Secrets.js +21 -21
  138. package/package.json +7 -8
package/README.md CHANGED
@@ -124,6 +124,33 @@ datalayer runtime exec my-script.py --runtime <runtime-id>
124
124
  datalayer snapshots create <pod-name> my-snapshot 'AI work!' False
125
125
  ```
126
126
 
127
+ ### 4. Subscription and Credits CLI
128
+
129
+ Use these commands to inspect billing and manage credits distribution.
130
+
131
+ ```bash
132
+ # End-user billing view
133
+ datalayer subscriptions show
134
+ datalayer subscriptions available
135
+ datalayer subscriptions move
136
+ datalayer subscriptions topups
137
+ datalayer subscriptions dry-run
138
+
139
+ # Organization and team credits visibility
140
+ datalayer usage org-overview --organization-uid <org_uid>
141
+ datalayer usage team-overview --team-uid <team_uid>
142
+
143
+ # Monitoring-driven credit management
144
+ datalayer usage org-monitor --organization-uid <org_uid> --window-hours 24
145
+ datalayer usage team-monitor --team-uid <team_uid> --window-hours 24
146
+
147
+ # Credits transfer operations (owners/admins)
148
+ datalayer usage org-allocate-team --organization-uid <org_uid> --team-uid <team_uid> --amount 50
149
+ datalayer usage org-revoke-team --organization-uid <org_uid> --team-uid <team_uid> --amount 20
150
+ datalayer usage team-allocate-member --team-uid <team_uid> --member-uid <member_uid> --amount 15
151
+ datalayer usage team-revoke-member --team-uid <team_uid> --member-uid <member_uid> --amount 5
152
+ ```
153
+
127
154
  ## Examples
128
155
 
129
156
  ### Python Examples
@@ -14,7 +14,7 @@ export declare class RunResponseError extends Error {
14
14
  /**
15
15
  * Create a new response error.
16
16
  */
17
- constructor(response: Response, message?: string, warnings?: undefined, errors?: undefined, exceptionMessage?: undefined, traceback?: string);
17
+ constructor(response: Response, message?: string, warnings?: undefined, errors?: undefined, exceptionMessage?: undefined, traceback?: string, detail?: unknown);
18
18
  /**
19
19
  * Warnings listed in the response.
20
20
  */
@@ -35,6 +35,10 @@ export declare class RunResponseError extends Error {
35
35
  * The traceback associated with the error.
36
36
  */
37
37
  readonly traceback: string;
38
+ /**
39
+ * Optional structured backend detail payload.
40
+ */
41
+ readonly detail: unknown;
38
42
  private static _defaultMessage;
39
43
  }
40
44
  /**
@@ -11,6 +11,24 @@
11
11
  import { URLExt } from '@jupyterlab/coreutils';
12
12
  import axios from 'axios';
13
13
  import { sleep } from '../utils/Sleep.js';
14
+ function isFormDataBody(body) {
15
+ if (!body || typeof body !== 'object') {
16
+ return false;
17
+ }
18
+ // `instanceof FormData` is not reliable across realms (e.g. jsdom/undici).
19
+ if (typeof FormData !== 'undefined' && body instanceof FormData) {
20
+ return true;
21
+ }
22
+ const formDataTag = Object.prototype.toString.call(body);
23
+ if (formDataTag === '[object FormData]') {
24
+ return true;
25
+ }
26
+ const candidate = body;
27
+ return (typeof candidate.append === 'function' &&
28
+ typeof candidate.get === 'function' &&
29
+ typeof candidate.has === 'function' &&
30
+ typeof candidate.entries === 'function');
31
+ }
14
32
  /**
15
33
  * Error wrapper for failed HTTP responses.
16
34
  * Includes response details, warnings, errors, and tracebacks.
@@ -26,11 +44,17 @@ export class RunResponseError extends Error {
26
44
  static async create(response) {
27
45
  try {
28
46
  const data = await response.json();
29
- const { message, errors, warnings, traceback, exception } = data;
47
+ const { message, errors, warnings, traceback, exception, detail } = data;
48
+ const resolvedMessage = message ??
49
+ (typeof detail === 'string'
50
+ ? detail
51
+ : detail && typeof detail === 'object' && 'message' in detail
52
+ ? String(detail.message)
53
+ : undefined);
30
54
  if (traceback) {
31
55
  console.error(traceback);
32
56
  }
33
- const responseError = new RunResponseError(response, message ?? RunResponseError._defaultMessage(response), warnings, errors, exception, traceback ?? '');
57
+ const responseError = new RunResponseError(response, resolvedMessage ?? RunResponseError._defaultMessage(response), warnings, errors, exception, traceback ?? '', detail);
34
58
  return responseError;
35
59
  }
36
60
  catch (e) {
@@ -41,7 +65,7 @@ export class RunResponseError extends Error {
41
65
  /**
42
66
  * Create a new response error.
43
67
  */
44
- constructor(response, message = RunResponseError._defaultMessage(response), warnings = undefined, errors = undefined, exceptionMessage = undefined, traceback = '') {
68
+ constructor(response, message = RunResponseError._defaultMessage(response), warnings = undefined, errors = undefined, exceptionMessage = undefined, traceback = '', detail = undefined) {
45
69
  super(message);
46
70
  this.name = 'RunResponseError';
47
71
  this.warnings = warnings ?? [];
@@ -49,6 +73,7 @@ export class RunResponseError extends Error {
49
73
  this.response = response;
50
74
  this.exceptionMessage = exceptionMessage;
51
75
  this.traceback = traceback;
76
+ this.detail = detail;
52
77
  }
53
78
  /**
54
79
  * Warnings listed in the response.
@@ -70,6 +95,10 @@ export class RunResponseError extends Error {
70
95
  * The traceback associated with the error.
71
96
  */
72
97
  traceback;
98
+ /**
99
+ * Optional structured backend detail payload.
100
+ */
101
+ detail;
73
102
  static _defaultMessage(response) {
74
103
  return `Invalid response: ${response.status} ${response.statusText}`;
75
104
  }
@@ -110,7 +139,7 @@ export class NetworkError extends TypeError {
110
139
  */
111
140
  export async function requestDatalayerAPI({ url, method, body, token, signal, headers = {}, }) {
112
141
  // Handle FormData differently from JSON
113
- const isFormData = body instanceof FormData;
142
+ const isFormData = isFormDataBody(body);
114
143
  // Prepare axios config
115
144
  const axiosConfig = {
116
145
  url,
@@ -198,10 +227,28 @@ export async function requestDatalayerAPI({ url, method, body, token, signal, he
198
227
  async function handleAxiosRedirection(response, originalConfig) {
199
228
  let redirect = response.headers.location;
200
229
  if (redirect) {
201
- const parsedURL = URLExt.parse(originalConfig.url);
202
- const baseUrl = parsedURL.protocol + '//' + parsedURL.hostname;
203
- if (!redirect.startsWith(baseUrl)) {
204
- redirect = URLExt.join(baseUrl, redirect);
230
+ const baseUrl = originalConfig.url ?? '';
231
+ const normalizedRedirect = String(redirect).replace(/^([a-z][a-z0-9+.-]*):\/(?!\/)/i, '$1://');
232
+ try {
233
+ const resolved = new URL(normalizedRedirect, baseUrl);
234
+ const base = new URL(baseUrl, typeof window !== 'undefined' ? window.location.origin : undefined);
235
+ // If a proxy emits an http Location for the same host while the
236
+ // original request is https, force https to avoid mixed-content errors
237
+ // that browsers often report as CORS/network failures.
238
+ if (base.protocol === 'https:' &&
239
+ resolved.protocol === 'http:' &&
240
+ resolved.hostname === base.hostname) {
241
+ resolved.protocol = 'https:';
242
+ if (resolved.port === '80') {
243
+ resolved.port = '';
244
+ }
245
+ }
246
+ redirect = resolved.toString();
247
+ }
248
+ catch {
249
+ const parsedURL = URLExt.parse(baseUrl);
250
+ const fallbackBase = parsedURL.protocol + '//' + parsedURL.hostname;
251
+ redirect = URLExt.join(fallbackBase, normalizedRedirect);
205
252
  }
206
253
  }
207
254
  let sleepTimeout = 1000;
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * OAuth2 provider types supported by the platform
3
3
  */
4
- export type OAuth2Provider = 'github' | 'linkedin' | 'okta';
4
+ export type OAuth2Provider = 'github' | 'google' | 'linkedin' | 'okta';
5
5
  /**
6
6
  * Response from the OAuth2 authorization URL endpoint
7
7
  */
@@ -26,7 +26,7 @@ export interface OAuth2CallbackParams {
26
26
  export type OAuth2CallbackResponse = string;
27
27
  /**
28
28
  * Get the OAuth2 authorization URL for a specific provider
29
- * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
29
+ * @param provider - OAuth2 provider (github, google, linkedin, okta)
30
30
  * @param callbackUri - Server endpoint to call with the authz token
31
31
  * @param nonce - Optional nonce for security
32
32
  * @param baseUrl - Base URL for the API (defaults to production IAM URL)
@@ -45,7 +45,7 @@ export type OAuth2CallbackResponse = string;
45
45
  export declare const getOAuth2AuthzUrl: (provider: OAuth2Provider, callbackUri: string, nonce?: string, baseUrl?: string) => Promise<OAuth2AuthzUrlResponse>;
46
46
  /**
47
47
  * Get the OAuth2 authorization URL for linking a provider to an existing account
48
- * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
48
+ * @param provider - OAuth2 provider (github, google, linkedin, okta)
49
49
  * @param callbackUri - Server endpoint to call with the authz token
50
50
  * @param baseUrl - Base URL for the API (defaults to production IAM URL)
51
51
  * @returns OAuth2 authorization URL response
@@ -13,7 +13,7 @@ import { requestDatalayerAPI } from '../DatalayerApi.js';
13
13
  import { API_BASE_PATHS, DEFAULT_SERVICE_URLS } from '../constants.js';
14
14
  /**
15
15
  * Get the OAuth2 authorization URL for a specific provider
16
- * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
16
+ * @param provider - OAuth2 provider (github, google, linkedin, okta)
17
17
  * @param callbackUri - Server endpoint to call with the authz token
18
18
  * @param nonce - Optional nonce for security
19
19
  * @param baseUrl - Base URL for the API (defaults to production IAM URL)
@@ -71,7 +71,7 @@ export const getOAuth2AuthzUrl = async (provider, callbackUri, nonce, baseUrl =
71
71
  };
72
72
  /**
73
73
  * Get the OAuth2 authorization URL for linking a provider to an existing account
74
- * @param provider - OAuth2 provider (bluesky, github, linkedin, okta)
74
+ * @param provider - OAuth2 provider (github, google, linkedin, okta)
75
75
  * @param callbackUri - Server endpoint to call with the authz token
76
76
  * @param baseUrl - Base URL for the API (defaults to production IAM URL)
77
77
  * @returns OAuth2 authorization URL response
@@ -1,4 +1,4 @@
1
- import { MembershipsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
1
+ import { MembershipsResponse, ShareablePrincipalsResponse, UserMeResponse, WhoAmIResponse } from '../../models/IAM';
2
2
  /**
3
3
  * Get current authenticated user profile
4
4
  * @param token - Authentication token (required)
@@ -20,3 +20,11 @@ export declare const whoami: (token: string, baseUrl?: string) => Promise<WhoAmI
20
20
  * @returns Current user identity and profile information
21
21
  */
22
22
  export declare const memberships: (token: string, baseUrl?: string) => Promise<MembershipsResponse>;
23
+ /**
24
+ * Get the set of principals the authenticated user can share artifacts with
25
+ * (self + member organizations + member teams).
26
+ *
27
+ * @param token - Authentication token (required)
28
+ * @param baseUrl - Base URL for the API (defaults to production IAM URL)
29
+ */
30
+ export declare const principalsShareable: (token: string, baseUrl?: string) => Promise<ShareablePrincipalsResponse>;
@@ -54,3 +54,18 @@ export const memberships = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) =>
54
54
  token,
55
55
  });
56
56
  };
57
+ /**
58
+ * Get the set of principals the authenticated user can share artifacts with
59
+ * (self + member organizations + member teams).
60
+ *
61
+ * @param token - Authentication token (required)
62
+ * @param baseUrl - Base URL for the API (defaults to production IAM URL)
63
+ */
64
+ export const principalsShareable = async (token, baseUrl = DEFAULT_SERVICE_URLS.IAM) => {
65
+ validateToken(token);
66
+ return requestDatalayerAPI({
67
+ url: `${baseUrl}${API_BASE_PATHS.IAM}/principals/shareable`,
68
+ method: 'GET',
69
+ token,
70
+ });
71
+ };
@@ -6,7 +6,7 @@
6
6
  * Runtime checkpoints API functions for the Datalayer platform.
7
7
  *
8
8
  * Provides functions for managing CRIU full-pod checkpoints.
9
- * These are distinct from runtime snapshots (Jupyter sandbox snapshots).
9
+ * These are distinct from code sandbox snapshots (Jupyter sandbox snapshots).
10
10
  *
11
11
  * @module api/runtimes/checkpoints
12
12
  */
@@ -1,4 +1,4 @@
1
- import { CreateRuntimeSnapshotRequest, ListRuntimeSnapshotsResponse, GetRuntimeSnapshotResponse, CreateRuntimeSnapshotResponse } from '../../models/RuntimeSnapshotDTO';
1
+ import { CreateCodeSandboxSnapshotRequest, ListCodeSandboxSnapshotsResponse, GetCodeSandboxSnapshotResponse, CreateCodeSandboxSnapshotResponse } from '../../models/CodeSandboxSnapshotDTO';
2
2
  /**
3
3
  * Create a snapshot of a runtime instance.
4
4
  * @param token - Authentication token
@@ -7,17 +7,17 @@ import { CreateRuntimeSnapshotRequest, ListRuntimeSnapshotsResponse, GetRuntimeS
7
7
  * @returns Promise resolving to the created snapshot response
8
8
  * @throws {Error} If authentication token is missing or invalid
9
9
  */
10
- export declare const createSnapshot: (token: string, data: CreateRuntimeSnapshotRequest, baseUrl?: string) => Promise<CreateRuntimeSnapshotResponse>;
10
+ export declare const createSnapshot: (token: string, data: CreateCodeSandboxSnapshotRequest, baseUrl?: string) => Promise<CreateCodeSandboxSnapshotResponse>;
11
11
  /**
12
- * List all runtime snapshots.
12
+ * List all code sandbox snapshots.
13
13
  * @param token - Authentication token
14
14
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
15
15
  * @returns Promise resolving to list of snapshots
16
16
  * @throws {Error} If authentication token is missing or invalid
17
17
  */
18
- export declare const listSnapshots: (token: string, baseUrl?: string) => Promise<ListRuntimeSnapshotsResponse>;
18
+ export declare const listSnapshots: (token: string, baseUrl?: string) => Promise<ListCodeSandboxSnapshotsResponse>;
19
19
  /**
20
- * Get details for a specific runtime snapshot.
20
+ * Get details for a specific code sandbox snapshot.
21
21
  * @param token - Authentication token
22
22
  * @param snapshotId - The unique identifier of the snapshot
23
23
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
@@ -25,9 +25,9 @@ export declare const listSnapshots: (token: string, baseUrl?: string) => Promise
25
25
  * @throws {Error} If authentication token is missing or invalid
26
26
  * @throws {Error} If snapshot ID is missing or invalid
27
27
  */
28
- export declare const getSnapshot: (token: string, snapshotId: string, baseUrl?: string) => Promise<GetRuntimeSnapshotResponse>;
28
+ export declare const getSnapshot: (token: string, snapshotId: string, baseUrl?: string) => Promise<GetCodeSandboxSnapshotResponse>;
29
29
  /**
30
- * Delete a runtime snapshot.
30
+ * Delete a code sandbox snapshot.
31
31
  * @param token - Authentication token
32
32
  * @param snapshotId - The unique identifier of the snapshot to delete
33
33
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
@@ -3,9 +3,9 @@
3
3
  * Distributed under the terms of the Modified BSD License.
4
4
  */
5
5
  /**
6
- * Runtime snapshots API functions for the Datalayer platform.
6
+ * Code Sandbox snapshots API functions for the Datalayer platform.
7
7
  *
8
- * Provides functions for managing runtime snapshots (saved runtime states).
8
+ * Provides functions for managing code sandbox snapshots (saved runtime states).
9
9
  *
10
10
  * @module api/runtimes/snapshots
11
11
  */
@@ -23,14 +23,14 @@ import { validateToken, validateRequiredString } from '../utils/validation.js';
23
23
  export const createSnapshot = async (token, data, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
24
24
  validateToken(token);
25
25
  return requestDatalayerAPI({
26
- url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-snapshots`,
26
+ url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots`,
27
27
  method: 'POST',
28
28
  token,
29
29
  body: data,
30
30
  });
31
31
  };
32
32
  /**
33
- * List all runtime snapshots.
33
+ * List all code sandbox snapshots.
34
34
  * @param token - Authentication token
35
35
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
36
36
  * @returns Promise resolving to list of snapshots
@@ -39,13 +39,13 @@ export const createSnapshot = async (token, data, baseUrl = DEFAULT_SERVICE_URLS
39
39
  export const listSnapshots = async (token, baseUrl = DEFAULT_SERVICE_URLS.RUNTIMES) => {
40
40
  validateToken(token);
41
41
  return requestDatalayerAPI({
42
- url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-snapshots`,
42
+ url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots`,
43
43
  method: 'GET',
44
44
  token,
45
45
  });
46
46
  };
47
47
  /**
48
- * Get details for a specific runtime snapshot.
48
+ * Get details for a specific code sandbox snapshot.
49
49
  * @param token - Authentication token
50
50
  * @param snapshotId - The unique identifier of the snapshot
51
51
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
@@ -57,13 +57,13 @@ export const getSnapshot = async (token, snapshotId, baseUrl = DEFAULT_SERVICE_U
57
57
  validateToken(token);
58
58
  validateRequiredString(snapshotId, 'Snapshot ID');
59
59
  return requestDatalayerAPI({
60
- url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-snapshots/${snapshotId}`,
60
+ url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots/${snapshotId}`,
61
61
  method: 'GET',
62
62
  token,
63
63
  });
64
64
  };
65
65
  /**
66
- * Delete a runtime snapshot.
66
+ * Delete a code sandbox snapshot.
67
67
  * @param token - Authentication token
68
68
  * @param snapshotId - The unique identifier of the snapshot to delete
69
69
  * @param baseUrl - Base URL for the API (defaults to production Runtimes URL)
@@ -75,7 +75,7 @@ export const deleteSnapshot = async (token, snapshotId, baseUrl = DEFAULT_SERVIC
75
75
  validateToken(token);
76
76
  validateRequiredString(snapshotId, 'Snapshot ID');
77
77
  return requestDatalayerAPI({
78
- url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/runtime-snapshots/${snapshotId}`,
78
+ url: `${baseUrl}${API_BASE_PATHS.RUNTIMES}/sandbox-snapshots/${snapshotId}`,
79
79
  method: 'DELETE',
80
80
  token,
81
81
  });
@@ -11,6 +11,68 @@
11
11
  * Token storage backend implementations
12
12
  */
13
13
  import { DATALAYER_IAM_TOKEN_KEY, DATALAYER_IAM_USER_KEY, } from '../../state/storage/IAMStorage.js';
14
+ /**
15
+ * Resolve a real Node `require` function that survives bundling.
16
+ *
17
+ * `module.createRequire()` is the documented Node API for obtaining a
18
+ * require function that resolves modules against `node_modules`. Three
19
+ * runtimes need to be supported:
20
+ *
21
+ * 1. **Native Node ESM** (this package is `"type": "module"`). The
22
+ * global `require` is undefined here, so we resolve `module` via
23
+ * `process.getBuiltinModule('module')` (added in Node 22.3 / 20.16).
24
+ * 2. **Native Node CommonJS** and **bundler-injected CJS shims**
25
+ * (e.g. webpack with `target: 'node'`). These expose a working
26
+ * global `require`, and `require('module')` resolves to the real
27
+ * Node builtin even after bundling.
28
+ * 3. **Native browser**. None of the above is available; we return
29
+ * `null`.
30
+ *
31
+ * @returns A real Node `require`, or `null` outside Node, or
32
+ * `undefined` if Node is detected but no `createRequire` source is
33
+ * reachable (extremely old Node, or a hostile sandbox).
34
+ */
35
+ function resolveNodeRequire() {
36
+ if (typeof process === 'undefined' || !process.versions?.node) {
37
+ return null;
38
+ }
39
+ const fname = typeof __filename !== 'undefined'
40
+ ? __filename
41
+ : process.cwd() + '/__datalayer_keytar_loader__.js';
42
+ // 1. ESM-safe path: process.getBuiltinModule (Node 22.3+ / 20.16+).
43
+ // Lets a `"type": "module"` package reach into `module` without a
44
+ // CommonJS-only `require`.
45
+ const nodeProcess = process;
46
+ try {
47
+ const mod = nodeProcess.getBuiltinModule?.('module');
48
+ if (typeof mod?.createRequire === 'function') {
49
+ return mod.createRequire(fname);
50
+ }
51
+ }
52
+ catch {
53
+ // Fall through to the CommonJS / bundler path.
54
+ }
55
+ // 2. CommonJS path: `require('module')` is left intact by webpack
56
+ // when target: 'node'. Also covers older Node CJS where
57
+ // getBuiltinModule does not exist.
58
+ try {
59
+ if (typeof require === 'function') {
60
+ const mod = require('module');
61
+ if (typeof mod?.createRequire === 'function') {
62
+ return mod.createRequire(fname);
63
+ }
64
+ }
65
+ }
66
+ catch {
67
+ // Fall through to globalThis.require.
68
+ }
69
+ // 3. Last-ditch: a globalThis.require shim from some host environments.
70
+ const g = globalThis;
71
+ if (typeof g.require === 'function') {
72
+ return g.require;
73
+ }
74
+ return undefined;
75
+ }
14
76
  /**
15
77
  * Browser localStorage-based token storage
16
78
  */
@@ -136,21 +198,50 @@ export class NodeStorage {
136
198
  typeof process !== 'undefined' &&
137
199
  process.versions?.node) {
138
200
  try {
139
- // Use eval to hide require from bundlers (Vite/Rollup/webpack)
140
- const nodeRequire = eval('require');
141
- try {
142
- this.keytar = nodeRequire('keytar');
143
- }
144
- catch {
145
- try {
146
- this.keytar = nodeRequire('@vscode/keytar');
147
- }
148
- catch {
149
- // Keyring not available
201
+ // Resolve a real Node `require` even when this module ends up
202
+ // inside a webpack bundle.
203
+ //
204
+ // Why not the previous `string-evaluated require` pattern? Webpack
205
+ // rewrites that pattern to its own loader (`__webpack_require__`),
206
+ // which has no entry for these runtime-only keyring modules
207
+ // (`@github/keytar`, `@vscode/keytar`, or legacy `keytar`)
208
+ // because the require call is hidden behind a string and is
209
+ // therefore invisible to webpack's static analysis — even when
210
+ // consumers declare those package IDs as commonjs/runtime
211
+ // externals. The result was that `this.keytar` silently stayed
212
+ // `null` in any webpacked host (e.g. the VS Code extension), so
213
+ // tokens written via `setAsync()` only landed in the in-memory
214
+ // `Map` and never made it to the OS keyring. They appeared to
215
+ // "save" within a session, but vanished on reload.
216
+ //
217
+ // `module.createRequire(...)` is the documented Node API for
218
+ // obtaining the real require, and webpack/Vite/Rollup all leave
219
+ // it intact when the host targets Node.
220
+ const nodeRequire = resolveNodeRequire();
221
+ if (nodeRequire) {
222
+ // Try variants in order of preference:
223
+ // 1. @github/keytar — actively maintained, ships prebuilt
224
+ // binaries for every platform in the npm tarball, so a
225
+ // single multi-platform VSIX / Electron build can ship
226
+ // it without per-OS rebuilds.
227
+ // 2. @vscode/keytar — historically bundled with VS Code,
228
+ // no longer published to npm but still resolvable in
229
+ // some host environments.
230
+ // 3. keytar — the original, deprecated upstream. Kept as a
231
+ // fallback so existing CLI installs that still depend
232
+ // on it keep working.
233
+ for (const id of ['@github/keytar', '@vscode/keytar', 'keytar']) {
234
+ try {
235
+ this.keytar = nodeRequire(id);
236
+ break;
237
+ }
238
+ catch {
239
+ // Try next variant.
240
+ }
150
241
  }
151
242
  }
152
243
  }
153
- catch (e) {
244
+ catch {
154
245
  // Keyring not available, tokens will not persist across sessions
155
246
  console.warn('keytar not available, tokens will not persist');
156
247
  }
@@ -19,7 +19,7 @@ import type { UserDTO } from './../models/UserDTO';
19
19
  import type { CreditsDTO } from '../models/CreditsDTO';
20
20
  import type { EnvironmentDTO } from '../models/EnvironmentDTO';
21
21
  import type { RuntimeDTO } from '../models/RuntimeDTO';
22
- import type { RuntimeSnapshotDTO } from '../models/RuntimeSnapshotDTO';
22
+ import type { CodeSandboxSnapshotDTO } from '../models/CodeSandboxSnapshotDTO';
23
23
  import type { SpaceDTO } from '../models/SpaceDTO';
24
24
  import type { NotebookDTO } from '../models/NotebookDTO';
25
25
  import type { LexicalDTO } from '../models/LexicalDTO';
@@ -65,8 +65,8 @@ export { RuntimeDTO as Runtime } from '../models/RuntimeDTO';
65
65
  export type { RuntimeJSON, RuntimeData, CreateRuntimeRequest, CreateRuntimeResponse, ListRuntimesResponse, } from '../models/RuntimeDTO';
66
66
  export { EnvironmentDTO as Environment } from '../models/EnvironmentDTO';
67
67
  export type { EnvironmentJSON, EnvironmentData, ListEnvironmentsResponse, } from '../models/EnvironmentDTO';
68
- export { RuntimeSnapshotDTO as Snapshot } from '../models/RuntimeSnapshotDTO';
69
- export type { RuntimeSnapshotJSON, RuntimeSnapshotData, CreateRuntimeSnapshotRequest, CreateRuntimeSnapshotResponse, GetRuntimeSnapshotResponse, ListRuntimeSnapshotsResponse, } from '../models/RuntimeSnapshotDTO';
68
+ export { CodeSandboxSnapshotDTO as Snapshot } from '../models/CodeSandboxSnapshotDTO';
69
+ export type { CodeSandboxSnapshotJSON, CodeSandboxSnapshotData, CreateCodeSandboxSnapshotRequest, CreateCodeSandboxSnapshotResponse, GetCodeSandboxSnapshotResponse, ListCodeSandboxSnapshotsResponse, } from '../models/CodeSandboxSnapshotDTO';
70
70
  export { SpaceDTO as Space } from '../models/SpaceDTO';
71
71
  export type { SpaceJSON, SpaceData, SpaceItem, CreateSpaceRequest, CreateSpaceResponse, SpacesForUserResponse, CollaborationSessionResponse, DeleteSpaceItemResponse, GetSpaceItemResponse, GetSpaceItemsResponse, CreateNotebookRequest, CreateNotebookResponse, GetNotebookResponse, UpdateNotebookRequest, UpdateNotebookResponse, UpdateSpaceRequest, GetSpaceResponse, UpdateSpaceResponse, DeleteSpaceResponse, GetSpaceDefaultItemsResponse, GetSpacesByTypeResponse, } from '../models/SpaceDTO';
72
72
  export { ProjectDTO as Project } from '../models/ProjectDTO';
@@ -97,7 +97,7 @@ export type { ISpace, IBaseSpace, IAnySpace, ISpaceVariant, } from '../models/Sp
97
97
  export type { IBaseTeam, IAnyTeam } from '../models/Team';
98
98
  export type { IOrganization, IAnyOrganization, IBaseOrganization, } from '../models/Organization';
99
99
  export type { IRuntimeModel, IRuntimePod, IRuntimeType, IRuntimeLocation, IRuntimeCapabilities, } from '../models/Runtime';
100
- export type { IRuntimeSnapshot } from '../models/RuntimeSnapshot';
100
+ export type { ICodeSandboxSnapshot } from '../models/CodeSandboxSnapshot';
101
101
  export type { IDatalayerEnvironment, IResources, ISnippet, } from '../models/Environment';
102
102
  export type { IRole } from '../models/Role';
103
103
  export type { IAssignment } from '../models/Assignment';
@@ -170,9 +170,9 @@ export interface DatalayerClient {
170
170
  getRuntime(podName: string): Promise<RuntimeDTO>;
171
171
  deleteRuntime(podName: string): Promise<void>;
172
172
  terminateAllRuntimes(): Promise<PromiseSettledResult<void>[]>;
173
- createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<RuntimeSnapshotDTO>;
174
- listSnapshots(): Promise<RuntimeSnapshotDTO[]>;
175
- getSnapshot(id: string): Promise<RuntimeSnapshotDTO>;
173
+ createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<CodeSandboxSnapshotDTO>;
174
+ listSnapshots(): Promise<CodeSandboxSnapshotDTO[]>;
175
+ getSnapshot(id: string): Promise<CodeSandboxSnapshotDTO>;
176
176
  deleteSnapshot(id: string): Promise<void>;
177
177
  checkRuntimesHealth(): Promise<HealthCheck>;
178
178
  getMySpaces(): Promise<SpaceDTO[]>;
@@ -68,7 +68,7 @@ export { DatalayerClientBase };
68
68
  export { UserDTO as User } from './../models/UserDTO.js';
69
69
  export { RuntimeDTO as Runtime } from '../models/RuntimeDTO.js';
70
70
  export { EnvironmentDTO as Environment } from '../models/EnvironmentDTO.js';
71
- export { RuntimeSnapshotDTO as Snapshot } from '../models/RuntimeSnapshotDTO.js';
71
+ export { CodeSandboxSnapshotDTO as Snapshot } from '../models/CodeSandboxSnapshotDTO.js';
72
72
  export { SpaceDTO as Space } from '../models/SpaceDTO.js';
73
73
  export { ProjectDTO as Project } from '../models/ProjectDTO.js';
74
74
  export { NotebookDTO as Notebook } from '../models/NotebookDTO.js';
@@ -1,7 +1,7 @@
1
1
  import type { Constructor } from '../utils/mixins';
2
2
  import { EnvironmentDTO } from '../../models/EnvironmentDTO';
3
3
  import { RuntimeDTO } from '../../models/RuntimeDTO';
4
- import { RuntimeSnapshotDTO } from '../../models/RuntimeSnapshotDTO';
4
+ import { CodeSandboxSnapshotDTO } from '../../models/CodeSandboxSnapshotDTO';
5
5
  import { HealthCheck } from '../../models/HealthCheck';
6
6
  /** Options for ensuring a runtime is available. */
7
7
  export interface EnsureRuntimeOptions {
@@ -22,7 +22,7 @@ export interface EnsureRuntimeOptions {
22
22
  export declare function RuntimesMixin<TBase extends Constructor>(Base: TBase): {
23
23
  new (...args: any[]): {
24
24
  _extractRuntimePodName(runtimePodNameOrInstance: string | RuntimeDTO): string;
25
- _extractSnapshotId(snapshotIdOrInstance: string | RuntimeSnapshotDTO): string;
25
+ _extractSnapshotId(snapshotIdOrInstance: string | CodeSandboxSnapshotDTO): string;
26
26
  /**
27
27
  * List all available computational environments.
28
28
  * @returns Array of Environment model instances
@@ -67,18 +67,18 @@ export declare function RuntimesMixin<TBase extends Constructor>(Base: TBase): {
67
67
  * @param stop - Whether to stop the runtime after creating snapshot (defaults to false)
68
68
  * @returns Created snapshot
69
69
  */
70
- createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<RuntimeSnapshotDTO>;
70
+ createSnapshot(podName: string, name: string, description: string, stop?: boolean): Promise<CodeSandboxSnapshotDTO>;
71
71
  /**
72
- * List all runtime snapshots.
72
+ * List all code sandbox snapshots.
73
73
  * @returns Array of snapshots
74
74
  */
75
- listSnapshots(): Promise<RuntimeSnapshotDTO[]>;
75
+ listSnapshots(): Promise<CodeSandboxSnapshotDTO[]>;
76
76
  /**
77
77
  * Get details for a specific snapshot by ID.
78
78
  * @param id - Snapshot ID
79
79
  * @returns Snapshot details
80
80
  */
81
- getSnapshot(id: string): Promise<RuntimeSnapshotDTO>;
81
+ getSnapshot(id: string): Promise<CodeSandboxSnapshotDTO>;
82
82
  /**
83
83
  * Delete a snapshot permanently.
84
84
  * @param id - Snapshot ID
@@ -11,7 +11,7 @@ import * as runtimes from '../../api/runtimes/runtimes.js';
11
11
  import * as snapshots from '../../api/runtimes/snapshots.js';
12
12
  import { EnvironmentDTO } from '../../models/EnvironmentDTO.js';
13
13
  import { RuntimeDTO } from '../../models/RuntimeDTO.js';
14
- import { RuntimeSnapshotDTO } from '../../models/RuntimeSnapshotDTO.js';
14
+ import { CodeSandboxSnapshotDTO } from '../../models/CodeSandboxSnapshotDTO.js';
15
15
  import { HealthCheck } from '../../models/HealthCheck.js';
16
16
  /** Runtimes mixin providing computational environment and runtime management. */
17
17
  export function RuntimesMixin(Base) {
@@ -148,17 +148,17 @@ export function RuntimesMixin(Base) {
148
148
  stop,
149
149
  };
150
150
  const response = await snapshots.createSnapshot(token, data, runtimesRunUrl);
151
- return new RuntimeSnapshotDTO(response.snapshot, this);
151
+ return new CodeSandboxSnapshotDTO(response.snapshot, this);
152
152
  }
153
153
  /**
154
- * List all runtime snapshots.
154
+ * List all code sandbox snapshots.
155
155
  * @returns Array of snapshots
156
156
  */
157
157
  async listSnapshots() {
158
158
  const token = this.getToken();
159
159
  const runtimesRunUrl = this.getRuntimesRunUrl();
160
160
  const response = await snapshots.listSnapshots(token, runtimesRunUrl);
161
- return response.snapshots.map(s => new RuntimeSnapshotDTO(s, this));
161
+ return response.snapshots.map(s => new CodeSandboxSnapshotDTO(s, this));
162
162
  }
163
163
  /**
164
164
  * Get details for a specific snapshot by ID.
@@ -169,7 +169,7 @@ export function RuntimesMixin(Base) {
169
169
  const token = this.getToken();
170
170
  const runtimesRunUrl = this.getRuntimesRunUrl();
171
171
  const response = await snapshots.getSnapshot(token, id, runtimesRunUrl);
172
- return new RuntimeSnapshotDTO(response.snapshot, this);
172
+ return new CodeSandboxSnapshotDTO(response.snapshot, this);
173
173
  }
174
174
  /**
175
175
  * Delete a snapshot permanently.